diff options
author | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-07-27 12:30:10 -0700 |
---|---|---|
committer | Stephen Hemminger <stephen.hemminger@vyatta.com> | 2009-07-27 12:37:50 -0700 |
commit | bdbd1c9b842ad5931b33a1ccf483354a59ce8dab (patch) | |
tree | 3b15b3bf0cc65dbfae369726e1d4627a74bc1b6f | |
parent | be441212b4e726b37ac74f7889ea40ac29679c11 (diff) | |
download | vyatta-cfg-system-bdbd1c9b842ad5931b33a1ccf483354a59ce8dab.tar.gz vyatta-cfg-system-bdbd1c9b842ad5931b33a1ccf483354a59ce8dab.zip |
Remove slaves before changing mode
Since kernel driver does not handle mode changes properly. Workaround
by removing slaves (and readding) before changing mode.
Bug 4758
-rwxr-xr-x | scripts/vyatta-bonding.pl | 90 | ||||
-rw-r--r-- | templates/interfaces/bonding/node.tag/mode/node.def | 2 |
2 files changed, 73 insertions, 19 deletions
diff --git a/scripts/vyatta-bonding.pl b/scripts/vyatta-bonding.pl index a0bdbd6e..53e6bffa 100755 --- a/scripts/vyatta-bonding.pl +++ b/scripts/vyatta-bonding.pl @@ -46,45 +46,99 @@ my %modes = ( ); sub set_mode { - my ($intf, $mode) = @_; + my ( $intf, $mode ) = @_; my $val = $modes{$mode}; die "Unknown bonding mode $mode\n" unless defined($val); open my $fm, '>', "/sys/class/net/$intf/bonding/mode" - or die "Error: $intf is not a bonding device:$!\n"; + or die "Error: $intf is not a bonding device:$!\n"; print {$fm} $val, "\n"; close $fm - or die "Error: $intf can not set mode $val:$!\n"; + or die "Error: $intf can not set mode $val:$!\n"; } +sub get_slaves { + my $intf = shift; + + open my $f, '<', "/sys/class/net/$intf/bonding/slaves" + or die "$intf is not a bonding interface"; + my $slaves = <$f>; + close $f; + chomp $slaves; + + return split( ' ', $slaves ); +} + +sub add_slave { + my ( $intf, @slaves ) = @_; + + 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"; + } + close $f; +} + +sub remove_slave { + my ( $intf, @slaves ) = @_; + + 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"; + } + close $f; +} sub change_mode { - my ($intf, $mode) = @_; + my ( $intf, $mode ) = @_; my $interface = new Vyatta::Interface($intf); die "$intf is not a valid interface" unless $interface; - if ($interface->up()) { - system "sudo ip link set $intf down" - and die "Could not set $intf down ($!)\n"; + my @slaves = get_slaves($intf); + + remove_slave $intf, @slaves if (@slaves); + + if ( $interface->up() ) { + system "sudo ip link set $intf down" + and die "Could not set $intf down ($!)\n"; - set_mode($intf, $mode); + set_mode( $intf, $mode ); - system "sudo ip link set $intf up" - and die "Could not set $intf up ($!)\n"; - } else { - set_mode($intf, $mode); + system "sudo ip link set $intf up" + and die "Could not set $intf up ($!)\n"; } + else { + set_mode( $intf, $mode ); + } + + add_slave $intf, @slaves if (@slaves); } sub usage { - print "Usage: $0 --set-mode=s{2}\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"; + exit 1; } -my @mode_change; +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(); + +die "$0: device not specified\n" unless $dev; -GetOptions( - 'set-mode=s{2}' => \@mode_change, -) or usage(); +change_mode($dev, $mode) if $mode; +add_slave($dev, $add_port) if $add_port; +remove_slave($dev, $add_port) if $remove_port; -change_mode( @mode_change ) if @mode_change; diff --git a/templates/interfaces/bonding/node.tag/mode/node.def b/templates/interfaces/bonding/node.tag/mode/node.def index 4551ee47..bf8a1a8c 100644 --- a/templates/interfaces/bonding/node.tag/mode/node.def +++ b/templates/interfaces/bonding/node.tag/mode/node.def @@ -8,7 +8,7 @@ syntax:expression: $VAR(@) in \ "mode must be 802.3ad, active-backup, broadcast, round-robin, \ transmit-load-balance, adaptive-load-balance, or xor" help: Sets the bonding mode -update: sudo ${vyatta_sbindir}/vyatta-bonding.pl --set-mode $VAR(../@) $VAR(@) +update: sudo ${vyatta_sbindir}/vyatta-bonding.pl --dev=$VAR(../@) --mode=$VAR(@) comp_help: Possible bonding mode 802.3ad IEEE 802.3ad Dynamic link aggregation (Default) |