* [Patch net-next v4 2/3] bridge: only expire the mdb entry when query is received
2013-05-17 1:59 [Patch net-next v4 1/3] bridge: use the bridge IP addr as source addr for querier Cong Wang
@ 2013-05-17 1:59 ` Cong Wang
2013-05-17 1:59 ` [Patch net-next v4 3/3] bridge: send query as soon as leave " Cong Wang
2013-05-17 2:08 ` [Patch net-next v4 1/3] bridge: use the bridge IP addr as source addr for querier Cong Wang
2 siblings, 0 replies; 4+ messages in thread
From: Cong Wang @ 2013-05-17 1:59 UTC (permalink / raw)
To: netdev
Cc: Herbert Xu, Stephen Hemminger, David S. Miller, Adam Baker,
Cong Wang
From: Cong Wang <amwang@redhat.com>
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 said "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>
---
v4: remove some useless timer code
v3: fix the code in br_multicast_leave_group()
v2: add a flag to check if timer is fired or not
net/bridge/br_multicast.c | 39 ++++++++++++---------------------------
net/bridge/br_private.h | 1 +
2 files changed, 13 insertions(+), 27 deletions(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index c52d4f3..9b589bd 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 695033f..cd2552c 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
--
1.7.7.6
^ permalink raw reply related [flat|nested] 4+ messages in thread* [Patch net-next v4 3/3] bridge: send query as soon as leave is received
2013-05-17 1:59 [Patch net-next v4 1/3] bridge: use the bridge IP addr as source addr for querier Cong Wang
2013-05-17 1:59 ` [Patch net-next v4 2/3] bridge: only expire the mdb entry when query is received Cong Wang
@ 2013-05-17 1:59 ` Cong Wang
2013-05-17 2:08 ` [Patch net-next v4 1/3] bridge: use the bridge IP addr as source addr for querier Cong Wang
2 siblings, 0 replies; 4+ messages in thread
From: Cong Wang @ 2013-05-17 1:59 UTC (permalink / raw)
To: netdev
Cc: Herbert Xu, Stephen Hemminger, David S. Miller, Adam Baker,
Cong Wang
From: Cong Wang <amwang@redhat.com>
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>
---
v4: use the right timeout value
re-arm timers here
v3: use non-general query
v2: only send query to the port received leave
net/bridge/br_multicast.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 9b589bd..1e414ce 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;
--
1.7.7.6
^ permalink raw reply related [flat|nested] 4+ messages in thread