Skip to content

Commit 9f00b2e

Browse files
Cong Wangdavem330
Cong Wang
authored andcommitted
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>
1 parent 1c8ad5b commit 9f00b2e

File tree

2 files changed

+13
-27
lines changed

2 files changed

+13
-27
lines changed

Diff for: net/bridge/br_multicast.c

+12-27
Original file line numberDiff line numberDiff line change
@@ -617,8 +617,6 @@ struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br,
617617

618618
mp->br = br;
619619
mp->addr = *group;
620-
setup_timer(&mp->timer, br_multicast_group_expired,
621-
(unsigned long)mp);
622620

623621
hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);
624622
mdb->size++;
@@ -656,7 +654,6 @@ static int br_multicast_add_group(struct net_bridge *br,
656654
struct net_bridge_mdb_entry *mp;
657655
struct net_bridge_port_group *p;
658656
struct net_bridge_port_group __rcu **pp;
659-
unsigned long now = jiffies;
660657
int err;
661658

662659
spin_lock(&br->multicast_lock);
@@ -671,15 +668,14 @@ static int br_multicast_add_group(struct net_bridge *br,
671668

672669
if (!port) {
673670
mp->mglist = true;
674-
mod_timer(&mp->timer, now + br->multicast_membership_interval);
675671
goto out;
676672
}
677673

678674
for (pp = &mp->ports;
679675
(p = mlock_dereference(*pp, br)) != NULL;
680676
pp = &p->next) {
681677
if (p->port == port)
682-
goto found;
678+
goto out;
683679
if ((unsigned long)p->port < (unsigned long)port)
684680
break;
685681
}
@@ -690,8 +686,6 @@ static int br_multicast_add_group(struct net_bridge *br,
690686
rcu_assign_pointer(*pp, p);
691687
br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
692688

693-
found:
694-
mod_timer(&p->timer, now + br->multicast_membership_interval);
695689
out:
696690
err = 0;
697691

@@ -1131,6 +1125,10 @@ static int br_ip4_multicast_query(struct net_bridge *br,
11311125
if (!mp)
11321126
goto out;
11331127

1128+
setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp);
1129+
mod_timer(&mp->timer, now + br->multicast_membership_interval);
1130+
mp->timer_armed = true;
1131+
11341132
max_delay *= br->multicast_last_member_count;
11351133

11361134
if (mp->mglist &&
@@ -1205,6 +1203,10 @@ static int br_ip6_multicast_query(struct net_bridge *br,
12051203
if (!mp)
12061204
goto out;
12071205

1206+
setup_timer(&mp->timer, br_multicast_group_expired, (unsigned long)mp);
1207+
mod_timer(&mp->timer, now + br->multicast_membership_interval);
1208+
mp->timer_armed = true;
1209+
12081210
max_delay *= br->multicast_last_member_count;
12091211
if (mp->mglist &&
12101212
(timer_pending(&mp->timer) ?
@@ -1263,7 +1265,7 @@ static void br_multicast_leave_group(struct net_bridge *br,
12631265
call_rcu_bh(&p->rcu, br_multicast_free_pg);
12641266
br_mdb_notify(br->dev, port, group, RTM_DELMDB);
12651267

1266-
if (!mp->ports && !mp->mglist &&
1268+
if (!mp->ports && !mp->mglist && mp->timer_armed &&
12671269
netif_running(br->dev))
12681270
mod_timer(&mp->timer, jiffies);
12691271
}
@@ -1275,30 +1277,12 @@ static void br_multicast_leave_group(struct net_bridge *br,
12751277
br->multicast_last_member_interval;
12761278

12771279
if (!port) {
1278-
if (mp->mglist &&
1280+
if (mp->mglist && mp->timer_armed &&
12791281
(timer_pending(&mp->timer) ?
12801282
time_after(mp->timer.expires, time) :
12811283
try_to_del_timer_sync(&mp->timer) >= 0)) {
12821284
mod_timer(&mp->timer, time);
12831285
}
1284-
1285-
goto out;
1286-
}
1287-
1288-
for (p = mlock_dereference(mp->ports, br);
1289-
p != NULL;
1290-
p = mlock_dereference(p->next, br)) {
1291-
if (p->port != port)
1292-
continue;
1293-
1294-
if (!hlist_unhashed(&p->mglist) &&
1295-
(timer_pending(&p->timer) ?
1296-
time_after(p->timer.expires, time) :
1297-
try_to_del_timer_sync(&p->timer) >= 0)) {
1298-
mod_timer(&p->timer, time);
1299-
}
1300-
1301-
break;
13021286
}
13031287

13041288
out:
@@ -1674,6 +1658,7 @@ void br_multicast_stop(struct net_bridge *br)
16741658
hlist_for_each_entry_safe(mp, n, &mdb->mhash[i],
16751659
hlist[ver]) {
16761660
del_timer(&mp->timer);
1661+
mp->timer_armed = false;
16771662
call_rcu_bh(&mp->rcu, br_multicast_free_group);
16781663
}
16791664
}

Diff for: net/bridge/br_private.h

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ struct net_bridge_mdb_entry
112112
struct timer_list timer;
113113
struct br_ip addr;
114114
bool mglist;
115+
bool timer_armed;
115116
};
116117

117118
struct net_bridge_mdb_htable

0 commit comments

Comments
 (0)