Hi all,
I'm setting up a firewall with 2 load-balanced redundant Internet
links. To ensure the host itself can load balance its outbound
connections (and fail-over correctly if one of those links dies) I'm
configuring ifstated to handle updating the default routes for the
host based on a simple ping test to assess if I can contact the next
hop for each interface.
The configuration I've included below works fine if both links are
active, and in a single link failure on either link it fails over
correctly and fails back if both links are found to be available
again. However there's a worst-case where both links go, for which
I've included the 'alldown' state to prevent my host flapping, but it
never manage to reach 'alldown', it just flap back and forth between
'link1only' and 'link2only' - note my test situation is included below
including ifconfig output for the IF's, ping test output, ifstated
output, and a trascription of my ifstated.conf.
My reading of the ifstated.conf man page is that the BNF definitely
supports the && clauses I'm using, and executes the body in-order, so
does anyone know why I'm not reaching state 'alldown' ??
All help is greatly appreciated :-)
Cheers
Dave
--
re0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:14:d1:13:78:25
priority: 0
media: Ethernet autoselect (none)
status: no carrier
inet6 fe80::214:d1ff:fe13:7825%re0 prefixlen 64 scopeid 0x1
inet 192.168.5.10 netmask 0xffffff00 broadcast 192.168.5.255
re1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
lladdr 00:14:d1:13:71:e8
priority: 0
groups: egress
media: Ethernet autoselect (none)
status: no carrier
inet6 fe80::214:d1ff:fe13:71e8%re1 prefixlen 64 scopeid 0x2
inet 192.168.6.10 netmask 0xffffff00 broadcast 192.168.6.255
# ping -I 192.168.5.10 -q -c 1 -w 1 192.168.5.2; echo $?
PING 192.168.5.2 (192.168.5.2): 56 data bytes
--- 192.168.5.2 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
1
# ping -I 192.168.6.10 -q -c 1 -w 1 192.168.6.1; echo $?
PING 192.168.6.1 (192.168.6.1): 56 data bytes
--- 192.168.6.1 ping statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss
1
---
# ifstated -vvd
net_inet1 = "( "ping -I 192.168.5.10 -q -c 1 -w 1 192.168.5.2 >
/dev/null" every 20 )"
net_inet2 = "( "ping -I 192.168.6.10 -q -c 1 -w 1 192.168.6.1 >
/dev/null" every 20 )"
initial state: primary
changing state to primary
running ping -I 192.168.5.10 -q -c 1 -w 1 192.168.5.2 > /dev/null
running ping -I 192.168.6.10 -q -c 1 -w 1 192.168.6.1 > /dev/null
running route add -mpath default 192.168.5.2
add net default: gateway 192.168.5.2
running route add -mpath default 192.168.6.1
route: writing to routing socket: File exists
add net default: gateway 192.168.6.1: File exists
changing state to link1only
running ping -I 192.168.5.10 -q -c 1 -w 1 192.168.5.2 > /dev/null
running ping -I 192.168.6.10 -q -c 1 -w 1 192.168.6.1 > /dev/null
running route delete default 192.168.6.1
delete net default: gateway 192.168.6.1
running route add -mpath default 192.168.5.2
route: writing to routing socket: File exists
add net default: gateway 192.168.5.2: File exists
changing state to link2only
running ping -I 192.168.5.10 -q -c 1 -w 1 192.168.5.2 > /dev/null
running ping -I 192.168.6.10 -q -c 1 -w 1 192.168.6.1 > /dev/null
running route delete default 192.168.5.2
delete net default: gateway 192.168.5.2
running route add -mpath default 192.168.6.1
add net default: gateway 192.168.6.1
changing state to link1only
running ping -I 192.168.5.10 -q -c 1 -w 1 192.168.5.2 > /dev/null
ping: sendto: Host is down
running ping -I 192.168.6.10 -q -c 1 -w 1 192.168.6.1 > /dev/null
running route delete default 192.168.6.1
delete net default: gateway 192.168.6.1
running route add -mpath default 192.168.5.2
add net default: gateway 192.168.5.2
changing state to link2only
...
---
net_inet1 = '( "ping -I 192.168.5.10 -q -c 1 -w 1 192.168.5.2 >
/dev/null" every 20 )'
net_inet2 = '( "ping -I 192.168.6.10 -q -c 1 -w 1 192.168.6.1 >
/dev/null" every 20 )'
init-state "primary"
state primary {
init {
run "route add -mpath default 192.168.5.2"
run "route add -mpath default 192.168.6.1"
}
# both links are down
if (!$net_inet1) && (!$net_inet2)
set-state alldown
# link1 is down - go to link2
if ! $net_inet1
set-state link2only
# link2 is down - go to link1
if ! $net_inet2
set-state link1only
}
# only link1 is up
state link1only {
init {
run "route delete default 192.168.6.1"
run "route add -mpath default 192.168.5.2"
}
# both links are up (all metrics are go)
if $net_inet1 && $net_inet2
set-state primary
# both links are down
if (! $net_inet1) && (! $net_inet2)
set-state alldown
# this link (link1) is down
if ! $net_inet1
set-state link2only
}
# only link2 is up
state link2only {
init {
run "route delete default 192.168.5.2"
run "route add -mpath default 192.168.6.1"
}
# both links are up (all metrics are go)
if $net_inet1 && $net_inet2
set-state primary
# both links are down
if (! $net_inet1) && (! $net_inet2)
set-state alldown
# this link (link2) is down
if ! $net_inet2
set-state link1only
}
# all down !
state alldown {
init {
run "route add -mpath default 192.168.5.2"
run "route add -mpath default 192.168.6.1"
}
# both links are up (all metrics are go)
if $net_inet1 && $net_inet2
set-state primary
# link1 is up
if $net_inet1
set-state link1only
# link2 is up
if $net_inet2
set-state link2only
}