Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2486

kernel-2.6.18-238.el5.src.rpm

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;
 		}
 	}