|
@@ -1257,6 +1257,8 @@ static int bond_compute_features(struct bonding *bond)
|
|
|
static void bond_setup_by_slave(struct net_device *bond_dev,
|
|
|
struct net_device *slave_dev)
|
|
|
{
|
|
|
+ struct bonding *bond = bond_dev->priv;
|
|
|
+
|
|
|
bond_dev->neigh_setup = slave_dev->neigh_setup;
|
|
|
|
|
|
bond_dev->type = slave_dev->type;
|
|
@@ -1265,6 +1267,7 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
|
|
|
|
|
|
memcpy(bond_dev->broadcast, slave_dev->broadcast,
|
|
|
slave_dev->addr_len);
|
|
|
+ bond->setup_by_slave = 1;
|
|
|
}
|
|
|
|
|
|
/* enslave device <slave> to bond device <master> */
|
|
@@ -1827,6 +1830,35 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
|
return 0; /* deletion OK */
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+* Destroy a bonding device.
|
|
|
+* Must be under rtnl_lock when this function is called.
|
|
|
+*/
|
|
|
+void bond_destroy(struct bonding *bond)
|
|
|
+{
|
|
|
+ bond_deinit(bond->dev);
|
|
|
+ bond_destroy_sysfs_entry(bond);
|
|
|
+ unregister_netdevice(bond->dev);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+* First release a slave and than destroy the bond if no more slaves iare left.
|
|
|
+* Must be under rtnl_lock when this function is called.
|
|
|
+*/
|
|
|
+int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
|
+{
|
|
|
+ struct bonding *bond = bond_dev->priv;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ ret = bond_release(bond_dev, slave_dev);
|
|
|
+ if ((ret == 0) && (bond->slave_cnt == 0)) {
|
|
|
+ printk(KERN_INFO DRV_NAME ": %s: destroying bond %s.\n",
|
|
|
+ bond_dev->name, bond_dev->name);
|
|
|
+ bond_destroy(bond);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* This function releases all slaves.
|
|
|
*/
|
|
@@ -3325,6 +3357,11 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave
|
|
|
* ... Or is it this?
|
|
|
*/
|
|
|
break;
|
|
|
+ case NETDEV_GOING_DOWN:
|
|
|
+ dprintk("slave %s is going down\n", slave_dev->name);
|
|
|
+ if (bond->setup_by_slave)
|
|
|
+ bond_release_and_destroy(bond_dev, slave_dev);
|
|
|
+ break;
|
|
|
case NETDEV_CHANGEMTU:
|
|
|
/*
|
|
|
* TODO: Should slaves be allowed to
|
|
@@ -4298,6 +4335,7 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
|
|
|
bond->primary_slave = NULL;
|
|
|
bond->dev = bond_dev;
|
|
|
bond->send_grat_arp = 0;
|
|
|
+ bond->setup_by_slave = 0;
|
|
|
INIT_LIST_HEAD(&bond->vlan_list);
|
|
|
|
|
|
/* Initialize the device entry points */
|