Skip to content

Commit 4cdd0d1

Browse files
Nikolay Aleksandrovdavem330
authored andcommitted
net: bridge: multicast: check if should use vlan mcast ctx
Add helpers which check if the current bridge/port multicast context should be used (i.e. they're not disabled) and use them for Rx IGMP/MLD processing, timers and new group addition. It is important for vlans to disable processing of timer/packet after the multicast_lock is obtained if the vlan context doesn't have BR_VLFLAG_MCAST_ENABLED. There are two cases when that flag is missing: - if the vlan is getting destroyed it will be removed and timers will be stopped - if the vlan mcast snooping is being disabled Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent eb1593a commit 4cdd0d1

File tree

2 files changed

+62
-15
lines changed

2 files changed

+62
-15
lines changed

net/bridge/br_multicast.c

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge_mcast *brmctx,
147147
struct net_bridge *br = brmctx->br;
148148
struct br_ip ip;
149149

150-
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
150+
if (!br_opt_get(br, BROPT_MULTICAST_ENABLED) ||
151+
br_multicast_ctx_vlan_global_disabled(brmctx))
151152
return NULL;
152153

153154
if (BR_INPUT_SKB_CB(skb)->igmp)
@@ -230,6 +231,24 @@ br_multicast_pg_to_port_ctx(const struct net_bridge_port_group *pg)
230231
return pmctx;
231232
}
232233

