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)
}
/*
* 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)
{
slave_t *slave;
switch (multicast_mode) {
case BOND_MULTICAST_ACTIVE :
/* write lock already acquired */
if (bond->current_slave != NULL)
if (USES_PRIMARY(bond_mode)) {
if (bond->current_slave) {
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);
break;
case BOND_MULTICAST_DISABLED :
break;
}
}
}
......@@ -1213,20 +1212,23 @@ static void set_multicast_list(struct net_device *master)
bonding_t *bond = master->priv;
struct dev_mc_list *dmi;
if (multicast_mode == BOND_MULTICAST_DISABLED)
return;
/*
* Lock the private data for the master
*/
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) )
bond_set_promiscuity(bond, 1);
if ( !(master->flags & IFF_PROMISC) && (bond->flags & IFF_PROMISC) )
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 */
if ( (master->flags & IFF_ALLMULTI) && !(bond->flags & IFF_ALLMULTI) )
bond_set_allmulti(bond, 1);
......@@ -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
* 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)
{
struct dev_mc_list *dmi;
switch(multicast_mode) {
case BOND_MULTICAST_ACTIVE :
if (USES_PRIMARY(bond_mode)) {
if (bond->device->flags & IFF_PROMISC) {
if (old != NULL && new != old)
if (old)
dev_set_promiscuity(old->dev, -1);
dev_set_promiscuity(new->dev, 1);
if (new)
dev_set_promiscuity(new->dev, 1);
}
}
switch(multicast_mode) {
case BOND_MULTICAST_ACTIVE :
if (bond->device->flags & IFF_ALLMULTI) {
if (old != NULL && new != old)
if (old)
dev_set_allmulti(old->dev, -1);
dev_set_allmulti(new->dev, 1);
if (new)
dev_set_allmulti(new->dev, 1);
}
/* first remove all mc addresses from old slave if any,
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)
dev_mc_delete(old->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
}
for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
if (new) {
for (dmi = bond->device->mc_list; dmi != NULL; dmi = dmi->next)
dev_mc_add(new->dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
}
break;
case BOND_MULTICAST_ALL :
/* 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,
}
}
if (multicast_mode == BOND_MULTICAST_ALL) {
/* set promiscuity level to new slave */
if (master_dev->flags & IFF_PROMISC)
/* set promiscuity level to new slave */
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);
}
}
if (multicast_mode == BOND_MULTICAST_ALL) {
/* set allmulti level to new slave */
if (master_dev->flags & IFF_ALLMULTI)
dev_set_allmulti(slave_dev, 1);
......@@ -2024,16 +2042,22 @@ static int bond_release(struct net_device *master, struct net_device *slave)
return -EINVAL;
}
/* 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) {
/* flush master's mc_list from slave */
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 */
if (master->flags & IFF_ALLMULTI)
dev_set_allmulti(slave, -1);
......@@ -2129,17 +2153,17 @@ static int bond_release_all(struct net_device *master)
*/
write_unlock_bh(&bond->lock);
if (multicast_mode == BOND_MULTICAST_ALL
|| (multicast_mode == BOND_MULTICAST_ACTIVE
&& old_current == our_slave)) {
/* unset promiscuity level from slave */
if (master->flags & IFF_PROMISC) {
if (!USES_PRIMARY(bond_mode)) {
dev_set_promiscuity(slave_dev, -1);
}
}
if (multicast_mode == BOND_MULTICAST_ALL) {
/* flush master's mc_list from slave */
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 */
if (master->flags & IFF_ALLMULTI)
dev_set_allmulti(slave_dev, -1);
......@@ -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) {
multicast_mode = bond_parse_parm(multicast, bond_mc_tbl);
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