New: Bonding: Holes in arp_ip_target list cause ARP replies to be ignored
Subsystems (4)
A message that is not in the archive (sent off-list or not yet received): [email protected]/
(switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface).
Quoted 99 lines · On Fri, 3 Apr 2009 20:17:37 GMT [email protected] wrote:
http://bugzilla.kernel.org/show_bug.cgi?id=13006
URL: www.astutenetworks.com
Summary: Bonding: Holes inarp_ip_targetlist cause ARP replies
to be ignored
Product: Drivers
Version: 2.5
Kernel Version: 2.6.25
Platform: All
OS/Version: Linux
Tree: Mainline
Status: NEW
Severity: normal
Priority: P1
Component: Network
AssignedTo: [email protected]
ReportedBy: [email protected]
Regression: NoI know there have been changes to bonding driver since 2.6.25, but this bug is still there.
To Recreate:
Set up a bond as follows:
mode active-backup
arp_interval1000
arp_ip_target1.1.1.1 2.2.2.2 (address 2 points to a reachable target)
/sys/class/net/bond0/bonding/active_slavecontains an interface nameNow delete the first target (cat -1.1.1.1 >arp_ip_target)
The first target is deleted, but
active_slaveis now empty.The proglem is in line 2611 of
bond_main.c, inbond_validate_arp()for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {This is the loop that searches the
arp_ip_targetsarray for a match with an incomming ARP. The problem is that when we deleted the first entry, it was set to zero. This "for" loop exits before comparing with the remaining entries in targets[].One fix is to delete the " && targets[i]" from the termination conditions. Then the loop will always search the full list.
A better fix is to make sure there are no empty holes in the target[] array, beceause there may other code which expects no holes.
This can be done by modifying this loop in
bond_sysfs.cat line 792, which is where entries are deleted inbonding_store_arp_targets(). This change deletes the hole just created by removing an entry.for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) { if (targets[i] == newtarget) { printk(KERN_INFO DRV_NAME ": %s: removing ARP target %d.%d.%d.%d.\n", bond->dev->name, NIPQUAD(newtarget)); targets[i] = 0; done = 1; // Move any entries after this one into the newly // empty slot, so there are no holes. Be careful not to access // more than BOND_MAX_ARP_TARGETS in the array. for (j = i; (j < (BOND_MAX_ARP_TARGETS-1)) && targets[j + 1]; j++) { targets[j] = targets[j + 1]; targets[j + 1] = 0; } } }1Here is the output of
ver_linux:Linux caspianB012a 2.6.25-astute-v15 #19 SMP Fri Apr 3 09:32:28 PDT 2009 i686
GNU/Linux
Gnu C 18:
/stim2/steve/work/acp/host/caspian/pd/kernel/scripts/ver_linux: line 24: ld:
command not found
binutilsutil-linux 2.13 mount 2.13 module-init-tools 3.2-pre1 e2fsprogs 1.40 Linux C Library 2.5.90 /stim2/steve/work/acp/host/caspian/pd/kernel/scripts/ver_linux: line 69: ldd: command not found Procps 3.2.7 Net-tools 1.60 Kbd 82: Sh-utils 5.97 udev 105 Modules Loaded nfs lockd sunrpc pegasus iSCSITarget ScsiGatewayShimScsiGateway
an2000_l2pthruamodlinux_user_bdelinux_kernel_bdeastute_hostapi_modmegaraid_sasan2k afpga e1000eipmi_poweroffipmi_watchdogipmi_devintfipmi_siipmi_msghandler
PATCH 1/1 Bonding: fix zero address hole bug in arp_ip_target list
In reply to a message not in the archiveFix a zero address hole bug in the bonding arp_ip_target list that was causing the bond to ignore ARP replies (bugz 13006). Instead of just setting the array entry to zero, we now copy any additional entries down one slot, putting the zero entry at the end. With this change we can now have all the loops that walk the array stop when they hit a zero since there will be no addresses after it.
--- Documentation/networking/bonding.txt | 2 +- drivers/net/bonding/bond_main.c | 5 ++--- drivers/net/bonding/bond_sysfs.c | 14 ++++++++------ 3 files changed, 11 insertions(+), 10 deletions(-)
Documentation/networking/bonding.txt +1 -1
@@ -1242,7 +1242,7 @@ monitoring is enabled, and vice-versa. To add ARP targets: # echo +192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target # echo +192.168.0.101 > /sys/class/net/bond0/bonding/arp_ip_target - NOTE: up to 10 target addresses may be specified. + NOTE: up to 16 target addresses may be specified. To remove an ARP target: # echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target
drivers/net/bonding/bond_main.c +2 -3
@@ -2570,7 +2570,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)for (i =0 ; (i <BOND_MAX_ARP_TARGETS ); i++) {if (!targets[i]) -continue ; +break ;pr_debug ("basa: target %x\n" , targets[i]);if (list_empty (&bond->vlan_list)) {pr_debug ("basa: empty vlan: arp_send\n" );
@@ -2677,7 +2677,6 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32int i;__be32 *targets = bond->params.arp_targets; - targets = bond->params.arp_targets;for (i =0 ; (i <BOND_MAX_ARP_TARGETS ) && targets[i]; i++) {pr_debug ("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n" , &sip, &tip, i, &targets[i],bond_has_this_ip (bond, tip));
@@ -3303,7 +3302,7 @@ static void bond_info_show_master(struct seq_file *seq)for (i =0 ; (i <BOND_MAX_ARP_TARGETS ) ;i++) {if (!bond->params.arp_targets[i]) -continue ; +break ;if (printed)seq_printf (seq,"," );seq_printf (seq," %pI4" , &bond->params.arp_targets[i]);
drivers/net/bonding/bond_sysfs.c +8 -6
@@ -684,17 +684,15 @@ static ssize_t bonding_store_arp_targets(struct device *d, goto out; }/* look for an empty slot to put the target in, and check for dupes */ -for (i =0 ; (i <BOND_MAX_ARP_TARGETS ); i++) { +for (i =0 ; (i <BOND_MAX_ARP_TARGETS ) && !done; i++) {if (targets[i] == newtarget) {/* duplicate */ printk(KERN_ERR DRV_NAME": %s: ARP target %pI4 is already present\n" , bond->dev->name, &newtarget); -if (done) - targets[i] =0 ; ret = -EINVAL ; goto out; } -if (targets[i] ==0 && !done) { +if (targets[i] ==0 ) { printk(KERN_INFO DRV_NAME": %s: adding ARP target %pI4.\n" , bond->dev->name, &newtarget);
@@ -720,12 +718,16 @@ static ssize_t bonding_store_arp_targets(struct device *d, goto out; } -for (i =0 ; (i <BOND_MAX_ARP_TARGETS ); i++) { +for (i =0 ; (i <BOND_MAX_ARP_TARGETS ) && !done; i++) {if (targets[i] == newtarget) { +int j; printk(KERN_INFO DRV_NAME": %s: removing ARP target %pI4.\n" , bond->dev->name, &newtarget); - targets[i] =0 ; +for (j = i; (j < (BOND_MAX_ARP_TARGETS -1 )) && targets[j+1 ]; j++) + targets[j] = targets[j+1 ]; + + targets[j] =0 ; done =1 ; } }
Signature · 1 line
1.5.4.3
Re: [PATCH] Bonding: fix zero address hole bug in arp_ip_target list
Quoted 9 lines · Brian Haley
Fix a zero address hole bug in the bonding
arp_ip_targetlist that was causing the bond to ignore ARP replies (bugz 13006). Instead of just setting the array entry to zero, we now copy any additional entries down one slot, putting the zero entry at the end. With this change we can now have all the loops that walk the array stop when they hit a zero since there will be no addresses after it.Signed-off-by Brian Haley <[email protected]>
This all looks reasonable to me. This patch appears to be an
extension of some code (not as a patch) provided in bugzilla 13006 by Steve Howard <[email protected]>, so I suspect he should sign off on this as well, or at the very least be credited in the log; I'd write that as:
Changes are based in part on code fragment provided in kernel
bugzilla 13006 by Steve Howard <[email protected]>.
This can go to -stable, too. -J
Quoted 99 lines
---
Documentation/networking/bonding.txt | 2 +- drivers/net/bonding/bond_main.c | 5 ++--- drivers/net/bonding/bond_sysfs.c | 14 ++++++++------ 3 files changed, 11 insertions(+), 10 deletions(-)Documentation/networking/bonding.txt +0
-0@@ -1242,7 +1242,7 @@ monitoring is enabled, and vice-versa.To add ARP targets:
# echo +192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_target # echo +192.168.0.101 > /sys/class/net/bond0/bonding/arp_ip_targetDocumentation/networking/bonding.txt +1
-1- NOTE: up to 10 target addresses may be specified. + NOTE: up to 16 target addresses may be specified.To remove an ARP target:
# echo -192.168.0.100 > /sys/class/net/bond0/bonding/arp_ip_targetdrivers/net/bonding/bond_main.c +2
-3@@ -2570,7 +2570,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)for (i =0 ; (i <BOND_MAX_ARP_TARGETS ); i++) {if (!targets[i]) -continue ; +break ;pr_debug ("basa: target %x\n" , targets[i]);if (list_empty (&bond->vlan_list)) {pr_debug ("basa: empty vlan: arp_send\n" );@@ -2677,7 +2677,6 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32int i;__be32 *targets = bond->params.arp_targets; - targets = bond->params.arp_targets;for (i =0 ; (i <BOND_MAX_ARP_TARGETS ) && targets[i]; i++) {pr_debug ("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n" , &sip, &tip, i, &targets[i],bond_has_this_ip (bond, tip));@@ -3303,7 +3302,7 @@ static void bond_info_show_master(struct seq_file *seq)for (i =0 ; (i <BOND_MAX_ARP_TARGETS ) ;i++) {if (!bond->params.arp_targets[i]) -continue ; +break ;if (printed)seq_printf (seq,"," );seq_printf (seq," %pI4" , &bond->params.arp_targets[i]);drivers/net/bonding/bond_sysfs.c +8
-6@@ -684,17 +684,15 @@ static ssize_t bonding_store_arp_targets(struct device *d, goto out; }/* look for an empty slot to put the target in, and check for dupes */ -for (i =0 ; (i <BOND_MAX_ARP_TARGETS ); i++) { +for (i =0 ; (i <BOND_MAX_ARP_TARGETS ) && !done; i++) {if (targets[i] == newtarget) {/* duplicate */ printk(KERN_ERR DRV_NAME": %s: ARP target %pI4 is already present\n" , bond->dev->name, &newtarget); -if (done) - targets[i] =0 ; ret = -EINVAL ; goto out; } -if (targets[i] ==0 && !done) { +if (targets[i] ==0 ) { printk(KERN_INFO DRV_NAME": %s: adding ARP target %pI4.\n" , bond->dev->name, &newtarget);@@ -720,12 +718,16 @@ static ssize_t bonding_store_arp_targets(struct device *d, goto out; } -for (i =0 ; (i <BOND_MAX_ARP_TARGETS ); i++) { +for (i =0 ; (i <BOND_MAX_ARP_TARGETS ) && !done; i++) {if (targets[i] == newtarget) { +int j; printk(KERN_INFO DRV_NAME": %s: removing ARP target %pI4.\n" , bond->dev->name, &newtarget); - targets[i] =0 ; +for (j = i; (j < (BOND_MAX_ARP_TARGETS -1 )) && targets[j+1 ]; j++) + targets[j] = targets[j+1 ]; + + targets[j] =0 ; done =1 ; } }Signature · 6 lines
1.5.4.3 -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
David Miller
maintainerRe: [PATCH] Bonding: fix zero address hole bug in arp_ip_target list
From: Jay Vosburgh <[email protected]>
Date: Fri, 10 Apr 2009 23:51:19 -0700
Quoted 18 lines
Quoted 9 lines · Brian Haley
Fix a zero address hole bug in the bonding
arp_ip_targetlist that was causing the bond to ignore ARP replies (bugz 13006). Instead of just setting the array entry to zero, we now copy any additional entries down one slot, putting the zero entry at the end. With this change we can now have all the loops that walk the array stop when they hit a zero since there will be no addresses after it.Signed-off-by Brian Haley <[email protected]>This all looks reasonable to me. This patch appears to be an
extension of some code (not as a patch) provided in bugzilla 13006 by Steve Howard <[email protected]>, so I suspect he should sign off on this as well, or at the very least be credited in the log; I'd write that as:
Quoted 8 lines
Changes are based in part on code fragment provided in kernel
bugzilla 13006 by Steve Howard <[email protected]>.This can go to -stable, too. -JSigned-off-by Jay Vosburgh <[email protected]>
Indeed, please fix up the attribution and I will apply this and queue up for -stable.