* keepalived-1.1.13 released.
* VRRP : Added a new notify script to be launch during vrrp
instances shutdown. This new notify hook is configured
using notify_stop keyword inside vrrp_instance block.
* VRRP : Willy Tarreau <w at 1wt.eu> fixed an errno issue in
thread_fetch(), errno is lost during set_time_now(). This
patch saves it across the call to set_time_now() in order
to get the valid error.
* VRRP : Willy Tarreau <w at 1wt.eu> extended timer framework
to save errno in timer_now() and set_time_now() just in
case other functions do not expect these functions to modify
it. This is a safer approach than the initial patch to
thread_fetch(), while still compatible.
* VRRP : Willy Tarreau <w at 1wt.eu> fixed an FSM silent issue.
By default, the VRRP daemon stops sending during new MASTER
elections. This causes 3 to 4 seconds of silence depending on
the local priority, and sometimes causes flapping when the
differences in priorities are very low, due to the kernel timer's
resolution : sometimes, the old master receives a first
advertisement, enters backup, waits 3 seconds, sees nothing and
finally becomes master again, which forces a new reelection on
the other one.
* VRRP : Willy Tarreau <w at 1wt.eu> extended VRRP framework to
support floating priority. Replace the priority in each
vrrp_instance with a base priority and an effective priority,
to prepare the support for floating priorities. The configuration
sets the base_priority, and all comparisons use the new
effective_priority value. This one is computed in the
vrrp_update_priority() thread by adding an offset to base_priority,
based on the result of various checks.
* VRRP : Willy Tarreau <w at 1wt.eu> extended notify script to add
the priority in "$4" when calling a notify script. This is
important in labs and datacenters when systems can display the
priority on a front LCD, because it allows workers to carefully
operate without causing unexpected reelections.
* VRRP : Willy Tarreau <w at 1wt.eu> extended interface tracking
framework to let interface tracking change the priority by adding
a "weight" parameter. If the weight is positive, it will be added
to the priority when the interface is UP. If the weight is negative,
it will be subtracted from the priority when the interface is down.
If the weight is zero (default), a down interface will switch the
instance to the FAULT state.
* VRRP : Willy Tarreau <w at 1wt.eu> added a new "vrrp_script" section
to monitor local processes or do any type of local processing to
decide whether the machine is in good enough health to be elected
as master. A same script will be run once for all instances which
monitor it. If no instance use it, it will not be run, so that it's
safe to declare a lot of useful scripts. A weight is associated to
the script result. If the weight is positive, it will be added to
the priority when the result is OK (exit 0). If the weight is
negative, it will be subtracted from the priority when the result
is KO (exit != 0). If the weight is zero, the script will not be
monitored. The default value is 2.
* VRRP : Willy Tarreau <w at 1wt.eu> extended vrrp scheduler so that
when a VRRP is part of a SYNC group, it must not use floating
priorities, otherwise this may lead to infinite re-election after
every advertisement because some VRRPs will announce higher prios
than the peer, while others will announce lower prios. The solution
is to set all weights to 0 to enable standard interface tracking,
and to disable the update prio thread if VRRP SYNC is enabled on a
VRRP.
* VRRP : Willy Tarreau <w at 1wt.eu> added some documentation and
examples for the brand new VRRP tracking mechanisms.
* VRRP : Ranko Zivojnovic, <ranko at spidernet.net> fixed vrrp
scheduler to execute notify* scripts in transition from the
failed state to the backup state.
* Nick Couchman, <nick.couchman at seakr.com>, added support for
real server upper and lower thresholds. This allows you to set
a minimum and maximum number of connections to each real server
using the "uthreshold" (maximum) and "lthreshold" (minimum)
options in the real_server section of the configuration file.
* Chris Caputo, <ccaputo at alt.net> extended autoconf script
to support recent move of UTS_RELEASE from linux/version.h to
linux/utsrelease.h.
* Chris Caputo, <ccaputo at alt.net> extended ipvswrapper 2.4
code to support misc_dynamic weight.
Kevin Lindsay, <kevinl@netnation.com> :
o Fixed shadowed declaration reported by -Wshadow.
o Redesigned signal handling.
+
+Nick Couchman, <nick.couchman at seakr.com> :
+ o Patch for u_threshold and l_threshold support.
+
+Willy Tarreau, <w at 1wt.eu> :
+ o Extended VRRP framework to support floating
+ priority.
+2006-10-11 Alexandre Cassen <acassen@linux-vs.org>
+ * keepalived-1.1.13 released.
+ * VRRP : Added a new notify script to be launch during vrrp
+ instances shutdown. This new notify hook is configured
+ using notify_stop keyword inside vrrp_instance block.
+ * VRRP : Willy Tarreau <w at 1wt.eu> fixed an errno issue in
+ thread_fetch(), errno is lost during set_time_now(). This
+ patch saves it across the call to set_time_now() in order
+ to get the valid error.
+ * VRRP : Willy Tarreau <w at 1wt.eu> extended timer framework
+ to save errno in timer_now() and set_time_now() just in
+ case other functions do not expect these functions to modify
+ it. This is a safer approach than the initial patch to
+ thread_fetch(), while still compatible.
+ * VRRP : Willy Tarreau <w at 1wt.eu> fixed an FSM silent issue.
+ By default, the VRRP daemon stops sending during new MASTER
+ elections. This causes 3 to 4 seconds of silence depending on
+ the local priority, and sometimes causes flapping when the
+ differences in priorities are very low, due to the kernel timer's
+ resolution : sometimes, the old master receives a first
+ advertisement, enters backup, waits 3 seconds, sees nothing and
+ finally becomes master again, which forces a new reelection on
+ the other one.
+ * VRRP : Willy Tarreau <w at 1wt.eu> extended VRRP framework to
+ support floating priority. Replace the priority in each
+ vrrp_instance with a base priority and an effective priority,
+ to prepare the support for floating priorities. The configuration
+ sets the base_priority, and all comparisons use the new
+ effective_priority value. This one is computed in the
+ vrrp_update_priority() thread by adding an offset to base_priority,
+ based on the result of various checks.
+ * VRRP : Willy Tarreau <w at 1wt.eu> extended notify script to add
+ the priority in "$4" when calling a notify script. This is
+ important in labs and datacenters when systems can display the
+ priority on a front LCD, because it allows workers to carefully
+ operate without causing unexpected reelections.
+ * VRRP : Willy Tarreau <w at 1wt.eu> extended interface tracking
+ framework to let interface tracking change the priority by adding
+ a "weight" parameter. If the weight is positive, it will be added
+ to the priority when the interface is UP. If the weight is negative,
+ it will be subtracted from the priority when the interface is down.
+ If the weight is zero (default), a down interface will switch the
+ instance to the FAULT state.
+ * VRRP : Willy Tarreau <w at 1wt.eu> added a new "vrrp_script" section
+ to monitor local processes or do any type of local processing to
+ decide whether the machine is in good enough health to be elected
+ as master. A same script will be run once for all instances which
+ monitor it. If no instance use it, it will not be run, so that it's
+ safe to declare a lot of useful scripts. A weight is associated to
+ the script result. If the weight is positive, it will be added to
+ the priority when the result is OK (exit 0). If the weight is
+ negative, it will be subtracted from the priority when the result
+ is KO (exit != 0). If the weight is zero, the script will not be
+ monitored. The default value is 2.
+ * VRRP : Willy Tarreau <w at 1wt.eu> extended vrrp scheduler so that
+ when a VRRP is part of a SYNC group, it must not use floating
+ priorities, otherwise this may lead to infinite re-election after
+ every advertisement because some VRRPs will announce higher prios
+ than the peer, while others will announce lower prios. The solution
+ is to set all weights to 0 to enable standard interface tracking,
+ and to disable the update prio thread if VRRP SYNC is enabled on a
+ VRRP.
+ * VRRP : Willy Tarreau <w at 1wt.eu> added some documentation and
+ examples for the brand new VRRP tracking mechanisms.
+ * VRRP : Ranko Zivojnovic, <ranko at spidernet.net> fixed vrrp
+ scheduler to execute notify* scripts in transition from the
+ failed state to the backup state.
+ * Nick Couchman, <nick.couchman at seakr.com>, added support for
+ real server upper and lower thresholds. This allows you to set
+ a minimum and maximum number of connections to each real server
+ using the "uthreshold" (maximum) and "lthreshold" (minimum)
+ options in the real_server section of the configuration file.
+ * Chris Caputo, <ccaputo at alt.net> extended autoconf script
+ to support recent move of UTS_RELEASE from linux/version.h to
+ linux/utsrelease.h.
+ * Chris Caputo, <ccaputo at alt.net> extended ipvswrapper 2.4
+ code to support misc_dynamic weight.
+
2006-03-09 Alexandre Cassen <acassen@linux-vs.org>
* keepalived-1.1.12 released.
* VRRP : Christophe Varoqui, <Christophe.Varoqui@free.fr> extended
#include <stdlib.h>
#include <stdio.h>
#include <linux/version.h>
+ #if !defined(UTS_RELEASE)
+ #include <linux/utsrelease.h>
+ #endif
int main (void) {
FILE *fp = fopen ("linuxinfo", "w");
if (!fp) return 1;
#include <stdlib.h>
#include <stdio.h>
#include <linux/version.h>
+ #if !defined(UTS_RELEASE)
+ #include <linux/utsrelease.h>
+ #endif
int main (void) {
FILE *fp = fopen ("linuxinfo", "w");
if (!fp) return 1;
2. VRRP configuration
-This block is divided in 2 sub-block :
+This block is divided in 3 sub-block :
+ * VRRP scripts
* VRRP synchronization group
* VRRP instance
- 2.1. VRRP synchronization group
+ 2.1. VRRP scripts
+
+ The configuration block looks like :
+
+vrrp_script <STRING> { # VRRP script declaration
+ script <QUOTED_STRING> # script to run periodically
+ interval <INTEGER> # run the script this every seconds
+ weight <INTEGER:-254..254> # adjust priority by this weight
+}
+
+The script will be executed periodically, every <interval> seconds. Its exit
+code will be recorded for all VRRP instances which will want to monitor it.
+Note that the script will only be executed if at least one VRRP instance
+monitors it with a non-zero weight. Thus, any number of scripts may be
+declared without taking the system down.
+
+If unspecified, the weight equals 2, which means that a success will add +2
+to the priority of all VRRP instances which monitor it. On the opposite, a
+negative weight will be subtracted from the initial priority in case of
+failure.
+
+ 2.2. VRRP synchronization group
The configuration block looks like :
$1 and $3 are ALWAYS sent in uppercase, and the possible strings sent are the
same ones listed above ("GROUP"/"INSTANCE", "MASTER"/"BACKUP"/"FAULT").
- 2.2. VRRP instance
+Important: for a SYNC group to run reliably, it is vital that all instances in
+ the group are MASTER or that they are all either BACKUP or FAULT. A
+ situation with half instances having higher priority on machine A
+ half others with higher priority on machine B will lead to constant
+ re-elections. For this reason, when instances are grouped, their
+ tracking weights are automatically set to zero, in order to avoid
+ inconsistent priorities across instances.
+
+ 2.3. VRRP instance
The configuration block looks like :
track_interface { # Interfaces state we monitor
<STRING>
<STRING>
+ <STRING> weight <INTEGER:-254..254>
+ ...
+ }
+ track_script { # Scripts state we monitor
+ <STRING>
+ <STRING> weight <INTEGER:-254..254>
...
}
dont_track_primary # (default unset) ignore VRRP interface faults.
notify_master <STRING>|<QUOTED-STRING> # Same as vrrp_sync_group
notify_backup <STRING>|<QUOTED-STRING> # Same as vrrp_sync_group
notify_fault <STRING>|<QUOTED-STRING> # Same as vrrp_sync_group
+ notify_stop <STRING>|<QUOTED-STRING> # Script to launch when stopping vrrp
notify <STRING>|<QUOTED-STRING> # Same as vrrp_sync_group
smtp_alert # Same as vrrp_sync_group
}
* nowhere
* global
+When a weight is specified in track_interface, instead of setting the vrrp
+instance to the FAULT state in case of failure, its priority will be
+increased by the weight when the interface is up (for positive weights),
+or decreased by the weight's absolute value when the interface is down
+(for negative weights). The weight must be comprised between -254 and +254
+inclusive. 0 is the default behaviour which means that a failure implies a
+FAULT state. The common practise is to use positive weights to count a
+limited number of good services so that the server with the highest count
+becomes master. Negative weights are better to count unexpected failures
+among a high number of interfaces, as it will not saturate even with high
+number of interfaces.
+
+The same principle can be applied to track_script entries, except that an
+unspecified weight means that the default weight declared in the script
+will be used.
+
+
3. LVS configuration
This block is divided in 2 sub-block :
--- /dev/null
+! Configuration File for keepalived
+
+vrrp_script chk_sshd {
+ script "killall -0 sshd" # cheaper than pidof
+ interval 2 # check every 2 seconds
+ weight -4 # default prio: -4 if KO
+}
+
+vrrp_script chk_haproxy {
+ script "killall -0 haproxy" # cheaper than pidof
+ interval 2 # check every 2 seconds
+}
+
+vrrp_script chk_http_port {
+ script "</dev/tcp/127.0.0.1/80" # connects and exits
+ interval 1 # check every second
+ weight -2 # default prio: -2 if connect fails
+}
+
+vrrp_script chk_https_port {
+ script "</dev/tcp/127.0.0.1/443"
+ interval 1
+ weight -2
+}
+
+vrrp_script chk_smtp_port {
+ script "</dev/tcp/127.0.0.1/25"
+ interval 1
+ weight -2
+}
+
+vrrp_instance VI_1 {
+ interface eth0
+ state MASTER
+ virtual_router_id 51
+ priority 100
+ virtual_ipaddress {
+ 192.168.200.18/25
+ }
+ track_interface {
+ eth1 weight 2 # prio = +2 if UP
+ eth2 weight -2 # prio = -2 if DOWN
+ eth3 # no weight, fault if down
+ }
+ track_script {
+ chk_sshd # use default weight from the script
+ chk_haproxy weight 2 # +2 if process is present
+ chk_http_port
+ chk_https_port
+ chk_smtp_port
+ }
+}
+
+vrrp_instance VI_2 {
+ interface eth1
+ state MASTER
+ virtual_router_id 52
+ priority 100
+ virtual_ipaddress {
+ 192.168.201.18/26
+ }
+ track_interface {
+ eth0 weight 2 # prio = +2 if UP
+ eth2 weight -2 # prio = -2 if DOWN
+ eth3 # no weight, fault if down
+ }
+ track_script {
+ chk_haproxy weight 2
+ chk_http_port
+ chk_https_port
+ chk_smtp_port
+ }
+}
+
+vrrp_instance VI_3 {
+ interface eth0
+ virtual_router_id 53
+ priority 100
+ virtual_ipaddress {
+ 192.168.200.19/27
+ }
+}
+
+vrrp_instance VI_4 {
+ interface eth1
+ virtual_router_id 54
+ priority 100
+ virtual_ipaddress {
+ 192.168.201.19/28
+ }
+}
+
+vrrp_instance VI_5 {
+ state MASTER
+ interface eth0
+ virtual_router_id 55
+ priority 100
+ virtual_ipaddress {
+ 192.168.200.20/27
+ }
+}
+
+
+vrrp_instance VI_6 {
+ state MASTER
+ interface eth0
+ virtual_router_id 56
+ priority 100
+ virtual_ipaddress {
+ 192.168.200.21/27
+ }
+}
+
+vrrp_instance VI_7 {
+ state MASTER
+ interface eth0
+ virtual_router_id 57
+ priority 100
+ virtual_ipaddress {
+ 192.168.200.22/27
+ }
+}
+
+vrrp_instance VI_8 {
+ state MASTER
+ interface eth0
+ virtual_router_id 58
+ priority 100
+ virtual_ipaddress {
+ 192.168.200.23/27
+ }
+}
+
+vrrp_instance VI_9 {
+ state MASTER
+ interface eth0
+ virtual_router_id 59
+ priority 100
+ virtual_ipaddress {
+ 192.168.200.24/27
+ }
+}
# Makefile.in
#
-# Copyright (C) 2001-2005 Alexandre Cassen, <acassen@linux-vs.org>
+# Copyright (C) 2001-2006 Alexandre Cassen, <acassen@linux-vs.org>
EXEC = genhash
BIN = ../bin
#
# Keepalived OpenSource project.
#
-# Copyright (C) 2001, 2002, 2003 Alexandre Cassen, <acassen@linux-vs.org>
+# Copyright (C) 2001-2006 Alexandre Cassen, <acassen@linux-vs.org>
EXEC = keepalived
BIN = ../bin
*
* Part: Checkers registration.
*
- * Version: $Id: check_api.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_api.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Healthcheckrs child process handling.
*
- * Version: $Id: check_daemon.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_daemon.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Healthcheckers dynamic data structure definition.
*
- * Version: $Id: check_data.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_data.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: WEB CHECK. Common HTTP/SSL checker primitives.
*
- * Version: $Id: check_http.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_http.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
* Part: MISC CHECK. Perform a system call to run an extra
* system prog or script.
*
- * Version: $Id: check_misc.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_misc.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
* data structure representation the conf file representing
* the loadbalanced server pool.
*
- * Version: $Id: check_parser.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_parser.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
real_server *rs = LIST_TAIL_DATA(vs->rs);
rs->weight = atoi(VECTOR_SLOT(strvec, 1));
}
+#ifdef _KRNL_2_6_
+static void
+uthreshold_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(check_data->vs);
+ real_server *rs = LIST_TAIL_DATA(vs->rs);
+ rs->u_threshold = atoi(VECTOR_SLOT(strvec, 1));
+}
+static void
+lthreshold_handler(vector strvec)
+{
+ virtual_server *vs = LIST_TAIL_DATA(check_data->vs);
+ real_server *rs = LIST_TAIL_DATA(vs->rs);
+ rs->l_threshold = atoi(VECTOR_SLOT(strvec, 1));
+}
+#endif
static void
inhibit_handler(vector strvec)
{
install_keyword("real_server", &rs_handler);
install_sublevel();
install_keyword("weight", &weight_handler);
+#ifdef _KRNL_2_6_
+ install_keyword("uthreshold", &uthreshold_handler);
+ install_keyword("lthreshold", <hreshold_handler);
+#endif
install_keyword("inhibit_on_failure", &inhibit_handler);
install_keyword("notify_up", ¬ify_up_handler);
install_keyword("notify_down", ¬ify_down_handler);
*
* Part: SMTP CHECK. Check an SMTP-server.
*
- * Version: $Id: check_smtp.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_smtp.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Jeremy Rumpf, <jrumpf@heavyload.net>
* Alexandre Cassen, <acassen@linux-vs.org>
* url, compute a MD5 over this result and match it to the
* expected value.
*
- * Version: $Id: check_ssl.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_ssl.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: TCP checker.
*
- * Version: $Id: check_tcp.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_tcp.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* library to add/remove server MASQ rules to the kernel
* firewall framework.
*
- * Version: $Id: ipfwwrapper.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: ipfwwrapper.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: IPVS Kernel wrapper. Use setsockopt call to add/remove
* server to/from the loadbalanced server pool.
*
- * Version: $Id: ipvswrapper.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: ipvswrapper.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
memset(drule, 0, sizeof (struct ip_vs_dest_user));
drule->weight = 1;
+ drule->u_threshold = 0;
+ drule->l_threshold = 0;
drule->conn_flags = vs->loadbalancing_kind;
strncpy(srule->sched_name, vs->sched, IP_VS_SCHEDNAME_MAXLEN);
srule->netmask = ((u_int32_t) 0xffffffff);
/* SVR specific */
if (rs) {
- if (cmd == IP_VS_SO_SET_ADDDEST || cmd == IP_VS_SO_SET_DELDEST) {
+ if (cmd == IP_VS_SO_SET_ADDDEST
+ || cmd == IP_VS_SO_SET_DELDEST
+ || cmd == IP_VS_SO_SET_EDITDEST) {
drule->weight = rs->weight;
drule->addr = SVR_IP(rs);
drule->port = SVR_PORT(rs);
+ drule->u_threshold = rs->u_threshold;
+ drule->l_threshold = rs->l_threshold;
}
}
}
srule->fwmark = vsge->vfwmark;
srule->addr = SVR_IP(vsge);
srule->port = SVR_PORT(vsge);
+ drule->u_threshold = rs->u_threshold;
+ drule->l_threshold = rs->l_threshold;
/* Talk to the IPVS channel */
ipvs_talk(IP_VS_SO_SET_DELDEST);
*
* Part: Manipulation functions for IPVS & IPFW wrappers.
*
- * Version: $Id: ipwrapper.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: ipwrapper.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: main.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: global_data.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: global_data.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* data structure representation the conf file representing
* the loadbalanced server pool.
*
- * Version: $Id: global_parser.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: global_parser.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: Layer4 checkers handling. Register worker threads &
* upper layer checkers.
*
- * Version: $Id: layer4.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: layer4.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: main.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: pidfile utility.
*
- * Version: $Id: pidfile.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: pidfile.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* using the smtp protocol according to the RFC 821. A non blocking
* timeouted connection is used to handle smtp protocol.
*
- * Version: $Id: smtp.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: smtp.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Checkers arguments structures definitions.
*
- * Version: $Id: check_api.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_api.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: check_daemon.c include file.
*
- * Version: $Id: check_daemon.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_daemon.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Healthcheckers dynamic data structure definition.
*
- * Version: $Id: check_data.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_data.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
uint32_t addr_ip;
uint16_t addr_port;
int weight;
+#ifdef _KRNL_2_6_
+ uint32_t u_threshold; /* Upper connection limit. */
+ uint32_t l_threshold; /* Lower connection limit. */
+#endif
int inhibit; /* Set weight to 0 instead of removing
* the service from IPVS topology.
*/
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_http.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: check_misc.c include file.
*
- * Version: $Id: check_misc.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_misc.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
*
* Part: check_parser.c include file.
*
- * Version: $Id: check_parser.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_parser.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: check_smtp.c include file.
*
- * Version: $Id: check_smtp.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_smtp.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
* Jeremy Rumpf, <jrumpf@heavyload.net>
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_http.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: check_tcp.c include file.
*
- * Version: $Id: check_tcp.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: check_tcp.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Configuration include file.
*
- * Version: $Id: config.h.in,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: config.h.in,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Jacob Rief, <jacob.rief@tiscover.com>
*
*
* Part: Daemon process handling.
*
- * Version: $Id: daemon.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: daemon.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: global_data.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: global_data.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_parser.c include file.
*
- * Version: $Id: global_parser.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: global_parser.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipfwwrapper.c include file.
*
- * Version: $Id: ipfwwrapper.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: ipfwwrapper.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipvswrapper.c include file.
*
- * Version: $Id: ipvswrapper.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: ipvswrapper.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipwrapper.c include file.
*
- * Version: $Id: ipwrapper.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: ipwrapper.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: layer4.c include file.
*
- * Version: $Id: layer4.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: layer4.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Main program include file.
*
- * Version: $Id: main.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: main.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: pidfile.c include file.
*
- * Version: $Id: pidfile.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: pidfile.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: smtp.c include file.
*
- * Version: $Id: smtp.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: smtp.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp.c program include file.
*
- * Version: $Id: vrrp.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
interface *ifp; /* Interface we belong to */
int dont_track_primary; /* If set ignores ifp faults */
list track_ifp; /* Interface state we monitor */
+ list track_script; /* Script state we monitor */
uint32_t mcast_saddr; /* Src IP address to use in VRRP IP header */
char *lvs_syncd_if; /* handle LVS sync daemon state using this
* instance FSM & running on specific interface
*/
int garp_delay; /* Delay to launch gratuitous ARP */
int vrid; /* virtual id. from 1(!) to 255 */
- int priority; /* priority value */
+ int base_priority; /* configured priority value */
+ int effective_priority; /* effective priority value */
int vipset; /* All the vips are set ? */
list vip; /* list of virtual ip addresses */
list evip; /* list of protocol excluded VIPs.
char *script_backup;
char *script_master;
char *script_fault;
+ char *script_stop;
char *script;
/* rfc2336.6.2 */
#define VRRP_SEND_BUFFER(V) ((V)->send_buffer)
#define VRRP_SEND_BUFFER_SIZE(V) ((V)->send_buffer_size)
-#define VRRP_TIMER_SKEW(svr) ((256-(svr)->priority)*TIMER_HZ/256)
+#define VRRP_TIMER_SKEW(svr) ((256-(svr)->base_priority)*TIMER_HZ/256)
#define VRRP_VIP_ISSET(V) ((V)->vipset)
#define VRRP_MIN(a, b) ((a) < (b)?(a):(b))
*
* Part: vrrp_arp.c include file.
*
- * Version: $Id: vrrp_arp.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_arp.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_daemon.c include file.
*
- * Version: $Id: vrrp_daemon.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_daemon.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: vrrp_data.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_data.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
list vrrp_index;
list vrrp_index_fd;
list vrrp_socket_pool;
+ list vrrp_script;
} vrrp_conf_data;
/* Global Vars exported */
extern void alloc_vrrp_sync_group(char *gname);
extern void alloc_vrrp(char *iname);
extern void alloc_vrrp_track(vector strvec);
+extern void alloc_vrrp_script(char *sname);
+extern void alloc_vrrp_track_script(vector strvec);
extern void alloc_vrrp_vip(vector strvec);
extern void alloc_vrrp_evip(vector strvec);
extern void alloc_vrrp_vroute(vector strvec);
*
* Part: vrrp_if.c include file.
*
- * Version: $Id: vrrp_if.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_if.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
int linkbeat; /* LinkBeat from MII BMSR req */
} interface;
+/* Tracked interface structure definition */
+typedef struct _tracked_if {
+ int weight; /* tracking weight when non-zero */
+ interface *ifp; /* interface backpointer, cannot be NULL */
+} tracked_if;
+
/* Macros */
#define IF_NAME(X) ((X)->ifname)
#define IF_INDEX(X) ((X)->ifindex)
*
* Part: vrrp_index.c include file.
*
- * Version: $Id: vrrp_index.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_index.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_ipaddress.c include file.
*
- * Version: $Id: vrrp_ipaddress.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_iproute.c include file.
*
- * Version: $Id: vrrp_iproute.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_iproute.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_ipsecah.c include file.
*
- * Version: $Id: vrrp_ipsecah.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_netlink.c include file.
*
- * Version: $Id: vrrp_netlink.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_netlink.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_notify.c include file.
*
- * Version: $Id: vrrp_notify.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_notify.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_parser.c include file.
*
- * Version: $Id: vrrp_parser.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_parser.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_scheduler.c include file.
*
- * Version: $Id: vrrp_scheduler.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_scheduler.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_sync.c include file.
*
- * Version: $Id: vrrp_sync.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_sync.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_track.c include file.
*
- * Version: $Id: vrrp_track.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_track.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* Macro definition */
#define TRACK_ISUP(L) (vrrp_tracked_up((L)))
+/* VRRP script tracking defaults */
+#define VRRP_SCRIPT_DI 1 /* external script track interval (in sec) */
+#define VRRP_SCRIPT_DW 2 /* external script default weight */
+
+/* VRRP script tracking results */
+#define VRRP_SCRIPT_STATUS_DISABLED 0
+#define VRRP_SCRIPT_STATUS_INIT 1
+#define VRRP_SCRIPT_STATUS_NONE 2
+#define VRRP_SCRIPT_STATUS_GOOD 3
+
+/* external script we call to track local processes */
+typedef struct _vrrp_script {
+ char *sname; /* instance name */
+ char *script; /* the command to be called */
+ int interval; /* interval between script calls */
+ int weight; /* weight associated to this script */
+ int result; /* result of last call to this script */
+ int inuse; /* how many users have weight>0 ? */
+} vrrp_script;
+
+/* Tracked script structure definition */
+typedef struct _tracked_sc {
+ int weight; /* tracking weight when non-zero */
+ vrrp_script *scr; /* script pointer, cannot be NULL */
+} tracked_sc;
+
/* prototypes */
extern void dump_track(void *track_data_obj);
extern void alloc_track(list track_list, vector strvec);
+extern void dump_track_script(void *track_data_obj);
+extern void alloc_track_script(list track_list, vector strvec);
extern int vrrp_tracked_up(list l);
extern void vrrp_log_tracked_down(list l);
+extern int vrrp_tracked_weight(list l);
+extern int vrrp_script_weight(list l);
#endif
../include/ipvswrapper.h ../../lib/list.h ../../lib/memory.h ../../lib/parser.h \
../../lib/signals.h
vrrp_data.o: vrrp_data.c ../include/vrrp_data.h \
- ../include/vrrp_sync.h ../include/vrrp_index.h ../include/vrrp.h ../../lib/memory.h \
- ../../lib/utils.h
+ ../include/vrrp_sync.h ../include/vrrp_if.h ../include/vrrp_index.h \
+ ../include/vrrp.h ../../lib/memory.h ../../lib/utils.h ../../lib/notify.h
vrrp_parser.o: vrrp_parser.c ../include/vrrp_parser.h \
../include/vrrp_data.h ../include/vrrp_sync.h ../include/vrrp_index.h \
../include/vrrp.h ../include/global_data.h ../include/global_parser.h \
../include/vrrp_ipsecah.h ../include/vrrp_if.h ../include/vrrp.h \
../include/vrrp_sync.h ../include/vrrp_notify.h ../include/ipvswrapper.h \
../../lib/memory.h ../../lib/list.h ../include/vrrp_data.h ../include/vrrp_index.h \
- ../include/smtp.h
+ ../include/smtp.h ../../lib/notify.h
vrrp_sync.o: vrrp_sync.c ../include/vrrp_sync.h ../include/vrrp_if.h \
../include/vrrp_notify.h ../include/vrrp_data.h
vrrp_index.o: vrrp_index.c ../include/vrrp_index.h ../include/vrrp.h \
* master fails, a backup server takes over.
* The original implementation has been made by jerome etienne.
*
- * Version: $Id: vrrp.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "list.h"
#include "main.h"
#include "utils.h"
+#include "notify.h"
/* add/remove Virtual IP addresses */
static int
* Send an advertisement. To force a new master
* election.
*/
- vrrp_send_adv(vrrp, vrrp->priority);
+ vrrp_send_adv(vrrp, vrrp->effective_priority);
vrrp->state = VRRP_STATE_MAST;
syslog(LOG_INFO, "VRRP_Instance(%s) Transition to MASTER STATE",
3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
} else if (hd->priority == 0) {
vrrp->ms_down_timer = VRRP_TIMER_SKEW(vrrp);
- } else if (vrrp->nopreempt || hd->priority >= vrrp->priority ||
+ } else if (vrrp->nopreempt || hd->priority >= vrrp->effective_priority ||
timer_cmp(vrrp->preempt_time, timer_now()) > 0) {
vrrp->ms_down_timer =
3 * vrrp->adver_int + VRRP_TIMER_SKEW(vrrp);
- } else if (hd->priority < vrrp->priority) {
+ } else if (hd->priority < vrrp->effective_priority) {
syslog(LOG_INFO,
"VRRP_Instance(%s) forcing a new MASTER election",
vrrp->iname);
vrrp->wantstate = VRRP_STATE_GOTO_MASTER;
- vrrp_send_adv(vrrp, vrrp->priority);
+ vrrp_send_adv(vrrp, vrrp->effective_priority);
}
}
}
vrrp_send_adv(vrrp,
- (prio ==
- VRRP_PRIO_OWNER) ? VRRP_PRIO_OWNER : vrrp->priority);
+ (prio == VRRP_PRIO_OWNER) ? VRRP_PRIO_OWNER :
+ vrrp->effective_priority);
return ret;
}
"VRRP_Instance(%s) Dropping received VRRP packet...",
vrrp->iname);
return 0;
- } else if (hd->priority < vrrp->priority) {
+ } else if (hd->priority < vrrp->effective_priority) {
/* We receive a lower prio adv we just refresh remote ARP cache */
syslog(LOG_INFO, "VRRP_Instance(%s) Received lower prio advert"
", forcing new election", vrrp->iname);
vrrp->ipsecah_counter->seq_number = ntohl(ah->seq_number) + 1;
vrrp->ipsecah_counter->cycle = 0;
}
- vrrp_send_adv(vrrp, vrrp->priority);
+ vrrp_send_adv(vrrp, vrrp->effective_priority);
vrrp_send_gratuitous_arp(vrrp);
return 0;
} else if (hd->priority == 0) {
- vrrp_send_adv(vrrp, vrrp->priority);
+ vrrp_send_adv(vrrp, vrrp->effective_priority);
return 0;
- } else if (hd->priority > vrrp->priority ||
- (hd->priority == vrrp->priority &&
+ } else if (hd->priority > vrrp->effective_priority ||
+ (hd->priority == vrrp->effective_priority &&
ntohl(iph->saddr) > VRRP_PKT_SADDR(vrrp))) {
syslog(LOG_INFO,
"VRRP_Instance(%s) Received higher prio advert",
"VRRP_Instance(%s) Dropping received VRRP packet...",
vrrp->iname);
return 0;
- } else if (vrrp->priority > hd->priority ||
+ } else if (vrrp->effective_priority > hd->priority ||
hd->priority == VRRP_PRIO_OWNER)
return 1;
if (vrrp->state == VRRP_STATE_MAST)
vrrp_restore_interface(vrrp, 1);
+ /* Run stop script */
+ if (vrrp->script_stop)
+ notify_exec(vrrp->script_stop);
+
#ifdef _HAVE_IPVS_SYNCD_
/*
* Stop stalled syncd. IPVS syncd state is the
vrrp->state = VRRP_STATE_INIT;
if (!vrrp->adver_int)
vrrp->adver_int = VRRP_ADVER_DFL * TIMER_HZ;
- if (!vrrp->priority)
- vrrp->priority = VRRP_PRIO_DFL;
+ if (!vrrp->effective_priority)
+ vrrp->effective_priority = VRRP_PRIO_DFL;
return (chk_min_cfg(vrrp));
}
*
* Part: ARP primitives.
*
- * Version: $Id: vrrp_arp.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_arp.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: VRRP child process handling.
*
- * Version: $Id: vrrp_daemon.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_daemon.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: vrrp_data.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_data.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_data.h"
#include "vrrp_index.h"
#include "vrrp_sync.h"
+#include "vrrp_if.h"
#include "vrrp.h"
#include "memory.h"
#include "utils.h"
syslog(LOG_INFO, " Using smtp notification");
}
+static void
+free_vscript(void *data)
+{
+ vrrp_script *vscript = data;
+
+ FREE(vscript->sname);
+ FREE_PTR(vscript->script);
+ FREE(vscript);
+}
+static void
+dump_vscript(void *data)
+{
+ vrrp_script *vscript = data;
+ char *str;
+
+ syslog(LOG_INFO, " VRRP Script = %s", vscript->sname);
+ syslog(LOG_INFO, " Command = %s", vscript->script);
+ syslog(LOG_INFO, " Interval = %d sec", vscript->interval / TIMER_HZ);
+ syslog(LOG_INFO, " Weight = %d", vscript->weight);
+
+ switch (vscript->result) {
+ case VRRP_SCRIPT_STATUS_INIT:
+ str = "INIT"; break;
+ case VRRP_SCRIPT_STATUS_NONE:
+ str = "BAD"; break;
+ case VRRP_SCRIPT_STATUS_GOOD:
+ str = "GOOD"; break;
+ case VRRP_SCRIPT_STATUS_DISABLED:
+ default:
+ str = "DISABLED"; break;
+ }
+ syslog(LOG_INFO, " Status = %s", str);
+}
+
/* Socket pool functions */
static void
free_sock(void *sock_data_obj)
free_vrrp(void *data)
{
vrrp_rt *vrrp = data;
+ element e;
FREE(vrrp->iname);
FREE_PTR(vrrp->send_buffer);
FREE_PTR(vrrp->script_backup);
FREE_PTR(vrrp->script_master);
FREE_PTR(vrrp->script_fault);
+ FREE_PTR(vrrp->script_stop);
FREE_PTR(vrrp->script);
FREE(vrrp->ipsecah_counter);
+
+ if (!LIST_ISEMPTY(vrrp->track_ifp))
+ for (e = LIST_HEAD(vrrp->track_ifp); e; ELEMENT_NEXT(e))
+ FREE(ELEMENT_DATA(e));
free_list(vrrp->track_ifp);
+
+ if (!LIST_ISEMPTY(vrrp->track_script))
+ for (e = LIST_HEAD(vrrp->track_script); e; ELEMENT_NEXT(e))
+ FREE(ELEMENT_DATA(e));
+ free_list(vrrp->track_script);
+
free_list(vrrp->vip);
free_list(vrrp->evip);
free_list(vrrp->vroutes);
syslog(LOG_INFO, " Gratuitous ARP delay = %d",
vrrp->garp_delay/TIMER_HZ);
syslog(LOG_INFO, " Virtual Router ID = %d", vrrp->vrid);
- syslog(LOG_INFO, " Priority = %d", vrrp->priority);
+ syslog(LOG_INFO, " Priority = %d", vrrp->base_priority);
syslog(LOG_INFO, " Advert interval = %dsec",
vrrp->adver_int / TIMER_HZ);
if (vrrp->nopreempt)
syslog(LOG_INFO, " Tracked interfaces = %d", LIST_SIZE(vrrp->track_ifp));
dump_list(vrrp->track_ifp);
}
+ if (!LIST_ISEMPTY(vrrp->track_script)) {
+ syslog(LOG_INFO, " Tracked scripts = %d",
+ LIST_SIZE(vrrp->track_script));
+ dump_list(vrrp->track_script);
+ }
if (!LIST_ISEMPTY(vrrp->vip)) {
syslog(LOG_INFO, " Virtual IP = %d", LIST_SIZE(vrrp->vip));
dump_list(vrrp->vip);
if (vrrp->script_fault)
syslog(LOG_INFO, " Fault state transition script = %s",
vrrp->script_fault);
+ if (vrrp->script_stop)
+ syslog(LOG_INFO, " Stop state transition script = %s",
+ vrrp->script_stop);
if (vrrp->script)
syslog(LOG_INFO, " Generic state transition script = '%s'",
vrrp->script);
}
void
+alloc_vrrp_track_script(vector strvec)
+{
+ vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
+
+ if (LIST_ISEMPTY(vrrp->track_script))
+ vrrp->track_script = alloc_list(NULL, dump_track_script);
+ alloc_track_script(vrrp->track_script, strvec);
+}
+
+void
alloc_vrrp_vip(vector strvec)
{
vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
alloc_route(vrrp->vroutes, strvec);
}
+void
+alloc_vrrp_script(char *sname)
+{
+ int size = strlen(sname);
+ vrrp_script *new;
+
+ /* Allocate new VRRP group structure */
+ new = (vrrp_script *) MALLOC(sizeof (vrrp_script));
+ new->sname = (char *) MALLOC(size + 1);
+ memcpy(new->sname, sname, size);
+ new->interval = VRRP_SCRIPT_DI * TIMER_HZ;
+ new->weight = VRRP_SCRIPT_DW;
+ new->result = VRRP_SCRIPT_STATUS_INIT;
+ new->inuse = 0;
+ list_add(vrrp_data->vrrp_script, new);
+}
+
/* data facility functions */
void
alloc_vrrp_buffer(void)
new->vrrp_index = alloc_mlist(NULL, NULL, 255);
new->vrrp_index_fd = alloc_mlist(NULL, NULL, 1024+1);
new->vrrp_sync_group = alloc_list(free_vgroup, dump_vgroup);
+ new->vrrp_script = alloc_list(free_vscript, dump_vscript);
new->vrrp_socket_pool = alloc_list(free_sock, dump_sock);
return new;
free_mlist(vrrp_data_obj->vrrp_index_fd, 1024+1);
free_list(vrrp_data_obj->vrrp);
free_list(vrrp_data_obj->vrrp_sync_group);
+ free_list(vrrp_data_obj->vrrp_script);
free_list(vrrp_data_obj->vrrp_socket_pool);
FREE(vrrp_data_obj);
}
syslog(LOG_INFO, "------< VRRP Sync groups >------");
dump_list(vrrp_data_obj->vrrp_sync_group);
}
+ if (!LIST_ISEMPTY(vrrp_data_obj->vrrp_script)) {
+ syslog(LOG_INFO, "------< VRRP Scripts >------");
+ dump_list(vrrp_data_obj->vrrp_script);
+ }
}
*
* Part: Interfaces manipulation.
*
- * Version: $Id: vrrp_if.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_if.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: VRRP instance index table.
*
- * Version: $Id: vrrp_index.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_index.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: NETLINK IPv4 address manipulation.
*
- * Version: $Id: vrrp_ipaddress.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: NETLINK IPv4 routes manipulation.
*
- * Version: $Id: vrrp_iproute.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_iproute.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* authentication data encryption using HMAC MD5 according to
* RFCs 2085 & 2104.
*
- * Version: $Id: vrrp_ipsecah.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: NETLINK kernel command channel.
*
- * Version: $Id: vrrp_netlink.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_netlink.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: VRRP state transition notification scripts handling.
*
- * Version: $Id: vrrp_notify.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_notify.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
}
static int
-notify_script_exec(char* script, char *type, int state_num, char* name)
+notify_script_exec(char* script, char *type, int state_num, char* name, int prio)
{
char *state = "{UNKNOWN}";
char *command_line = NULL;
* Determine the length of the buffer that we'll need to generate the command
* to run:
*
- * "script" {GROUP|INSTANCE} "NAME" {MASTER|BACKUP|FAULT}
+ * "script" {GROUP|INSTANCE} "NAME" {MASTER|BACKUP|FAULT} PRIO
*
* Thus, the length of the buffer will be:
*
- * ( strlen(script) + 3 ) + ( strlen(type) + 1 ) + ( strlen(state) + 1 ) + ( strlen(name) + 2 ) + 1
+ * ( strlen(script) + 3 ) + ( strlen(type) + 1 ) + ( strlen(name) + 1 ) +
+ * ( strlen(state) + 2 ) + ( strlen(prio) + 1 ) + 1
+ *
+ * Note that the prio will be indicated as zero for a group.
*
* Which is:
* - The length of the script plus two enclosing quotes plus adjacent space
* - The length of the type string plus the adjacent space
- * - The length of the state string plus the adjacent space
* - The length of the name of the instance or group, plus two enclosing
* quotes (just in case)
+ * - The length of the state string plus the adjacent space
+ * - The length of the priority value (3 digits) plus the adjacent
+ * space
* - The null-terminator
*
* Which results in:
*
- * strlen(script) + strlen(type) + strlen(state) + strlen(name) + 8
+ * strlen(script) + strlen(type) + strlen(state) + strlen(name) + 12
*/
switch (state_num) {
case VRRP_STATE_MAST : state = "MASTER" ; break;
case VRRP_STATE_FAULT : state = "FAULT" ; break;
}
- size = strlen(script) + strlen(type) + strlen(state) + strlen(name) + 8;
+ size = strlen(script) + strlen(type) + strlen(state) + strlen(name) + 12;
command_line = MALLOC(size);
if (!command_line)
return 0;
/* Launch the script */
- snprintf(command_line, size, "\"%s\" %s \"%s\" %s",script, type, name, state);
+ snprintf(command_line, size, "\"%s\" %s \"%s\" %s %d",
+ script, type, name, state, prio);
notify_exec(command_line);
FREE(command_line);
return 1;
/* Launch the generic notify script */
if (gscript && script_open_litteral(gscript)) {
- notify_script_exec(gscript, "INSTANCE", state, vrrp->iname);
+ notify_script_exec(gscript, "INSTANCE", state, vrrp->iname,
+ vrrp->effective_priority);
ret = 1;
}
/* Launch the generic notify script */
if (gscript && script_open_litteral(gscript)) {
- notify_script_exec(gscript, "GROUP", state, vgroup->gname);
+ notify_script_exec(gscript, "GROUP", state, vgroup->gname, 0);
ret = 1;
}
* data structure representation the conf file representing
* the loadbalanced server pool.
*
- * Version: $Id: vrrp_parser.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_parser.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
alloc_value_block(strvec, alloc_vrrp_track);
}
static void
+vrrp_track_scr_handler(vector strvec)
+{
+ alloc_value_block(strvec, alloc_vrrp_track_script);
+}
+static void
vrrp_dont_track_handler(vector strvec)
{
vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
vrrp_prio_handler(vector strvec)
{
vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
- vrrp->priority = atoi(VECTOR_SLOT(strvec, 1));
+ vrrp->effective_priority = vrrp->base_priority = atoi(VECTOR_SLOT(strvec, 1));
- if (VRRP_IS_BAD_PRIORITY(vrrp->priority)) {
+ if (VRRP_IS_BAD_PRIORITY(vrrp->base_priority)) {
syslog(LOG_INFO, "VRRP Error : Priority not valid !\n");
syslog(LOG_INFO,
" must be between 1 & 255. reconfigure !\n");
syslog(LOG_INFO, " Using default value : 100\n");
- vrrp->priority = 100;
+ vrrp->effective_priority = vrrp->base_priority = 100;
}
}
static void
vrrp->notify_exec = 1;
}
static void
+vrrp_notify_stop_handler(vector strvec)
+{
+ vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
+ vrrp->script_stop = set_value(strvec);
+ vrrp->notify_exec = 1;
+}
+static void
vrrp_notify_handler(vector strvec)
{
vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
{
alloc_value_block(strvec, alloc_vrrp_vroute);
}
+static void
+vrrp_script_handler(vector strvec)
+{
+ alloc_vrrp_script(VECTOR_SLOT(strvec, 1));
+}
+static void
+vrrp_vscript_script_handler(vector strvec)
+{
+ vrrp_script *vscript = LIST_TAIL_DATA(vrrp_data->vrrp_script);
+ vscript->script = set_value(strvec);
+}
+static void
+vrrp_vscript_interval_handler(vector strvec)
+{
+ vrrp_script *vscript = LIST_TAIL_DATA(vrrp_data->vrrp_script);
+ vscript->interval = atoi(VECTOR_SLOT(strvec, 1)) * TIMER_HZ;
+}
+static void
+vrrp_vscript_weight_handler(vector strvec)
+{
+ vrrp_script *vscript = LIST_TAIL_DATA(vrrp_data->vrrp_script);
+ vscript->weight = atoi(VECTOR_SLOT(strvec, 1));
+}
vector
vrrp_init_keywords(void)
install_keyword("interface", &vrrp_int_handler);
install_keyword("dont_track_primary", &vrrp_dont_track_handler);
install_keyword("track_interface", &vrrp_track_int_handler);
+ install_keyword("track_script", &vrrp_track_scr_handler);
install_keyword("mcast_src_ip", &vrrp_mcastip_handler);
install_keyword("virtual_router_id", &vrrp_vrid_handler);
install_keyword("priority", &vrrp_prio_handler);
install_keyword("notify_backup", &vrrp_notify_backup_handler);
install_keyword("notify_master", &vrrp_notify_master_handler);
install_keyword("notify_fault", &vrrp_notify_fault_handler);
+ install_keyword("notify_stop", &vrrp_notify_stop_handler);
install_keyword("notify", &vrrp_notify_handler);
install_keyword("smtp_alert", &vrrp_smtp_handler);
install_keyword("lvs_sync_daemon_interface", &vrrp_lvs_syncd_handler);
install_keyword("auth_type", &vrrp_auth_type_handler);
install_keyword("auth_pass", &vrrp_auth_pass_handler);
install_sublevel_end();
+ install_keyword_root("vrrp_script", &vrrp_script_handler);
+ install_keyword("script", &vrrp_vscript_script_handler);
+ install_keyword("interval", &vrrp_vscript_interval_handler);
+ install_keyword("weight", &vrrp_vscript_weight_handler);
return keywords;
}
*
* Part: Sheduling framework for vrrp code.
*
- * Version: $Id: vrrp_scheduler.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_scheduler.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_index.h"
#include "ipvswrapper.h"
#include "memory.h"
+#include "notify.h"
#include "list.h"
#include "main.h"
#include "smtp.h"
static void vrrp_master(vrrp_rt *);
static void vrrp_fault(vrrp_rt *);
+static int vrrp_update_priority(thread * thread_obj);
+static int vrrp_script_child_timeout_thread(thread * thread_obj);
+static int vrrp_script_child_thread(thread * thread_obj);
+static int vrrp_script_thread(thread * thread_obj);
+
struct {
void (*read) (vrrp_rt *, char *, int);
void (*read_to) (vrrp_rt *);
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- if (vrrp->priority == VRRP_PRIO_OWNER ||
+ /* In case of VRRP SYNC, we have to carefully check that we are
+ * not running floating priorities on any VRRP instance.
+ */
+ if (vrrp->sync) {
+ element e;
+ tracked_sc *sc;
+ tracked_if *tip;
+ int warning = 0;
+
+ if (!LIST_ISEMPTY(vrrp->track_ifp)) {
+ for (e = LIST_HEAD(vrrp->track_ifp); e; ELEMENT_NEXT(e)) {
+ tip = ELEMENT_DATA(e);
+ if (tip->weight) {
+ tip->weight = 0;
+ warning++;
+ }
+ }
+ }
+
+ if (!LIST_ISEMPTY(vrrp->track_script)) {
+ for (e = LIST_HEAD(vrrp->track_script); e;
+ ELEMENT_NEXT(e)) {
+ sc = ELEMENT_DATA(e);
+ if (sc->weight) {
+ sc->weight = 0;
+ sc->scr->inuse--;
+ warning++;
+ }
+ }
+ }
+
+ if (warning > 0) {
+ syslog(LOG_INFO, "VRRP_Instance(%s) : ignoring "
+ "track weights due to SYNC group",
+ vrrp->iname);
+ }
+ } else {
+ /* Register new priority update thread */
+ thread_add_timer(master, vrrp_update_priority,
+ vrrp, vrrp->adver_int);
+ }
+
+ if (vrrp->base_priority == VRRP_PRIO_OWNER ||
vrrp->wantstate == VRRP_STATE_MAST) {
#ifdef _HAVE_IPVS_SYNCD_
/* Check if sync daemon handling is needed */
}
}
+/* if run after vrrp_init_state(), it will be able to detect scripts that
+ * have been disabled because of a sync group and will avoid to start them.
+ */
+static void
+vrrp_init_script(list l)
+{
+ vrrp_script *vscript;
+ element e;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vscript = ELEMENT_DATA(e);
+ if (vscript->inuse == 0)
+ vscript->result = VRRP_SCRIPT_STATUS_DISABLED;
+
+ if (vscript->result == VRRP_SCRIPT_STATUS_INIT) {
+ vscript->result = VRRP_SCRIPT_STATUS_NONE;
+ thread_add_timer(master, vrrp_script_thread,
+ vscript, vscript->interval);
+ }
+ }
+}
+
/* Timer functions */
static TIMEVAL
vrrp_compute_timer(const int fd)
/* Init VRRP instances sands */
vrrp_init_sands(vrrp_data->vrrp);
+ /* Init VRRP tracking scripts */
+ if (!LIST_ISEMPTY(vrrp_data->vrrp_script))
+ vrrp_init_script(vrrp_data->vrrp_script);
+
/* Register VRRP workers threads */
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
sock_obj = ELEMENT_DATA(e);
vrrp->iname);
vrrp->state = VRRP_STATE_BACK;
vrrp_smtp_notifier(vrrp);
+ notify_instance_exec(vrrp, VRRP_STATE_BACK);
}
} else {
syslog(LOG_INFO, "VRRP_Instance(%s) Entering BACKUP STATE",
vrrp->iname);
vrrp->state = VRRP_STATE_BACK;
vrrp_smtp_notifier(vrrp);
+ notify_instance_exec(vrrp, VRRP_STATE_BACK);
}
}
}
return 0;
}
+/* Update VRRP effective priority based on multiple checkers.
+ * This is a thread which is executed every adver_int.
+ */
+static int
+vrrp_update_priority(thread * thread_obj)
+{
+ vrrp_rt *vrrp = THREAD_ARG(thread_obj);
+ int prio_offset, new_prio;
+
+ /* compute prio_offset right here */
+ prio_offset = 0;
+
+ /* Now we will sum the weights of all interfaces which are tracked. */
+ if (!vrrp->sync && !LIST_ISEMPTY(vrrp->track_ifp))
+ prio_offset += vrrp_tracked_weight(vrrp->track_ifp);
+
+ /* Now we will sum the weights of all scripts which are tracked. */
+ if (!vrrp->sync && !LIST_ISEMPTY(vrrp->track_script))
+ prio_offset += vrrp_script_weight(vrrp->track_script);
+
+ if (vrrp->base_priority == VRRP_PRIO_OWNER) {
+ /* we will not run a PRIO_OWNER into a non-PRIO_OWNER */
+ vrrp->effective_priority = VRRP_PRIO_OWNER;
+ } else {
+ /* WARNING! we must compute new_prio on a signed int in order
+ to detect overflows and avoid wrapping. */
+ new_prio = vrrp->base_priority + prio_offset;
+ if (new_prio < 1)
+ new_prio = 1;
+ else if (new_prio > 254)
+ new_prio = 254;
+ vrrp->effective_priority = new_prio;
+ }
+
+ /* Register next priority update thread */
+ thread_add_timer(master, vrrp_update_priority, vrrp, vrrp->adver_int);
+ return 0;
+}
+
static void
vrrp_master(vrrp_rt * vrrp)
{
return 0;
}
+
+/* Script tracking threads */
+static int
+vrrp_script_thread(thread * thread_obj)
+{
+ vrrp_script *vscript = THREAD_ARG(thread_obj);
+ int status;
+ pid_t pid;
+
+ /* Register next timer tracker */
+ thread_add_timer(thread_obj->master, vrrp_script_thread, vscript,
+ vscript->interval);
+
+ /* Daemonization to not degrade our scheduling timer */
+ pid = fork();
+
+ /* In case of fork is error. */
+ if (pid < 0) {
+ syslog(LOG_INFO, "Failed fork process");
+ return -1;
+ }
+
+ /* In case of this is parent process */
+ if (pid) {
+ long timeout;
+ timeout = vscript->interval;
+ thread_add_child(thread_obj->master, vrrp_script_child_thread,
+ vscript, pid, timeout);
+ return 0;
+ }
+
+ /* Child part */
+ closeall(0);
+ open("/dev/null", O_RDWR);
+ dup(0);
+ dup(0);
+
+ /* Also need to reset the signal state */
+ {
+ sigset_t empty_set;
+ sigemptyset(&empty_set);
+ sigprocmask(SIG_SETMASK, &empty_set, NULL);
+
+ signal(SIGHUP, SIG_DFL);
+ signal(SIGINT, SIG_DFL);
+ signal(SIGTERM, SIG_DFL);
+ signal(SIGKILL, SIG_DFL);
+ }
+
+ status = system_call(vscript->script);
+
+ if (status < 0 || !WIFEXITED(status))
+ status = 0; /* Script errors aren't server errors */
+ else
+ status = WEXITSTATUS(status);
+
+ exit(status);
+}
+
+static int
+vrrp_script_child_thread(thread * thread_obj)
+{
+ int wait_status;
+ vrrp_script *vscript = THREAD_ARG(thread_obj);
+
+ if (thread_obj->type == THREAD_CHILD_TIMEOUT) {
+ pid_t pid;
+
+ pid = THREAD_CHILD_PID(thread_obj);
+
+ /* The child hasn't responded. Kill it off. */
+ vscript->result = VRRP_SCRIPT_STATUS_NONE;
+ kill(pid, SIGTERM);
+ thread_add_child(thread_obj->master, vrrp_script_child_timeout_thread,
+ vscript, pid, 2);
+ return 0;
+ }
+
+ wait_status = THREAD_CHILD_STATUS(thread_obj);
+
+ if (WIFEXITED(wait_status)) {
+ int status;
+ status = WEXITSTATUS(wait_status);
+ vscript->result = (status == 0) ? VRRP_SCRIPT_STATUS_GOOD :
+ VRRP_SCRIPT_STATUS_NONE;
+ }
+
+ return 0;
+}
+
+static int
+vrrp_script_child_timeout_thread(thread * thread_obj)
+{
+ pid_t pid;
+
+ if (thread_obj->type != THREAD_CHILD_TIMEOUT)
+ return 0;
+
+ /* OK, it still hasn't exited. Now really kill it off. */
+ pid = THREAD_CHILD_PID(thread_obj);
+ if (kill(pid, SIGKILL) < 0) {
+ /* Its possible it finished while we're handing this */
+ if (errno != ESRCH)
+ DBG("kill error: %s", strerror(errno));
+ return 0;
+ }
+
+ syslog(LOG_WARNING, "Process [%d] didn't respond to SIGTERM", pid);
+ waitpid(pid, NULL, 0);
+
+ return 0;
+}
*
* Part: VRRP synchronization framework.
*
- * Version: $Id: vrrp_sync.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_sync.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
if (vrrp->state == VRRP_STATE_MAST ||
vrrp->state == VRRP_STATE_GOTO_MASTER ||
- vrrp->state == VRRP_STATE_GOTO_FAULT) {
+ vrrp->state == VRRP_STATE_GOTO_FAULT ||
+ vrrp->wantstate == VRRP_STATE_GOTO_MASTER) {
vrrp->sands.tv_sec = time_now.tv_sec + vrrp->adver_int / TIMER_HZ;
vrrp->sands.tv_usec = time_now.tv_usec;
return;
syslog(LOG_INFO,
"VRRP_Instance(%s) forcing a new MASTER election",
isync->iname);
- vrrp_send_adv(isync, isync->priority);
+ vrrp_send_adv(isync, isync->effective_priority);
}
}
}
*
* Part: Interface tracking framework.
*
- * Version: $Id: vrrp_track.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vrrp_track.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
void
dump_track(void *track_data_obj)
{
- interface *ifp = track_data_obj;
- syslog(LOG_INFO, " %s", IF_NAME(ifp));
+ tracked_if *tip = track_data_obj;
+ syslog(LOG_INFO, " %s weight %d", IF_NAME(tip->ifp), tip->weight);
}
void
alloc_track(list track_list, vector strvec)
{
interface *ifp = NULL;
+ tracked_if *tip = NULL;
+ int weight = 0;
char *tracked = VECTOR_SLOT(strvec, 0);
ifp = if_get_by_ifname(tracked);
return;
}
- list_add(track_list, ifp);
+ if (VECTOR_SIZE(strvec) >= 3 &&
+ !strcmp(VECTOR_SLOT(strvec, 1), "weight")) {
+ weight = atoi(VECTOR_SLOT(strvec, 2));
+ if (weight < -254 || weight > 254) {
+ syslog(LOG_INFO, " %s: weight must be between "
+ "[-254..254] inclusive. Ignoring...", tracked);
+ weight = 0;
+ }
+ }
+
+ tip = (tracked_if *) MALLOC(sizeof (tracked_if));
+ tip->ifp = ifp;
+ tip->weight = weight;
+
+ list_add(track_list, tip);
+}
+
+static vrrp_script *
+find_script_by_name(char *name)
+{
+ element e;
+ vrrp_script *scr;
+
+ if (LIST_ISEMPTY(vrrp_data->vrrp_script))
+ return NULL;
+
+ for (e = LIST_HEAD(vrrp_data->vrrp_script); e; ELEMENT_NEXT(e)) {
+ scr = ELEMENT_DATA(e);
+ if (!strcmp(scr->sname, name))
+ return scr;
+ }
+ return NULL;
+}
+
+/* Track script dump */
+void
+dump_track_script(void *track_data_obj)
+{
+ tracked_sc *tsc = track_data_obj;
+ syslog(LOG_INFO, " %s weight %d", tsc->scr->sname, tsc->weight);
+}
+void
+alloc_track_script(list track_list, vector strvec)
+{
+ vrrp_script *vsc = NULL;
+ tracked_sc *tsc = NULL;
+ int weight = 0;
+ char *tracked = VECTOR_SLOT(strvec, 0);
+
+ vsc = find_script_by_name(tracked);
+
+ /* Ignoring if no interface found */
+ if (!vsc) {
+ syslog(LOG_INFO, " %s no match, ignoring...", tracked);
+ return;
+ }
+
+ /* default weight */
+ weight = vsc->weight;
+
+ if (VECTOR_SIZE(strvec) >= 3 &&
+ !strcmp(VECTOR_SLOT(strvec, 1), "weight")) {
+ weight = atoi(VECTOR_SLOT(strvec, 2));
+ if (weight < -254 || weight > 254) {
+ weight = vsc->weight;
+ syslog(LOG_INFO, " %s: weight must be between [-254..254]"
+ " inclusive, ignoring...",
+ tracked);
+ }
+ }
+
+ tsc = (tracked_sc *) MALLOC(sizeof (tracked_sc));
+ tsc->scr = vsc;
+ tsc->weight = weight;
+ if (weight > 0)
+ vsc->inuse++;
+ list_add(track_list, tsc);
}
-/* Test if all tracked interfaces are UP */
+/* Test if all tracked interfaces are either UP or weight-tracked */
int
vrrp_tracked_up(list l)
{
element e;
- interface *ifp;
+ tracked_if *tip;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
- ifp = ELEMENT_DATA(e);
- if (!IF_ISUP(ifp))
+ tip = ELEMENT_DATA(e);
+ if (!tip->weight && !IF_ISUP(tip->ifp))
return 0;
}
vrrp_log_tracked_down(list l)
{
element e;
- interface *ifp;
+ tracked_if *tip;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
- ifp = ELEMENT_DATA(e);
- if (!IF_ISUP(ifp))
+ tip = ELEMENT_DATA(e);
+ if (!IF_ISUP(tip->ifp))
syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
- IF_NAME(ifp));
+ IF_NAME(tip->ifp));
+ }
+}
+
+/* Returns total weights of all tracked interfaces :
+ * - a positive interface weight adds to the global weight when the
+ * interface is UP.
+ * - a negative interface weight subtracts from the global weight when the
+ * interface is DOWN.
+ *
+ */
+int
+vrrp_tracked_weight(list l)
+{
+ element e;
+ tracked_if *tip;
+ int weight = 0;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ tip = ELEMENT_DATA(e);
+ if (IF_ISUP(tip->ifp)) {
+ if (tip->weight > 0)
+ weight += tip->weight;
+ } else {
+ if (tip->weight < 0)
+ weight += tip->weight;
+ }
}
+
+ return weight;
+}
+
+/* Returns total weights of all tracked scripts :
+ * - a positive weight adds to the global weight when the result is OK
+ * - a negative weight subtracts from the global weight when the result is bad
+ *
+ */
+int
+vrrp_script_weight(list l)
+{
+ element e;
+ tracked_sc *tsc;
+ int weight = 0;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ tsc = ELEMENT_DATA(e);
+ if (tsc->scr->result == VRRP_SCRIPT_STATUS_GOOD) {
+ if (tsc->weight > 0)
+ weight += tsc->weight;
+ } else if (tsc->scr->result == VRRP_SCRIPT_STATUS_NONE) {
+ if (tsc->weight < 0)
+ weight += tsc->weight;
+ }
+ }
+
+ return weight;
}
*
* Part: HTML stream parser utility functions.
*
- * Version: $Id: html.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: html.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: parser.c include file.
*
- * Version: $Id: html.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: html.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: List structure manipulation.
*
- * Version: $Id: list.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: list.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: list.c include file.
*
- * Version: $Id: list.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: list.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: Memory management framework. This framework is used to
* find any memory leak.
*
- * Version: $Id: memory.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: memory.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: memory.c include file.
*
- * Version: $Id: memory.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: memory.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: Forked system call to launch an extra script.
*
- * Version: $Id: notify.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: notify.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: notify.c include file.
*
- * Version: $Id: notify.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: notify.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* data structure representation the conf file representing
* the loadbalanced server pool.
*
- * Version: $Id: parser.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: parser.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: cfreader.c include file.
*
- * Version: $Id: parser.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: parser.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* the thread management routine (thread.c) present in the
* very nice zebra project (http://www.zebra.org).
*
- * Version: $Id: scheduler.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: scheduler.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
thread *
thread_fetch(thread_master * m, thread * fetch)
{
- int ret;
+ int ret, old_errno;
thread *thread_obj;
fd_set readfd;
fd_set writefd;
sigprocmask(SIG_SETMASK, &saveset, NULL);
}
+ /* we have to save errno here because the next syscalls will set it */
+ old_errno = errno;
+
/*
* When we receive a signal, we only add it to the signal_mask. This
* is so that we can run our handler functions in a safe place and
set_time_now();
if (ret < 0) {
- if (errno != EINTR) {
+ if (old_errno != EINTR) {
/* Real error. */
- DBG("select error: %s", strerror(errno));
+ DBG("select error: %s", strerror(old_errno));
assert(0);
} else {
/*
*
* Part: scheduler.c include file.
*
- * Version: $Id: scheduler.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: scheduler.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Signals framework.
*
- * Version: $Id: signals.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: signals.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Kevin Lindsay, <kevinl@netnation.com>
* Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: signals.c include file.
*
- * Version: $Id: signals.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: signals.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Kevin Lindsay, <kevinl@netnation.com>
* Alexandre Cassen, <acassen@linux-vs.org>
*
* Part: Timer manipulations.
*
- * Version: $Id: timer.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: timer.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <stdio.h>
#include <string.h>
+#include <errno.h>
#include "timer.h"
/* time_now holds current time */
timer_now(void)
{
TIMEVAL curr_time;
+ int old_errno = errno;
/* init timer */
TIMER_RESET(curr_time);
gettimeofday(&curr_time, NULL);
+ errno = old_errno;
return curr_time;
}
TIMEVAL
set_time_now(void)
{
+ int old_errno = errno;
+
/* init timer */
TIMER_RESET(time_now);
gettimeofday(&time_now, NULL);
+ errno = old_errno;
return time_now;
}
*
* Part: timer.c include file.
*
- * Version: $Id: timer.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: timer.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: General program utils.
*
- * Version: $Id: utils.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: utils.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: utils.h include file.
*
- * Version: $Id: utils.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: utils.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Vector structure manipulation.
*
- * Version: $Id: vector.c,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vector.c,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vector.c include file.
*
- * Version: $Id: vector.h,v 1.1.12 2006/03/09 01:22:13 acassen Exp $
+ * Version: $Id: vector.h,v 1.1.13 2006/10/11 05:22:13 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*