[pve-devel] [PATCH] multicast snooping bridge fixes

Alexandre Derumier aderumier at odiso.com
Tue Jun 11 17:51:27 CEST 2013


https://bugzilla.redhat.com/show_bug.cgi?id=926954
https://bugzilla.redhat.com/show_bug.cgi?id=880035

Original patches backported
https://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/net/bridge?id=9f00b2e7cf241fa389733d41b615efdaa2cb0f5b
https://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/net/bridge?id=6b7df111ece130fa979a0c4f58e53674c1e47d3e

The first patch form the series in not yet included. (cisco bug fix)
 https://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/net/bridge?id=1c8ad5bfa2be5025b0c81e3c2decd0574d453ab1

Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 ...-expire-the-mdb-entry-when-query-is-recei.patch |  144 ++++++++++++++++++++
 ...e-send-query-as-soon-as-leave-is-received.patch |   58 ++++++++
 Makefile                                           |    2 +
 3 files changed, 204 insertions(+)
 create mode 100644 0001-bridge-only-expire-the-mdb-entry-when-query-is-recei.patch
 create mode 100644 0002-bridge-send-query-as-soon-as-leave-is-received.patch

diff --git a/0001-bridge-only-expire-the-mdb-entry-when-query-is-recei.patch b/0001-bridge-only-expire-the-mdb-entry-when-query-is-recei.patch
new file mode 100644
index 0000000..cd357b4
--- /dev/null
+++ b/0001-bridge-only-expire-the-mdb-entry-when-query-is-recei.patch
@@ -0,0 +1,144 @@
+From 88654a86563317f36c38a279ea47e7aa09892192 Mon Sep 17 00:00:00 2001
+From: Alexandre Derumier <aderumier at odiso.com>
+Date: Mon, 3 Jun 2013 17:26:49 +0200
+Subject: [PATCH 1/2] bridge: only expire the mdb entry when query is received
+
+Currently we arm the expire timer when the mdb entry is added, however,
+this causes problem when there is no querier sent
+out after that.
+
+So we should only arm the timer when a corresponding query is received, as suggested by Herbert.
+And he also mentioned "if there is no querier then group subscriptions shouldn't expire.
+There has to be at least one querier in the network for this thing to work.
+Otherwise it just degenerates into a non-snooping switch, which is OK."
+
+Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
+---
+ net/bridge/br_multicast.c |   37 +++++++++++--------------------------
+ net/bridge/br_private.h   |    1 +
+ 2 files changed, 12 insertions(+), 26 deletions(-)
+
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index 97b06de..ceb364a 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -677,8 +677,6 @@ rehash:
+ 
+ 	mp->br = br;
+ 	mp->addr = *group;
+-	setup_timer(&mp->timer, br_multicast_group_expired,
+-		    (unsigned long)mp);
+ 	setup_timer(&mp->query_timer, br_multicast_group_query_expired,
+ 		    (unsigned long)mp);
+ 
+@@ -696,7 +694,6 @@ static int br_multicast_add_group(struct net_bridge *br,
+ 	struct net_bridge_mdb_entry *mp;
+ 	struct net_bridge_port_group *p;
+ 	struct net_bridge_port_group **pp;
+-	unsigned long now = jiffies;
+ 	int err;
+ 
+ 	spin_lock(&br->multicast_lock);
+@@ -712,13 +709,12 @@ static int br_multicast_add_group(struct net_bridge *br,
+ 	if (!port) {
+ 		if (hlist_unhashed(&mp->mglist))
+ 			hlist_add_head(&mp->mglist, &br->mglist);
+-		mod_timer(&mp->timer, now + br->multicast_membership_interval);
+ 		goto out;
+ 	}
+ 
+ 	for (pp = &mp->ports; (p = *pp); pp = &p->next) {
+ 		if (p->port == port)
+-			goto found;
++			goto out;
+ 		if ((unsigned long)p->port < (unsigned long)port)
+ 			break;
+ 	}
+@@ -739,8 +735,6 @@ static int br_multicast_add_group(struct net_bridge *br,
+ 
+ 	rcu_assign_pointer(*pp, p);
+ 
+-found:
+-	mod_timer(&p->timer, now + br->multicast_membership_interval);
+ out:
+ 	err = 0;
+ 
+@@ -1151,6 +1145,10 @@ static int br_ip4_multicast_query(struct net_bridge *br,
+ 	if (!mp)
+ 		goto out;
+ 
++        setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp);
++        mod_timer(&mp->timer, now + br->multicast_membership_interval);
++        mp->timer_armed = true;
++
+ 	max_delay *= br->multicast_last_member_count;
+ 
+ 	if (!hlist_unhashed(&mp->mglist) &&
+@@ -1220,6 +1218,10 @@ static int br_ip6_multicast_query(struct net_bridge *br,
+ 	if (!mp)
+ 		goto out;
+ 
++	setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp);
++	mod_timer(&mp->timer, now + br->multicast_membership_interval);
++	mp->timer_armed = true;
++
+ 	max_delay *= br->multicast_last_member_count;
+ 	if (!hlist_unhashed(&mp->mglist) &&
+ 	    (timer_pending(&mp->timer) ?
+@@ -1266,7 +1268,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
+ 		     br->multicast_last_member_interval;
+ 
+ 	if (!port) {
+-		if (!hlist_unhashed(&mp->mglist) &&
++		if (!hlist_unhashed(&mp->mglist) && mp->timer_armed &&
+ 		    (timer_pending(&mp->timer) ?
+ 		     time_after(mp->timer.expires, time) :
+ 		     try_to_del_timer_sync(&mp->timer) >= 0)) {
+@@ -1276,24 +1278,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
+ 			mod_timer(&mp->query_timer, now);
+ 		}
+ 
+-		goto out;
+-	}
+-
+-	for (p = mp->ports; p; p = p->next) {
+-		if (p->port != port)
+-			continue;
+-
+-		if (!hlist_unhashed(&p->mglist) &&
+-		    (timer_pending(&p->timer) ?
+-		     time_after(p->timer.expires, time) :
+-		     try_to_del_timer_sync(&p->timer) >= 0)) {
+-			mod_timer(&p->timer, time);
+-
+-			p->queries_sent = 0;
+-			mod_timer(&p->query_timer, now);
+-		}
+-
+-		break;
+ 	}
+ 
+ out:
+@@ -1650,6 +1634,7 @@ void br_multicast_stop(struct net_bridge *br)
+ 		hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i],
+ 					  hlist[ver]) {
+ 			del_timer(&mp->timer);
++			mp->timer_armed = false;
+ 			del_timer(&mp->query_timer);
+ 			call_rcu_bh(&mp->rcu, br_multicast_free_group);
+ 		}
+diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
+index 03a4afc..e8ecef1 100644
+--- a/net/bridge/br_private.h
++++ b/net/bridge/br_private.h
+@@ -91,6 +91,7 @@ struct net_bridge_mdb_entry
+ 	struct timer_list		query_timer;
+ 	struct br_ip			addr;
+ 	u32				queries_sent;
++	bool 				timer_armed;
+ };
+ 
+ struct net_bridge_mdb_htable
+-- 
+1.7.10.4
+
diff --git a/0002-bridge-send-query-as-soon-as-leave-is-received.patch b/0002-bridge-send-query-as-soon-as-leave-is-received.patch
new file mode 100644
index 0000000..6ba5e46
--- /dev/null
+++ b/0002-bridge-send-query-as-soon-as-leave-is-received.patch
@@ -0,0 +1,58 @@
+From fa6209a8834a92dc83dd31451738cb6a46c18126 Mon Sep 17 00:00:00 2001
+From: Alexandre Derumier <aderumier at odiso.com>
+Date: Mon, 3 Jun 2013 17:35:42 +0200
+Subject: [PATCH 2/2] bridge: send query as soon as leave is received
+
+Continue sending queries when leave is received if the user marks it as a querier.
+
+Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
+---
+ net/bridge/br_multicast.c |   25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index ceb364a..cb308ff 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -1249,6 +1249,8 @@ static void br_multicast_leave_group(struct net_bridge *br,
+ 	struct net_bridge_mdb_htable *mdb;
+ 	struct net_bridge_mdb_entry *mp;
+ 	struct net_bridge_port_group *p;
++        struct net_bridge_port_group **pp;
++
+ 	unsigned long now;
+ 	unsigned long time;
+ 
+@@ -1263,6 +1265,29 @@ static void br_multicast_leave_group(struct net_bridge *br,
+ 	if (!mp)
+ 		goto out;
+ 
++	if (br->multicast_querier &&
++	    !timer_pending(&br->multicast_querier_timer)) {
++		__br_multicast_send_query(br, port, &mp->addr);
++
++		time = jiffies + br->multicast_last_member_count *
++				 br->multicast_last_member_interval;
++		mod_timer(port ? &port->multicast_query_timer :
++				 &br->multicast_query_timer, time);
++
++		for (pp = &mp->ports; (p = *pp); pp = &p->next) {
++			if (p->port != port)
++				continue;
++
++			if (!hlist_unhashed(&p->mglist) &&
++			    (timer_pending(&p->timer) ?
++			     time_after(p->timer.expires, time) :
++			     try_to_del_timer_sync(&p->timer) >= 0)) {
++				mod_timer(&p->timer, time);
++			}
++
++			break;
++		}
++	}
+ 	now = jiffies;
+ 	time = now + br->multicast_last_member_count *
+ 		     br->multicast_last_member_interval;
+-- 
+1.7.10.4
+
diff --git a/Makefile b/Makefile
index b302edd..f528014 100644
--- a/Makefile
+++ b/Makefile
@@ -149,6 +149,8 @@ ${KERNEL_SRC}/README: ${KERNEL_SRC}.org/README
 	cd ${KERNEL_SRC}; patch -p1 <../0003-bridge-disable-querier.patch
 	cd ${KERNEL_SRC}; patch -p1 <../0004-bridge-disable-querier.patch
 	cd ${KERNEL_SRC}; patch -p1 <../0005-bridge-disable-querier.patch
+	cd ${KERNEL_SRC}; patch -p1 <../0001-bridge-only-expire-the-mdb-entry-when-query-is-recei.patch
+	cd ${KERNEL_SRC}; patch -p1 <../0002-bridge-send-query-as-soon-as-leave-is-received.patch
 	cd ${KERNEL_SRC}; patch -p1 <../fix-aspm-policy.patch
 	cd ${KERNEL_SRC}; patch -p1 <../kbuild-generate-mudules-builtin.patch
 	cd ${KERNEL_SRC}; patch -p1 <../add-tiocgdev-ioctl.patch
-- 
1.7.10.4




More information about the pve-devel mailing list