234+
/* when snooping we need to check if the contexts should be used
235+
* in the following order:
236+
* - if pmctx is non-NULL (port), check if it should be used
237+
* - if pmctx is NULL (bridge), check if brmctx should be used
238+
*/
239+
static bool
240+
br_multicast_ctx_should_use(const struct net_bridge_mcast *brmctx,
241+
const struct net_bridge_mcast_port *pmctx)
242+
{
243+
if (!netif_running(brmctx->br->dev))
244+
return false;
245+
246+
if (pmctx)
247+
return !br_multicast_port_ctx_state_disabled(pmctx);
248+
else
249+
return !br_multicast_ctx_vlan_disabled(brmctx);
250+
}
251+
233252
static bool br_port_group_equal(struct net_bridge_port_group *p,
234253
struct net_bridge_port *port,
235254
const unsigned char *src)
@@ -1311,8 +1330,7 @@ __br_multicast_add_group(struct net_bridge_mcast *brmctx,
13111330
struct net_bridge_mdb_entry *mp;
13121331
unsigned long now = jiffies;
13131332

1314-
if (!netif_running(brmctx->br->dev) ||
1315-
(pmctx && pmctx->port->state == BR_STATE_DISABLED))
1333+
if (!br_multicast_ctx_should_use(brmctx, pmctx))
13161334
goto out;
13171335

13181336
mp = br_multicast_new_group(brmctx->br, group);
@@ -1532,6 +1550,7 @@ static void br_multicast_querier_expired(struct net_bridge_mcast *brmctx,
15321550
{
15331551
spin_lock(&brmctx->br->multicast_lock);
15341552
if (!netif_running(brmctx->br->dev) ||
1553+
br_multicast_ctx_vlan_global_disabled(brmctx) ||
15351554
!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED))
15361555
goto out;
15371556

@@ -1619,7 +1638,7 @@ static void br_multicast_send_query(struct net_bridge_mcast *brmctx,
16191638
struct br_ip br_group;
16201639
unsigned long time;
16211640

1622-
if (!netif_running(brmctx->br->dev) ||
1641+
if (!br_multicast_ctx_should_use(brmctx, pmctx) ||
16231642
!br_opt_get(brmctx->br, BROPT_MULTICAST_ENABLED) ||
16241643
!br_opt_get(brmctx->br, BROPT_MULTICAST_QUERIER))
16251644
return;
@@ -1655,16 +1674,16 @@ br_multicast_port_query_expired(struct net_bridge_mcast_port *pmctx,
16551674
struct bridge_mcast_own_query *query)
16561675
{
16571676
struct net_bridge *br = pmctx->port->br;
1677+
struct net_bridge_mcast *brmctx;
16581678

16591679
spin_lock(&br->multicast_lock);
1660-
if (pmctx->port->state == BR_STATE_DISABLED ||
1661-
pmctx->port->state == BR_STATE_BLOCKING)
1680+
if (br_multicast_port_ctx_state_stopped(pmctx))
16621681
goto out;
1663-
1664-
if (query->startup_sent < br->multicast_ctx.multicast_startup_query_count)
1682+
brmctx = br_multicast_port_ctx_get_global(pmctx);
1683+
if (query->startup_sent < brmctx->multicast_startup_query_count)
16651684
query->startup_sent++;
16661685

1667-
br_multicast_send_query(&br->multicast_ctx, pmctx, query);
1686+
br_multicast_send_query(brmctx, pmctx, query);
16681687

16691688
out:
16701689
spin_unlock(&br->multicast_lock);
@@ -2582,6 +2601,9 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge_mcast *brmctx,
25822601
continue;
25832602

25842603
spin_lock_bh(&brmctx->br->multicast_lock);
2604+
if (!br_multicast_ctx_should_use(brmctx, pmctx))
2605+
goto unlock_continue;
2606+
25852607
mdst = br_mdb_ip4_get(brmctx->br, group, vid);
25862608
if (!mdst)
25872609
goto unlock_continue;
@@ -2717,6 +2739,9 @@ static int br_ip6_multicast_mld2_report(struct net_bridge_mcast *brmctx,
27172739
continue;
27182740

27192741
spin_lock_bh(&brmctx->br->multicast_lock);
2742+
if (!br_multicast_ctx_should_use(brmctx, pmctx))
2743+
goto unlock_continue;
2744+
27202745
mdst = br_mdb_ip6_get(brmctx->br, &grec->grec_mca, vid);
27212746
if (!mdst)
27222747
goto unlock_continue;
@@ -2962,6 +2987,9 @@ static void br_multicast_mark_router(struct net_bridge_mcast *brmctx,
29622987
{
29632988
unsigned long now = jiffies;
29642989

2990+
if (!br_multicast_ctx_should_use(brmctx, pmctx))
2991+
return;
2992+
29652993
if (!pmctx) {
29662994
if (brmctx->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) {
29672995
if (!br_ip4_multicast_is_router(brmctx) &&
@@ -3060,8 +3088,7 @@ static void br_ip4_multicast_query(struct net_bridge_mcast *brmctx,
30603088
__be32 group;
30613089

30623090
spin_lock(&brmctx->br->multicast_lock);
3063-
if (!netif_running(brmctx->br->dev) ||
3064-
(pmctx && pmctx->port->state == BR_STATE_DISABLED))
3091+
if (!br_multicast_ctx_should_use(brmctx, pmctx))
30653092
goto out;
30663093

30673094
group = ih->group;
@@ -3144,8 +3171,7 @@ static int br_ip6_multicast_query(struct net_bridge_mcast *brmctx,
31443171
int err = 0;
31453172

31463173
spin_lock(&brmctx->br->multicast_lock);
3147-
if (!netif_running(brmctx->br->dev) ||
3148-
(pmctx && pmctx->port->state == BR_STATE_DISABLED))
3174+
if (!br_multicast_ctx_should_use(brmctx, pmctx))
31493175
goto out;
31503176

31513177
if (transport_len == sizeof(*mld)) {
@@ -3229,8 +3255,7 @@ br_multicast_leave_group(struct net_bridge_mcast *brmctx,
32293255
unsigned long time;
32303256

32313257
spin_lock(&brmctx->br->multicast_lock);
3232-
if (!netif_running(brmctx->br->dev) ||
3233-
(pmctx && pmctx->port->state == BR_STATE_DISABLED))
3258+
if (!br_multicast_ctx_should_use(brmctx, pmctx))
32343259
goto out;
32353260

32363261
mp = br_mdb_ip_get(brmctx->br, group);
@@ -3609,11 +3634,15 @@ static void br_multicast_query_expired(struct net_bridge_mcast *brmctx,
36093634
struct bridge_mcast_querier *querier)
36103635
{
36113636
spin_lock(&brmctx->br->multicast_lock);
3637+
if (br_multicast_ctx_vlan_disabled(brmctx))
3638+
goto out;
3639+
36123640
if (query->startup_sent < brmctx->multicast_startup_query_count)
36133641
query->startup_sent++;
36143642

36153643
RCU_INIT_POINTER(querier->port, NULL);
36163644
br_multicast_send_query(brmctx, NULL, query);
3645+
out:
36173646
spin_unlock(&brmctx->br->multicast_lock);
36183647
}
36193648

net/bridge/br_private.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,24 @@ br_multicast_port_ctx_vlan_disabled(const struct net_bridge_mcast_port *pmctx)
11131113
return br_multicast_port_ctx_is_vlan(pmctx) &&
11141114
!(pmctx->vlan->priv_flags & BR_VLFLAG_MCAST_ENABLED);
11151115
}
1116+
1117+
static inline bool
1118+
br_multicast_port_ctx_state_disabled(const struct net_bridge_mcast_port *pmctx)
1119+
{
1120+
return pmctx->port->state == BR_STATE_DISABLED ||
1121+
(br_multicast_port_ctx_is_vlan(pmctx) &&
1122+
(br_multicast_port_ctx_vlan_disabled(pmctx) ||
1123+
pmctx->vlan->state == BR_STATE_DISABLED));
1124+
}
1125+
1126+
static inline bool
1127+
br_multicast_port_ctx_state_stopped(const struct net_bridge_mcast_port *pmctx)
1128+
{
1129+
return br_multicast_port_ctx_state_disabled(pmctx) ||
1130+
pmctx->port->state == BR_STATE_BLOCKING ||
1131+
(br_multicast_port_ctx_is_vlan(pmctx) &&
1132+
pmctx->vlan->state == BR_STATE_BLOCKING);
1133+
}
11161134
#else
11171135
static inline int br_multicast_rcv(struct net_bridge_mcast **brmctx,
11181136
struct net_bridge_mcast_port **pmctx,

0 commit comments

Comments
 (0)