Commit a2fd940f authored by Andy Gospodarek's avatar Andy Gospodarek Committed by David S. Miller

bonding: fix broken multicast with round-robin mode

Round-robin (mode 0) does nothing to ensure that any multicast traffic
originally destined for the host will continue to arrive at the host when
the link that sent the IGMP join or membership report goes down.  One of
the benefits of absolute round-robin transmit.

Keeping track of subscribed multicast groups for each slave did not seem
like a good use of resources, so I decided to simply send on the
curr_active slave of the bond (typically the first enslaved device that
is up).  This makes failover management simple as IGMP membership
reports only need to be sent when the curr_active_slave changes.  I
tested this patch and it appears to work as expected.

Originally reported by Lon Hohberger <lhh@redhat.com>.
Signed-off-by: default avatarAndy Gospodarek <andy@greyhouse.net>
CC: Lon Hohberger <lhh@redhat.com>
CC: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 44ebb952
......@@ -1235,6 +1235,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
write_lock_bh(&bond->curr_slave_lock);
}
}
/* resend IGMP joins since all were sent on curr_active_slave */
if (bond->params.mode == BOND_MODE_ROUNDROBIN) {
bond_resend_igmp_join_requests(bond);
}
}
/**
......@@ -4138,15 +4143,33 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
int i, slave_no, res = 1;
struct iphdr *iph = ip_hdr(skb);
read_lock(&bond->lock);
if (!BOND_IS_OK(bond))
goto out;
/*
* Start with the curr_active_slave that joined the bond as the
* default for sending IGMP traffic. For failover purposes one
* needs to maintain some consistency for the interface that will
* send the join/membership reports. The curr_active_slave found
* will send all of this type of traffic.
*/
if ((iph->protocol == htons(IPPROTO_IGMP)) &&
(skb->protocol == htons(ETH_P_IP))) {
read_lock(&bond->curr_slave_lock);
slave = bond->curr_active_slave;
read_unlock(&bond->curr_slave_lock);
if (!slave)
goto out;
} else {
/*
* Concurrent TX may collide on rr_tx_counter; we accept that
* as being rare enough not to justify using an atomic op here
* Concurrent TX may collide on rr_tx_counter; we accept
* that as being rare enough not to justify using an
* atomic op here.
*/
slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
......@@ -4155,6 +4178,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
if (slave_no < 0)
break;
}
}
start_at = slave;
bond_for_each_slave_from(bond, slave, i, start_at) {
......
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