diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-07-31 14:58:37 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-07-31 14:58:37 -0700 |
commit | c6b895817534113809c11c85d236d3170152df4f (patch) | |
tree | 72615369c6dcb75d1b0d33c5d7ff18b466aecf1c | |
parent | a480b37344085966baa6aa4b4ee1143dfe9f28a0 (diff) | |
download | vyatta-cfg-system-c6b895817534113809c11c85d236d3170152df4f.tar.gz vyatta-cfg-system-c6b895817534113809c11c85d236d3170152df4f.zip |
bonding: remove primary slave last
Need to remove the primary interface last, to avoid issues
with bonding driver.
-rwxr-xr-x | scripts/vyatta-bonding.pl | 109 |
1 files changed, 71 insertions, 38 deletions
diff --git a/scripts/vyatta-bonding.pl b/scripts/vyatta-bonding.pl index 5e90948b..66417f9f 100755 --- a/scripts/vyatta-bonding.pl +++ b/scripts/vyatta-bonding.pl @@ -67,80 +67,113 @@ sub get_slaves { return unless $slaves; chomp $slaves; - return split( ' ', $slaves ); } sub add_slave { - my ( $intf, @slaves ) = @_; + my ( $intf, $slave ) = @_; open my $f, '>', "/sys/class/net/$intf/bonding/slaves" or die "$intf is not a bonding interface"; - foreach my $slave (@slaves) { - print {$f} "+$slave\n"; - } + print {$f} "+$slave\n"; close $f; } sub remove_slave { - my ( $intf, @slaves ) = @_; + my ( $intf, $slave ) = @_; open my $f, '>', "/sys/class/net/$intf/bonding/slaves" or die "$intf is not a bonding interface"; - foreach my $slave (@slaves) { - print {$f} "-$slave\n"; - } + print {$f} "-$slave\n"; close $f; } -sub change_mode { - my ( $intf, $mode ) = @_; - my $interface = new Vyatta::Interface($intf); +# Go dumpster diving to figure out which ethernet interface (if any) +# gave it's address to be used by all bonding devices. +sub primary_slave { + my ( $intf, $bond_addr ) = @_; + + open my $p, '<', "/proc/net/bonding/$intf" + or die "Can't open /proc/net/bonding/$intf : $!"; + + my ( $dev, $match ); + while ( my $line = <$p> ) { + chomp $line; + if ( $line =~ m/^Slave Interface: (.*)$/ ) { + $dev = $1; + } + elsif ( $line =~ m/^Permanent HW addr: (.*)$/ ) { + if ( $1 eq $bond_addr ) { + $match = $dev; + last; + } + } + } + close $p; - die "$intf is not a valid interface" unless $interface; - my @slaves = get_slaves($intf); + return $match; +} - remove_slave $intf, @slaves if (@slaves); +sub if_down { + my $intf = shift; + system "ip link set dev $intf down" + and die "Could not set $intf up ($!)\n"; +} - if ( $interface->up() ) { - system "sudo ip link set $intf down" - and die "Could not set $intf down ($!)\n"; +sub if_up { + my $intf = shift; + system "ip link set dev $intf up" + and die "Could not set $intf up ($!)\n"; +} - set_mode( $intf, $mode ); +sub change_mode { + my ( $intf, $mode ) = @_; + my $interface = new Vyatta::Interface($intf); + die "$intf is not a valid interface" unless $interface; + my $primary = primary_slave( $intf, $interface->hw_address() ); - system "sudo ip link set $intf up" - and die "Could not set $intf up ($!)\n"; + my @slaves = get_slaves($intf); + foreach my $slave (@slaves) { + if_down($slave); + remove_slave( $intf, $slave ) unless ( $primary && $slave eq $primary ); } - else { - set_mode( $intf, $mode ); + if ($primary) { + if_down($primary); + remove_slave( $intf, $primary ); } - add_slave $intf, @slaves if (@slaves); + my $bond_up = $interface->up(); + if_down($intf) if $bond_up; + set_mode( $intf, $mode ); + if_up($intf) if $bond_up; + + foreach my $slave ( @slaves ) { + add_slave( $intf, $slave ); + } } sub usage { - print "Usage: $0 --dev=bondX --mode={mode}\n", + print "Usage: $0 --dev=bondX --mode={mode}\n"; print " $0 --dev=bondX --add-port=ethX\n"; print " $0 --dev=bondX --remove-port=ethX\n"; - print - print "modes := ", join(',', sort(keys %modes)), "\n"; + print print "modes := ", join( ',', sort( keys %modes ) ), "\n"; exit 1; } -my ($dev, $mode, $add_port, $remove_port); - -GetOptions('dev=s' => \$dev, - 'mode=s' => \$mode, - 'add-port=s' => \$add_port, - 'remove-port=s' => \$remove_port, - ) or usage(); +my ( $dev, $mode, $add_port, $rem_port ); -die "$0: device not specified\n" unless $dev; +GetOptions( + 'dev=s' => \$dev, + 'mode=s' => \$mode, + 'add=s' => \$add_port, + 'remove=s' => \$rem_port, +) or usage(); -change_mode($dev, $mode) if $mode; -add_slave($dev, $add_port) if $add_port; -remove_slave($dev, $add_port) if $remove_port; +die "$0: device not specified\n" unless $dev; +change_mode( $dev, $mode ) if $mode; +add_slave( $dev, $add_port ) if $add_port; +remove_slave( $dev, $rem_port ) if $rem_port; |