Commit bb71b2f8 authored by Amir Noam's avatar Amir Noam Committed by Stephen Hemminger

[PATCH] [bonding 2.6] Decouple promiscuous handling from multicast mode setting

parent 550da6a8
...@@ -1151,23 +1151,22 @@ static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2) ...@@ -1151,23 +1151,22 @@ static inline int dmi_same(struct dev_mc_list *dmi1, struct dev_mc_list *dmi2)
} }
/* /*
* Push the promiscuity flag down to all slaves * Push the promiscuity flag down to appropriate slaves
*/ */
static void bond_set_promiscuity(bonding_t *bond, int inc) static void bond_set_promiscuity(bonding_t *bond, int inc)
{ {
slave_t *slave; slave_t *slave;
switch (multicast_mode) {
case BOND_MULTICAST_ACTIVE : if (USES_PRIMARY(bond_mode)) {
/* write lock already acquired */ if (bond->current_slave) {
if (bond->current_slave != NULL)
dev_set_promiscuity(bond->current_slave->dev, inc); dev_set_promiscuity(bond->current_slave->dev, inc);
break; }
case BOND_MULTICAST_ALL :
for (slave = bond->prev; slave != (slave_t*)bond; slave = slave->prev) } else {
for (slave = bond->prev; slave != (slave_t*)bond;
slave = slave->prev) {
dev_set_promiscuity(slave->dev, inc); dev_set_promiscuity(slave->dev, inc);
break; }
case BOND_MULTICAST_DISABLED :
break;
} }
} }
...@@ -1213,20 +1212,23 @@ static void set_multicast_list(struct net_device *master) ...@@ -1213,20 +1212,23 @@ static void set_multicast_list(struct net_device *master)
bonding_t *bond = master->priv; bonding_t *bond = master->priv;
struct dev_mc_list *dmi; struct dev_mc_list *dmi;
if (multicast_mode == BOND_MULTICAST_DISABLED)
return;
/*
* Lock the private data for the master
*/
write_lock_bh(&bond->lock); write_lock_bh(&bond->lock);
/* set promiscuity flag to slaves */ /*
* Do promisc before checking multicast_mode
*/
if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) ) if ( (master->flags & IFF_PROMISC) && !(bond->flags & IFF_PROMISC) )
bond_set_promiscuity(bond, 1); bond_set_promiscuity(bond, 1);
if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) ) if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) )
bond_set_promiscuity(bond, -1); bond_set_promiscuity(bond, -1);
if (multicast_mode == BOND_MULTICAST_DISABLED) {
bond->flags = master->flags;
write_unlock_bh(&bond->lock);
return;
}
/* set allmulti flag to slaves */ /* set allmulti flag to slaves */
if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) ) if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) )
bond_set_allmulti(bond, 1); bond_set_allmulti(bond, 1);
...@@ -1258,32 +1260,40 @@ static void set_multicast_list(struct net_device *master) ...@@ -1258,32 +1260,40 @@ static void set_multicast_list(struct net_device *master)
/* /*
* Update the mc list and multicast-related flags for the new and * Update the mc list and multicast-related flags for the new and
* old active slaves (if any) according to the multicast mode * old active slaves (if any) according to the multicast mode, and
* promiscuous flags unconditionally.
*/ */
static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old) static void bond_mc_update(bonding_t *bond, slave_t *new, slave_t *old)
{ {
struct dev_mc_list *dmi; struct dev_mc_list *dmi;
switch(multicast_mode) { if (USES_PRIMARY(bond_mode)) {
case BOND_MULTICAST_ACTIVE :
if (bond->device->flags & IFF_PROMISC) { if (bond->device->flags & IFF_PROMISC) {
if (old != NULL && new != old) if (old)
dev_set_promiscuity(old->dev, -1); dev_set_promiscuity(old->dev, -1);
if (new)
dev_set_promiscuity(new->dev, 1); dev_set_promiscuity(new->dev, 1);
} }
}
switch(multicast_mode) {
case BOND_MULTICAST_ACTIVE :
if (bond->device->flags & IFF_ALLMULTI) { if (bond->device->flags & IFF_ALLMULTI) {
if (old != NULL && new != old) if (old)
dev_set_allmulti(old->dev, -1); dev_set_allmulti(old->dev, -1);
if (new)
dev_set_allmulti(new->dev, 1); dev_set_allmulti(new->dev, 1);
} }
/* first remove all mc addresses from old slave if any, /* first remove all mc addresses from old slave if any,
and _then_ add them to new active slave */ and _then_ add them to new active slave */
if (old != NULL && new != old) { if (old) {
for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next) for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
dev_mc_delete(old->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); dev_mc_delete(old->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
} }
if (new) {
for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next) for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
}
break; break;
case BOND_MULTICAST_ALL : case BOND_MULTICAST_ALL :
/* nothing to do: mc list is already up-to-date on all slaves */ /* nothing to do: mc list is already up-to-date on all slaves */
...@@ -1445,11 +1455,19 @@ static int bond_enslave(struct net_device *master_dev, ...@@ -1445,11 +1455,19 @@ static int bond_enslave(struct net_device *master_dev,
} }
} }
if (multicast_mode == BOND_MULTICAST_ALL) {
/* set promiscuity level to new slave */ /* set promiscuity level to new slave */
if (master_dev->flags & IFF_PROMISC) if (master_dev->flags & IFF_PROMISC) {
/* If the mode USES_PRIMARY, then the new slave gets the
* master's promisc (and mc) settings only if it becomes the
* current_slave, and that is taken care of later when calling
* bond_change_active()
*/
if (!USES_PRIMARY(bond_mode)) {
dev_set_promiscuity(slave_dev, 1); dev_set_promiscuity(slave_dev, 1);
}
}
if (multicast_mode == BOND_MULTICAST_ALL) {
/* set allmulti level to new slave */ /* set allmulti level to new slave */
if (master_dev->flags & IFF_ALLMULTI) if (master_dev->flags & IFF_ALLMULTI)
dev_set_allmulti(slave_dev, 1); dev_set_allmulti(slave_dev, 1);
...@@ -2024,16 +2042,22 @@ static int bond_release(struct net_device *master, struct net_device *slave) ...@@ -2024,16 +2042,22 @@ static int bond_release(struct net_device *master, struct net_device *slave)
return -EINVAL; return -EINVAL;
} }
/* undo settings and restore original values */ /* unset promiscuity level from slave */
if (master->flags & IFF_PROMISC) {
/* If the mode USES_PRIMARY, then we should only remove its
* promisc settings if it was the current_slave, but that was
* already taken care of above when we detached the slave
*/
if (!USES_PRIMARY(bond_mode)) {
dev_set_promiscuity(slave, -1);
}
}
/* undo settings and restore original values */
if (multicast_mode == BOND_MULTICAST_ALL) { if (multicast_mode == BOND_MULTICAST_ALL) {
/* flush master's mc_list from slave */ /* flush master's mc_list from slave */
bond_mc_list_flush (slave, master); bond_mc_list_flush (slave, master);
/* unset promiscuity level from slave */
if (master->flags & IFF_PROMISC)
dev_set_promiscuity(slave, -1);
/* unset allmulti level from slave */ /* unset allmulti level from slave */
if (master->flags & IFF_ALLMULTI) if (master->flags & IFF_ALLMULTI)
dev_set_allmulti(slave, -1); dev_set_allmulti(slave, -1);
...@@ -2129,17 +2153,17 @@ static int bond_release_all(struct net_device *master) ...@@ -2129,17 +2153,17 @@ static int bond_release_all(struct net_device *master)
*/ */
write_unlock_bh(&bond->lock); write_unlock_bh(&bond->lock);
if (multicast_mode == BOND_MULTICAST_ALL /* unset promiscuity level from slave */
|| (multicast_mode == BOND_MULTICAST_ACTIVE if (master->flags & IFF_PROMISC) {
&& old_current == our_slave)) { if (!USES_PRIMARY(bond_mode)) {
dev_set_promiscuity(slave_dev, -1);
}
}
if (multicast_mode == BOND_MULTICAST_ALL) {
/* flush master's mc_list from slave */ /* flush master's mc_list from slave */
bond_mc_list_flush (slave_dev, master); bond_mc_list_flush (slave_dev, master);
/* unset promiscuity level from slave */
if (master->flags & IFF_PROMISC)
dev_set_promiscuity(slave_dev, -1);
/* unset allmulti level from slave */ /* unset allmulti level from slave */
if (master->flags & IFF_ALLMULTI) if (master->flags & IFF_ALLMULTI)
dev_set_allmulti(slave_dev, -1); dev_set_allmulti(slave_dev, -1);
...@@ -3662,6 +3686,12 @@ static int __init bonding_init(void) ...@@ -3662,6 +3686,12 @@ static int __init bonding_init(void)
} }
} }
if (USES_PRIMARY(bond_mode)) {
multicast_mode = BOND_MULTICAST_ACTIVE;
} else {
multicast_mode = BOND_MULTICAST_ALL;
}
if (multicast) { if (multicast) {
multicast_mode = bond_parse_parm(multicast, bond_mc_tbl); multicast_mode = bond_parse_parm(multicast, bond_mc_tbl);
if (multicast_mode == -1) { if (multicast_mode == -1) {
......
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