* keepalived-1.1.0 released.
* The release focus is : "High Performance"
* Name cleanup for the healthchecking directory. use check
instead of healthcheck to be in conformance with watchdog and
global software architecture.
* updated the SYNOPSIS file for documenting the table arg inside
virtual/static_routes declaration. You can set routes refering
to a specific TABLE-ID.
* Added a dummy debug var in the genhash declaration code to
support compilation when compilation is done with debug flag.
* Added a set flag inside the real_server declaration correctly
relfect the IPVS topology when inhibit_on_failure is used.
* fixed a daemon.h include depandency on signal.h
* VRRP : Added support to a global shared buffer for incoming
advert handling. A new buffer is no longer allocated each time
processing incoming advert, instead a shared room is used.
* VRRP : Added support to pre-allocated shared buffer for
outgoing adverts. Each vrrp instance use a 'one time'
allocated buffer instead of a 'all time' one.
* VRRP : Extended the socket pool design to support shared fd
for the outbound channel. Now, socket pool create a sending
socket and affect the fd returned to vrrp instances. This
forces instances to use a shared socket instead of creating
new socket for each outgoing adverts. The error detection
is based on the incoming socket, so that outgoing socket is
not created as long as incoming socket can not be created.
* Added support to netlink ipaddress as global keyword
"static_ipaddress".
look at doc/samples/keepalived.conf.static_ipaddress.
IP addresses specified into this block will be added during
daemon bootstrap and removed during daemon shutdown.
Differential conf parsing is enabled for this block,
removing/adding static_ipaddress can be done on the fly
sending SIGHUP signal to daemon.
* VRRP : Extended track_interface to support multiple interface
tracking. For those familiar with Nokia monitored circuit,
this extention provide the same functionality.
look at doc/samples/keepalived.conf.track_interface.
* VRRP : The VRRP instance lookup framework has been extended
to use a o(1) scheduling design. Rewrote the whole instance
lookup to use o(1) lookup instead of previous o(n^2). When
receiving incoming adverts vrrp_scheduler performs a lookup
over the VRID received to get local instance representation.
Since the internal instance representation is an non-sorted
linked list, then we run a lookup at o(n^2) complexity that
introduce lantency and scheduling jitter side effect when
runing large number of instances. To avoid this limitation
a static hash table of 255 buckets were created. Since
lookup is performed over VRID and since VRID is 8bit fixed,
then the hashkey will be VRID. In order to extend code the
hashkey is based on incoming fd too. Internally, a NIC is
represented by a 2 fds : sending socket and receiving socket.
Those fds are NIC specific so we are using them as a hash
table lookup collision resolver. With this design we can now
use the same VRID on different NICs. The collision design
is a linked list so lookup is o(n^2) but due to low number
of entries we can consider o(1) speed. But to reach best
perf, differents VRID on all instance must be used. The
design can be sumed by :
VRID hash table :
+---+---+---+---+---+---+.........+-----+
| 1 | 2 | 3 | 4 | 5 | 6 |.........| 255 |
+---+---+---+---+---+---+.........+-----+
| |
+---+ +---+
|fd3| |fd1|
+---+ +---+
|
+---+
|fd5|
+---+
This hash table is filled during configuration parsing and
VRRP instances are not duplicated but dynamically pointed
to optimize memory.
* VRRP : The VRRP synchronization group lookup has been
extended. During bootstrap a VRRP instance index is built upon
sync_group instance name. This extension speed up
synchronization since while synchronizing it perfoms the
instance index instead of lookup by instance_name. The
previous synchornization code has been rewritten to use this
'list visiting' design for FAULT/BACKUP/MASTER states
synchronization.
* VRRP : Optimized the vrrp_timer_vrid_timeout(...) to speed
up vrid lookup over timeouted fd using a one pass lookup.
* Bradley Baetz, <bradley.baetz@optusnet.com.au> extended
the scheduler framework to support child process handling.
Adding support to new thread child facility for handling
child processes, and modifying the scheduling select
loop & signal handling to catch SIGCHLD, and call the
appropriate process.
* Bradley Baetz, <bradley.baetz@optusnet.com.au> fixed
the misc_check healthchecker using new thread child
scheduling facility. Introduced a new keyword
"misc_timeout" to kill processes which take too long
time (default is delay_loop). SIGKILL is send to processes
if they take too long time to shutdown.
* Bradley Baetz, <bradley.baetz@optusnet.com.au> extended
daemon framework to block SIGCHLD to only receive it
whn its unblocked in the scheduling loop.
* Extended healthchecker delay_loop to support long
delay (ie: >1000s).
* VRRP : Added support to a shared kernel netlink command
channel for setting ip address and routes.
* Extended the genhash code to support verbose output
selection. command arg '-v' will generate a very verbose
output.
* VRRP : Extended the logging code to select verbose log
output or not. This selection is done by passing the
'-D' option to command line while starting daemon.
By default the output is silent.
* VRRP : Extended the gratuitous ARP framework to support
shared buffer and shared socket. This increase performances
for instances owning a bunch of VIP.
* VRRP : Extended the scheduling timer computation to support
timer auto-recalibrating. While computing next instance
timer, the scheduler will substract the time taken by
previous advert handling. This provide software overhead
adaptation. The recalibration is performed over usec timer
to not pertube global scheduler.
* VRRP : Fixed a gratuitous ARP issue. Extended the
ipaddress framework to point directly to interface
reflected by netlink channel instead of storing device
index. Extended the gratuitous ARP code to use new
ipaddress structure and for sending garp over device
ipaddess belong to. Needed if you run an instance on
one device interface and set VRRP VIP on different
interface.
* Extended watchdog framework to support polling delay
selection via daemon command line. Created two new
cmdline options :
--wdog-vrrp -R Define VRRP watchdog polling
delay. (default=5s)
--wdog-check -H Define checkers watchdog
polling delay. (default=5s)
* Extended SMTP code to support bigger buffer while
processing remote mta messages.
* Erik Barker, <erikb@netnation.com> extended initscript
to support native redhat init functions.
* Extended the autoconf scripts and Makefile(s) to support
code profiling. New configure option : --enable-profile
* list library has been extended to support multi-sized list &
specific element deletion. Extended to return when list is
empty. This reduce duplicated code to test is list is empty
while processing.
* VRRP : Extended VRRP scheduler to support fd hash
table design. Speed up instance lookup while
computing instance sands. This offer o(1) design
if we consider limited number of instances per
device.
* VRRP : Extended vrrp new socket creation to replace
refreshed instance fd into fd hash table index.
* VRRP : Extended vrrp framework to support
blank virtual_ipaddress block, can be usefull
if someone want to use just the VRRP advert
as hello monitoring channel.
* Some code cleaning.
-Jan Holmberg, <jan@artech.net>
+Jan Holmberg, <jan@artech.net> :
+ o Memory framework
+ o HTTP/SSL checkers
+
+Bradley Baetz, <bradley.baetz@optusnet.com.au> :
+ o MISC checker redesign
+ o Scheduler framework extension to support
+ child process handling.
+ o Daemon framework extension to block SIGCHLD
+ to only receive it when its unblocked in the
+ scheduling select loop.
+2003-07-22 Alexandre Cassen <acassen@linux-vs.org>
+ * keepalived-1.1.0 released.
+ * The release focus is : "High Performance"
+ * Name cleanup for the healthchecking directory. use check
+ instead of healthcheck to be in conformance with watchdog and
+ global software architecture.
+ * updated the SYNOPSIS file for documenting the table arg inside
+ virtual/static_routes declaration. You can set routes refering
+ to a specific TABLE-ID.
+ * Added a dummy debug var in the genhash declaration code to
+ support compilation when compilation is done with debug flag.
+ * Added a set flag inside the real_server declaration correctly
+ relfect the IPVS topology when inhibit_on_failure is used.
+ * fixed a daemon.h include depandency on signal.h
+ * VRRP : Added support to a global shared buffer for incoming
+ advert handling. A new buffer is no longer allocated each time
+ processing incoming advert, instead a shared room is used.
+ * VRRP : Added support to pre-allocated shared buffer for
+ outgoing adverts. Each vrrp instance use a 'one time'
+ allocated buffer instead of a 'all time' one.
+ * VRRP : Extended the socket pool design to support shared fd
+ for the outbound channel. Now, socket pool create a sending
+ socket and affect the fd returned to vrrp instances. This
+ forces instances to use a shared socket instead of creating
+ new socket for each outgoing adverts. The error detection
+ is based on the incoming socket, so that outgoing socket is
+ not created as long as incoming socket can not be created.
+ * Added support to netlink ipaddress as global keyword
+ "static_ipaddress".
+ look at doc/samples/keepalived.conf.static_ipaddress.
+ IP addresses specified into this block will be added during
+ daemon bootstrap and removed during daemon shutdown.
+ Differential conf parsing is enabled for this block,
+ removing/adding static_ipaddress can be done on the fly
+ sending SIGHUP signal to daemon.
+ * VRRP : Extended track_interface to support multiple interface
+ tracking. For those familiar with Nokia monitored circuit,
+ this extention provide the same functionality.
+ look at doc/samples/keepalived.conf.track_interface.
+ * VRRP : The VRRP instance lookup framework has been extended
+ to use a o(1) scheduling design. Rewrote the whole instance
+ lookup to use o(1) lookup instead of previous o(n^2). When
+ receiving incoming adverts vrrp_scheduler performs a lookup
+ over the VRID received to get local instance representation.
+ Since the internal instance representation is an non-sorted
+ linked list, then we run a lookup at o(n^2) complexity that
+ introduce lantency and scheduling jitter side effect when
+ runing large number of instances. To avoid this limitation
+ a static hash table of 255 buckets were created. Since
+ lookup is performed over VRID and since VRID is 8bit fixed,
+ then the hashkey will be VRID. In order to extend code the
+ hashkey is based on incoming fd too. Internally, a NIC is
+ represented by a 2 fds : sending socket and receiving socket.
+ Those fds are NIC specific so we are using them as a hash
+ table lookup collision resolver. With this design we can now
+ use the same VRID on different NICs. The collision design
+ is a linked list so lookup is o(n^2) but due to low number
+ of entries we can consider o(1) speed. But to reach best
+ perf, differents VRID on all instance must be used. The
+ design can be sumed by :
+
+ VRID hash table :
+
+ +---+---+---+---+---+---+.........+-----+
+ | 1 | 2 | 3 | 4 | 5 | 6 |.........| 255 |
+ +---+---+---+---+---+---+.........+-----+
+ | |
+ +---+ +---+
+ |fd3| |fd1|
+ +---+ +---+
+ |
+ +---+
+ |fd5|
+ +---+
+
+ This hash table is filled during configuration parsing and
+ VRRP instances are not duplicated but dynamically pointed
+ to optimize memory.
+ * VRRP : The VRRP synchronization group lookup has been
+ extended. During bootstrap a VRRP instance index is built upon
+ sync_group instance name. This extension speed up
+ synchronization since while synchronizing it perfoms the
+ instance index instead of lookup by instance_name. The
+ previous synchornization code has been rewritten to use this
+ 'list visiting' design for FAULT/BACKUP/MASTER states
+ synchronization.
+ * VRRP : Optimized the vrrp_timer_vrid_timeout(...) to speed
+ up vrid lookup over timeouted fd using a one pass lookup.
+ * Bradley Baetz, <bradley.baetz@optusnet.com.au> extended
+ the scheduler framework to support child process handling.
+ Adding support to new thread child facility for handling
+ child processes, and modifying the scheduling select
+ loop & signal handling to catch SIGCHLD, and call the
+ appropriate process.
+ * Bradley Baetz, <bradley.baetz@optusnet.com.au> fixed
+ the misc_check healthchecker using new thread child
+ scheduling facility. Introduced a new keyword
+ "misc_timeout" to kill processes which take too long
+ time (default is delay_loop). SIGKILL is send to processes
+ if they take too long time to shutdown.
+ * Bradley Baetz, <bradley.baetz@optusnet.com.au> extended
+ daemon framework to block SIGCHLD to only receive it
+ whn its unblocked in the scheduling loop.
+ * Extended healthchecker delay_loop to support long
+ delay (ie: >1000s).
+ * VRRP : Added support to a shared kernel netlink command
+ channel for setting ip address and routes.
+ * Extended the genhash code to support verbose output
+ selection. command arg '-v' will generate a very verbose
+ output.
+ * VRRP : Extended the logging code to select verbose log
+ output or not. This selection is done by passing the
+ '-D' option to command line while starting daemon.
+ By default the output is silent.
+ * VRRP : Extended the gratuitous ARP framework to support
+ shared buffer and shared socket. This increase performances
+ for instances owning a bunch of VIP.
+ * VRRP : Extended the scheduling timer computation to support
+ timer auto-recalibrating. While computing next instance
+ timer, the scheduler will substract the time taken by
+ previous advert handling. This provide software overhead
+ adaptation. The recalibration is performed over usec timer
+ to not pertube global scheduler.
+ * VRRP : Fixed a gratuitous ARP issue. Extended the
+ ipaddress framework to point directly to interface
+ reflected by netlink channel instead of storing device
+ index. Extended the gratuitous ARP code to use new
+ ipaddress structure and for sending garp over device
+ ipaddess belong to. Needed if you run an instance on
+ one device interface and set VRRP VIP on different
+ interface.
+ * Extended watchdog framework to support polling delay
+ selection via daemon command line. Created two new
+ cmdline options :
+ --wdog-vrrp -R Define VRRP watchdog polling
+ delay. (default=5s)
+ --wdog-check -H Define checkers watchdog
+ polling delay. (default=5s)
+ * Extended SMTP code to support bigger buffer while
+ processing remote mta messages.
+ * Erik Barker, <erikb@netnation.com> extended initscript
+ to support native redhat init functions.
+ * Extended the autoconf scripts and Makefile(s) to support
+ code profiling. New configure option : --enable-profile
+ * list library has been extended to support multi-sized list &
+ specific element deletion. Extended to return when list is
+ empty. This reduce duplicated code to test is list is empty
+ while processing.
+ * VRRP : Extended VRRP scheduler to support fd hash
+ table design. Speed up instance lookup while
+ computing instance sands. This offer o(1) design
+ if we consider limited number of instances per
+ device.
+ * VRRP : Extended vrrp new socket creation to replace
+ refreshed instance fd into fd hash table index.
+ * VRRP : Extended vrrp framework to support
+ blank virtual_ipaddress block, can be usefull
+ if someone want to use just the VRRP advert
+ as hello monitoring channel.
+ * Some code cleaning.
+
2003-05-12 Alexandre Cassen <acassen@linux-vs.org>
* keepalived-1.0.3 released.
* This release has been sponsorized by :
@echo ""
@echo "Make complete"
+profile:
+ $(MAKE) -C lib || exit 1;
+ $(MAKE) -C keepalived profile
+ @echo ""
+ @echo "Make complete"
+
clean:
$(MAKE) -C lib clean
$(MAKE) -C keepalived clean
--with-ci_linux Compile with Cluster Infrastructure support (default no)"
ac_help="$ac_help
--enable-debug compile with debugging flags"
+ac_help="$ac_help
+ --enable-profile compile with profiling flags"
# Initialize some variables set by options.
# The variables have the same names as the options, with
# Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:543: checking for $ac_word" >&5
+echo "configure:545: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:573: checking for $ac_word" >&5
+echo "configure:575: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:624: checking for $ac_word" >&5
+echo "configure:626: checking for $ac_word" >&5
if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:656: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:658: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
ac_ext=c
# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
cat > conftest.$ac_ext << EOF
-#line 667 "configure"
+#line 669 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:672: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:674: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
{ echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:698: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:700: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
cross_compiling=$ac_cv_prog_cc_cross
echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:703: checking whether we are using GNU C" >&5
+echo "configure:705: checking whether we are using GNU C" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:712: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:714: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
ac_cv_prog_gcc=yes
else
ac_cv_prog_gcc=no
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:731: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:733: checking whether ${CC-cc} accepts -g" >&5
if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:793: checking for a BSD compatible install" >&5
+echo "configure:795: checking for a BSD compatible install" >&5
if test -z "$INSTALL"; then
if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
:
fi
+# Check whether --enable-profile or --disable-profile was given.
+if test "${enable_profile+set}" = set; then
+ enableval="$enable_profile"
+ :
+fi
+
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:888: checking how to run the C preprocessor" >&5
+echo "configure:896: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 903 "configure"
+#line 911 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:909: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:917: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 920 "configure"
+#line 928 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:926: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:934: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
-#line 937 "configure"
+#line 945 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:943: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:951: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
echo "$ac_t""$CPP" 1>&6
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:968: checking for ANSI C header files" >&5
+echo "configure:976: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 973 "configure"
+#line 981 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:981: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:989: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 998 "configure"
+#line 1006 "configure"
#include "confdefs.h"
#include <string.h>
EOF
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1016 "configure"
+#line 1024 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
:
else
cat > conftest.$ac_ext <<EOF
-#line 1037 "configure"
+#line 1045 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
exit (0); }
EOF
-if { (eval echo configure:1048: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1056: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
fi
echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:1072: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:1080: checking for sys/wait.h that is POSIX.1 compatible" >&5
if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1077 "configure"
+#line 1085 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/wait.h>
s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
; return 0; }
EOF
-if { (eval echo configure:1093: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1101: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_sys_wait_h=yes
else
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1117: checking for $ac_hdr" >&5
+echo "configure:1125: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1122 "configure"
+#line 1130 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1127: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1135: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1157: checking for $ac_hdr" >&5
+echo "configure:1165: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1162 "configure"
+#line 1170 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1167: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1175: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1197: checking for $ac_hdr" >&5
+echo "configure:1205: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1202 "configure"
+#line 1210 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1207: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1215: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1241: checking for $ac_hdr" >&5
+echo "configure:1249: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1246 "configure"
+#line 1254 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1251: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1259: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
fi
echo $ac_n "checking for MD5_Init in -lcrypto""... $ac_c" 1>&6
-echo "configure:1281: checking for MD5_Init in -lcrypto" >&5
+echo "configure:1289: checking for MD5_Init in -lcrypto" >&5
ac_lib_var=`echo crypto'_'MD5_Init | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lcrypto $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1289 "configure"
+#line 1297 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
MD5_Init()
; return 0; }
EOF
-if { (eval echo configure:1300: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for SSL_CTX_new in -lssl""... $ac_c" 1>&6
-echo "configure:1329: checking for SSL_CTX_new in -lssl" >&5
+echo "configure:1337: checking for SSL_CTX_new in -lssl" >&5
ac_lib_var=`echo ssl'_'SSL_CTX_new | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lssl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1337 "configure"
+#line 1345 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
SSL_CTX_new()
; return 0; }
EOF
-if { (eval echo configure:1348: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
fi
echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6
-echo "configure:1377: checking for poptGetContext in -lpopt" >&5
+echo "configure:1385: checking for poptGetContext in -lpopt" >&5
ac_lib_var=`echo popt'_'poptGetContext | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lpopt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1385 "configure"
+#line 1393 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
poptGetContext()
; return 0; }
EOF
-if { (eval echo configure:1396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
if test "${ci_linux}" = "yes"; then
echo $ac_n "checking for cluster_maxnodes in -lcluster""... $ac_c" 1>&6
-echo "configure:1426: checking for cluster_maxnodes in -lcluster" >&5
+echo "configure:1434: checking for cluster_maxnodes in -lcluster" >&5
ac_lib_var=`echo cluster'_'cluster_maxnodes | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
ac_save_LIBS="$LIBS"
LIBS="-lcluster $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1434 "configure"
+#line 1442 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
cluster_maxnodes()
; return 0; }
EOF
-if { (eval echo configure:1445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1453: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
CPPFLAGS="$CPPFLAGS -I$kernelinc"
CFLAGS="$CFLAGS -I$kernelinc"
echo $ac_n "checking for kernel >= 2.4.0""... $ac_c" 1>&6
-echo "configure:1478: checking for kernel >= 2.4.0" >&5
+echo "configure:1486: checking for kernel >= 2.4.0" >&5
if test "$cross_compiling" = yes; then
KERN="_KRNL_2_2_"
else
cat > conftest.$ac_ext <<EOF
-#line 1486 "configure"
+#line 1494 "configure"
#include "confdefs.h"
#include <stdlib.h>
#endif
}
EOF
-if { (eval echo configure:1499: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1507: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
KERN="_KRNL_2_4_"
if test "$enable_lvs" != "no"; then
ac_safe=`echo "net/ip_vs.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for net/ip_vs.h""... $ac_c" 1>&6
-echo "configure:1523: checking for net/ip_vs.h" >&5
+echo "configure:1531: checking for net/ip_vs.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1528 "configure"
+#line 1536 "configure"
#include "confdefs.h"
#include <net/ip_vs.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1533: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1541: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
echo $ac_n "checking for IPVS version""... $ac_c" 1>&6
-echo "configure:1565: checking for IPVS version" >&5
+echo "configure:1573: checking for IPVS version" >&5
if test "$cross_compiling" = yes; then
IPVS_MAJOR="0"
else
cat > conftest.$ac_ext <<EOF
-#line 1574 "configure"
+#line 1582 "configure"
#include "confdefs.h"
#include <stdlib.h>
}
EOF
-if { (eval echo configure:1589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1597: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
IPVS_MAJOR=`head -n 1 ipvsinfo | tail -n 1`
VRRP_SUPPORT="_WITHOUT_VRRP_"
if test "$enable_vrrp" != "no"; then
echo $ac_n "checking for kernel netlink support""... $ac_c" 1>&6
-echo "configure:1623: checking for kernel netlink support" >&5
+echo "configure:1631: checking for kernel netlink support" >&5
if test "$cross_compiling" = yes; then
echo "$ac_t""no" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1630 "configure"
+#line 1638 "configure"
#include "confdefs.h"
#include <asm/types.h>
exit(0);
}
EOF
-if { (eval echo configure:1644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1652: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
echo "$ac_t""yes" 1>&6
fi
+if test "${enable_profile}" = "yes"; then
+ CFLAGS="$CFLAGS -pg"
+fi
+
IPVS_SYNCD="_WITHOUT_IPVS_SYNCD_"
if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
echo $ac_n "checking for LVS syncd support""... $ac_c" 1>&6
-echo "configure:1687: checking for LVS syncd support" >&5
+echo "configure:1699: checking for LVS syncd support" >&5
if test "$IPVS_MAJOR" -ge 1 -a "$KERN" = "_KRNL_2_4_"; then
IPVS_SYNCD="_HAVE_IPVS_SYNCD_"
elif test "$IPVS_MINOR" -ge 9 -a "$IPVS_PATCH" -ge 2 -a "$KERN" = "_KRNL_2_4_"; then
echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1710: checking for working const" >&5
+echo "configure:1722: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1715 "configure"
+#line 1727 "configure"
#include "confdefs.h"
int main() {
; return 0; }
EOF
-if { (eval echo configure:1764: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1776: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
fi
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:1785: checking for pid_t" >&5
+echo "configure:1797: checking for pid_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1790 "configure"
+#line 1802 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
fi
echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:1818: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:1830: checking whether time.h and sys/time.h may both be included" >&5
if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1823 "configure"
+#line 1835 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/time.h>
struct tm *tp;
; return 0; }
EOF
-if { (eval echo configure:1832: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1844: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_header_time=yes
else
if test $ac_cv_prog_gcc = yes; then
echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:1855: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:1867: checking whether ${CC-cc} needs -traditional" >&5
if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_pattern="Autoconf.*'x'"
cat > conftest.$ac_ext <<EOF
-#line 1861 "configure"
+#line 1873 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
if test $ac_cv_prog_gcc_traditional = no; then
cat > conftest.$ac_ext <<EOF
-#line 1879 "configure"
+#line 1891 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
fi
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:1901: checking return type of signal handlers" >&5
+echo "configure:1913: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1906 "configure"
+#line 1918 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
int i;
; return 0; }
EOF
-if { (eval echo configure:1923: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1935: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
for ac_func in gettimeofday select socket strerror strtol uname
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1944: checking for $ac_func" >&5
+echo "configure:1956: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1949 "configure"
+#line 1961 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
; return 0; }
EOF
-if { (eval echo configure:1972: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1984: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
OUTPUT_TARGET="$OUTPUT_TARGET keepalived/vrrp/Makefile"
fi
if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
- OUTPUT_TARGET="$OUTPUT_TARGET keepalived/healthcheck/Makefile"
+ OUTPUT_TARGET="$OUTPUT_TARGET keepalived/check/Makefile"
if test "$KERN" = "_KRNL_2_4_"; then
OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs/Makefile"
else
[ci_linux="no"])
AC_ARG_ENABLE(debug,
[ --enable-debug compile with debugging flags])
+AC_ARG_ENABLE(profile,
+ [ --enable-profile compile with profiling flags])
dnl ----[ Checks for header files ]----
AC_HEADER_STDC
AC_SUBST(DFLAGS)
fi
+if test "${enable_profile}" = "yes"; then
+ CFLAGS="$CFLAGS -pg"
+fi
+
AC_SUBST(IPVS_SUPPORT)
AC_SUBST(VRRP_SUPPORT)
AC_SUBST(CI_LINUX)
OUTPUT_TARGET="$OUTPUT_TARGET keepalived/vrrp/Makefile"
fi
if test "$IPVS_SUPPORT" = "_WITH_LVS_"; then
- OUTPUT_TARGET="$OUTPUT_TARGET keepalived/healthcheck/Makefile"
+ OUTPUT_TARGET="$OUTPUT_TARGET keepalived/check/Makefile"
if test "$KERN" = "_KRNL_2_4_"; then
OUTPUT_TARGET="$OUTPUT_TARGET keepalived/libipvs/Makefile"
else
The configuration block looks like :
global_defs { # Block identification
- notification_email { # Email to send alertes to
+ notification_email { # Email to send alertes to
<EMAIL ADDRESS> # Standard email address
<EMAIL ADDRESS>
...
lvs_id <STRING> # String identifying router
}
- 1.2. Static routes
+ 1.2. Static addresses
+
+ The configuration block looks like :
+
+static_ipaddress { # block identification
+ <IP ADDRESS>/<MASK> dev <STRING> scope <SCOPE>
+ <IP ADDRESS>/<MASK> dev <STRING> scope <SCOPE>
+ ...
+}
+
+SCOPE can take the following values :
+ * site
+ * link
+ * host
+ * nowhere
+ * global
+
+ 1.3. Static routes
The configuration block looks like :
static_routes { # block identification
- src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> # to is optional
- src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> # to is optional
+ src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> table <TABLE-ID> # to is optional
+ src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> table <TABLE-ID> # to is optional
...
}
vrrp_instance <STRING> { # VRRP instance declaration
state MASTER|BACKUP # Start-up default state
interface <STRING> # Binding interface
- track_interface <STRING> # Interface state we monitor
+ track_interface { # Interfaces state we monitor
+ <STRING>
+ <STRING>
+ ...
+ }
mcast_src_ip <IP ADDRESS> # src_ip to use into the VRRP packets
lvs_sync_daemon_interface <STRING> # Binding interface for lvs syncd
garp_master_delay <INTEGER> # delay for gratuitous ARP after MASTER
...
}
virtual_routes { # VRRP virtual routes
- src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> # to is optional
- src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> # to is optional
+ src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> table <TABLE-ID> # to is optional
+ src <IP ADDRESS> [to] <IP ADDRESS>/<MASK> via|gw <IP ADDRESS> dev <STRING> scope <SCOPE> table <TABLE-ID> # to is optional
...
}
preempt # VRRP preempt mode (default set)
connect_timeout <INTEGER> # Timeout connection
}
}
+
+ real_server <IP ADDRESS> <PORT> { # Idem
+ weight <INTEGER> # Idem
+ inhibit_on_failure # Idem
+ notify_up <STRING>|<QUOTED-STRING> # Idem
+ notify_down <STRING>|<QUOTED-STRING> # Idem
+
+ MISC_CHECK { # MISC healthchecker
+ misc_path <STRING>|<QUOTED-STRING> # External system script or program
+ misc_timeout <INTEGER> # Script execution timeout
+ }
+ }
}
vrrp_instance VI_1 {
state MASTER
interface eth0.1 # Vlaned interface
- track_interface eth0 # Interface state we monitor
+ track_interface { # Interface state we monitor
+ eth0
+ eth1
+ }
virtual_router_id 51
priority 100
virtual_ipaddress {
--- /dev/null
+! Configuration File for keepalived
+
+global_defs {
+ lvs_id LVS_DEVEL
+}
+
+static_ipaddress {
+ 192.168.200.16 dev eth0 scope link
+ 192.168.200.17 dev eth1 scope link
+ 192.168.200.18 dev eth2
+}
+
+vrrp_instance VI_1 {
+ state MASTER
+ interface eth0
+ virtual_router_id 51
+ priority 100
+ virtual_ipaddress {
+ 192.168.200.20
+ }
+ virtual_routes {
+ src 192.168.100.1 192.168.109.0/24 via 192.168.200.254 dev eth1
+ 192.168.110.0/24 via 192.168.200.254 dev eth1
+ 192.168.111.0/24 dev eth2
+ 192.168.112.0/24 via 192.168.100.254
+ }
+}
unsigned char digest[16];
int i;
- printf("\n");
/* Compute final MD5 digest */
MD5_Final(digest, &sock->context);
- printf(HTML_MD5);
- print_buffer(16, digest);
-
- printf(HTML_MD5_FINAL);
+ if (req->verbose) {
+ printf("\n");
+ printf(HTML_MD5);
+ print_buffer(16, digest);
+
+ printf(HTML_MD5_FINAL);
+ }
+ printf("MD5SUM = ");
for (i = 0; i < 16; i++)
printf("%02x", digest[i]);
printf("\n\n");
sock->total_size += r;
if (!sock->extracted) {
- printf(HTTP_HEADER_HEXA);
+ if (req->verbose)
+ printf(HTTP_HEADER_HEXA);
if ((sock->extracted =
extract_html(sock->buffer, sock->size))) {
- print_buffer(sock->extracted - sock->buffer, sock->buffer);
- printf(HTTP_HEADER_ASCII);
- for (r = 0; r < sock->extracted - sock->buffer; r++)
- printf("%c", sock->buffer[r]);
- printf("\n");
-
- printf(HTML_HEADER_HEXA);
+ if (req->verbose) {
+ print_buffer(sock->extracted - sock->buffer, sock->buffer);
+ printf(HTTP_HEADER_ASCII);
+ for (r = 0; r < sock->extracted - sock->buffer; r++)
+ printf("%c", sock->buffer[r]);
+ printf("\n");
+ printf(HTML_HEADER_HEXA);
+ }
r = sock->size - (sock->extracted - sock->buffer);
if (r) {
- print_buffer(r, sock->extracted);
+ if (req->verbose)
+ print_buffer(r, sock->extracted);
memcpy(sock->buffer, sock->extracted, r);
MD5_Update(&sock->context, sock->buffer,
r);
}
}
} else if (sock->size) {
- print_buffer(r, sock->buffer);
+ if (req->verbose)
+ print_buffer(r, sock->buffer);
MD5_Update(&sock->context, sock->buffer,
sock->size);
sock->size = 0;
/* Global variables */
REQ *req; /* Cmd line arguments */
+unsigned int debug;
/* Data buffer length description */
#define BUFSIZE 1024
Name: keepalived
Summary: HA monitor built upon LVS, VRRP and services poller
Packager: Christophe Varoqui, <christophe.varoqui@free.fr>
-Version: 1.0.3
+Version: 1.1.0
Release: 1
Source: http://www.keepalived.org/software/%{name}-%{version}.tar.gz
Copyright: GPL
SUBDIRS = core
ifeq ($(IPVS_FLAG),_WITH_LVS_)
- SUBDIRS += healthcheck
+ SUBDIRS += check
endif
ifeq ($(VRRP_FLAG),_WITH_VRRP_)
@echo ""
@echo "Make complete"
+profile:
+ @set -e; \
+ for i in $(SUBDIRS); do \
+ $(MAKE) -C $$i || exit 1; done && \
+ echo "Building $(BIN)/$(EXEC)" && \
+ $(CC) -o $(BIN)/$(EXEC) $(LDFLAGS) -pg `find $(SUBDIRS) ../lib -name '*.[oa]'`
+ @echo ""
+ @echo "Make complete"
+
clean:
@set -e; \
for i in $(SUBDIRS); do \
../include/check_parser.h ../include/check_data.h ../include/check_api.h \
../include/global_data.h ../include/ipwrapper.h ../include/pidfile.h \
../include/daemon.h ../../lib/list.h ../../lib/memory.h \
- ../../lib/parser.h ../../lib/watchdog.h
+ ../../lib/parser.h ../../lib/watchdog.h ../include/vrrp_netlink.h \
+ ../include/vrrp_if.h
check_data.o: check_data.c ../include/check_data.h \
../include/check_api.h ../../lib/memory.h ../../lib/utils.h
check_parser.o: check_parser.c ../include/check_parser.h \
*
* Part: Checkers registration.
*
- * Version: $Id: check_api.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_api.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* External vars */
extern thread_master *master;
extern check_conf_data *check_data;
+extern unsigned int debug;
/* free checker data */
static void
element e;
/* Display netlink operation */
- syslog(LOG_INFO, "Netlink reflector reports IP %s %s",
- inet_ntop2(address), (enable) ? "added" : "removed");
+ if (debug & 32)
+ syslog(LOG_INFO, "Netlink reflector reports IP %s %s",
+ inet_ntop2(address), (enable) ? "added" : "removed");
/* Processing Healthcheckers queue */
if (!LIST_ISEMPTY(checkers_queue))
*
* Part: CI-LINUX checker. Integration to Compaq Cluster Infrastructure.
*
- * Version: $Id: check_ci.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_ci.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Aneesh Kumar K.V, <aneesh.kumar@digital.com>
*
* Part: Healthcheckrs child process handling.
*
- * Version: $Id: check_daemon.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_daemon.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "memory.h"
#include "parser.h"
#include "watchdog.h"
+#include "vrrp_netlink.h"
+#include "vrrp_if.h"
/* Global vars */
check_conf_data *check_data;
extern pid_t checkers_child;
extern char *conf_file;
extern int init_ssl_ctx(void);
+extern int wdog_delay_check;
/* Daemon stop sequence */
static void
/* Clean data */
free_global_data(data);
free_check_data(check_data);
+ free_interface_queue();
#ifdef _DEBUG_
keepalived_free_final("Healthcheck child process");
{
/* Initialize sub-system */
init_checkers_queue();
+ init_interface_queue();
+ kernel_netlink_init();
/* Parse configuration file */
data = alloc_global_data();
signal_set(SIGINT, sigend_check);
signal_set(SIGTERM, sigend_check);
signal_set(SIGKILL, sigend_check);
- signal_set(SIGCHLD, sigchld);
+ signal_noignore_sigchld();
}
/* Register VRRP thread */
, strerror(errno));
return -1;
} else if (pid) {
+ int poll_delay = (wdog_delay_check) ? wdog_delay_check : WATCHDOG_DELAY;
checkers_child = pid;
syslog(LOG_INFO, "Starting Healthcheck child process, pid=%d"
, pid);
/* Connect child watchdog */
check_wdog_data.wdog_pid = pid;
thread_add_timer(master, wdog_boot_thread, &check_wdog_data,
- WATCHDOG_DELAY);
+ poll_delay);
return 0;
}
*
* Part: Healthcheckers dynamic data structure definition.
*
- * Version: $Id: check_data.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_data.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
FREE_PTR(vs->vsgname);
FREE_PTR(vs->virtualhost);
FREE_PTR(vs->s_svr);
- if (!LIST_ISEMPTY(vs->rs))
- free_list(vs->rs);
+ free_list(vs->rs);
FREE(vs);
}
static void
, ntohs(SVR_PORT(vs)));
if (vs->virtualhost)
syslog(LOG_INFO, " VirtualHost = %s", vs->virtualhost);
- syslog(LOG_INFO, " delay_loop = %d, lb_algo = %s", vs->delay_loop,
+ syslog(LOG_INFO, " delay_loop = %lu, lb_algo = %s",
+ (vs->delay_loop >= TIMER_MAX_SEC) ? vs->delay_loop/TIMER_HZ :
+ vs->delay_loop,
vs->sched);
if (atoi(vs->timeout_persistence) > 0)
syslog(LOG_INFO, " persistence timeout = %s",
*
* Part: WEB CHECK. Common HTTP/SSL checker primitives.
*
- * Version: $Id: check_http.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_http.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
http_arg *http_arg = HTTP_ARG(http_get_check);
REQ *req = HTTP_REQ(http_arg);
uint16_t addr_port = get_service_port(checker);
- int delay = 0;
+ long delay = 0;
if (method) {
http_arg->url_it += t ? t : -http_arg->url_it;
* Part: MISC CHECK. Perform a system call to run an extra
* system prog or script.
*
- * Version: $Id: check_misc.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_misc.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
+ * Bradley Baetz, <bradley.baetz@optusnet.com.au>
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "utils.h"
#include "parser.h"
#include "notify.h"
+#include "daemon.h"
int misc_check_thread(thread *);
+int misc_check_child_thread(thread *);
+int misc_check_child_timeout_thread(thread *);
/* Configuration stream handling */
void
syslog(LOG_INFO, " Keepalive method = MISC_CHECK");
syslog(LOG_INFO, " script = %s", misc_chk->path);
+ syslog(LOG_INFO, " timeout = %d", misc_chk->timeout);
}
void
misc_path_handler(vector strvec)
{
misc_checker *misc_chk = CHECKER_GET();
-
misc_chk->path = CHECKER_VALUE_STRING(strvec);
}
void
+misc_timeout_handler(vector strvec)
+{
+ misc_checker *misc_chk = CHECKER_GET();
+ misc_chk->timeout = CHECKER_VALUE_INT(strvec);
+}
+
+void
install_misc_check_keyword(void)
{
install_keyword("MISC_CHECK", &misc_check_handler);
install_sublevel();
install_keyword("misc_path", &misc_path_handler);
+ install_keyword("misc_timeout", &misc_timeout_handler);
install_sublevel_end();
}
}
/* In case of this is parent process */
- if (pid)
+ if (pid) {
+ long timeout;
+ timeout = (misc_chk->timeout) ? misc_chk->timeout : checker->vs->delay_loop;
+
+ thread_add_child(thread->master, misc_check_child_thread,
+ checker, pid, timeout);
return 0;
+ }
/* Child part */
closeall(0);
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(misc_chk->path);
- if (status >= 0) { /* script error assumed not an svr error */
+ if (status < 0 || !WIFEXITED(status))
+ status = 0; /* Script errors aren't server errors */
+ else
+ status = WEXITSTATUS(status);
+
+ exit(status);
+}
+
+int
+misc_check_child_thread(thread * thread)
+{
+ int wait_status;
+ checker *checker;
+ misc_checker *misc_chk;
+
+ checker = THREAD_ARG(thread);
+ misc_chk = CHECKER_ARG(checker);
+
+ if (thread->type == THREAD_CHILD_TIMEOUT) {
+ pid_t pid;
+
+ pid = THREAD_CHILD_PID(thread);
+
+ /* The child hasn't responded. Kill it off. */
+ if (ISALIVE(checker->rs)) {
+ syslog(LOG_INFO, "Misc check to [%s] for [%s] timed out",
+ inet_ntop2(CHECKER_RIP(checker)),
+ misc_chk->path);
+ smtp_alert(thread->master, checker->rs, NULL, NULL,
+ "DOWN",
+ "=> MISC CHECK script timeout on service <=");
+ perform_svr_state(DOWN, checker->vs, checker->rs);
+ }
+
+ kill(pid, SIGTERM);
+ thread_add_child(thread->master, misc_check_child_timeout_thread,
+ checker, pid, 2);
+ return 0;
+ }
+
+ wait_status = THREAD_CHILD_STATUS(thread);
+
+ if (WIFEXITED(wait_status)) {
+ int status;
+ status = WEXITSTATUS(wait_status);
if (status == 0) {
/* everything is good */
if (!ISALIVE(checker->rs)) {
+ syslog(LOG_INFO, "Misc check to [%s] for [%s] success.",
+ inet_ntop2(CHECKER_RIP(checker)),
+ misc_chk->path);
smtp_alert(thread->master, checker->rs, NULL, NULL,
"UP",
"=> MISC CHECK succeed on service <=");
- perform_svr_state(UP, checker->vs, checker->rs);
}
} else {
if (ISALIVE(checker->rs)) {
+ syslog(LOG_INFO, "Misc check to [%s] for [%s] failed.",
+ inet_ntop2(CHECKER_RIP(checker)),
+ misc_chk->path);
smtp_alert(thread->master, checker->rs, NULL, NULL,
"DOWN",
"=> MISC CHECK failed on service <=");
- perform_svr_state(DOWN, checker->vs, checker->rs);
}
}
}
- exit(0);
+ return 0;
+}
+
+int
+misc_check_child_timeout_thread(thread * thread)
+{
+ pid_t pid;
+
+ if (thread->type != THREAD_CHILD_TIMEOUT)
+ return 0;
+
+ /* OK, it still hasn't exited. Now really kill it off. */
+ pid = THREAD_CHILD_PID(thread);
+ 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;
}
* data structure representation the conf file representing
* the loadbalanced server pool.
*
- * Version: $Id: check_parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_parser.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
delay_handler(vector strvec)
{
virtual_server *vs = LIST_TAIL_DATA(check_data->vs);
- vs->delay_loop = atoi(VECTOR_SLOT(strvec, 1));
+ vs->delay_loop = atoi(VECTOR_SLOT(strvec, 1)) * TIMER_HZ;
}
static void
lbalgo_handler(vector strvec)
* url, compute a MD5 over this result and match it to the
* expected value.
*
- * Version: $Id: check_ssl.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_ssl.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Jan Holmberg, <jan@artech.net>
*
* Part: TCP checker.
*
- * Version: $Id: check_tcp.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_tcp.c,v 1.1.0 2003/07/20 23:41:34 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.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: ipfwwrapper.c,v 1.1.0 2003/07/20 23:41:34 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.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: ipvswrapper.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
urule->weight = 0;
cmd = IP_VS_SO_SET_EDITDEST;
}
- if (cmd == IP_VS_SO_SET_ADDDEST && rs->inhibit && !rs->alive)
+ if (cmd == IP_VS_SO_SET_ADDDEST && rs->inhibit && rs->set)
cmd = IP_VS_SO_SET_EDITDEST;
+ /* Set flag */
+ if (cmd == IP_VS_SO_SET_ADDDEST && !rs->set)
+ rs->set = 1;
+ if (cmd == IP_VS_SO_SET_DELDEST && rs->set)
+ rs->set = 0;
+
/* Set vs rule and send to kernel */
if (vs->vsgname) {
err = ipvs_group_cmd(cmd, vs_group, rs, urule, vs->vsgname);
*
* Part: Manipulation functions for IPVS & IPFW wrappers.
*
- * Version: $id: ipwrapper.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $id: ipwrapper.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* already set IPVS rule.
*/
rs->alive = old_rs->alive;
+ rs->set = old_rs->set;
return 1;
}
}
{
element e;
list l = check_data->vs;
- virtual_server *vsrv;
+ virtual_server *vsvr;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
- vsrv = ELEMENT_DATA(e);
- if (VS_ISEQ(vs, vsrv))
- return vsrv->rs;
+ vsvr = ELEMENT_DATA(e);
+ if (VS_ISEQ(vs, vsvr))
+ return vsvr->rs;
}
/* most of the time never reached */
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: main.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* stuck waiting child termination.
*/
void
-sigchld(int sig)
+dummy_handler(int sig)
{
- while (waitpid(-1, NULL, WNOHANG) > 0);
+ /* Dummy */
+}
+
+void
+signal_noignore_sigchld(void)
+{
+ struct sigaction sa;
+ sigset_t mask;
+
+ /* Need to remove the NOCHLD flag */
+ sigemptyset(&mask);
+ sa.sa_handler = dummy_handler;
+ sa.sa_mask = mask;
+ sa.sa_flags = 0;
+
+ sigaction(SIGCHLD, &sa, NULL);
+
+ /* Block SIGCHLD so that we only receive it
+ * when required (ie when its unblocked in the
+ * select loop)
+ */
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_BLOCK, &mask, NULL);
}
/* Signal wrapper */
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: global_data.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: global_data.c,v 1.1.0 2003/07/20 23:41:34 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.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: global_parser.c,v 1.1.0 2003/07/20 23:41:34 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.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: layer4.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Main program structure.
*
- * Version: $Id: main.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: main.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
sigend(int sig)
{
int status;
+ sigset_t mask;
/* register the terminate thread */
syslog(LOG_INFO, "Terminating on signal");
thread_add_terminate_event(master);
- /* Signal child process */
+ /*
+ * Signal child process.
+ * Disable and unblock the SIGCHLD handler
+ * so that wait() works.
+ */
+ signal_ignore(SIGCHLD);
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ sigprocmask(SIG_UNBLOCK, &mask, NULL);
+
if (vrrp_child > 0) {
kill(vrrp_child, SIGTERM);
- wait(&status);
+ waitpid(vrrp_child, &status, WNOHANG);
}
if (checkers_child > 0) {
kill(checkers_child, SIGTERM);
- wait(&status);
+ waitpid(checkers_child, &status, WNOHANG);
}
}
signal_set(SIGINT, sigend);
signal_set(SIGTERM, sigend);
signal_set(SIGKILL, sigend);
- signal_set(SIGCHLD, sigchld);
+ signal_noignore_sigchld();
}
/* Usage function */
" %s --dont-fork -n Dont fork the daemon process.\n"
" %s --use-file -f Use the specified configuration file.\n"
" Default is /etc/keepalived/keepalived.conf.\n"
+ " %s --wdog-vrrp -R Define VRRP watchdog polling delay. (default=5s)\n"
+ " %s --wdog-check -H Define checkers watchdog polling delay. (default=5s)\n"
" %s --dump-conf -d Dump the configuration data.\n"
" %s --log-console -l Log message to local console.\n"
+ " %s --log-detail -D Detailed log messages.\n"
" %s --help -h Display this short inlined help screen.\n"
" %s --version -v Display the version number\n",
- prog, prog, prog, prog, prog, prog, prog, prog);
+ prog, prog, prog, prog, prog, prog, prog, prog, prog, prog, prog);
}
/* Command line parser */
{"version", 'v', POPT_ARG_NONE, NULL, 'v'},
{"help", 'h', POPT_ARG_NONE, NULL, 'h'},
{"log-console", 'l', POPT_ARG_NONE, NULL, 'l'},
+ {"log-detail", 'D', POPT_ARG_NONE, NULL, 'D'},
{"dont-release-vrrp", 'V', POPT_ARG_NONE, NULL, 'V'},
{"dont-release-ipvs", 'I', POPT_ARG_NONE, NULL, 'I'},
{"dont-fork", 'n', POPT_ARG_NONE, NULL, 'n'},
{"dump-conf", 'd', POPT_ARG_NONE, NULL, 'd'},
{"use-file", 'f', POPT_ARG_STRING, &optarg, 'f'},
+ {"wdog-vrrp", 'R', POPT_ARG_STRING, &optarg, 'R'},
+ {"wdog-check", 'H', POPT_ARG_STRING, &optarg, 'H'},
{NULL, 0, 0, NULL, 0}
};
case 'I':
debug |= 16;
break;
+ case 'D':
+ debug |= 32;
+ break;
case 'f':
conf_file = optarg;
break;
+ case 'R':
+ wdog_delay_vrrp = atoi(optarg);
+ break;
+ case 'H':
+ wdog_delay_check = atoi(optarg);
+ break;
}
/* the others */
case 'I':
debug |= 16;
break;
+ case 'D':
+ debug |= 32;
+ break;
case 'f':
conf_file = optarg;
break;
+ case 'R':
+ wdog_delay_vrrp = atoi(optarg);
+ break;
+ case 'H':
+ wdog_delay_check = atoi(optarg);
+ break;
}
}
*
* Part: pidfile utility.
*
- * Version: $Id: pidfile.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: pidfile.c,v 1.1.0 2003/07/20 23:41:34 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.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: smtp.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
case "$1" in
start)
echo -n "Starting Keepalived for LVS: "
- keepalived
+ keepalived -D
touch /var/lock/subsys/keepalived
echo
;;
kill $PID
echo
echo -n "Starting Keepalived for LVS: "
- keepalived
+ keepalived -D
echo
;;
reload)
--- /dev/null
+#!/bin/sh
+#
+# Startup script for the Keepalived daemon
+#
+# processname: keepalived
+# pidfile: /var/run/keepalived.pid
+# config: /etc/keepalived/keepalived.conf
+# chkconfig: 35 21 79
+# description: Start and stop Keepalived
+
+# Global definitions
+PID_FILE="/var/run/keepalived.pid"
+
+# source function library
+. /etc/init.d/functions
+
+RETVAL=0
+
+start() {
+ echo -n "Starting Keepalived for LVS: "
+ daemon keepalived -D
+ RETVAL=$?
+ echo
+ [ $RETVAL -eq 0 ] && touch /var/lock/subsys/keepalived
+ return $RETVAL
+}
+
+stop() {
+ echo -n "Shutting down Keepalived for LVS: "
+ killproc keepalived
+ RETVAL=0
+ echo
+ [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/keepalived
+ return $RETVAL
+}
+
+reload() {
+ echo -n "Reloading Keepalived config: "
+ killproc keepalived -1
+ RETVAL=$?
+ echo
+ return $RETVAL
+}
+
+# See how we were called.
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ stop
+ start
+ ;;
+ reload)
+ reload
+ ;;
+ status)
+ status keepalived
+ ;;
+ condrestart)
+ [ -f /var/lock/subsys/keepalived ] && $0 restart || :
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|reload|condrestart|status}"
+ exit 1
+esac
+
+exit 0
+++ /dev/null
-# Generated automatically from Makefile.in by configure.
-# Makefile
-#
-# Keepalived OpenSource project.
-#
-# Copyright (C) 2001, 2002, 2003 Alexandre Cassen, <acassen@linux-vs.org>
-
-KERNEL = _KRNL_2_4_
-CC = gcc
-CI_LINUX =
-ifeq ($(CI_LINUX),_WITH_CI_LINUX_)
-CI_LINUX_OBJ = check_ci.o
-CIFLAGS = -D$(CI_LINUX)
-endif
-INCLUDES = -I../include -I../../lib
-CFLAGS = -g -O2 -I/usr/src/linux/include $(INCLUDES) \
- -Wall -Wunused -Wstrict-prototypes
-DEFS = -D$(KERNEL) -D_WITH_LVS_ -D_HAVE_IPVS_SYNCD_ -D_WITH_VRRP_ $(CIFLAGS)
-COMPILE = $(CC) $(CFLAGS) $(DEFS)
-
-OBJS = check_daemon.o check_data.o check_parser.o \
- check_api.o check_tcp.o check_http.o check_ssl.o \
- check_misc.o ipwrapper.o ipvswrapper.o $(CI_LINUX_OBJ)
-
-ifeq ($(KERNEL),_KRNL_2_2_)
- OBJS += ipfwwrapper.o
- HEADERS += ipfwwrapper.h
-endif
-
-HEADERS = $(OBJS:.o=.h)
-
-.c.o:
- $(COMPILE) -c $<
-
-all: $(OBJS)
-
-clean:
- rm -f *.a *.o *~
-
-distclean: clean
- rm -f Makefile
-
-check_daemon.o: check_daemon.c ../include/check_daemon.h \
- ../include/check_parser.h ../include/check_data.h ../include/check_api.h \
- ../include/global_data.h ../include/ipwrapper.h ../include/pidfile.h \
- ../include/daemon.h ../../lib/list.h ../../lib/memory.h \
- ../../lib/parser.h ../../lib/watchdog.h
-check_data.o: check_data.c ../include/check_data.h \
- ../include/check_api.h ../../lib/memory.h ../../lib/utils.h
-check_parser.o: check_parser.c ../include/check_parser.h \
- ../include/check_data.h ../include/check_api.h ../include/global_data.h \
- ../include/global_parser.h ../../lib/parser.h ../../lib/memory.h \
- ../../lib/utils.h
-check_api.o: check_api.c ../include/check_api.h ../../lib/parser.h \
- ../../lib/memory.h ../../lib/utils.h ../include/check_misc.h \
- ../include/check_tcp.h ../include/check_http.h ../include/check_ssl.h
-check_tcp.o: check_tcp.c ../include/check_tcp.h ../include/check_api.h \
- ../../lib/memory.h ../include/ipwrapper.h ../include/layer4.h \
- ../include/smtp.h ../../lib/utils.h ../../lib/parser.h
-check_http.o: check_http.c ../include/check_http.h ../include/check_ssl.h \
- ../include/check_api.h ../../lib/memory.h ../../lib/parser.h \
- ../../lib/utils.h
-check_ssl.o: check_ssl.c ../include/check_ssl.h ../include/check_api.h \
- ../../lib/memory.h ../../lib/parser.h ../include/smtp.h \
- ../../lib/utils.h
-check_misc.o: check_misc.c ../include/check_misc.h ../include/check_api.h \
- ../../lib/memory.h ../include/ipwrapper.h ../include/smtp.h \
- ../../lib/utils.h ../../lib/notify.h ../../lib/parser.h ../include/daemon.h
-ipwrapper.o: ipwrapper.c ../include/ipwrapper.h ../../lib/utils.h \
- ../../lib/notify.h
-ipvswrapper.o: ipvswrapper.c ../include/ipvswrapper.h ../../lib/utils.h \
- ../../lib/memory.h
*
* Part: Checkers arguments structures definitions.
*
- * Version: $Id: check_api.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_api.h,v 1.1.0 2003/07/20 23:41:34 ACAssen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: check_ci.c include file.
*
- * Version: $Id: check_ci.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_ci.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Authors: Alexandre Cassen, <acassen@linux-vs.org>
* Aneesh Kumar K.V, <aneesh.kumar@digital.com>
*
* Part: check_daemon.c include file.
*
- * Version: $Id: check_daemon.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_daemon.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Healthcheckers dynamic data structure definition.
*
- * Version: $Id: check_data.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_data.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
char *notify_up; /* Script to launch when RS is added to LVS */
char *notify_down; /* Script to launch when RS is removed from LVS */
int alive;
+ int set; /* in the IPVS table */
} real_server;
/* Virtual Server group definition */
uint16_t addr_port;
uint32_t vfwmark;
uint16_t service_type;
- int delay_loop;
+ long delay_loop;
int ha_suspend;
char sched[SCHED_MAX_LENGTH];
char timeout_persistence[MAX_TIMEOUT_LENGTH];
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_http.h,v 1.1.0 2003/07/20 23:41:34 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.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_misc.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
* Eric Jarman, <ehj38230@cmsu2.cmsu.edu>
/* Checker argument structure */
typedef struct _misc_checker {
char *path;
+ int timeout;
} misc_checker;
/* Prototypes defs */
*
* Part: check_parser.c include file.
*
- * Version: $Id: check_parser.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_parser.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: check_http.c include file.
*
- * Version: $Id: check_http.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_http.h,v 1.1.0 2003/07/20 23:41:34 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.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: check_tcp.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Daemon process handling.
*
- * Version: $Id: daemon.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: daemon.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
+#include <signal.h>
/* prototype */
extern pid_t xdaemon(int, int, int);
-extern void sigchld(int sig);
extern void *signal_set(int signo, void (*func) (int));
extern void *signal_ignore(int signo);
+extern void signal_noignore_sigchld(void);
#endif
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: global_data.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: global_data.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_parser.c include file.
*
- * Version: $Id: global_parser.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: global_parser.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipfwwrapper.c include file.
*
- * Version: $Id: ipfwwrapper.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: ipfwwrapper.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipvswrapper.c include file.
*
- * Version: $Id: ipvswrapper.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: ipvswrapper.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: ipwrapper.c include file.
*
- * Version: $Id: ipwrapper.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: ipwrapper.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: layer4.c include file.
*
- * Version: $Id: layer4.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: layer4.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Main program include file.
*
- * Version: $Id: main.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: main.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
unsigned int debug; /* Debugging flags */
pid_t vrrp_child = -1; /* VRRP child process ID */
pid_t checkers_child = -1; /* Healthcheckers child process ID */
+int wdog_delay_vrrp = 0; /* VRRP child polling delay */
+int wdog_delay_check = 0; /* Healthchecker child polling delay */
conf_data *data; /* Global configuration data */
/* Build version */
#define PROG "Keepalived"
-#define VERSION_CODE 0x010003
-#define DATE_CODE 0x0C0503
+#define VERSION_CODE 0x010100
+#define DATE_CODE 0x140703
#define KEEPALIVED_VERSION(version) \
(version >> 16) & 0xFF, \
*
* Part: pidfile.c include file.
*
- * Version: $Id: pidfile.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: pidfile.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: smtp.c include file.
*
- * Version: $Id: smtp.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: smtp.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* global defs */
#define SMTP_PORT 25
-#define SMTP_BUFFER_LENGTH 128
-#define SMTP_BUFFER_MAX 256
+#define SMTP_BUFFER_LENGTH 512
+#define SMTP_BUFFER_MAX 1024
#define SMTP_MAX_FSM_STATE 10
/* SMTP command stage */
*
* Part: vrrp.c program include file.
*
- * Version: $Id: vrrp.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_iproute.h"
#include "vrrp_ipsecah.h"
#include "vrrp_if.h"
+#include "vrrp_track.h"
#include "timer.h"
#include "utils.h"
#include "vector.h"
typedef struct _vrrp_sgroup {
char *gname; /* Group name */
vector iname; /* Set of VRRP instances in this group */
+ list index; /* List of VRRP instances */
int state; /* current stable state */
/* State transition notification */
/* parameters per virtual router -- rfc2338.6.1.2 */
typedef struct _vrrp_rt {
char *iname; /* Instance Name */
- vrrp_sgroup *sync;
+ vrrp_sgroup *sync; /* Sync group we belong to */
interface *ifp; /* Interface we belong to */
- interface *track_ifp; /* Interface state we monitor */
+ list track_ifp; /* Interface 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 state; /* internal state (init/backup/master) */
int init_state; /* the initial state of the instance */
int wantstate; /* user explicitly wants a state (back/mast) */
- int fd; /* the socket descriptor */
+ int fd_in; /* IN socket descriptor */
+ int fd_out; /* OUT socket descriptor */
int debug; /* Debug level 0-4 */
uint32_t ms_down_timer;
struct timeval sands;
+ /* Sending buffer */
+ char *send_buffer; /* Allocated send buffer */
+ int send_buffer_size;
+
/* Authentication data */
int auth_type; /* authentification type. VRRP_AUTH_* */
uint8_t auth_data[8]; /* authentification data */
/* VRRP Packet fixed lenght */
#define VRRP_MAX_VIP 20
-#define VRRP_PACKET_TEMP_LEN 512
+#define VRRP_PACKET_TEMP_LEN 1024
#define VRRP_AUTH_LEN 8
#define VRRP_VIP_TYPE (1 << 0)
#define VRRP_EVIP_TYPE (1 << 1)
#define VRRP_IS_BAD_PRIORITY(p) ((p)<1 || (p)>255) /* rfc2338.6.1.prio */
#define VRRP_IS_BAD_ADVERT_INT(d) ((d)<1)
#define VRRP_IS_BAD_DEBUG_INT(d) ((d)<0 || (d)>4)
+#define VRRP_SEND_BUFFER(V) ((V)->send_buffer)
+#define VRRP_SEND_BUFFER_SIZE(V) ((V)->send_buffer_size)
-#define VRRP_TIMER_SKEW(srv) ((256-(srv)->priority)*TIMER_HZ/256)
+#define VRRP_TIMER_SKEW(svr) ((256-(svr)->priority)*TIMER_HZ/256)
#define VRRP_VIP_ISSET(V) ((V)->vipset)
#define VRRP_MIN(a, b) ((a) < (b)?(a):(b))
#define VRRP_PKT_SADDR(V) (((V)->mcast_saddr) ? (V)->mcast_saddr : IF_ADDR((V)->ifp))
-#define VRRP_ISUP(V) (IF_ISUP((V)->ifp) & (((V)->track_ifp) ? IF_ISUP((V)->track_ifp) : 1))
+#define VRRP_ISUP(V) (IF_ISUP((V)->ifp) & \
+ ((!LIST_ISEMPTY((V)->track_ifp)) ? TRACK_ISUP((V)->track_ifp) : 1))
/* prototypes */
+extern int open_vrrp_send_socket(const int proto, const int index);
extern int open_vrrp_socket(const int proto, const int index);
extern int new_vrrp_socket(vrrp_rt * vrrp);
extern void close_vrrp_socket(vrrp_rt * vrrp);
*
* Part: vrrp_arp.c include file.
*
- * Version: $Id: vrrp_arp.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_arp.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local includes */
#include "vrrp.h"
+#include "vrrp_ipaddress.h"
/* local definitions */
#define ETHERNET_HW_LEN 6
unsigned char __ar_tip[4]; /* Target IP address. */
} m_arphdr;
+/* Global var */
+char *garp_buffer;
+int garp_fd;
+
/* prototypes */
-extern int send_gratuitous_arp(vrrp_rt * vrrp, int addr);
+extern void gratuitous_arp_init(void);
+extern void gratuitous_arp_close(void);
+extern int send_gratuitous_arp(ip_address *ipaddress);
#endif
*
* Part: vrrp_daemon.c include file.
*
- * Version: $Id: vrrp_daemon.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_daemon.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: vrrp_data.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_data.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* Configuration data root */
typedef struct _vrrp_conf_data {
+ list static_addresses;
list static_routes;
list vrrp_sync_group;
list vrrp;
+ list vrrp_index;
+ list vrrp_index_fd;
} vrrp_conf_data;
+/* Global Vars */
+char *vrrp_buffer;
+
/* prototypes */
+extern void alloc_saddress(vector strvec);
extern void alloc_sroute(vector strvec);
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_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.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_if.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: vrrp_index.c include file.
+ *
+ * Version: $Id: vrrp_index.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
+ *
+ * Author: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _VRRP_INDEX_H
+#define _VRRP_INDEX_H
+
+/* global includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <syslog.h>
+
+/* local includes */
+#include "vrrp.h"
+
+/* Macro definition */
+
+/* prototypes */
+extern void alloc_vrrp_bucket(vrrp_rt *vrrp);
+extern void alloc_vrrp_fd_bucket(vrrp_rt *vrrp);
+extern void remove_vrrp_fd_bucket(vrrp_rt *vrrp);
+extern void set_vrrp_fd_bucket(int old_fd, vrrp_rt *vrrp);
+extern vrrp_rt *vrrp_index_lookup(const int vrid, const int fd);
+
+#endif
*
* Part: vrrp_ipaddress.c include file.
*
- * Version: $Id: vrrp_ipaddress.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include <syslog.h>
/* local includes */
+#include "vrrp_if.h"
#include "list.h"
#include "vector.h"
typedef struct {
uint32_t addr; /* the ip address */
uint8_t mask; /* the ip address CIDR netmask */
- int ifindex; /* Interface owning IP address */
+ interface *ifp; /* Interface owning IP address */
int scope; /* the ip address scope */
int set; /* TRUE if addr is set */
} ip_address;
#define IPADDRESS_DEL 0
#define IPADDRESS_ADD 1
+#define DFLT_INT "eth0"
/* Macro definition */
-#define IP_ISEQ(X,Y) ((X)->addr == (Y)->addr && \
- (X)->mask == (Y)->mask && \
- (X)->ifindex == (Y)->ifindex && \
- (X)->scope == (Y)->scope)
+#define IP_ISEQ(X,Y) ((X)->addr == (Y)->addr && \
+ (X)->mask == (Y)->mask && \
+ IF_INDEX((X)->ifp) == IF_INDEX((Y)->ifp) && \
+ (X)->scope == (Y)->scope)
/* prototypes */
extern int netlink_address_ipv4(ip_address *ipaddr, int cmd);
extern void netlink_iplist_ipv4(list ip_list, int cmd);
extern void free_ipaddress(void *data);
extern void dump_ipaddress(void *data);
-extern void alloc_ipaddress(list ip_list, vector strvec, int ifindex);
+extern void alloc_ipaddress(list ip_list, vector strvec, interface *ifp);
extern void clear_diff_address(list l, list n);
+extern void clear_diff_saddresses(void);
#endif
*
* Part: vrrp_iproute.c include file.
*
- * Version: $Id: vrrp_iproute.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_iproute.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* prototypes */
extern int netlink_route_ipv4(ip_route *iproute, int cmd);
extern void netlink_rtlist_ipv4(list rt_list, int cmd);
-extern void free_route(void *data);
-extern void dump_route(void *data);
+extern void free_iproute(void *data);
+extern void dump_iproute(void *data);
extern void alloc_route(list rt_list, vector strvec);
extern void clear_diff_routes(list l, list n);
extern void clear_diff_sroutes(void);
*
* Part: vrrp_ipsecah.c include file.
*
- * Version: $Id: vrrp_ipsecah.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_netlink.c include file.
*
- * Version: $Id: vrrp_netlink.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_netlink.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* Define types */
#define NETLINK_TIMER 30
-/* Our global netlink reflection handler */
-struct nl_handle nl_kernel;
+/* Our global netlink handler */
+struct nl_handle nl_kernel; /* Kernel reflection channel */
+struct nl_handle nl_cmd; /* Command channel */
/* prototypes */
extern int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data);
*
* Part: vrrp_notify.c include file.
*
- * Version: $Id: vrrp_notify.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_notify.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_parser.c include file.
*
- * Version: $Id: vrrp_parser.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_parser.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: vrrp_scheduler.c include file.
*
- * Version: $Id: vrrp_scheduler.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_scheduler.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
typedef struct {
int ifindex;
int proto;
- int fd;
+ int fd_in;
+ int fd_out;
} sock;
/* VRRP FSM Macro */
*
* Part: vrrp_sync.c include file.
*
- * Version: $Id: vrrp_sync.h,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_sync.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* extern prototypes */
extern void vrrp_init_instance_sands(vrrp_rt *);
-extern vrrp_sgroup *vrrp_get_sync_group(char *);
extern void vrrp_sync_set_group(vrrp_sgroup *);
extern int vrrp_sync_group_up(vrrp_sgroup *);
extern int vrrp_sync_leave_fault(vrrp_rt *);
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: vrrp_track.c include file.
+ *
+ * Version: $Id: vrrp_track.h,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
+ *
+ * Author: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _VRRP_TRACK_H
+#define _VRRP_TRACK_H
+
+/* global includes */
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <syslog.h>
+
+/* local includes */
+#include "vector.h"
+#include "list.h"
+
+/* Macro definition */
+#define TRACK_ISUP(L) (vrrp_tracked_up((L)))
+
+/* prototypes */
+extern void dump_track(void *data);
+extern void alloc_track(list track_list, vector strvec);
+extern int vrrp_tracked_up(list l);
+extern void vrrp_log_tracked_down(list l);
+
+#endif
+++ /dev/null
-# Generated automatically from Makefile.in by configure.
-# Makefile to make libipvsc.
-
-CC = gcc
-CFLAGS = -g -O2 -I/usr/src/linux/include -Wall -Wunused
-
-export OBJS += libipvs.a
-
-all: libipvs.a
-
-libipvs.a: libipvs.a(libipvs.o)
-
-libipvsc.o: libipvs.h
-
-clean:
- rm -f *.a *.o *~
-
-distclean: clean
- rm -f Makefile
COMPILE = $(CC) $(CFLAGS) $(DEFS)
OBJS = vrrp_daemon.o vrrp_data.o vrrp_parser.o \
- vrrp.o vrrp_notify.o vrrp_scheduler.o vrrp_sync.o vrrp_netlink.o \
- vrrp_arp.o vrrp_if.o vrrp_ipaddress.o vrrp_iproute.o vrrp_ipsecah.o
+ vrrp.o vrrp_notify.o vrrp_scheduler.o vrrp_sync.o vrrp_index.o \
+ vrrp_netlink.o vrrp_arp.o vrrp_if.o vrrp_track.o vrrp_ipaddress.o \
+ vrrp_iproute.o vrrp_ipsecah.o
HEADERS = $(OBJS:.o=.h)
.c.o:
rm -f Makefile
vrrp_daemon.o: vrrp_daemon.c ../include/vrrp_daemon.h ../include/vrrp_scheduler.h \
- ../include/vrrp_if.h ../include/vrrp_netlink.h ../include/vrrp_iproute.h \
- ../include/vrrp_parser.h ../include/vrrp_data.h ../include/vrrp.h \
- ../include/global_data.h ../include/pidfile.h ../include/daemon.h \
+ ../include/vrrp_if.h ../include/vrrp_arp.h ../include/vrrp_netlink.h ../include/vrrp_iproute.h \
+ ../include/vrrp_iproute.h ../include/vrrp_parser.h ../include/vrrp_data.h \
+ ../include/vrrp.h ../include/global_data.h ../include/pidfile.h ../include/daemon.h \
../../lib/list.h ../../lib/memory.h ../../lib/parser.h ../../lib/watchdog.h
vrrp_data.o: vrrp_data.c ../include/vrrp_data.h \
- ../include/vrrp_sync.h ../include/vrrp.h ../../lib/memory.h \
+ ../include/vrrp_sync.h ../include/vrrp_index.h ../include/vrrp.h ../../lib/memory.h \
../../lib/utils.h
vrrp_parser.o: vrrp_parser.c ../include/vrrp_parser.h \
- ../include/vrrp_data.h ../include/vrrp_sync.h ../include/vrrp.h \
- ../include/global_data.h ../include/global_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 \
../../lib/parser.h ../../lib/memory.h
vrrp.o: vrrp.c ../include/vrrp.h ../include/vrrp_scheduler.h \
../include/vrrp_notify.h ../include/ipvswrapper.h ../../lib/memory.h \
- ../../lib/list.h ../include/vrrp_data.h ../include/vrrp_arp.h
+ ../../lib/list.h ../include/vrrp_data.h ../include/vrrp_sync.h ../include/vrrp_index.h \
+ ../include/vrrp_arp.h
vrrp_notify.o: vrrp_notify.c ../include/vrrp_notify.h ../../lib/memory.h \
../../lib/notify.h
vrrp_scheduler.o: vrrp_scheduler.c ../include/vrrp_scheduler.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/smtp.h
+ ../../lib/memory.h ../../lib/list.h ../include/vrrp_data.h ../include/vrrp_index.h \
+ ../include/smtp.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 \
+ ../include/vrrp_data.h ../../lib/memory.h
vrrp_netlink.o: vrrp_netlink.c ../include/vrrp_netlink.h ../include/check_api.h \
../include/vrrp_if.h ../../lib/memory.h ../../lib/scheduler.h \
../../lib/utils.h
vrrp_arp.o: vrrp_arp.c ../include/vrrp_arp.h
+vrrp_track.o: vrrp_track.c ../include/vrrp_track.h ../include/vrrp_if.h \
+ ../include/vrrp_data.h ../../lib/memory.h
vrrp_if.o: vrrp_if.c ../include/vrrp_if.h ../include/vrrp_netlink.h \
../../lib/scheduler.h ../include/vrrp_data.h ../../lib/memory.h \
../../lib/utils.h
-vrrp_ipaddress.o: vrrp_ipaddress.c ../include/vrrp_ipaddress.h \
- ../include/vrrp_netlink.h ../../lib/utils.h
-vrrp_iproute.o: vrrp_iproute.c ../include/vrrp_iproute.h \
- ../include/vrrp_netlink.h ../../lib/utils.h
+vrrp_ipaddress.o: vrrp_ipaddress.c ../include/vrrp_ipaddress.h ../include/vrrp_netlink.h \
+ ../include/vrrp_if.h ../include/vrrp_data.h ../../lib/memory.h ../../lib/utils.h
+vrrp_iproute.o: vrrp_iproute.c ../include/vrrp_iproute.h ../include/vrrp_netlink.h \
+ ../include/vrrp_if.h ../include/vrrp_data.h ../../lib/memory.h ../../lib/utils.h
vrrp_ipsecah.o: vrrp_ipsecah.c ../include/vrrp_ipsecah.h
* master fails, a backup server takes over.
* The original implementation has been made by jerome etienne.
*
- * Version: $Id: vrrp.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "ipvswrapper.h"
#include "vrrp.h"
#include "vrrp_data.h"
+#include "vrrp_sync.h"
+#include "vrrp_index.h"
#include "memory.h"
#include "list.h"
/* extern global vars */
extern vrrp_conf_data *vrrp_data;
extern vrrp_conf_data *old_vrrp_data;
+extern unsigned int debug;
/* compute checksum */
static u_short
static int
vrrp_handle_ipaddress(vrrp_rt * vrrp, int cmd, int type)
{
- syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol %s", vrrp->iname,
- (cmd == IPADDRESS_ADD) ? "setting" : "removing",
- (type == VRRP_VIP_TYPE) ? "VIPs." : "E-VIPs");
+ if (debug & 32)
+ syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol %s", vrrp->iname,
+ (cmd == IPADDRESS_ADD) ? "setting" : "removing",
+ (type == VRRP_VIP_TYPE) ? "VIPs." : "E-VIPs.");
netlink_iplist_ipv4((type == VRRP_VIP_TYPE) ? vrrp->vip : vrrp->evip
, cmd);
return 1;
static int
vrrp_handle_iproutes(vrrp_rt * vrrp, int cmd)
{
- syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol Virtual Routes",
- vrrp->iname,
- (cmd == IPROUTE_ADD) ? "setting" : "removing");
+ if (debug & 32)
+ syslog(LOG_INFO, "VRRP_Instance(%s) %s protocol Virtual Routes",
+ vrrp->iname,
+ (cmd == IPROUTE_ADD) ? "setting" : "removing");
netlink_rtlist_ipv4(vrrp->vroutes, cmd);
return 1;
}
static int
vrrp_hd_len(vrrp_rt * vrrp)
{
- return sizeof (vrrp_pkt)
- + LIST_SIZE(vrrp->vip) * sizeof (uint32_t)
- + VRRP_AUTH_LEN;
+ int len = sizeof (vrrp_pkt) + VRRP_AUTH_LEN;
+ return (!LIST_ISEMPTY(vrrp->vip)) ?
+ len + LIST_SIZE(vrrp->vip) * sizeof (uint32_t) : len;
}
/*
return VRRP_PACKET_DROP;
}
- /*
- * MAY verify that the IP address(es) associated with the
- * VRID are valid
- */
- if (hd->naddr != LIST_SIZE(vrrp->vip)) {
- syslog(LOG_INFO,
- "receive an invalid ip number count associated with VRID!");
- return VRRP_PACKET_KO;
- }
+ if (!LIST_ISEMPTY(vrrp->vip)) {
+ /*
+ * MAY verify that the IP address(es) associated with the
+ * VRID are valid
+ */
+ if (hd->naddr != LIST_SIZE(vrrp->vip)) {
+ syslog(LOG_INFO,
+ "receive an invalid ip number count associated with VRID!");
+ return VRRP_PACKET_KO;
+ }
- if (!LIST_ISEMPTY(vrrp->vip))
for (e = LIST_HEAD(vrrp->vip); e; ELEMENT_NEXT(e)) {
ipaddress = ELEMENT_DATA(e);
if (!vrrp_in_chk_vips(vrrp, ipaddress->addr, vips)) {
return VRRP_PACKET_KO;
}
}
+ } else if (hd->naddr > 0) {
+ syslog(LOG_INFO,
+ "receive an invalid ip number count associated with VRID!");
+ return VRRP_PACKET_KO;
+ }
/*
* MUST verify that the Adver Interval in the packet is the same as
hd->vers_type = (VRRP_VERSION << 4) | VRRP_PKT_ADVERT;
hd->vrid = vrrp->vrid;
hd->priority = prio;
- hd->naddr = LIST_SIZE(vrrp->vip);
+ hd->naddr = (!LIST_ISEMPTY(vrrp->vip)) ? LIST_SIZE(vrrp->vip) : 0;
hd->auth_type = vrrp->auth_type;
hd->adver_int = vrrp->adver_int / TIMER_HZ;
/* copy the passwd if the authentication is VRRP_AH_PASS */
if (vrrp->auth_type == VRRP_AUTH_PASS) {
- char *pw = (char *) hd + sizeof (*hd) + LIST_SIZE(vrrp->vip) * 4;
+ int vip_count = (!LIST_ISEMPTY(vrrp->vip)) ? LIST_SIZE(vrrp->vip) : 0;
+ char *pw = (char *) hd + sizeof (*hd) + vip_count * 4;
memcpy(pw, vrrp->auth_data, sizeof (vrrp->auth_data));
}
/* build VRRP packet */
static void
-vrrp_build_pkt(vrrp_rt * vrrp, int prio, char *buffer, int buflen)
+vrrp_build_pkt(vrrp_rt * vrrp, int prio)
{
char *bufptr;
+ int len;
- bufptr = buffer;
+ /* save reference values */
+ bufptr = VRRP_SEND_BUFFER(vrrp);
+ len = VRRP_SEND_BUFFER_SIZE(vrrp);
/* build the ip header */
- vrrp_build_ip(vrrp, buffer, buflen);
+ vrrp_build_ip(vrrp, VRRP_SEND_BUFFER(vrrp), VRRP_SEND_BUFFER_SIZE(vrrp));
/* build the vrrp header */
- buffer += vrrp_iphdr_len(vrrp);
+ vrrp->send_buffer += vrrp_iphdr_len(vrrp);
if (vrrp->auth_type == VRRP_AUTH_AH)
- buffer += vrrp_ipsecah_len();
- buflen -= vrrp_iphdr_len(vrrp);
+ vrrp->send_buffer += vrrp_ipsecah_len();
+ vrrp->send_buffer_size -= vrrp_iphdr_len(vrrp);
if (vrrp->auth_type == VRRP_AUTH_AH)
- buflen -= vrrp_ipsecah_len();
- vrrp_build_vrrp(vrrp, prio, buffer, buflen);
+ vrrp->send_buffer_size -= vrrp_ipsecah_len();
+ vrrp_build_vrrp(vrrp, prio, vrrp->send_buffer, vrrp->send_buffer_size);
/* build the IPSEC AH header */
if (vrrp->auth_type == VRRP_AUTH_AH) {
- buflen += vrrp_iphdr_len(vrrp) + vrrp_ipsecah_len();
- vrrp_build_ipsecah(vrrp, bufptr, buflen);
+ vrrp->send_buffer_size += vrrp_iphdr_len(vrrp) + vrrp_ipsecah_len();
+ vrrp_build_ipsecah(vrrp, bufptr, VRRP_SEND_BUFFER_SIZE(vrrp));
}
+
+ /* restore reference values */
+ vrrp->send_buffer = bufptr;
+ vrrp->send_buffer_size = len;
}
/* send VRRP packet */
static int
-vrrp_send_pkt(vrrp_rt * vrrp, char *buffer, int buflen)
+vrrp_send_pkt(vrrp_rt * vrrp)
{
struct sockaddr_in dst;
struct msghdr msg;
struct iovec iov;
- int fd;
- int ret;
-
- /* Create and init socket descriptor */
- fd = socket(AF_INET
- , SOCK_RAW
- , (vrrp->auth_type == VRRP_AUTH_AH) ? IPPROTO_IPSEC_AH : IPPROTO_VRRP);
- if_setsockopt_hdrincl(fd);
- if_setsockopt_bindtodevice(fd, vrrp->ifp);
- if_setsockopt_mcast_loop(fd);
/* Sending path */
memset(&dst, 0, sizeof(dst));
msg.msg_namelen = sizeof(dst);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
- iov.iov_base = buffer;
- iov.iov_len = buflen;
+ iov.iov_base = VRRP_SEND_BUFFER(vrrp);
+ iov.iov_len = VRRP_SEND_BUFFER_SIZE(vrrp);
/* Send the packet */
- ret = sendmsg(fd, &msg, MSG_DONTROUTE);
+ return sendmsg(vrrp->fd_out, &msg, MSG_DONTROUTE);
+}
- close(fd);
- return 0;
+/* Allocate the sending buffer */
+static void
+vrrp_alloc_send_buffer(vrrp_rt * vrrp)
+{
+ vrrp->send_buffer_size = vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
+ if (vrrp->auth_type == VRRP_AUTH_AH)
+ vrrp->send_buffer_size += vrrp_ipsecah_len();
+ vrrp->send_buffer = MALLOC(VRRP_SEND_BUFFER_SIZE(vrrp));
}
/* send VRRP advertissement */
int
vrrp_send_adv(vrrp_rt * vrrp, int prio)
{
- int buflen, ret;
- char *buffer;
-
- /* alloc the memory */
- buflen = vrrp_iphdr_len(vrrp) + vrrp_hd_len(vrrp);
- if (vrrp->auth_type == VRRP_AUTH_AH)
- buflen += vrrp_ipsecah_len();
-
- buffer = MALLOC(buflen);
+ /* alloc send buffer */
+ if (!vrrp->send_buffer)
+ vrrp_alloc_send_buffer(vrrp);
+ else
+ memset(vrrp->send_buffer, 0, VRRP_SEND_BUFFER_SIZE(vrrp));
- /* build the packet */
- vrrp_build_pkt(vrrp, prio, buffer, buflen);
+ /* build the packet */
+ vrrp_build_pkt(vrrp, prio);
/* send it */
- ret = vrrp_send_pkt(vrrp, buffer, buflen);
-
- /* free the memory */
- FREE(buffer);
- return ret;
+ return vrrp_send_pkt(vrrp);
}
/* Received packet processing */
return;
/* send gratuitous arp for each virtual ip */
- syslog(LOG_INFO, "VRRP_Instance(%s) Sending gratuitous ARP on %s",
- vrrp->iname, IF_NAME(vrrp->ifp));
+ if (debug & 32)
+ syslog(LOG_INFO, "VRRP_Instance(%s) Sending gratuitous ARP on %s",
+ vrrp->iname, IF_NAME(vrrp->ifp));
for (j = 0; j < 5; j++) {
if (!LIST_ISEMPTY(vrrp->vip))
for (e = LIST_HEAD(vrrp->vip); e; ELEMENT_NEXT(e)) {
ipaddress = ELEMENT_DATA(e);
- send_gratuitous_arp(vrrp, ipaddress->addr);
+ send_gratuitous_arp(ipaddress);
}
if (!LIST_ISEMPTY(vrrp->evip))
for (e = LIST_HEAD(vrrp->evip); e; ELEMENT_NEXT(e)) {
ipaddress = ELEMENT_DATA(e);
- send_gratuitous_arp(vrrp, ipaddress->addr);
+ send_gratuitous_arp(ipaddress);
}
}
}
return 1;
}
-/* open the socket and join the multicast group. */
+/* open a VRRP sending socket */
+int
+open_vrrp_send_socket(const int proto, const int index)
+{
+ interface *ifp;
+ int fd = -1;
+
+ /* Retreive interface */
+ ifp = if_get_by_ifindex(index);
+
+ /* Create and init socket descriptor */
+ fd = socket(AF_INET, SOCK_RAW, proto);
+ if (fd < 0) {
+ int err = errno;
+ syslog(LOG_INFO, "cant open raw socket. errno=%d",
+ err);
+ return -1;
+ }
+
+ /* Set fd */
+ if_setsockopt_hdrincl(fd);
+ if_setsockopt_bindtodevice(fd, ifp);
+ if_setsockopt_mcast_loop(fd);
+
+ return fd;
+}
+
+/* open a VRRP socket and join the multicast group. */
int
open_vrrp_socket(const int proto, const int index)
{
fd = socket(AF_INET, SOCK_RAW, proto);
if (fd < 0) {
int err = errno;
- syslog(LOG_INFO,
- "cant open raw socket. errno=%d. (try to run it as root)",
+ syslog(LOG_INFO, "cant open raw socket. errno=%d",
err);
return -1;
}
void
close_vrrp_socket(vrrp_rt * vrrp)
{
- if_leave_vrrp_group(vrrp->fd, vrrp->ifp);
+ if_leave_vrrp_group(vrrp->fd_in, vrrp->ifp);
+ close(vrrp->fd_out);
}
int
new_vrrp_socket(vrrp_rt * vrrp)
{
- int old_fd = vrrp->fd;
- list p = vrrp_data->vrrp;
- vrrp_rt *vrrp_ptr;
- element e;
+ int old_fd = vrrp->fd_in;
+ int proto;
/* close the desc & open a new one */
close_vrrp_socket(vrrp);
- if (vrrp->auth_type == VRRP_AUTH_AH)
- vrrp->fd =
- open_vrrp_socket(IPPROTO_IPSEC_AH, IF_INDEX(vrrp->ifp));
- else
- vrrp->fd = open_vrrp_socket(IPPROTO_VRRP, IF_INDEX(vrrp->ifp));
+ remove_vrrp_fd_bucket(vrrp);
+ proto = (vrrp->auth_type == VRRP_AUTH_AH) ? IPPROTO_IPSEC_AH : IPPROTO_VRRP;
+ vrrp->fd_in = open_vrrp_socket(proto, IF_INDEX(vrrp->ifp));
+ vrrp->fd_out = open_vrrp_send_socket(proto, IF_INDEX(vrrp->ifp));
+ alloc_vrrp_fd_bucket(vrrp);
/* Sync the other desc */
- for (e = LIST_HEAD(p); e; ELEMENT_NEXT(e)) {
- vrrp_ptr = ELEMENT_DATA(e);
- if (vrrp_ptr->fd == old_fd)
- vrrp_ptr->fd = vrrp->fd;
- }
+ set_vrrp_fd_bucket(old_fd, vrrp);
- return vrrp->fd;
+ return vrrp->fd_in;
}
/* handle terminate state */
int
vrrp_complete_init(void)
{
- list l = vrrp_data->vrrp;
+ list l;
element e;
vrrp_rt *vrrp;
+ vrrp_sgroup *sgroup;
+ /* Complete VRRP instance initialization */
+ l = vrrp_data->vrrp;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
if (!vrrp_complete_instance(vrrp))
return 0;
}
+
+ /* Build synchronization group index */
+ l = vrrp_data->vrrp_sync_group;
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ sgroup = ELEMENT_DATA(e);
+ vrrp_sync_set_group(sgroup);
+ }
+
return 1;
}
*
* Part: ARP primitives.
*
- * Version: $Id: vrrp_arp.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_arp.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "memory.h"
#include "utils.h"
-/* Send the gratuitous ARP message */
-static int send_arp(vrrp_rt *vrrp, char *buffer, int buflen)
+/* Make shared socket */
+void gratuitous_arp_init(void)
{
- int fd;
- int len;
- struct sockaddr_ll sll;
+ /* Initalize shared buffer */
+ garp_buffer = (char *)MALLOC(sizeof(m_arphdr) + ETHER_HDR_LEN);
/* Create the socket descriptor */
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RARP));
+ garp_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RARP));
+
+ if (garp_fd > 0)
+ syslog(LOG_INFO, "Registering gratutious ARP shared channel");
+ else
+ syslog(LOG_INFO, "Error while registering gratutious ARP shared channel");
+}
+void gratuitous_arp_close(void)
+{
+ FREE(garp_buffer);
+ close(garp_fd);
+}
+
+/* Send the gratuitous ARP message */
+static int send_arp(ip_address *ipaddress)
+{
+ struct sockaddr_ll sll;
+ int len;
/* Build the dst device */
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
- strncpy(sll.sll_addr, IF_HWADDR(vrrp->ifp), sizeof(sll.sll_addr));
+ strncpy(sll.sll_addr, IF_HWADDR(ipaddress->ifp), sizeof(sll.sll_addr));
sll.sll_halen = ETHERNET_HW_LEN;
- sll.sll_ifindex = IF_INDEX(vrrp->ifp);
+ sll.sll_ifindex = IF_INDEX(ipaddress->ifp);
/* Send packet */
- len = sendto(fd, buffer, buflen, 0,(struct sockaddr *)&sll, sizeof(sll));
-
- close(fd);
+ len = sendto(garp_fd, garp_buffer, sizeof(m_arphdr) + ETHER_HDR_LEN
+ , 0, (struct sockaddr *)&sll, sizeof(sll));
+ if (len < 0)
+ syslog(LOG_INFO, "Error sending gratutious ARP on %s for %s"
+ , IF_NAME(ipaddress->ifp), inet_ntop2(ipaddress->addr));
return len;
}
/* Build a gratuitous ARP message over a specific interface */
-int send_gratuitous_arp(vrrp_rt * vrrp, int addr)
+int send_gratuitous_arp(ip_address *ipaddress)
{
- char buflen = sizeof(m_arphdr) + ETHER_HDR_LEN;
- char *buf = (char *)MALLOC(buflen);
- struct ether_header *eth = (struct ether_header *) buf;
- m_arphdr *arph = (m_arphdr *) (buf + ETHER_HDR_LEN);
- char *hwaddr = IF_HWADDR(vrrp->ifp);
+ struct ether_header *eth = (struct ether_header *) garp_buffer;
+ m_arphdr *arph = (m_arphdr *) (garp_buffer + ETHER_HDR_LEN);
+ char *hwaddr = IF_HWADDR(ipaddress->ifp);
int len;
/* Ethernet header */
arph->ar_pln = IPPROTO_ADDR_LEN;
arph->ar_op = htons(ARPOP_REQUEST);
memcpy(arph->__ar_sha, hwaddr, ETH_ALEN);
- memcpy(arph->__ar_sip, &addr, sizeof (addr));
- memcpy(arph->__ar_tip, &addr, sizeof (addr));
+ memcpy(arph->__ar_sip, &ipaddress->addr, sizeof (ipaddress->addr));
+ memcpy(arph->__ar_tip, &ipaddress->addr, sizeof (ipaddress->addr));
/* Send the ARP message */
- len = send_arp(vrrp, buf, buflen);
+ len = send_arp(ipaddress);
- FREE(buf);
+ /* Cleanup room for next round */
+ memset(garp_buffer, 0, sizeof(m_arphdr) + ETHER_HDR_LEN);
return len;
}
*
* Part: VRRP child process handling.
*
- * Version: $Id: vrrp_daemon.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_daemon.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_daemon.h"
#include "vrrp_scheduler.h"
#include "vrrp_if.h"
+#include "vrrp_arp.h"
#include "vrrp_netlink.h"
+#include "vrrp_ipaddress.h"
#include "vrrp_iproute.h"
#include "vrrp_parser.h"
#include "vrrp_data.h"
extern int reload;
extern pid_t vrrp_child;
extern char *conf_file;
+extern int wdog_delay_vrrp;
/* Daemon stop sequence */
static void
/* Destroy master thread */
thread_destroy_master(master);
- /* Clear static routes */
+ /* Clear static entries */
+ netlink_iplist_ipv4(vrrp_data->static_addresses, IPADDRESS_DEL);
netlink_rtlist_ipv4(vrrp_data->static_routes, IPROUTE_DEL);
if (!(debug & 8))
shutdown_vrrp_instances();
free_interface_queue();
+ gratuitous_arp_close();
/* Stop daemon */
pidfile_rm(VRRP_PID_FILE);
init_interface_queue();
kernel_netlink_init();
if_mii_poller_init();
+ gratuitous_arp_init();
/* Parse configuration file */
data = alloc_global_data();
return;
}
- /* Post initializations */
- syslog(LOG_INFO, "Configuration is using : %lu Bytes", mem_allocated);
-
if (reload) {
+ clear_diff_saddresses();
clear_diff_sroutes();
clear_diff_vrrp();
}
- /* Set static routes */
- netlink_rtlist_ipv4(vrrp_data->static_routes, IPROUTE_ADD);
-
/* Complete VRRP initialization */
if (!vrrp_complete_init()) {
stop_vrrp();
return;
}
+ /* Post initializations */
+ syslog(LOG_INFO, "Configuration is using : %lu Bytes", mem_allocated);
+
+ /* Set static entries */
+ netlink_iplist_ipv4(vrrp_data->static_addresses, IPADDRESS_ADD);
+ netlink_rtlist_ipv4(vrrp_data->static_routes, IPROUTE_ADD);
+
/* Dump configuration */
if (debug & 4) {
dump_global_data(data);
master = thread_make_master();
free_global_data(data);
free_interface_queue();
+ gratuitous_arp_close();
/* Save previous conf data */
old_vrrp_data = vrrp_data;
signal_set(SIGINT, sigend_vrrp);
signal_set(SIGTERM, sigend_vrrp);
signal_set(SIGKILL, sigend_vrrp);
- signal_set(SIGCHLD, sigchld);
+ signal_noignore_sigchld();
}
/* Register VRRP thread */
, strerror(errno));
return -1;
} else if (pid) {
+ int poll_delay = (wdog_delay_vrrp) ? wdog_delay_vrrp : WATCHDOG_DELAY;
vrrp_child = pid;
syslog(LOG_INFO, "Starting VRRP child process, pid=%d"
, pid);
/* Connect child watchdog */
vrrp_wdog_data.wdog_pid = pid;
thread_add_timer(master, wdog_boot_thread, &vrrp_wdog_data,
- WATCHDOG_DELAY);
+ poll_delay);
return 0;
}
*
* Part: Dynamic data structure definition.
*
- * Version: $Id: vrrp_data.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_data.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*/
#include "vrrp_data.h"
+#include "vrrp_index.h"
#include "vrrp_sync.h"
#include "vrrp.h"
#include "memory.h"
/* Externals vars */
extern vrrp_conf_data *vrrp_data;
-/* Static routes facility functions */
+/* Static addresses facility function */
+void
+alloc_saddress(vector strvec)
+{
+ if (LIST_ISEMPTY(vrrp_data->static_addresses))
+ vrrp_data->static_addresses = alloc_list(free_ipaddress, dump_ipaddress);
+ alloc_ipaddress(vrrp_data->static_addresses, strvec, NULL);
+}
+
+/* Static routes facility function */
void
alloc_sroute(vector strvec)
{
if (LIST_ISEMPTY(vrrp_data->static_routes))
- vrrp_data->static_routes = alloc_list(free_route, dump_route);
+ vrrp_data->static_routes = alloc_list(free_iproute, dump_iproute);
alloc_route(vrrp_data->static_routes, strvec);
}
FREE(vgroup->gname);
free_strvec(vgroup->iname);
+ free_list(vgroup->index);
FREE_PTR(vgroup->script_backup);
FREE_PTR(vgroup->script_master);
FREE_PTR(vgroup->script_fault);
vrrp_rt *vrrp = data;
FREE(vrrp->iname);
+ FREE_PTR(vrrp->send_buffer);
FREE_PTR(vrrp->lvs_syncd_if);
FREE_PTR(vrrp->script_backup);
FREE_PTR(vrrp->script_master);
FREE_PTR(vrrp->script_fault);
FREE(vrrp->ipsecah_counter);
- if (!LIST_ISEMPTY(vrrp->vip))
- free_list(vrrp->vip);
- if (!LIST_ISEMPTY(vrrp->evip))
- free_list(vrrp->evip);
- if (!LIST_ISEMPTY(vrrp->vroutes))
- free_list(vrrp->vroutes);
+ free_list(vrrp->track_ifp);
+ free_list(vrrp->vip);
+ free_list(vrrp->evip);
+ free_list(vrrp->vroutes);
FREE(vrrp);
}
static void
else
syslog(LOG_INFO, " Want State = MASTER");
syslog(LOG_INFO, " Runing on device = %s", IF_NAME(vrrp->ifp));
- if (vrrp->track_ifp)
- syslog(LOG_INFO, " Track interface = %s",
- IF_NAME(vrrp->track_ifp));
if (vrrp->mcast_saddr)
syslog(LOG_INFO, " Using mcast src_ip = %s",
inet_ntop2(vrrp->mcast_saddr));
VRRP_AUTH_AH) ? "IPSEC_AH" : "SIMPLE_PASSWORD");
syslog(LOG_INFO, " Password = %s", vrrp->auth_data);
}
+ if (!LIST_ISEMPTY(vrrp->track_ifp)) {
+ syslog(LOG_INFO, " Tracked interfaces = %d", LIST_SIZE(vrrp->track_ifp));
+ dump_list(vrrp->track_ifp);
+ }
if (!LIST_ISEMPTY(vrrp->vip)) {
syslog(LOG_INFO, " Virtual IP = %d", LIST_SIZE(vrrp->vip));
dump_list(vrrp->vip);
new->adver_int = TIMER_HZ;
new->iname = (char *) MALLOC(size + 1);
memcpy(new->iname, iname, size);
- new->sync = vrrp_get_sync_group(iname);
list_add(vrrp_data->vrrp, new);
}
void
+alloc_vrrp_track(vector strvec)
+{
+ vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
+
+ if (LIST_ISEMPTY(vrrp->track_ifp))
+ vrrp->track_ifp = alloc_list(NULL, dump_track);
+ alloc_track(vrrp->track_ifp, strvec);
+}
+
+void
alloc_vrrp_vip(vector strvec)
{
vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
if (LIST_ISEMPTY(vrrp->vip))
vrrp->vip = alloc_list(free_ipaddress, dump_ipaddress);
- alloc_ipaddress(vrrp->vip, strvec, IF_INDEX(vrrp->ifp));
+ alloc_ipaddress(vrrp->vip, strvec, vrrp->ifp);
}
void
alloc_vrrp_evip(vector strvec)
if (LIST_ISEMPTY(vrrp->evip))
vrrp->evip = alloc_list(free_ipaddress, dump_ipaddress);
- alloc_ipaddress(vrrp->evip, strvec, IF_INDEX(vrrp->ifp));
+ alloc_ipaddress(vrrp->evip, strvec, vrrp->ifp);
}
void
vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
if (LIST_ISEMPTY(vrrp->vroutes))
- vrrp->vroutes = alloc_list(free_route, dump_route);
+ vrrp->vroutes = alloc_list(free_iproute, dump_iproute);
alloc_route(vrrp->vroutes, strvec);
}
new = (vrrp_conf_data *) MALLOC(sizeof (vrrp_conf_data));
new->vrrp = alloc_list(free_vrrp, dump_vrrp);
+ 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);
+ vrrp_buffer = (char *) MALLOC(VRRP_PACKET_TEMP_LEN);
return new;
}
void
free_vrrp_data(vrrp_conf_data * vrrp_data)
{
+ free_list(vrrp_data->static_addresses);
+ free_list(vrrp_data->static_routes);
+ free_mlist(vrrp_data->vrrp_index, 255);
+ free_mlist(vrrp_data->vrrp_index_fd, 1024+1);
free_list(vrrp_data->vrrp);
free_list(vrrp_data->vrrp_sync_group);
FREE(vrrp_data);
+ FREE(vrrp_buffer);
}
void
dump_vrrp_data(vrrp_conf_data * vrrp_data)
{
+ if (!LIST_ISEMPTY(vrrp_data->static_addresses)) {
+ syslog(LOG_INFO, "------< Static Addresses >------");
+ dump_list(vrrp_data->static_addresses);
+ }
if (!LIST_ISEMPTY(vrrp_data->static_routes)) {
syslog(LOG_INFO, "------< Static Routes >------");
dump_list(vrrp_data->static_routes);
*
* Part: Interfaces manipulation.
*
- * Version: $Id: vrrp_if.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_if.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
if (!LIST_ISEMPTY(if_queue))
free_list(if_queue);
netlink_close(&nl_kernel);
+ netlink_close(&nl_cmd);
}
void
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: VRRP instance index table.
+ *
+ * Version: $Id: vrrp_index.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
+ *
+ * Author: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/* local include */
+#include "vrrp_index.h"
+#include "vrrp_data.h"
+#include "vrrp.h"
+#include "memory.h"
+#include "list.h"
+
+/* Externals vars */
+extern vrrp_conf_data *vrrp_data;
+
+/* VRID hash table */
+void
+alloc_vrrp_bucket(vrrp_rt *vrrp)
+{
+ list_add(&vrrp_data->vrrp_index[vrrp->vrid], vrrp);
+}
+
+vrrp_rt *
+vrrp_index_lookup(const int vrid, const int fd)
+{
+ vrrp_rt *vrrp;
+ element e;
+ list l = &vrrp_data->vrrp_index[vrid];
+
+ /* return if list is empty */
+ if (LIST_ISEMPTY(l))
+ return NULL;
+
+ /*
+ * If list size's is 1 then no collisions. So
+ * Test and return the singleton.
+ */
+ if (LIST_SIZE(l) == 1) {
+ vrrp = ELEMENT_DATA(LIST_HEAD(l));
+ return (vrrp->fd_in == fd) ? vrrp : NULL;
+ }
+
+ /*
+ * List collision on the vrid bucket. The same
+ * vrid is used on a different interface. We perform
+ * a fd lookup as collisions solver.
+ */
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+ if (vrrp->fd_in == fd)
+ return vrrp;
+ }
+
+ /* No match */
+ return NULL;
+}
+
+/* FD hash table */
+void
+alloc_vrrp_fd_bucket(vrrp_rt *vrrp)
+{
+ /* We use a mod key plus 1 */
+ list_add(&vrrp_data->vrrp_index_fd[vrrp->fd_in%1024 + 1], vrrp);
+}
+
+void
+remove_vrrp_fd_bucket(vrrp_rt *vrrp)
+{
+ list l = &vrrp_data->vrrp_index_fd[vrrp->fd_in%1024 + 1];
+ list_del(l, vrrp);
+}
+
+void set_vrrp_fd_bucket(int old_fd, vrrp_rt *vrrp)
+{
+ vrrp_rt *vrrp_ptr;
+ element e;
+ list l = &vrrp_data->vrrp_index_fd[old_fd%1024 + 1];
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp_ptr = ELEMENT_DATA(e);
+ if (IF_INDEX(vrrp_ptr->ifp) == IF_INDEX(vrrp->ifp)) {
+ vrrp_ptr->fd_in = vrrp->fd_in;
+ vrrp_ptr->fd_out = vrrp->fd_out;
+ }
+ }
+}
*
* Part: NETLINK IPv4 address manipulation.
*
- * Version: $Id: vrrp_ipaddress.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_ipaddress.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
/* local include */
#include "vrrp_ipaddress.h"
#include "vrrp_netlink.h"
-#include "vrrp_if.h"
+#include "vrrp_data.h"
#include "memory.h"
#include "utils.h"
+/* extern global vars */
+extern vrrp_conf_data *vrrp_data;
+extern vrrp_conf_data *old_vrrp_data;
+
/* Add/Delete IP address to a specific interface */
int
netlink_address_ipv4(ip_address *ipaddr, int cmd)
{
- struct nl_handle nlh;
int status = 1;
struct {
struct nlmsghdr n;
req.n.nlmsg_flags = NLM_F_REQUEST;
req.n.nlmsg_type = cmd ? RTM_NEWADDR : RTM_DELADDR;
req.ifa.ifa_family = AF_INET;
- req.ifa.ifa_index = ipaddr->ifindex;
+ req.ifa.ifa_index = IF_INDEX(ipaddr->ifp);
req.ifa.ifa_scope = ipaddr->scope;
req.ifa.ifa_prefixlen = ipaddr->mask;
addattr_l(&req.n, sizeof (req), IFA_LOCAL, &ipaddr->addr, sizeof (ipaddr->addr));
- if (netlink_socket(&nlh, 0) < 0)
- return -1;
-
- if (netlink_talk(&nlh, &req.n) < 0)
+ if (netlink_talk(&nl_cmd, &req.n) < 0)
status = -1;
-
- /* to close the socket */
- netlink_close(&nlh);
return status;
}
syslog(LOG_INFO, " %s/%d dev %s scope %s"
, inet_ntop2(ip_addr->addr)
, ip_addr->mask
- , IF_NAME(if_get_by_ifindex(ip_addr->ifindex))
+ , IF_NAME(ip_addr->ifp)
, netlink_scope_n2a(ip_addr->scope));
}
void
-alloc_ipaddress(list ip_list, vector strvec, int ifindex)
+alloc_ipaddress(list ip_list, vector strvec, interface *ifp)
{
ip_address *new;
uint32_t ipaddr = 0;
int i = 0;
new = (ip_address *) MALLOC(sizeof(ip_address));
- new->ifindex = ifindex;
+ new->ifp = ifp;
/* FMT parse */
while (i < VECTOR_SIZE(strvec)) {
/* cmd parsing */
if (!strcmp(str, "dev")) {
- new->ifindex = IF_INDEX(if_get_by_ifname(VECTOR_SLOT(strvec, ++i)));
+ new->ifp = if_get_by_ifname(VECTOR_SLOT(strvec, ++i));
} else if (!strcmp(str, "scope")) {
new->scope = netlink_scope_a2n(VECTOR_SLOT(strvec, ++i));
} else {
i++;
}
+ /* If index not set then use default interface index */
+ if (!ifp)
+ new->ifp = if_get_by_ifname(DFLT_INT);
+
list_add(ip_list, new);
}
syslog(LOG_INFO, "ip address %s/%d dev %s, no longer exist"
, inet_ntop2(ipaddress->addr)
, ipaddress->mask
- , IF_NAME(if_get_by_ifindex(ipaddress->ifindex)));
+ , IF_NAME(ipaddress->ifp));
netlink_address_ipv4(ipaddress, IPADDRESS_DEL);
}
}
}
+
+/* Clear static ip address */
+void
+clear_diff_saddresses(void)
+{
+ clear_diff_address(old_vrrp_data->static_addresses, vrrp_data->static_addresses);
+}
*
* Part: NETLINK IPv4 routes manipulation.
*
- * Version: $Id: vrrp_iproute.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_iproute.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
int
netlink_route_ipv4(ip_route *iproute, int cmd)
{
- struct nl_handle nlh;
int status = 1;
struct {
struct nlmsghdr n;
if (iproute->src)
addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &iproute->src, 4);
- /* Send to netlink channel */
- if (netlink_socket(&nlh, 0) < 0)
- return -1;
-
- if (netlink_talk(&nlh, &req.n) < 0)
+ if (netlink_talk(&nl_cmd, &req.n) < 0)
status = -1;
-
- /* to close the clocket */
- netlink_close(&nlh);
return status;
}
/* Route dump/allocation */
void
-free_route(void *data)
+free_iproute(void *data)
{
FREE(data);
}
void
-dump_route(void *data)
+dump_iproute(void *data)
{
ip_route *route = data;
char *log_msg = MALLOC(100);
* authentication data encryption using HMAC MD5 according to
* RFCs 2085 & 2104.
*
- * Version: $Id: vrrp_ipsecah.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_ipsecah.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
*
* Part: NETLINK kernel command channel.
*
- * Version: $Id: vrrp_netlink.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_netlink.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
syslog(LOG_INFO, "Registering Kernel netlink reflector");
thread_add_read(master, kernel_netlink, NULL, nl_kernel.fd,
NETLINK_TIMER);
- }
+ } else
+ syslog(LOG_INFO, "Error while registering Kernel netlink reflector channel");
+
+ /* Prepare netlink command channel. */
+ netlink_socket(&nl_cmd, 0);
+ if (nl_cmd.fd > 0)
+ syslog(LOG_INFO, "Registering Kernel netlink comand channel");
+ else
+ syslog(LOG_INFO, "Error while registering Kernel netlink cmd channel");
}
*
* Part: VRRP state transition notification scripts handling.
*
- * Version: $Id: vrrp_notify.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_notify.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
* data structure representation the conf file representing
* the loadbalanced server pool.
*
- * Version: $Id: vrrp_parser.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_parser.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_parser.h"
#include "vrrp_data.h"
#include "vrrp_sync.h"
+#include "vrrp_index.h"
#include "vrrp_if.h"
#include "vrrp.h"
#include "global_data.h"
extern vrrp_conf_data *vrrp_data;
extern unsigned long mem_allocated;
+/* Static addresses handler */
+static void
+static_addresses_handler(vector strvec)
+{
+ alloc_value_block(strvec, alloc_saddress);
+}
+
/* Static routes handler */
static void
static_routes_handler(vector strvec)
{
vrrp_sgroup *vgroup = LIST_TAIL_DATA(vrrp_data->vrrp_sync_group);
vgroup->iname = read_value_block();
- vrrp_sync_set_group(vgroup);
}
static void
vrrp_gnotify_backup_handler(vector strvec)
static void
vrrp_track_int_handler(vector strvec)
{
- vrrp_rt *vrrp = LIST_TAIL_DATA(vrrp_data->vrrp);
- char *name = VECTOR_SLOT(strvec, 1);
- vrrp->track_ifp = if_get_by_ifname(name);
+ alloc_value_block(strvec, alloc_vrrp_track);
}
static void
vrrp_mcastip_handler(vector strvec)
syslog(LOG_INFO, "VRRP Error : VRID not valid !\n");
syslog(LOG_INFO,
" must be between 1 & 255. reconfigure !\n");
- }
+ } else
+ alloc_vrrp_bucket(vrrp);
}
static void
vrrp_prio_handler(vector strvec)
global_init_keywords();
/* Static routes mapping */
+ install_keyword_root("static_ipaddress", &static_addresses_handler);
install_keyword_root("static_routes", &static_routes_handler);
/* VRRP Instance mapping */
*
* Part: Sheduling framework for vrrp code.
*
- * Version: $Id: vrrp_scheduler.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_scheduler.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
#include "vrrp_notify.h"
#include "vrrp_netlink.h"
#include "vrrp_data.h"
+#include "vrrp_index.h"
#include "ipvswrapper.h"
#include "memory.h"
#include "list.h"
/* Externals vars */
extern thread_master *master;
extern vrrp_conf_data *vrrp_data;
+extern unsigned int debug;
/* VRRP FSM (Finite State Machine) design.
*
if (!IF_ISUP(vrrp->ifp))
syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
IF_NAME(vrrp->ifp));
- if (vrrp->track_ifp)
- if (!IF_ISUP(vrrp->track_ifp))
- syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
- IF_NAME(vrrp->track_ifp));
+ if (!LIST_ISEMPTY(vrrp->track_ifp))
+ vrrp_log_tracked_down(vrrp->track_ifp);
}
static void vrrp_log_int_up(vrrp_rt *vrrp)
if (IF_ISUP(vrrp->ifp))
syslog(LOG_INFO, "Kernel is reporting: interface %s UP",
IF_NAME(vrrp->ifp));
- if (vrrp->track_ifp)
- if (IF_ISUP(vrrp->track_ifp))
- syslog(LOG_INFO, "Kernel is reporting: interface %s UP",
- IF_NAME(vrrp->track_ifp));
+ if (!LIST_ISEMPTY(vrrp->track_ifp))
+ syslog(LOG_INFO, "Kernel is reporting: tracked interface are UP");
}
/*
vrrp_compute_timer(const int fd)
{
vrrp_rt *vrrp;
- TIMEVAL timer;
element e;
- list l = vrrp_data->vrrp;
+ list l = &vrrp_data->vrrp_index_fd[fd%1024 + 1];
+ TIMEVAL timer;
- /* clean the memory */
+ /* Multiple instances on the same interface */
TIMER_RESET(timer);
-
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- if (vrrp->fd == fd) {
- if (timer_cmp(vrrp->sands, timer) < 0 ||
- TIMER_ISNULL(timer))
- timer = timer_dup(vrrp->sands);
- }
+ if (timer_cmp(vrrp->sands, timer) < 0 ||
+ TIMER_ISNULL(timer))
+ timer = timer_dup(vrrp->sands);
}
return timer;
vrrp_timer_vrid_timeout(const int fd)
{
vrrp_rt *vrrp;
- list l = vrrp_data->vrrp;
element e;
- TIMEVAL vrrp_timer;
+ list l = &vrrp_data->vrrp_index_fd[fd%1024 + 1];
+ TIMEVAL timer;
int vrid = 0;
- /* clean the memory */
- memset(&vrrp_timer, 0, sizeof (struct timeval));
- vrrp_timer = vrrp_compute_timer(fd);
-
+ /* Multiple instances on the same interface */
+ TIMER_RESET(timer);
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vrrp = ELEMENT_DATA(e);
- if (timer_cmp(vrrp->sands, vrrp_timer) == 0)
+ if (timer_cmp(vrrp->sands, timer) < 0 ||
+ TIMER_ISNULL(timer)) {
+ timer = timer_dup(vrrp->sands);
vrid = vrrp->vrid;
+ }
}
return vrid;
}
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
sock = ELEMENT_DATA(e);
/* jump to asynchronous handling */
- vrrp_timer = vrrp_timer_fd(sock->fd);
+ vrrp_timer = vrrp_timer_fd(sock->fd_in);
/* Register a timer thread if interface is shut */
- if (sock->fd == -1)
+ if (sock->fd_in == -1)
thread_add_timer(master, vrrp_read_dispatcher_thread,
(int *)THREAD_TIMER, vrrp_timer);
else
thread_add_read(master, vrrp_read_dispatcher_thread,
- NULL, sock->fd, vrrp_timer);
+ NULL, sock->fd_in, vrrp_timer);
}
}
dump_sock(void *data)
{
sock *sock = data;
- syslog(LOG_INFO, "VRRP sockpool: [ifindex(%d), proto(%d), fd(%d)]",
+ syslog(LOG_INFO, "VRRP sockpool: [ifindex(%d), proto(%d), fd(%d,%d)]",
sock->ifindex
, sock->proto
- , sock->fd);
+ , sock->fd_in
+ , sock->fd_out);
}
void
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
sock = ELEMENT_DATA(e);
- sock->fd = open_vrrp_socket(sock->proto, sock->ifindex);
+ sock->fd_in = open_vrrp_socket(sock->proto, sock->ifindex);
+ if (sock->fd_in == -1)
+ sock->fd_out = -1;
+ else
+ sock->fd_out = open_vrrp_send_socket(sock->proto,
+ sock->ifindex);
}
}
proto = IPPROTO_VRRP;
if ((sock->ifindex == IF_INDEX(vrrp->ifp)) &&
- (sock->proto == proto))
- vrrp->fd = sock->fd;
+ (sock->proto == proto)) {
+ vrrp->fd_in = sock->fd_in;
+ vrrp->fd_out = sock->fd_out;
+
+ /* append to hash index */
+ alloc_vrrp_fd_bucket(vrrp);
+ }
}
}
}
vrrp_register_workers(pool);
/* cleanup the temp socket pool */
- dump_list(pool);
+ if (debug & 32)
+ dump_list(pool);
free_list(pool);
return 1;
}
-static vrrp_rt *
-vrrp_search_instance(const int vrid)
-{
- vrrp_rt *vrrp;
- list l = vrrp_data->vrrp;
- element e;
-
- for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
- vrrp = ELEMENT_DATA(e);
- if (vrrp->vrid == vrid)
- return vrrp;
- }
- return NULL;
-}
-
static void
vrrp_backup(vrrp_rt * vrrp, char *vrrp_buffer, int len)
{
/* Searching for matching instance */
vrid = vrrp_timer_vrid_timeout(fd);
- vrrp = vrrp_search_instance(vrid);
+ vrrp = vrrp_index_lookup(vrid, fd);
/* Run the FSM handler */
prev_state = vrrp->state;
* compute new sands timer safely.
*/
vrrp_init_instance_sands(vrrp);
- return vrrp->fd;
+ return vrrp->fd_in;
}
/* Handle dispatcher read packet */
vrrp_dispatcher_read(int fd)
{
vrrp_rt *vrrp;
- char *vrrp_buffer;
struct iphdr *iph;
vrrp_pkt *hd;
int len = 0;
int prev_state = 0;
- /* allocate & clean the read buffer */
- vrrp_buffer = (char *) MALLOC(VRRP_PACKET_TEMP_LEN);
+ /* Clean the read buffer */
+ memset(vrrp_buffer, 0, VRRP_PACKET_TEMP_LEN);
/* read & affect received buffer */
len = read(fd, vrrp_buffer, VRRP_PACKET_TEMP_LEN);
/* GCC bug : end */
/* Searching for matching instance */
- vrrp = vrrp_search_instance(hd->vrid);
+ vrrp = vrrp_index_lookup(hd->vrid, fd);
/* If no instance found => ignore the advert */
- if (!vrrp) {
- FREE(vrrp_buffer);
+ if (!vrrp)
return fd;
- }
/* Run the FSM handler */
prev_state = vrrp->state;
*/
vrrp_init_instance_sands(vrrp);
- /* cleanup the room */
- FREE(vrrp_buffer);
return fd;
}
*
* Part: VRRP synchronization framework.
*
- * Version: $Id: vrrp_sync.c,v 1.0.3 2003/05/11 02:28:03 acassen Exp $
+ * Version: $Id: vrrp_sync.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
*
* Author: Alexandre Cassen, <acassen@linux-vs.org>
*
void
vrrp_init_instance_sands(vrrp_rt * vrrp)
{
- TIMEVAL timer;
-
- timer = timer_now();
-
- if (vrrp->state == VRRP_STATE_BACK || vrrp->state == VRRP_STATE_FAULT) {
- vrrp->sands.tv_sec = timer.tv_sec + vrrp->ms_down_timer / TIMER_HZ;
- vrrp->sands.tv_usec = timer.tv_usec + vrrp->ms_down_timer % TIMER_HZ;
+ TIMEVAL timer = timer_now();
+
+ /*
+ * We only make timer auto-recalibration while being in
+ * master state. Other state are transtions so recalibration
+ * is not needed. Here we estimate the VRRP advert time
+ * handling and substract it to new computed timer.
+ * We just take care to the usec sub timer and not sec one
+ * to not conflict scheduling decision.
+ */
+ if (vrrp->state == VRRP_STATE_MAST) {
+ long usec;
+ usec = timer.tv_usec - vrrp->sands.tv_usec;
+ vrrp->sands.tv_sec = timer.tv_sec + vrrp->adver_int / TIMER_HZ;
+ vrrp->sands.tv_usec = timer.tv_usec;
+ if (usec > 0)
+ vrrp->sands.tv_usec -= usec;
+ return;
}
+
if (vrrp->state == VRRP_STATE_GOTO_MASTER ||
- vrrp->state == VRRP_STATE_MAST ||
vrrp->state == VRRP_STATE_GOTO_FAULT) {
vrrp->sands.tv_sec = timer.tv_sec + vrrp->adver_int / TIMER_HZ;
vrrp->sands.tv_usec = timer.tv_usec;
+ return;
}
-}
-/* return the first group found for a specific instance */
-vrrp_sgroup *
-vrrp_get_sync_group(char *iname)
-{
- int i;
- char *str;
- element e;
- vrrp_sgroup *vgroup;
- list l = vrrp_data->vrrp_sync_group;
-
- for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
- vgroup = ELEMENT_DATA(e);
- if (vgroup->iname)
- for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
- str = VECTOR_SLOT(vgroup->iname, i);
- if (strcmp(str, iname) == 0)
- return vgroup;
- }
+ if (vrrp->state == VRRP_STATE_BACK || vrrp->state == VRRP_STATE_FAULT) {
+ vrrp->sands.tv_sec = timer.tv_sec + vrrp->ms_down_timer / TIMER_HZ;
+ vrrp->sands.tv_usec = timer.tv_usec + vrrp->ms_down_timer % TIMER_HZ;
}
- return NULL;
}
-/* jointure between instance and group => iname */
+/* Instance name lookup */
vrrp_rt *
vrrp_get_instance(char *iname)
{
for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
str = VECTOR_SLOT(vgroup->iname, i);
vrrp = vrrp_get_instance(str);
- if (vrrp)
+ if (vrrp) {
+ if (LIST_ISEMPTY(vgroup->index))
+ vgroup->index = alloc_list(NULL, NULL);
+ list_add(vgroup->index, vrrp);
vrrp->sync = vgroup;
+ }
}
}
int
vrrp_sync_group_up(vrrp_sgroup * vgroup)
{
- vrrp_rt *isync;
- char *str;
+ vrrp_rt *vrrp;
+ element e;
+ list l = vgroup->index;
int is_up = 0;
- int i;
- for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
- str = VECTOR_SLOT(vgroup->iname, i);
- isync = vrrp_get_instance(str);
- if (isync)
- if (VRRP_ISUP(isync))
- is_up++;
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ vrrp = ELEMENT_DATA(e);
+ if (VRRP_ISUP(vrrp))
+ is_up++;
}
- if (is_up == VECTOR_SIZE(vgroup->iname)) {
+ if (is_up == LIST_SIZE(vgroup->index)) {
syslog(LOG_INFO, "Kernel is reporting: Group(%s) UP"
, GROUP_NAME(vgroup));
return 1;
void
vrrp_sync_master_election(vrrp_rt * vrrp)
{
- int i;
- char *str;
vrrp_rt *isync;
vrrp_sgroup *vgroup = vrrp->sync;
+ list l = vgroup->index;
+ element e;
if (vrrp->wantstate != VRRP_STATE_GOTO_MASTER)
return;
syslog(LOG_INFO, "VRRP_Group(%s) Transition to MASTER state",
GROUP_NAME(vrrp->sync));
- for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
- str = VECTOR_SLOT(vgroup->iname, i);
- isync = vrrp_get_instance(str);
- if (isync)
- if (isync != vrrp) {
- /* Force a new protocol master election */
- isync->wantstate = VRRP_STATE_GOTO_MASTER;
- syslog(LOG_INFO,
- "VRRP_Instance(%s) forcing a new MASTER election",
- isync->iname);
- vrrp_send_adv(isync, isync->priority);
- }
+ /* Perform sync index */
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ isync = ELEMENT_DATA(e);
+ if (isync != vrrp) {
+ /* Force a new protocol master election */
+ isync->wantstate = VRRP_STATE_GOTO_MASTER;
+ syslog(LOG_INFO,
+ "VRRP_Instance(%s) forcing a new MASTER election",
+ isync->iname);
+ vrrp_send_adv(isync, isync->priority);
+ }
}
}
void
vrrp_sync_backup(vrrp_rt * vrrp)
{
- int i;
- char *str;
vrrp_rt *isync;
vrrp_sgroup *vgroup = vrrp->sync;
+ list l = vgroup->index;
+ element e;
syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to BACKUP state",
GROUP_NAME(vgroup));
- for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
- str = VECTOR_SLOT(vgroup->iname, i);
- isync = vrrp_get_instance(str);
- if (isync)
- if (isync != vrrp) {
- isync->wantstate = VRRP_STATE_BACK;
- vrrp_state_leave_master(isync);
- vrrp_init_instance_sands(isync);
- }
+ /* Perform sync index */
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ isync = ELEMENT_DATA(e);
+ if (isync != vrrp) {
+ isync->wantstate = VRRP_STATE_BACK;
+ vrrp_state_leave_master(isync);
+ vrrp_init_instance_sands(isync);
+ }
}
vgroup->state = VRRP_STATE_BACK;
vrrp_sync_smtp_notifier(vgroup);
void
vrrp_sync_master(vrrp_rt * vrrp)
{
- int i;
- char *str;
vrrp_rt *isync;
vrrp_sgroup *vgroup = vrrp->sync;
+ list l = vgroup->index;
+ element e;
if (GROUP_STATE(vrrp->sync) == VRRP_STATE_MAST)
return;
syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to MASTER state",
GROUP_NAME(vrrp->sync));
- for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
- str = VECTOR_SLOT(vgroup->iname, i);
- isync = vrrp_get_instance(str);
+ /* Perform sync index */
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ isync = ELEMENT_DATA(e);
/* Send the higher priority advert on all synced instances */
- if (isync)
- if (isync != vrrp) {
- isync->wantstate = VRRP_STATE_MAST;
- vrrp_state_goto_master(isync);
- vrrp_init_instance_sands(isync);
- }
+ if (isync != vrrp) {
+ isync->wantstate = VRRP_STATE_MAST;
+ vrrp_state_goto_master(isync);
+ vrrp_init_instance_sands(isync);
+ }
}
vgroup->state = VRRP_STATE_MAST;
vrrp_sync_smtp_notifier(vgroup);
void
vrrp_sync_fault(vrrp_rt * vrrp)
{
- int i;
- char *str;
vrrp_rt *isync;
vrrp_sgroup *vgroup = vrrp->sync;
+ list l = vgroup->index;
+ element e;
if (GROUP_STATE(vrrp->sync) == VRRP_STATE_FAULT)
return;
syslog(LOG_INFO, "VRRP_Group(%s) Syncing instances to FAULT state",
GROUP_NAME(vrrp->sync));
- for (i = 0; i < VECTOR_SIZE(vgroup->iname); i++) {
- str = VECTOR_SLOT(vgroup->iname, i);
- isync = vrrp_get_instance(str);
+ /* Perform sync index */
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ isync = ELEMENT_DATA(e);
/*
* We force sync instance to backup mode.
* => by default ms_down_timer is set to 3secs.
* => Takeover will be less than 3secs !
*/
- if (isync)
- if (isync != vrrp) {
- if (isync->state == VRRP_STATE_MAST)
- isync->wantstate = VRRP_STATE_GOTO_FAULT;
- if (isync->state == VRRP_STATE_BACK)
- isync->state = VRRP_STATE_FAULT;
- }
+ if (isync != vrrp) {
+ if (isync->state == VRRP_STATE_MAST)
+ isync->wantstate = VRRP_STATE_GOTO_FAULT;
+ if (isync->state == VRRP_STATE_BACK)
+ isync->state = VRRP_STATE_FAULT;
+ }
}
vgroup->state = VRRP_STATE_FAULT;
notify_group_exec(vgroup, VRRP_STATE_FAULT);
--- /dev/null
+/*
+ * Soft: Keepalived is a failover program for the LVS project
+ * <www.linuxvirtualserver.org>. It monitor & manipulate
+ * a loadbalanced server pool using multi-layer checks.
+ *
+ * Part: Interface tracking framework.
+ *
+ * Version: $Id: vrrp_track.c,v 1.1.0 2003/07/20 23:41:34 acassen Exp $
+ *
+ * Author: Alexandre Cassen, <acassen@linux-vs.org>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/* local include */
+#include "vrrp_track.h"
+#include "vrrp_if.h"
+#include "vrrp_data.h"
+#include "memory.h"
+
+/* Track interface dump */
+void
+dump_track(void *data)
+{
+ interface *ifp = data;
+ syslog(LOG_INFO, " %s", IF_NAME(ifp));
+}
+void
+alloc_track(list track_list, vector strvec)
+{
+ interface *ifp = NULL;
+ char *tracked = VECTOR_SLOT(strvec, 0);
+
+ ifp = if_get_by_ifname(tracked);
+
+ /* Ignoring if no interface found */
+ if (!ifp) {
+ syslog(LOG_INFO, " %s no match, ignoring...", tracked);
+ return;
+ }
+
+ list_add(track_list, ifp);
+}
+
+/* Test if all tracked interfaces are UP */
+int
+vrrp_tracked_up(list l)
+{
+ element e;
+ interface *ifp;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ ifp = ELEMENT_DATA(e);
+ if (!IF_ISUP(ifp))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Log tracked interface down */
+void
+vrrp_log_tracked_down(list l)
+{
+ element e;
+ interface *ifp;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ ifp = ELEMENT_DATA(e);
+ if (!IF_ISUP(ifp))
+ syslog(LOG_INFO, "Kernel is reporting: interface %s DOWN",
+ IF_NAME(ifp));
+ }
+}
#include "list.h"
#include "memory.h"
+/* Simple list helpers functions */
list
alloc_list(void (*free_func) (void *), void (*dump_func) (void *))
{
- list new = (list) MALLOC(sizeof (struct _list));
- new->free = free_func;
- new->dump = dump_func;
- return new;
+ return alloc_mlist(free_func, dump_func, 1);
}
static element
l->count++;
}
+void
+list_del(list l, void *data)
+{
+ element e;
+
+ for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
+ if (ELEMENT_DATA(e) == data) {
+ if (e->prev)
+ e->prev->next = e->next;
+ else
+ l->head = e->next;
+
+ if (e->next)
+ e->next->prev = e->prev;
+ else
+ l->tail = e->prev;
+
+ l->count--;
+ FREE(e);
+ return;
+ }
+ }
+}
+
void *
list_element(list l, int num)
{
- element e;
+ element e = LIST_HEAD(l);
int i = 0;
- e = LIST_HEAD(l);
-
/* fetch element number num */
for (i = 0; i < num; i++)
if (e)
(*l->dump) (e->data);
}
-void
-free_list(list l)
+static void
+free_element(list l)
{
element e;
element next;
(*l->free) (e->data);
FREE(e);
}
+}
+
+void
+free_list(list l)
+{
+ if (!l)
+ return;
+ free_element(l);
+ FREE(l);
+}
+
+
+/* Multiple list helpers functions */
+list
+alloc_mlist(void (*free_func) (void *), void (*dump_func) (void *), int size)
+{
+ list new = (list) MALLOC(size * sizeof (struct _list));
+ new->free = free_func;
+ new->dump = dump_func;
+ return new;
+}
+
+void
+dump_mlist(list l, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ dump_list(&l[i]);
+}
+
+void
+free_mlist(list l, int size)
+{
+ int i;
+
+ if (!l)
+ return;
+
+ for (i = 0; i < size; i++)
+ free_element(&l[i]);
FREE(l);
}
extern void *list_element(list l, int num);
extern void dump_list(list l);
extern void list_add(list l, void *data);
+extern void list_del(list l, void *data);
+extern list alloc_mlist(void (*free_func) (void *), void (*dump_func) (void *), int size);
+extern void dump_mlist(list l, int size);
+extern void free_mlist(list l, int size);
#endif
* 2 of the License, or (at your option) any later version.
*/
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/select.h>
#include "scheduler.h"
#include "memory.h"
#include "utils.h"
return thread;
}
+/* Add a child thread. */
+thread *
+thread_add_child(thread_master * m, int (*func) (thread *)
+ , void * arg, pid_t pid, long timer)
+{
+ thread *thread;
+ TIMEVAL time_now;
+
+ assert(m != NULL);
+
+ thread = thread_new(m);
+ thread->type = THREAD_CHILD;
+ thread->id = 0;
+ thread->master = m;
+ thread->func = func;
+ thread->arg = arg;
+ thread->u.c.pid = pid;
+ thread->u.c.status = 0;
+
+ /* Compute write timeout value */
+ time_now = timer_now();
+ if (timer >= TIMER_MAX_SEC) {
+ time_now.tv_sec += timer / TIMER_HZ;
+ time_now.tv_usec += timer % TIMER_HZ;
+ } else
+ time_now.tv_sec += timer;
+
+ thread->sands = time_now;
+
+ /* Sort by timeval. */
+ thread_list_add_timeval(&m->child, thread);
+
+ return thread;
+}
+
/* Add simple event thread. */
thread *
thread_add_event(thread_master * m, int (*func) (thread *)
case THREAD_TIMER:
thread_list_delete(&thread->master->timer, thread);
break;
+ case THREAD_CHILD:
+ /* Does this need to kill the child, or is that the
+ * caller's job?
+ * This function is currently unused, so leave it for now.
+ */
+ thread_list_delete(&thread->master->child, thread);
+ break;
case THREAD_EVENT:
thread_list_delete(&thread->master->event, thread);
break;
fd_set exceptfd;
TIMEVAL time_now;
TIMEVAL *timer_wait;
+ int status;
+ sigset_t sigset, dummy_sigset, block_sigset, pending;
assert(m != NULL);
+ /*
+ * Set up the signal mask for select, by removing
+ * SIGCHLD from the set of blocked signals.
+ */
+ sigemptyset(&dummy_sigset);
+ sigprocmask(SIG_BLOCK, &dummy_sigset, &sigset);
+ sigdelset(&sigset, SIGCHLD);
+
+ sigemptyset(&block_sigset);
+ sigaddset(&block_sigset, SIGCHLD);
+
/* Timer allocation */
timer_wait = (TIMEVAL *) MALLOC(sizeof (TIMEVAL));
writefd = m->writefd;
exceptfd = m->exceptfd;
- ret = select(FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
+ /*
+ * Linux doesn't have a pselect syscall. Need to manually
+ * check if we have a signal waiting for us, else we lose the SIGCHLD
+ * when the pselect emulation changes the procmask.
+ * Theres still a small race between the procmask change and the select
+ * call, but it'll be picked up in the next iteration.
+ * Note that we don't use pselect here for portability between glibc
+ * versions. Until/unless linux gets a pselect syscall, this is
+ * equivalent to what glibc does, anyway.
+ */
+
+ sigpending(&pending);
+ if (sigismember(&pending, SIGCHLD)) {
+ /* Clear the pending signal */
+ int sig;
+ sigwait(&block_sigset, &sig);
+
+ ret = -1;
+ errno = EINTR;
+ } else {
+ /* Emulate pselect */
+ sigset_t saveset;
+ sigprocmask(SIG_SETMASK, &sigset, &saveset);
+ ret = select(FD_SETSIZE, &readfd, &writefd, &exceptfd, timer_wait);
+ sigprocmask(SIG_SETMASK, &saveset, NULL);
+ }
+
if (ret < 0) {
if (errno != EINTR) {
/* Real error. */
DBG("select error: %s", strerror(errno));
assert(0);
+ } else {
+ /*
+ * This is O(n^2), but there will only be a few entries on
+ * this list.
+ */
+ pid_t pid;
+ while ((pid = waitpid(-1, &status, WNOHANG))) {
+ if (pid == -1) {
+ if (errno == ECHILD)
+ goto retry;
+ DBG("waitpid error: %s", strerror(errno));
+ assert(0);
+ } else {
+ thread = m->child.head;
+ while (thread) {
+ struct _thread *t;
+ t = thread;
+ thread = t->next;
+ if (pid == t->u.c.pid) {
+ thread_list_delete(&m->child, t);
+ thread_list_add(&m->ready, t);
+ t->u.c.status = status;
+ t->type = THREAD_READY;
+ break;
+ }
+ }
+ }
+ }
}
- /* Signal is coming. */
goto retry;
}
+ /* Timeout children */
+ time_now = timer_now();
+ thread = m->child.head;
+ while (thread) {
+ struct _thread *t;
+
+ t = thread;
+ thread = t->next;
+
+ if (timer_cmp(time_now, t->sands) >= 0) {
+ thread_list_delete(&m->child, t);
+ thread_list_add(&m->ready, t);
+ t->type = THREAD_CHILD_TIMEOUT;
+ }
+ }
+
/* Read thead. */
time_now = timer_now();
thread = m->read.head;
/* Our infinite scheduling loop */
extern thread_master *master;
+extern unsigned int debug;
void
launch_scheduler(void)
{
/* system includes */
#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
union {
int val; /* second argument of the event. */
int fd; /* file descriptor in case of read/write. */
+ struct {
+ pid_t pid; /* process id a child thread is wanting. */
+ int status; /* return status of the process */
+ } c;
} u;
} thread;
thread_list read;
thread_list write;
thread_list timer;
+ thread_list child;
thread_list event;
thread_list ready;
thread_list unuse;
} thread_master;
/* Thread types. */
-#define THREAD_READ 0
-#define THREAD_WRITE 1
-#define THREAD_TIMER 2
-#define THREAD_EVENT 3
-#define THREAD_READY 4
-#define THREAD_UNUSED 5
-#define THREAD_WRITE_TIMEOUT 6
-#define THREAD_READ_TIMEOUT 7
-#define THREAD_TERMINATE 8
+#define THREAD_READ 0
+#define THREAD_WRITE 1
+#define THREAD_TIMER 2
+#define THREAD_EVENT 3
+#define THREAD_CHILD 4
+#define THREAD_READY 5
+#define THREAD_UNUSED 6
+#define THREAD_WRITE_TIMEOUT 7
+#define THREAD_READ_TIMEOUT 8
+#define THREAD_CHILD_TIMEOUT 9
+#define THREAD_TERMINATE 10
+
/* MICRO SEC def */
#define BOOTSTRAP_DELAY 1
#define THREAD_ARG(X) ((X)->arg)
#define THREAD_FD(X) ((X)->u.fd)
#define THREAD_VAL(X) ((X)->u.val)
+#define THREAD_CHILD_PID(X) ((X)->u.c.pid)
+#define THREAD_CHILD_STATUS(X) ((X)->u.c.status)
/* Prototypes. */
extern thread_master *thread_make_master(void);
, void *arg, int fd, long timeout);
extern thread *thread_add_timer(thread_master * m, int (*func) (thread *)
, void *arg, long timer);
+extern thread *thread_add_child(thread_master * m, int (*func) (thread *)
+ , void *arg, pid_t pid, long timeout);
extern thread *thread_add_event(thread_master * m, int (*func) (thread *)
, void *arg, int val);
extern void thread_cancel(thread * thread);