|
Packit |
c22fc9 |
/*
|
|
Packit |
c22fc9 |
* Soft: Keepalived is a failover program for the LVS project
|
|
Packit |
c22fc9 |
* <www.linuxvirtualserver.org>. It monitor & manipulate
|
|
Packit |
c22fc9 |
* a loadbalanced server pool using multi-layer checks.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Part: Interface tracking framework.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Author: Alexandre Cassen, <acassen@linux-vs.org>
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
c22fc9 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
c22fc9 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
c22fc9 |
* See the GNU General Public License for more details.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* This program is free software; you can redistribute it and/or
|
|
Packit |
c22fc9 |
* modify it under the terms of the GNU General Public License
|
|
Packit |
c22fc9 |
* as published by the Free Software Foundation; either version
|
|
Packit |
c22fc9 |
* 2 of the License, or (at your option) any later version.
|
|
Packit |
c22fc9 |
*
|
|
Packit |
c22fc9 |
* Copyright (C) 2001-2017 Alexandre Cassen, <acassen@gmail.com>
|
|
Packit |
c22fc9 |
*/
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#include "config.h"
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#include <net/if.h>
|
|
Packit |
c22fc9 |
#include <stdlib.h>
|
|
Packit |
c22fc9 |
#include <limits.h>
|
|
Packit |
c22fc9 |
#include <stdlib.h>
|
|
Packit |
c22fc9 |
#include <errno.h>
|
|
Packit |
c22fc9 |
#include <sys/types.h>
|
|
Packit |
c22fc9 |
#include <fcntl.h>
|
|
Packit |
c22fc9 |
#include <stdio.h>
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* local include */
|
|
Packit Service |
dfccb1 |
#include "vrrp_track.h"
|
|
Packit |
c22fc9 |
#include "vrrp_data.h"
|
|
Packit |
c22fc9 |
#include "vrrp.h"
|
|
Packit |
c22fc9 |
#include "vrrp_sync.h"
|
|
Packit |
c22fc9 |
#include "logger.h"
|
|
Packit |
c22fc9 |
#include "memory.h"
|
|
Packit |
c22fc9 |
#include "vrrp_scheduler.h"
|
|
Packit |
c22fc9 |
#include "scheduler.h"
|
|
Packit |
c22fc9 |
#include "parser.h"
|
|
Packit Service |
dfccb1 |
#include "utils.h"
|
|
Packit Service |
dfccb1 |
#include "vrrp_notify.h"
|
|
Packit Service |
dfccb1 |
#include "bitops.h"
|
|
Packit Service |
dfccb1 |
#include "track_file.h"
|
|
Packit Service |
dfccb1 |
#ifdef _WITH_CN_PROC_
|
|
Packit Service |
dfccb1 |
#include "track_process.h"
|
|
Packit Service |
dfccb1 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Track interface dump */
|
|
Packit Service |
dfccb1 |
static void
|
|
Packit Service |
dfccb1 |
dump_track_if(FILE *fp, const tracked_if_t *tip)
|
|
Packit Service |
dfccb1 |
{
|
|
Packit Service |
dfccb1 |
conf_write(fp, " %s weight %d%s", IF_NAME(tip->ifp), tip->weight, tip->weight_reverse ? " reverse" : "");
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
dump_track_if_list(FILE *fp, const list_head_t *l)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
tracked_if_t *tip;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tip, l, e_list)
|
|
Packit Service |
dfccb1 |
dump_track_if(fp, tip);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
free_track_if(tracked_if_t *tip)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
list_del_init(&tip->e_list);
|
|
Packit |
c22fc9 |
FREE(tip);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
free_track_if_list(list_head_t *l)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
tracked_if_t *tip, *tip_tmp;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry_safe(tip, tip_tmp, l, e_list)
|
|
Packit Service |
dfccb1 |
free_track_if(tip);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
alloc_track_if(const char *name, list_head_t *l, const vector_t *strvec)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
interface_t *ifp;
|
|
Packit |
c22fc9 |
tracked_if_t *tip;
|
|
Packit |
c22fc9 |
int weight = 0;
|
|
Packit Service |
dfccb1 |
const char *tracked = strvec_slot(strvec, 0);
|
|
Packit Service |
dfccb1 |
bool reverse = false;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
ifp = if_get_by_ifname(tracked, IF_CREATE_IF_DYNAMIC);
|
|
Packit |
c22fc9 |
if (!ifp) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) tracked interface %s doesn't exist"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
/* Check this vrrp isn't already tracking the i/f */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tip, l, e_list) {
|
|
Packit |
c22fc9 |
if (tip->ifp == ifp) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) duplicate track_interface %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) >= 2) {
|
|
Packit Service |
dfccb1 |
if (strcmp(strvec_slot(strvec, 1), "weight")) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track_interface %s"
|
|
Packit Service |
dfccb1 |
" option %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked, strvec_slot(strvec, 1));
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) == 2) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight without value specified"
|
|
Packit Service |
dfccb1 |
" for track_interface %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit |
c22fc9 |
if (!read_int_strvec(strvec, 2, &weight, -254, 254, true)) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight %s for %s must be"
|
|
Packit Service |
dfccb1 |
" between [-253..253] inclusive. Ignoring..."
|
|
Packit Service |
dfccb1 |
, name, strvec_slot(strvec, 2), tracked);
|
|
Packit |
c22fc9 |
weight = 0;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if (weight == -254 || weight == 254) {
|
|
Packit |
c22fc9 |
/* This check can be removed once users have migrated away from +/-254 */
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight for %s cannot be +/-254."
|
|
Packit Service |
dfccb1 |
" Setting to +/-253"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
weight = weight == -254 ? -253 : 253;
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) >= 4) {
|
|
Packit Service |
dfccb1 |
if (!strcmp(strvec_slot(strvec, 3), "reverse"))
|
|
Packit Service |
dfccb1 |
reverse = true;
|
|
Packit Service |
dfccb1 |
else
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track_interace %s"
|
|
Packit Service |
dfccb1 |
" weight option %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked, strvec_slot(strvec, 3));
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
tip = (tracked_if_t *) MALLOC(sizeof(tracked_if_t));
|
|
Packit Service |
dfccb1 |
INIT_LIST_HEAD(&tip->e_list);
|
|
Packit |
c22fc9 |
tip->ifp = ifp;
|
|
Packit |
c22fc9 |
tip->weight = weight;
|
|
Packit Service |
dfccb1 |
tip->weight_reverse = reverse;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_add_tail(&tip->e_list, l);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
vrrp_script_t * __attribute__ ((pure))
|
|
Packit Service |
dfccb1 |
find_script_by_name(const char *name)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
vrrp_script_t *scr;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(scr, &vrrp_data->vrrp_script, e_list) {
|
|
Packit |
c22fc9 |
if (!strcmp(scr->sname, name))
|
|
Packit |
c22fc9 |
return scr;
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Track script dump */
|
|
Packit Service |
dfccb1 |
static void
|
|
Packit Service |
dfccb1 |
dump_track_script(FILE *fp, const tracked_sc_t *tsc)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
conf_write(fp, " %s weight %d%s", tsc->scr->sname, tsc->weight, tsc->weight_reverse ? " reverse" : "");
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
void
|
|
Packit Service |
dfccb1 |
dump_track_script_list(FILE *fp, const list_head_t *l)
|
|
Packit Service |
dfccb1 |
{
|
|
Packit Service |
dfccb1 |
tracked_sc_t *tsc;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tsc, l, e_list)
|
|
Packit Service |
dfccb1 |
dump_track_script(fp, tsc);
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
free_track_script(tracked_sc_t *tsc)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
list_del_init(&tsc->e_list);
|
|
Packit |
c22fc9 |
FREE(tsc);
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
void
|
|
Packit Service |
dfccb1 |
free_track_script_list(list_head_t *l)
|
|
Packit Service |
dfccb1 |
{
|
|
Packit Service |
dfccb1 |
tracked_sc_t *tsc, *tsc_tmp;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry_safe(tsc, tsc_tmp, l, e_list)
|
|
Packit Service |
dfccb1 |
free_track_script(tsc);
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
alloc_track_script(const char *name, list_head_t *l, const vector_t *strvec)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
vrrp_script_t *vsc;
|
|
Packit |
c22fc9 |
tracked_sc_t *tsc;
|
|
Packit |
c22fc9 |
int weight;
|
|
Packit Service |
dfccb1 |
const char *tracked = strvec_slot(strvec, 0);
|
|
Packit |
c22fc9 |
tracked_sc_t *etsc;
|
|
Packit Service |
dfccb1 |
bool reverse;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
vsc = find_script_by_name(tracked);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Ignoring if no script found */
|
|
Packit |
c22fc9 |
if (!vsc) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) track script %s not found, ignoring..."
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
/* Check this vrrp isn't already tracking the script */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(etsc, l, e_list) {
|
|
Packit Service |
dfccb1 |
if (etsc->scr == vsc) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) duplicate track_script %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* default weight */
|
|
Packit |
c22fc9 |
weight = vsc->weight;
|
|
Packit Service |
dfccb1 |
reverse = vsc->weight_reverse;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) >= 2) {
|
|
Packit Service |
dfccb1 |
if (strcmp(strvec_slot(strvec, 1), "weight")) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track script option %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, strvec_slot(strvec, 1));
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) == 2) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight without value specified for"
|
|
Packit Service |
dfccb1 |
" track script %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (!read_int_strvec(strvec, 2, &weight, -254, 254, true)) {
|
|
Packit |
c22fc9 |
weight = vsc->weight;
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) track script %s: weight must be"
|
|
Packit Service |
dfccb1 |
" between [-253..253] inclusive, ignoring..."
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else if (weight == -254 || weight == 254) {
|
|
Packit |
c22fc9 |
/* This check can be removed once users have migrated away from +/-254 */
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight for %s cannot be +/-254."
|
|
Packit Service |
dfccb1 |
" Setting to +/-253"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
weight = weight == -254 ? -253 : 253;
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) >= 4) {
|
|
Packit Service |
dfccb1 |
if (!strcmp(strvec_slot(strvec, 3), "reverse"))
|
|
Packit Service |
dfccb1 |
reverse = true;
|
|
Packit Service |
dfccb1 |
else if (!strcmp(strvec_slot(strvec, 3), "noreverse"))
|
|
Packit Service |
dfccb1 |
reverse = false;
|
|
Packit Service |
dfccb1 |
else
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track_script %s"
|
|
Packit Service |
dfccb1 |
" weight option %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked, strvec_slot(strvec, 3));
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
tsc = (tracked_sc_t *) MALLOC(sizeof(tracked_sc_t));
|
|
Packit Service |
dfccb1 |
INIT_LIST_HEAD(&tsc->e_list);
|
|
Packit |
c22fc9 |
tsc->scr = vsc;
|
|
Packit |
c22fc9 |
tsc->weight = weight;
|
|
Packit Service |
dfccb1 |
tsc->weight_reverse = reverse;
|
|
Packit |
c22fc9 |
vsc->init_state = SCRIPT_INIT_STATE_INIT;
|
|
Packit Service |
dfccb1 |
list_add_tail(&tsc->e_list, l);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
#ifdef _WITH_CN_PROC_
|
|
Packit Service |
dfccb1 |
static vrrp_tracked_process_t * __attribute__ ((pure))
|
|
Packit Service |
dfccb1 |
find_tracked_process_by_name(const char *name)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
vrrp_tracked_process_t *process;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(process, &vrrp_data->vrrp_track_processes, e_list) {
|
|
Packit Service |
dfccb1 |
if (!strcmp(process->pname, name))
|
|
Packit Service |
dfccb1 |
return process;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
/* Track process dump */
|
|
Packit Service |
dfccb1 |
static void
|
|
Packit Service |
dfccb1 |
dump_track_process(FILE *fp, const tracked_process_t *tprocess)
|
|
Packit Service |
dfccb1 |
{
|
|
Packit Service |
dfccb1 |
conf_write(fp, " %s, weight %d%s", tprocess->process->pname
|
|
Packit Service |
dfccb1 |
, tprocess->weight, tprocess->weight_reverse ? " reverse" : "");
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
dump_track_process_list(FILE *fp, const list_head_t *l)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
tracked_process_t *tprocess;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tprocess, l, e_list)
|
|
Packit Service |
dfccb1 |
dump_track_process(fp, tprocess);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
free_track_process_list(list_head_t *l)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
tracked_process_t *tprocess, *tprocess_tmp;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry_safe(tprocess, tprocess_tmp, l, e_list)
|
|
Packit Service |
dfccb1 |
FREE(tprocess);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
alloc_track_process(const char *name, list_head_t *l, const vector_t *strvec)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
vrrp_tracked_process_t *vsp;
|
|
Packit Service |
dfccb1 |
const char *tracked = strvec_slot(strvec, 0);
|
|
Packit Service |
dfccb1 |
tracked_process_t *tprocess;
|
|
Packit |
c22fc9 |
int weight;
|
|
Packit Service |
dfccb1 |
bool reverse;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
vsp = find_tracked_process_by_name(tracked);
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
/* Ignoring if no process found */
|
|
Packit Service |
dfccb1 |
if (!vsp) {
|
|
Packit Service |
dfccb1 |
if (proc_events_not_supported)
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) track process not supported by kernel"
|
|
Packit Service |
dfccb1 |
, name);
|
|
Packit Service |
dfccb1 |
else
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) track process %s not found, ignoring..."
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
/* Check this vrrp isn't already tracking the process */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tprocess, l, e_list) {
|
|
Packit Service |
dfccb1 |
if (tprocess->process == vsp) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) duplicate track_process %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
weight = vsp->weight;
|
|
Packit Service |
dfccb1 |
reverse = vsp->weight_reverse;
|
|
Packit |
c22fc9 |
if (vector_size(strvec) >= 2) {
|
|
Packit |
c22fc9 |
if (strcmp(strvec_slot(strvec, 1), "weight")) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track process option %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, strvec_slot(strvec, 1));
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) == 2) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight without value specified for"
|
|
Packit Service |
dfccb1 |
" track process %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (!read_int_strvec(strvec, 2, &weight, -254, 254, true)) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight for track process %s must be in "
|
|
Packit Service |
dfccb1 |
"[-254..254] inclusive. Ignoring..."
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit Service |
dfccb1 |
weight = vsp->weight;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) >= 4) {
|
|
Packit Service |
dfccb1 |
if (!strcmp(strvec_slot(strvec, 3), "reverse"))
|
|
Packit Service |
dfccb1 |
reverse = true;
|
|
Packit Service |
dfccb1 |
else if (!strcmp(strvec_slot(strvec, 3), "noreverse"))
|
|
Packit Service |
dfccb1 |
reverse = false;
|
|
Packit Service |
dfccb1 |
else
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track_process %s weight"
|
|
Packit Service |
dfccb1 |
" option %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked, strvec_slot(strvec, 3));
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
PMALLOC(tprocess);
|
|
Packit Service |
dfccb1 |
INIT_LIST_HEAD(&tprocess->e_list);
|
|
Packit Service |
dfccb1 |
tprocess->process = vsp;
|
|
Packit Service |
dfccb1 |
tprocess->weight = weight;
|
|
Packit Service |
dfccb1 |
tprocess->weight_reverse = reverse;
|
|
Packit Service |
dfccb1 |
list_add_tail(&tprocess->e_list, l);
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _WITH_BFD_
|
|
Packit Service |
dfccb1 |
/* VRRP Track bfd related */
|
|
Packit Service |
dfccb1 |
vrrp_tracked_bfd_t * __attribute__ ((pure))
|
|
Packit |
c22fc9 |
find_vrrp_tracked_bfd_by_name(const char *name)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
vrrp_tracked_bfd_t *bfd;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(bfd, &vrrp_data->vrrp_track_bfds, e_list) {
|
|
Packit |
c22fc9 |
if (!strcmp(bfd->bname, name))
|
|
Packit |
c22fc9 |
return bfd;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
return NULL;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
alloc_vrrp_tracked_bfd(const char *name, list_head_t *l)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
vrrp_tracked_bfd_t *tbfd;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (strlen(name) >= BFD_INAME_MAX) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "BFD name %s too long", name);
|
|
Packit Service |
dfccb1 |
skip_block(true);
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tbfd, l, e_list) {
|
|
Packit Service |
dfccb1 |
if (!strcmp(name, tbfd->bname)) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "BFD %s already specified", name);
|
|
Packit Service |
dfccb1 |
skip_block(true);
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
PMALLOC(tbfd);
|
|
Packit Service |
dfccb1 |
INIT_LIST_HEAD(&tbfd->e_list);
|
|
Packit Service |
dfccb1 |
strncpy(tbfd->bname, name, BFD_INAME_MAX-1); /* Not really need, but... */
|
|
Packit Service |
dfccb1 |
tbfd->weight = 0;
|
|
Packit Service |
dfccb1 |
tbfd->weight_reverse = false;
|
|
Packit Service |
dfccb1 |
tbfd->bfd_up = false;
|
|
Packit Service |
dfccb1 |
INIT_LIST_HEAD(&tbfd->tracking_vrrp);
|
|
Packit Service |
dfccb1 |
list_add_tail(&tbfd->e_list, l);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
/* Track bfd related */
|
|
Packit Service |
dfccb1 |
static void
|
|
Packit Service |
dfccb1 |
dump_tracked_bfd(FILE *fp, const tracked_bfd_t *tbfd)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
conf_write(fp, " %s: weight %d%s", tbfd->bfd->bname, tbfd->weight, tbfd->weight_reverse ? " reverse" : "");
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
dump_tracked_bfd_list(FILE *fp, const list_head_t *l)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
tracked_bfd_t *tbfd;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tbfd, l, e_list)
|
|
Packit Service |
dfccb1 |
dump_tracked_bfd(fp, tbfd);
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
void
|
|
Packit Service |
dfccb1 |
free_track_bfd(tracked_bfd_t *tbfd)
|
|
Packit Service |
dfccb1 |
{
|
|
Packit Service |
dfccb1 |
list_del_init(&tbfd->e_list);
|
|
Packit Service |
dfccb1 |
FREE(tbfd);
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
void
|
|
Packit Service |
dfccb1 |
free_track_bfd_list(list_head_t *l)
|
|
Packit Service |
dfccb1 |
{
|
|
Packit Service |
dfccb1 |
tracked_bfd_t *tbfd, *tbfd_tmp;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry_safe(tbfd, tbfd_tmp, l, e_list)
|
|
Packit Service |
dfccb1 |
free_track_bfd(tbfd);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
alloc_track_bfd(const char *name, list_head_t *l, const vector_t *strvec)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
vrrp_tracked_bfd_t *vtb;
|
|
Packit |
c22fc9 |
tracked_bfd_t *tbfd;
|
|
Packit Service |
dfccb1 |
const char *tracked = strvec_slot(strvec, 0);
|
|
Packit |
c22fc9 |
tracked_bfd_t *etbfd;
|
|
Packit |
c22fc9 |
int weight;
|
|
Packit Service |
dfccb1 |
bool reverse = false;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
vtb = find_vrrp_tracked_bfd_by_name(tracked);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Ignoring if no bfd found */
|
|
Packit |
c22fc9 |
if (!vtb) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) track bfd %s not found, ignoring..."
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
/* Check this vrrp isn't already tracking the bfd */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(etbfd, l, e_list) {
|
|
Packit |
c22fc9 |
if (etbfd->bfd == vtb) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) duplicate track_bfd %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
weight = vtb->weight;
|
|
Packit Service |
dfccb1 |
reverse = vtb->weight_reverse;
|
|
Packit |
c22fc9 |
if (vector_size(strvec) >= 2) {
|
|
Packit |
c22fc9 |
if (strcmp(strvec_slot(strvec, 1), "weight")) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track bfd %s option %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked, strvec_slot(strvec, 1));
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) == 2) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight without value specified"
|
|
Packit Service |
dfccb1 |
" for track bfd %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (!read_int_strvec(strvec, 2, &weight, -253, 253, true)) {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) weight for track bfd %s must be in "
|
|
Packit Service |
dfccb1 |
"[-253..253] inclusive. Ignoring..."
|
|
Packit Service |
dfccb1 |
, name, tracked);
|
|
Packit Service |
dfccb1 |
weight = vtb->weight;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (vector_size(strvec) >= 4) {
|
|
Packit Service |
dfccb1 |
if (!strcmp(strvec_slot(strvec, 3), "reverse"))
|
|
Packit Service |
dfccb1 |
reverse = true;
|
|
Packit Service |
dfccb1 |
else if (!strcmp(strvec_slot(strvec, 3), "noreverse"))
|
|
Packit Service |
dfccb1 |
reverse = false;
|
|
Packit Service |
dfccb1 |
else {
|
|
Packit Service |
dfccb1 |
report_config_error(CONFIG_GENERAL_ERROR, "(%s) unknown track bfd %s weight"
|
|
Packit Service |
dfccb1 |
" option %s - ignoring"
|
|
Packit Service |
dfccb1 |
, name, tracked, strvec_slot(strvec, 3));
|
|
Packit Service |
dfccb1 |
return;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
PMALLOC(tbfd);
|
|
Packit Service |
dfccb1 |
INIT_LIST_HEAD(&tbfd->e_list);
|
|
Packit |
c22fc9 |
tbfd->bfd = vtb;
|
|
Packit |
c22fc9 |
tbfd->weight = weight;
|
|
Packit Service |
dfccb1 |
tbfd->weight_reverse = reverse;
|
|
Packit Service |
dfccb1 |
list_add_tail(&tbfd->e_list, l);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
down_instance(vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (vrrp->num_script_if_fault++ == 0 || vrrp->state == VRRP_STATE_INIT) {
|
|
Packit |
c22fc9 |
vrrp->wantstate = VRRP_STATE_FAULT;
|
|
Packit |
c22fc9 |
if (vrrp->state == VRRP_STATE_MAST)
|
|
Packit |
c22fc9 |
vrrp_state_leave_master(vrrp, true);
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
vrrp_state_leave_fault(vrrp);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (vrrp->sync && vrrp->sync->num_member_fault++ == 0)
|
|
Packit |
c22fc9 |
vrrp_sync_fault(vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Set effective priorty, issue message on changes */
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
vrrp_set_effective_priority(vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
uint8_t new_prio;
|
|
Packit |
c22fc9 |
uint32_t old_down_timer;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Don't change priority if address owner */
|
|
Packit |
c22fc9 |
if (vrrp->base_priority == VRRP_PRIO_OWNER)
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (vrrp->total_priority < 1)
|
|
Packit |
c22fc9 |
new_prio = 1;
|
|
Packit |
c22fc9 |
else if (vrrp->total_priority >= VRRP_PRIO_OWNER)
|
|
Packit |
c22fc9 |
new_prio = VRRP_PRIO_OWNER - 1;
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
new_prio = (uint8_t)vrrp->total_priority;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (vrrp->effective_priority == new_prio)
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
log_message(LOG_INFO, "(%s) Changing effective priority from %d to %d",
|
|
Packit |
c22fc9 |
vrrp->iname, vrrp->effective_priority, new_prio);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
vrrp->effective_priority = new_prio;
|
|
Packit |
c22fc9 |
old_down_timer = vrrp->ms_down_timer;
|
|
Packit |
c22fc9 |
vrrp->ms_down_timer = 3 * vrrp->master_adver_int + VRRP_TIMER_SKEW(vrrp);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (vrrp->state == VRRP_STATE_BACK) {
|
|
Packit |
c22fc9 |
if (old_down_timer < vrrp->ms_down_timer)
|
|
Packit |
c22fc9 |
vrrp->sands = timer_add_long(vrrp->sands, vrrp->ms_down_timer - old_down_timer);
|
|
Packit |
c22fc9 |
else
|
|
Packit |
c22fc9 |
vrrp->sands = timer_sub_long(vrrp->sands, old_down_timer - vrrp->ms_down_timer);
|
|
Packit |
c22fc9 |
vrrp_thread_requeue_read(vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (vrrp->notify_priority_changes)
|
|
Packit Service |
dfccb1 |
send_instance_priority_notifies(vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static void
|
|
Packit Service |
dfccb1 |
process_script_update_priority(int weight, int multiplier, vrrp_script_t *vscript, bool script_ok, vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
bool instance_left_init = false;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (!weight) {
|
|
Packit |
c22fc9 |
if (vscript->init_state == SCRIPT_INIT_STATE_INIT) {
|
|
Packit |
c22fc9 |
/* We need to adjust the number of scripts in init state */
|
|
Packit |
c22fc9 |
if (!--vrrp->num_script_init) {
|
|
Packit |
c22fc9 |
instance_left_init = true;
|
|
Packit |
c22fc9 |
if (vrrp->sync)
|
|
Packit |
c22fc9 |
vrrp->sync->num_member_init--;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (script_ok != (multiplier == 1)) {
|
|
Packit |
c22fc9 |
/* The instance needs to go down */
|
|
Packit |
c22fc9 |
down_instance(vrrp);
|
|
Packit |
c22fc9 |
} else if (!vrrp->num_script_init &&
|
|
Packit |
c22fc9 |
(!vrrp->sync || !vrrp->sync->num_member_init)) {
|
|
Packit |
c22fc9 |
/* The instance can come up */
|
|
Packit |
c22fc9 |
try_up_instance(vrrp, instance_left_init); // Set want_state = BACKUP/MASTER, and check i/fs and sync groups
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (vscript->init_state == SCRIPT_INIT_STATE_INIT) {
|
|
Packit |
c22fc9 |
/* If the script hasn't previously exited, we need
|
|
Packit |
c22fc9 |
to only adjust the priority if the state the script
|
|
Packit |
c22fc9 |
is now in causes an adjustment to the priority */
|
|
Packit |
c22fc9 |
if (script_ok) {
|
|
Packit |
c22fc9 |
if (weight > 0)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += weight * multiplier;
|
|
Packit |
c22fc9 |
} else {
|
|
Packit |
c22fc9 |
if (weight < 0)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += weight * multiplier;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
} else {
|
|
Packit |
c22fc9 |
if (script_ok)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += abs(weight) * multiplier;
|
|
Packit |
c22fc9 |
else
|
|
Packit Service |
dfccb1 |
vrrp->total_priority -= abs(weight) * multiplier;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
vrrp_set_effective_priority(vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
update_script_priorities(vrrp_script_t *vscript, bool script_ok)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
tracking_obj_t* top;
|
|
Packit |
c22fc9 |
vrrp_t *vrrp;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* First process the vrrp instances tracking the script */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(top, &vscript->tracking_vrrp, e_list) {
|
|
Packit Service |
dfccb1 |
vrrp = top->obj.vrrp;
|
|
Packit Service |
dfccb1 |
process_script_update_priority(top->weight, top->weight_multiplier, vscript, script_ok, vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
initialise_track_script_state(tracked_sc_t *tsc, vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (!tsc->weight) {
|
|
Packit |
c22fc9 |
if (tsc->scr->init_state == SCRIPT_INIT_STATE_INIT)
|
|
Packit |
c22fc9 |
vrrp->num_script_init++;
|
|
Packit |
c22fc9 |
else if (tsc->scr->init_state == SCRIPT_INIT_STATE_FAILED ||
|
|
Packit |
c22fc9 |
(tsc->scr->result >= 0 && tsc->scr->result < tsc->scr->rise)) {
|
|
Packit |
c22fc9 |
/* The script is in fault state */
|
|
Packit |
c22fc9 |
vrrp->num_script_if_fault++;
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "(%s): entering FAULT state due to script %s", vrrp->iname, tsc->scr->sname);
|
|
Packit |
c22fc9 |
vrrp->state = VRRP_STATE_FAULT;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Don't change effective priority if address owner */
|
|
Packit |
c22fc9 |
if (vrrp->base_priority == VRRP_PRIO_OWNER)
|
|
Packit |
c22fc9 |
return;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (tsc->scr->init_state != SCRIPT_INIT_STATE_INIT)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
if (tsc->scr->result >= tsc->scr->rise) {
|
|
Packit |
c22fc9 |
if (tsc->weight > 0)
|
|
Packit |
c22fc9 |
vrrp->total_priority += tsc->weight;
|
|
Packit |
c22fc9 |
} else {
|
|
Packit |
c22fc9 |
if (tsc->weight < 0)
|
|
Packit |
c22fc9 |
vrrp->total_priority += tsc->weight;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _WITH_BFD_
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
initialise_track_bfd_state(tracked_bfd_t *tbfd, vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
int multiplier = tbfd->weight_reverse ? -1 : 1;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
if (tbfd->weight) {
|
|
Packit Service |
dfccb1 |
if (tbfd->bfd->bfd_up) {
|
|
Packit Service |
dfccb1 |
if (tbfd->weight > 0)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += tbfd->weight * multiplier;
|
|
Packit Service |
dfccb1 |
} else {
|
|
Packit Service |
dfccb1 |
if (tbfd->weight < 0)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += tbfd->weight * multiplier;
|
|
Packit Service |
dfccb1 |
else if (!tbfd->weight) {
|
|
Packit Service |
dfccb1 |
vrrp->num_script_if_fault++;
|
|
Packit Service |
dfccb1 |
vrrp->state = VRRP_STATE_FAULT;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
} else if (tbfd->bfd->bfd_up == tbfd->weight_reverse) {
|
|
Packit Service |
dfccb1 |
vrrp->num_script_if_fault++;
|
|
Packit Service |
dfccb1 |
vrrp->state = VRRP_STATE_FAULT;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
initialise_interface_tracking_priorities(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
tracking_obj_t *top;
|
|
Packit Service |
dfccb1 |
vrrp_t *vrrp;
|
|
Packit |
c22fc9 |
interface_t *ifp;
|
|
Packit Service |
dfccb1 |
list_head_t *ifq;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
ifq = get_interface_queue();
|
|
Packit Service |
dfccb1 |
list_for_each_entry(ifp, ifq, e_list) {
|
|
Packit Service |
dfccb1 |
list_for_each_entry(top, &ifp->tracking_vrrp, e_list) {
|
|
Packit Service |
dfccb1 |
vrrp = top->obj.vrrp;
|
|
Packit Service |
dfccb1 |
if (top->weight == VRRP_NOT_TRACK_IF)
|
|
Packit |
c22fc9 |
continue;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
if (!top->weight) {
|
|
Packit Service |
dfccb1 |
if (IF_FLAGS_UP(ifp) != (top->weight_multiplier == 1)) {
|
|
Packit |
c22fc9 |
/* The instance is down */
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "(%s): entering FAULT state (interface %s down)", vrrp->iname, ifp->ifname);
|
|
Packit Service |
dfccb1 |
vrrp->state = VRRP_STATE_FAULT;
|
|
Packit Service |
dfccb1 |
vrrp->num_script_if_fault++;
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
} else if (IF_FLAGS_UP(ifp)) {
|
|
Packit Service |
dfccb1 |
if (top->weight > 0)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += top->weight * top->weight_multiplier;
|
|
Packit Service |
dfccb1 |
} else {
|
|
Packit Service |
dfccb1 |
if (top->weight < 0)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += top->weight * top->weight_multiplier;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
static void
|
|
Packit Service |
dfccb1 |
initialise_vrrp_file_tracking_priorities(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
tracked_file_t *tfile;
|
|
Packit Service |
dfccb1 |
tracking_obj_t *top;
|
|
Packit Service |
dfccb1 |
vrrp_t *vrrp;
|
|
Packit |
c22fc9 |
int status;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tfile, &vrrp_data->vrrp_track_files, e_list) {
|
|
Packit Service |
dfccb1 |
list_for_each_entry(top, &tfile->tracking_obj, e_list) {
|
|
Packit Service |
dfccb1 |
vrrp = top->obj.vrrp;
|
|
Packit Service |
dfccb1 |
status = !top->weight ? (!!tfile->last_status == (top->weight_multiplier == 1) ? -254 : 0 ) : tfile->last_status * top->weight * top->weight_multiplier;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (status <= -254) {
|
|
Packit |
c22fc9 |
/* The instance is down */
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "(%s): entering FAULT state (tracked file %s has status %i)", vrrp->iname, tfile->fname, status);
|
|
Packit Service |
dfccb1 |
vrrp->state = VRRP_STATE_FAULT;
|
|
Packit Service |
dfccb1 |
vrrp->num_script_if_fault++;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
else
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += (status > 253 ? 253 : status);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
#ifdef _WITH_CN_PROC_
|
|
Packit Service |
dfccb1 |
static void
|
|
Packit Service |
dfccb1 |
initialise_process_tracking_priorities(void)
|
|
Packit Service |
dfccb1 |
{
|
|
Packit Service |
dfccb1 |
vrrp_tracked_process_t *tprocess;
|
|
Packit Service |
dfccb1 |
tracking_obj_t *top;
|
|
Packit Service |
dfccb1 |
vrrp_t *vrrp;
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tprocess, &vrrp_data->vrrp_track_processes, e_list) {
|
|
Packit Service |
dfccb1 |
tprocess->have_quorum =
|
|
Packit Service |
dfccb1 |
(tprocess->num_cur_proc >= tprocess->quorum &&
|
|
Packit Service |
dfccb1 |
tprocess->num_cur_proc <= tprocess->quorum_max);
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(top, &tprocess->tracking_vrrp, e_list) {
|
|
Packit Service |
dfccb1 |
vrrp = top->obj.vrrp;
|
|
Packit Service |
dfccb1 |
if (!top->weight) {
|
|
Packit Service |
dfccb1 |
if (tprocess->have_quorum != (top->weight_multiplier == 1)) {
|
|
Packit Service |
dfccb1 |
/* The instance is down */
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "(%s) entering FAULT state (tracked process %s"
|
|
Packit Service |
dfccb1 |
" quorum not achieved)"
|
|
Packit Service |
dfccb1 |
, vrrp->iname, tprocess->pname);
|
|
Packit Service |
dfccb1 |
vrrp->state = VRRP_STATE_FAULT;
|
|
Packit Service |
dfccb1 |
vrrp->num_script_if_fault++;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
else if (tprocess->have_quorum) {
|
|
Packit Service |
dfccb1 |
if (top->weight > 0)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += top->weight * top->weight_multiplier;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
else {
|
|
Packit Service |
dfccb1 |
if (top->weight < 0)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += top->weight * top->weight_multiplier;
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
}
|
|
Packit Service |
dfccb1 |
#endif
|
|
Packit Service |
dfccb1 |
|
|
Packit |
c22fc9 |
static void
|
|
Packit |
c22fc9 |
initialise_vrrp_tracking_priorities(vrrp_t *vrrp)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
tracked_sc_t *tsc;
|
|
Packit |
c22fc9 |
#ifdef _WITH_BFD_
|
|
Packit |
c22fc9 |
tracked_bfd_t *tbfd;
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* If no src address has been specified, and the interface doesn't have
|
|
Packit |
c22fc9 |
* an appropriate address, put the interface into fault state */
|
|
Packit |
c22fc9 |
if (vrrp->saddr.ss_family == AF_UNSPEC) {
|
|
Packit Service |
dfccb1 |
/* The instance is down */
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "(%s) entering FAULT state (no IPv%d address for interface)"
|
|
Packit Service |
dfccb1 |
, vrrp->iname, vrrp->family == AF_INET ? 4 : 6);
|
|
Packit |
c22fc9 |
vrrp->state = VRRP_STATE_FAULT;
|
|
Packit Service |
dfccb1 |
vrrp->num_script_if_fault++;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Initialise the vrrp instance's tracked scripts */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tsc, &vrrp->track_script, e_list)
|
|
Packit |
c22fc9 |
initialise_track_script_state(tsc, vrrp);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
#ifdef _WITH_BFD_
|
|
Packit |
c22fc9 |
/* Initialise the vrrp instance's tracked scripts */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tbfd, &vrrp->track_bfd, e_list)
|
|
Packit |
c22fc9 |
initialise_track_bfd_state(tbfd, vrrp);
|
|
Packit |
c22fc9 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* If have a sync group, initialise it's tracked scripts and bfds */
|
|
Packit |
c22fc9 |
if (vrrp->sync) {
|
|
Packit Service |
dfccb1 |
list_for_each_entry(tsc, &vrrp->sync->track_script, e_list)
|
|
Packit |
c22fc9 |
initialise_track_script_state(tsc, vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
vrrp_set_effective_priority(vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
void
|
|
Packit |
c22fc9 |
initialise_tracking_priorities(void)
|
|
Packit |
c22fc9 |
{
|
|
Packit |
c22fc9 |
vrrp_t *vrrp;
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Check for instance down due to an interface */
|
|
Packit |
c22fc9 |
initialise_interface_tracking_priorities();
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
initialise_vrrp_file_tracking_priorities();
|
|
Packit Service |
dfccb1 |
|
|
Packit Service |
dfccb1 |
#ifdef _WITH_CN_PROC_
|
|
Packit Service |
dfccb1 |
initialise_process_tracking_priorities();
|
|
Packit Service |
dfccb1 |
#endif
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
/* Now check for tracking scripts, files, bfd etc. */
|
|
Packit Service |
dfccb1 |
list_for_each_entry(vrrp, &vrrp_data->vrrp, e_list) {
|
|
Packit |
c22fc9 |
/* Set effective priority and fault state */
|
|
Packit |
c22fc9 |
initialise_vrrp_tracking_priorities(vrrp);
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
if (vrrp->sync) {
|
|
Packit |
c22fc9 |
if (vrrp->state == VRRP_STATE_FAULT) {
|
|
Packit |
c22fc9 |
if (vrrp->sync->state != VRRP_STATE_FAULT) {
|
|
Packit |
c22fc9 |
vrrp->sync->state = VRRP_STATE_FAULT;
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "VRRP_Group(%s): Syncing %s to FAULT state"
|
|
Packit Service |
dfccb1 |
, vrrp->sync->gname, vrrp->iname);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit |
c22fc9 |
vrrp->sync->num_member_fault++;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
if (vrrp->num_script_init) {
|
|
Packit |
c22fc9 |
/* Update init count on sync group if needed */
|
|
Packit |
c22fc9 |
vrrp->sync->num_member_init++;
|
|
Packit |
c22fc9 |
if (vrrp->sync->state != VRRP_STATE_FAULT)
|
|
Packit |
c22fc9 |
vrrp->sync->state = VRRP_STATE_INIT;
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
#ifdef _WITH_CN_PROC_
|
|
Packit |
c22fc9 |
void
|
|
Packit Service |
dfccb1 |
process_update_track_process_status(vrrp_tracked_process_t *tprocess, bool now_up)
|
|
Packit |
c22fc9 |
{
|
|
Packit Service |
dfccb1 |
tracking_obj_t *top;
|
|
Packit Service |
dfccb1 |
vrrp_t *vrrp;
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
log_message(LOG_INFO, "Quorum %s for tracked process %s", now_up ? "gained" : "lost", tprocess->pname);
|
|
Packit |
c22fc9 |
|
|
Packit Service |
dfccb1 |
list_for_each_entry(top, &tprocess->tracking_vrrp, e_list) {
|
|
Packit Service |
dfccb1 |
vrrp = top->obj.vrrp;
|
|
Packit Service |
dfccb1 |
if (!top->weight) {
|
|
Packit Service |
dfccb1 |
if (now_up == (top->weight_multiplier == 1))
|
|
Packit Service |
dfccb1 |
try_up_instance(vrrp, false);
|
|
Packit Service |
dfccb1 |
else
|
|
Packit Service |
dfccb1 |
down_instance(vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit Service |
dfccb1 |
else if (vrrp->base_priority != VRRP_PRIO_OWNER) {
|
|
Packit Service |
dfccb1 |
if ((top->weight > 0) == now_up)
|
|
Packit Service |
dfccb1 |
vrrp->total_priority += top->weight * top->weight_multiplier;
|
|
Packit Service |
dfccb1 |
else
|
|
Packit Service |
dfccb1 |
vrrp->total_priority -= top->weight * top->weight_multiplier;
|
|
Packit Service |
dfccb1 |
vrrp_set_effective_priority(vrrp);
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
}
|
|
Packit |
c22fc9 |
#endif
|