Commit c2edacf8 authored by Jay Vosburgh's avatar Jay Vosburgh Committed by Jeff Garzik

bonding / ipv6: no addrconf for slaves separately from master

	At present, when a device is enslaved to bonding, if ipv6 is
active then addrconf will be initated on the slave (because it is closed
then opened during the enslavement processing).  This causes DAD and RS
packets to be sent from the slave.  These packets in turn can confuse
switches that perform ipv6 snooping, causing them to incorrectly update
their forwarding tables (if, e.g., the slave being added is an inactve
backup that won't be used right away) and direct traffic away from the
active slave to a backup slave (where the incoming packets will be
dropped).

	This patch alters the behavior so that addrconf will only run on
the master device itself.  I believe this is logically correct, as it
prevents slaves from having an IPv6 identity independent from the
master.  This is consistent with the IPv4 behavior for bonding.

	This is accomplished by (a) having bonding set IFF_SLAVE sooner
in the enslavement processing than currently occurs (before open, not
after), and (b) having ipv6 addrconf ignore UP and CHANGE events on
slave devices.

	The eql driver also uses the IFF_SLAVE flag.  I inspected eql,
and I believe this change is reasonable for its usage of IFF_SLAVE, but
I did not test it.
Signed-off-by: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 89c0d26b
...@@ -1390,6 +1390,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1390,6 +1390,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_free; goto err_free;
} }
res = netdev_set_master(slave_dev, bond_dev);
if (res) {
dprintk("Error %d calling netdev_set_master\n", res);
goto err_close;
}
/* open the slave since the application closed it */ /* open the slave since the application closed it */
res = dev_open(slave_dev); res = dev_open(slave_dev);
if (res) { if (res) {
...@@ -1397,12 +1402,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1397,12 +1402,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_restore_mac; goto err_restore_mac;
} }
res = netdev_set_master(slave_dev, bond_dev);
if (res) {
dprintk("Error %d calling netdev_set_master\n", res);
goto err_close;
}
new_slave->dev = slave_dev; new_slave->dev = slave_dev;
slave_dev->priv_flags |= IFF_BONDING; slave_dev->priv_flags |= IFF_BONDING;
......
...@@ -2268,6 +2268,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, ...@@ -2268,6 +2268,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
break; break;
case NETDEV_UP: case NETDEV_UP:
case NETDEV_CHANGE: case NETDEV_CHANGE:
if (dev->flags & IFF_SLAVE)
break;
if (event == NETDEV_UP) { if (event == NETDEV_UP) {
if (!netif_carrier_ok(dev)) { if (!netif_carrier_ok(dev)) {
/* device is not ready yet. */ /* device is not ready yet. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment