From b931612b5d74e198377df9d54edb1dd024451e5a Mon Sep 17 00:00:00 2001 From: Stig Thormodsrud Date: Wed, 21 May 2008 15:17:33 -0700 Subject: Fix 3155: setting the third vrrp member with the highest priority doesn't change (update) the backup --- scripts/keepalived/VyattaKeepalived.pm | 11 +++ scripts/keepalived/vyatta-show-vrrp.pl | 122 ++++++++++++++++++++++++-------- scripts/keepalived/vyatta-vrrp-state.pl | 17 ++--- 3 files changed, 106 insertions(+), 44 deletions(-) (limited to 'scripts/keepalived') diff --git a/scripts/keepalived/VyattaKeepalived.pm b/scripts/keepalived/VyattaKeepalived.pm index c5abdc97..78421723 100755 --- a/scripts/keepalived/VyattaKeepalived.pm +++ b/scripts/keepalived/VyattaKeepalived.pm @@ -37,6 +37,17 @@ my $keepalived_pid = '/var/run/keepalived_vrrp.pid'; my $state_dir = '/var/log/vrrpd'; my $vrrp_log = "$state_dir/vrrp.log"; +sub snoop_for_master { + my ($intf, $group, $vip, $timeout) = @_; + + my $file = get_master_file($intf, $group); + + my $cap_filt = "-f \"host 224.0.0.18 and proto VRRP\""; + my $dis_filt = "-R \"vrrp.virt_rtr_id == $group and vrrp.ip_addr == $vip\""; + my $options = "-a duration:$timeout -p -i$intf -c1 -T pdml"; + my $cmd = "tshark $options $cap_filt $dis_filt"; + system("$cmd > $file 2> /dev/null"); +} sub vrrp_log { my $timestamp = strftime("%Y%m%d-%H:%M.%S", localtime); diff --git a/scripts/keepalived/vyatta-show-vrrp.pl b/scripts/keepalived/vyatta-show-vrrp.pl index 86dbef3d..78e58970 100755 --- a/scripts/keepalived/vyatta-show-vrrp.pl +++ b/scripts/keepalived/vyatta-show-vrrp.pl @@ -86,28 +86,84 @@ sub get_state_link { return ($state, $link); } +sub parse_arping { + my $file = shift; + + return "" if ! -f $file; + + open (my $FD, '<', $file) + or die "Can't open file $file"; + + my @lines = <$FD>; + close $FD; + my $mac = ''; + foreach my $line (@lines) { + # regex for xx:xx:xx:xx:xx:xx + if ($line =~ /(([0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2})/) { + $mac = $1; + return uc($mac); + } + } + return $mac; +} + sub get_master_info { - my ($intf, $group) = @_; - - my $file = VyattaKeepalived::get_master_file($intf, $group); - if ( -f $file) { - my $master = `grep ip.src $file`; - chomp $master; - if (defined $master and $master =~ m/show=\"(\d+\.\d+\.\d+\.\d+)\"/) { - $master = $1; + my ($intf, $group, $vip) = @_; + + # Calling snoop_for_master() is an expensive operation, so we + # normally only do it on vrrp state transitions by calling the + # vyatta-vrrp-state.pl script. However if there are more than + # 2 routers in the vrrp group when a transition occurs, then + # only those 2 routes that transitioned will know who the current + # master is and it's priority. So here we will arp for the VIP + # address and compare it to our masterfile. If it doesn't match + # then we will snoop for the new master. + + my $master_file = VyattaKeepalived::get_master_file($intf, $group); + my $arp_file = "$master_file.arp"; + + system("/usr/bin/arping -c1 -f -I $intf $vip > $arp_file"); + my $arp_mac = parse_arping($arp_file); + + if ( ! -f $master_file) { + VyattaKeepalived::snoop_for_master($intf, $group, $vip, 2); + } + + if ( -f $master_file) { + my $master_ip = `grep ip.src $master_file`; + my $master_mac = `grep eth.src $master_file`; + chomp $master_ip; chomp $master_mac; + + # regex for show="xx:xx:xx:xx:xx:xx + if (defined $master_mac and + $master_mac =~ /show=\"(([0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2})/) + { + $master_mac = uc($1); + if ($arp_mac ne $master_mac) { + VyattaKeepalived::snoop_for_master($intf, $group, $vip, 2); + $master_ip = `grep ip.src $master_file`; + } + } + + if (defined $master_ip and + $master_ip =~ m/show=\"(\d+\.\d+\.\d+\.\d+)\"/) + { + $master_ip = $1; } else { - $master = "unknown"; + $master_ip = "unknown"; } - my $priority = `grep vrrp.prio $file`; + + my $priority = `grep vrrp.prio $master_file`; chomp $priority; if (defined $priority and $priority =~ m/show=\"(\d+)\"/) { $priority = $1; } else { $priority = "unknown"; } - return ($master, $priority); + + return ($master_ip, $priority, $arp_mac); } else { - return ("unknown", "unknown"); + return ('unknown', 'unknown', ''); } } @@ -122,15 +178,13 @@ sub vrrp_showsummary { @vips) = VyattaKeepalived::vrrp_get_config($intf, $group); print "\n$intf\t\t$group\tint\t$primary_addr\t$link\t\t$state"; foreach my $vip (@vips){ - print "\n\t\t\tvip\t$vip"; - + print "\n\t\t\tvip\t$vip"; } } else { print "Physical interface $intf, State: unknown\n"; } } - sub vrrp_show { my ($file) = @_; @@ -138,6 +192,7 @@ sub vrrp_show { my ($start_time, $intf, $group, $state, $ltime) = VyattaKeepalived::vrrp_state_parse($file); my ($interface_state, $link) = get_state_link($intf); + my $first_vip = ''; if ($state eq "master" || $state eq "backup" || $state eq "fault") { my ($primary_addr, $priority, $preempt, $advert_int, $auth_type, @vips) = VyattaKeepalived::vrrp_get_config($intf, $group); @@ -150,6 +205,9 @@ sub vrrp_show { my $strlen = length($string); print $string; foreach my $vip (@vips) { + if ($first_vip eq '') { + $first_vip = $vip; + } if ($vip_count != scalar(@vips)) { print " " x $strlen; } @@ -159,15 +217,22 @@ sub vrrp_show { if ($state eq "master") { print " Master router: $primary_addr\n"; } elsif ($state eq "backup") { - my ($master_rtr, $master_prio) = get_master_info($intf, $group); - print " Master router: $master_rtr, "; - print "Master Priority: $master_prio\n"; + my ($master_rtr, $master_prio,$master_mac) = + get_master_info($intf, $group, $first_vip); + print " Master router: $master_rtr"; + if ($master_mac ne '') { + print " [$master_mac]" + } + print ", Master Priority: $master_prio\n"; } } else { print "Physical interface $intf, State: unknown\n"; } my $elapsed = elapse_time($start_time, $now_time); print " Last transition: $elapsed\n\n"; + if ($state eq "backup") { + + } } # @@ -178,13 +243,11 @@ my $group = "all"; my $showsummary = 0; if ($#ARGV >= 0) { - if ($ARGV[0] eq "summary") { $showsummary = 1; } else { $intf = $ARGV[0]; } - } if ($#ARGV == 1) { @@ -196,22 +259,19 @@ if (!VyattaKeepalived::is_running()) { exit 1; } +my $display_func; if ($showsummary == 1) { - - print "\t\tVRRP\tAddr\t\t\tInterface\tVRRP\n"; - print "Interface\tGroup\tType\tAddress\t\tState\t\tState\n"; - print "---------\t-----\t----\t-------\t\t-----\t\t-----"; - - + $display_func = \&vrrp_showsummary; + print "\t\tVRRP\tAddr\t\t\tInterface\tVRRP\n"; + print "Interface\tGroup\tType\tAddress\t\tState\t\tState\n"; + print "---------\t-----\t----\t-------\t\t-----\t\t-----"; +} else { + $display_func = \&vrrp_show; } my @state_files = VyattaKeepalived::get_state_files($intf, $group); foreach my $state_file (@state_files) { - if ($showsummary == 1) { - vrrp_showsummary($state_file); - } else { - vrrp_show($state_file); - } + &$display_func($state_file); } exit 0; diff --git a/scripts/keepalived/vyatta-vrrp-state.pl b/scripts/keepalived/vyatta-vrrp-state.pl index 2f3554d9..a3be3095 100755 --- a/scripts/keepalived/vyatta-vrrp-state.pl +++ b/scripts/keepalived/vyatta-vrrp-state.pl @@ -31,15 +31,6 @@ use strict; use warnings; -sub snoop_for_master { - my ($intf, $group, $vip, $file) = @_; - - my $cap_filt = "-f \"host 224.0.0.18 and proto VRRP\""; - my $dis_filt = "-R \"vrrp.virt_rtr_id == $group and vrrp.ip_addr == $vip\""; - my $cmd = "tshark -a duration:60 -p -i$intf -c1 -T pdml $cap_filt $dis_filt"; - system("$cmd > $file 2> /dev/null"); -} - sub vrrp_state_log { my ($state, $intf, $group) = @_; @@ -69,14 +60,15 @@ if (defined $old_state and $vrrp_state eq $old_state) { # restarts call the transition script even if it really hasn't # changed. # + VyattaKeepalived::vrrp_log("$vrrp_intf $vrrp_group same - $vrrp_state"); exit 0; } VyattaKeepalived::vrrp_log("$vrrp_intf $vrrp_group transition to $vrrp_state"); vrrp_state_log($vrrp_state, $vrrp_intf, $vrrp_group); -my $mfile = VyattaKeepalived::get_master_file($vrrp_intf, $vrrp_group); if ($vrrp_state eq "backup") { - snoop_for_master($vrrp_intf, $vrrp_group, $vrrp_vips[0], $mfile); + VyattaKeepalived::snoop_for_master($vrrp_intf, $vrrp_group, $vrrp_vips[0], + 60); } elsif ($vrrp_state eq "master") { # # keepalived will send gratuitous arp requests on master transition @@ -91,15 +83,14 @@ if ($vrrp_state eq "backup") { # # remove the old master file since we are now master # + my $mfile = VyattaKeepalived::get_master_file($vrrp_intf, $vrrp_group); system("rm -f $mfile"); } - if (!($vrrp_transitionscript eq "null")){ exec("$vrrp_transitionscript"); } - exit 0; # end of file -- cgit v1.2.3