diff options
Diffstat (limited to 'freed-ora/current/f20/bridge-only-expire-the-mdb-entry-when-query-is-received.patch')
-rw-r--r-- | freed-ora/current/f20/bridge-only-expire-the-mdb-entry-when-query-is-received.patch | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/freed-ora/current/f20/bridge-only-expire-the-mdb-entry-when-query-is-received.patch b/freed-ora/current/f20/bridge-only-expire-the-mdb-entry-when-query-is-received.patch new file mode 100644 index 000000000..b58b57083 --- /dev/null +++ b/freed-ora/current/f20/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 |