summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Boyer <jwboyer@redhat.com>2013-06-26 07:50:55 -0400
committerJosh Boyer <jwboyer@redhat.com>2013-06-26 07:51:29 -0400
commit69c0bf478219b2fbb38fb3c707b220b75bfa4129 (patch)
tree05c8bb10cd71353428b266b9078c40c5c4adb01d
parent0a517e3c24f320b2b6336a3413fd9884bc36c954 (diff)
downloadkernel-69c0bf478219b2fbb38fb3c707b220b75bfa4129.tar.gz
kernel-69c0bf478219b2fbb38fb3c707b220b75bfa4129.tar.xz
kernel-69c0bf478219b2fbb38fb3c707b220b75bfa4129.zip
Add two patches to fix bridge networking issues (rhbz 880035)
-rw-r--r--bridge-only-expire-the-mdb-entry-when-query-is-received.patch159
-rw-r--r--bridge-send-query-as-soon-as-leave-is-received.patch57
-rw-r--r--kernel.spec11
3 files changed, 227 insertions, 0 deletions
diff --git a/bridge-only-expire-the-mdb-entry-when-query-is-received.patch b/bridge-only-expire-the-mdb-entry-when-query-is-received.patch
new file mode 100644
index 000000000..b58b57083
--- /dev/null
+++ b/bridge-only-expire-the-mdb-entry-when-query-is-received.patch
@@ -0,0 +1,159 @@
+From 9f00b2e7cf241fa389733d41b615efdaa2cb0f5b Mon Sep 17 00:00:00 2001
+From: Cong Wang <amwang@redhat.com>
+Date: Tue, 21 May 2013 21:52:55 +0000
+Subject: 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."
+
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Stephen Hemminger <stephen@networkplumber.org>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Adam Baker <linux@baker-net.org.uk>
+Signed-off-by: Cong Wang <amwang@redhat.com>
+Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+(limited to 'net/bridge')
+
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index 2475147..40bda80 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -617,8 +617,6 @@ rehash:
+
+ mp->br = br;
+ mp->addr = *group;
+- setup_timer(&mp->timer, br_multicast_group_expired,
+- (unsigned long)mp);
+
+ hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);
+ mdb->size++;
+@@ -656,7 +654,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 __rcu **pp;
+- unsigned long now = jiffies;
+ int err;
+
+ spin_lock(&br->multicast_lock);
+@@ -671,7 +668,6 @@ static int br_multicast_add_group(struct net_bridge *br,
+
+ if (!port) {
+ mp->mglist = true;
+- mod_timer(&mp->timer, now + br->multicast_membership_interval);
+ goto out;
+ }
+
+@@ -679,7 +675,7 @@ static int br_multicast_add_group(struct net_bridge *br,
+ (p = mlock_dereference(*pp, br)) != NULL;
+ pp = &p->next) {
+ if (p->port == port)
+- goto found;
++ goto out;
+ if ((unsigned long)p->port < (unsigned long)port)
+ break;
+ }
+@@ -690,8 +686,6 @@ static int br_multicast_add_group(struct net_bridge *br,
+ rcu_assign_pointer(*pp, p);
+ br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
+
+-found:
+- mod_timer(&p->timer, now + br->multicast_membership_interval);
+ out:
+ err = 0;
+
+@@ -1131,6 +1125,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 (mp->mglist &&
+@@ -1205,6 +1203,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 (mp->mglist &&
+ (timer_pending(&mp->timer) ?
+@@ -1263,7 +1265,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
+ call_rcu_bh(&p->rcu, br_multicast_free_pg);
+ br_mdb_notify(br->dev, port, group, RTM_DELMDB);
+
+- if (!mp->ports && !mp->mglist &&
++ if (!mp->ports && !mp->mglist && mp->timer_armed &&
+ netif_running(br->dev))
+ mod_timer(&mp->timer, jiffies);
+ }
+@@ -1275,30 +1277,12 @@ static void br_multicast_leave_group(struct net_bridge *br,
+ br->multicast_last_member_interval;
+
+ if (!port) {
+- if (mp->mglist &&
++ if (mp->mglist && mp->timer_armed &&
+ (timer_pending(&mp->timer) ?
+ time_after(mp->timer.expires, time) :
+ try_to_del_timer_sync(&mp->timer) >= 0)) {
+ mod_timer(&mp->timer, time);
+ }
+-
+- goto out;
+- }
+-
+- for (p = mlock_dereference(mp->ports, br);
+- p != NULL;
+- p = mlock_dereference(p->next, br)) {
+- 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;
+ }
+
+ out:
+@@ -1674,6 +1658,7 @@ void br_multicast_stop(struct net_bridge *br)
+ hlist_for_each_entry_safe(mp, n, &mdb->mhash[i],
+ hlist[ver]) {
+ del_timer(&mp->timer);
++ mp->timer_armed = false;
+ call_rcu_bh(&mp->rcu, br_multicast_free_group);
+ }
+ }
+diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
+index e260710..1b0ac95 100644
+--- a/net/bridge/br_private.h
++++ b/net/bridge/br_private.h
+@@ -112,6 +112,7 @@ struct net_bridge_mdb_entry
+ struct timer_list timer;
+ struct br_ip addr;
+ bool mglist;
++ bool timer_armed;
+ };
+
+ struct net_bridge_mdb_htable
+--
+cgit v0.9.2
diff --git a/bridge-send-query-as-soon-as-leave-is-received.patch b/bridge-send-query-as-soon-as-leave-is-received.patch
new file mode 100644
index 000000000..8b6652e7e
--- /dev/null
+++ b/bridge-send-query-as-soon-as-leave-is-received.patch
@@ -0,0 +1,57 @@
+From 6b7df111ece130fa979a0c4f58e53674c1e47d3e Mon Sep 17 00:00:00 2001
+From: Cong Wang <amwang@redhat.com>
+Date: Tue, 21 May 2013 21:52:56 +0000
+Subject: bridge: send query as soon as leave is received
+
+Continue sending queries when leave is received if the user marks
+it as a querier.
+
+Cc: Herbert Xu <herbert@gondor.apana.org.au>
+Cc: Stephen Hemminger <stephen@networkplumber.org>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Adam Baker <linux@baker-net.org.uk>
+Signed-off-by: Cong Wang <amwang@redhat.com>
+Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+(limited to 'net/bridge')
+
+diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
+index 40bda80..37a4676 100644
+--- a/net/bridge/br_multicast.c
++++ b/net/bridge/br_multicast.c
+@@ -1250,6 +1250,32 @@ 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 (p = mlock_dereference(mp->ports, br);
++ p != NULL;
++ p = mlock_dereference(p->next, br)) {
++ 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;
++ }
++ }
++
+ if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
+ struct net_bridge_port_group __rcu **pp;
+
+--
+cgit v0.9.2
diff --git a/kernel.spec b/kernel.spec
index 60e7df687..27fd3f20b 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -781,6 +781,10 @@ Patch25047: drm-radeon-Disable-writeback-by-default-on-ppc.patch
#rhbz 903741
Patch25052: HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch
+#rhbz 880035
+Patch25053: bridge-only-expire-the-mdb-entry-when-query-is-received.patch
+Patch25054: bridge-send-query-as-soon-as-leave-is-received.patch
+
# END OF PATCH DEFINITIONS
%endif
@@ -1490,6 +1494,10 @@ ApplyPatch drm-radeon-Disable-writeback-by-default-on-ppc.patch
#rhbz 903741
ApplyPatch HID-input-return-ENODATA-if-reading-battery-attrs-fails.patch
+#rhbz 880035
+ApplyPatch bridge-only-expire-the-mdb-entry-when-query-is-received.patch
+ApplyPatch bridge-send-query-as-soon-as-leave-is-received.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -2286,6 +2294,9 @@ fi
# ||----w |
# || ||
%changelog
+* Wed Jun 26 2013 Josh Boyer <jwboyer@redhat.com>
+- Add two patches to fix bridge networking issues (rhbz 880035)
+
* Mon Jun 24 2013 Josh Boyer <jwboyer@redhat.com>
- Fix battery issue with bluetooth keyboards (rhbz 903741)