From: Andy Gospodarek <gospo@redhat.com> Date: Wed, 19 May 2010 12:30:49 -0400 Subject: [net] bonding: fix broken multicast with round-robin mode Message-id: <20100519123049.GO23636@gospo.rdu.redhat.com> Patchwork-id: 25277 O-Subject: Re: [PATCH RHEL5.6 v2] bonding: fix broken multicast with round-robin mode Bugzilla: 570645 RH-Acked-by: Stefan Assmann <sassmann@redhat.com> Backport of the following upstream commits: commit 00ae702847df5566ce9182e9c895185e2ad1c181 Author: Eric Dumazet <eric.dumazet@gmail.com> Date: Tue Mar 30 23:08:37 2010 +0000 bonding: bond_xmit_roundrobin() fix commit a2fd940f4cff74b932728bd6ca12848da21a0234 Author: Andy Gospodarek <andy@greyhouse.net> Date: Thu Mar 25 14:49:05 2010 +0000 bonding: fix broken multicast with round-robin mode Verified by cluster team who first reported the problem. This will resolve RHBZ 570645. Signed-off-by: Jarod Wilson <jarod@redhat.com> diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 018e61e..0ec122e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1273,6 +1273,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) bond_send_unsolicited_na(bond); } } + + /* resend IGMP joins since all were sent on curr_active_slave */ + if (bond->params.mode == BOND_MODE_ROUNDROBIN) { + bond_resend_igmp_join_requests(bond); + } } /** @@ -4341,23 +4346,41 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev struct bonding *bond = bond_dev->priv; 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; } - /* - * Concurrent TX may collide on rr_tx_counter; we accept that - * as being rare enough not to justify using an atomic op here + * 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. */ - slave_no = bond->rr_tx_counter++ % bond->slave_cnt; + if ((iph->protocol == IPPROTO_IGMP) && + (skb->protocol == htons(ETH_P_IP))) { - bond_for_each_slave(bond, slave, i) { - slave_no--; - if (slave_no < 0) { - break; + 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. + */ + slave_no = bond->rr_tx_counter++ % bond->slave_cnt; + + bond_for_each_slave(bond, slave, i) { + slave_no--; + if (slave_no < 0) + break; } }