Skip to content

Commit 4aefc79

Browse files
committed
Merge branch 'bridge-vlan-fixes'
Nikolay Aleksandrov says: ==================== net: bridge: vlan: fixes for vlan mcast contexts These are four fixes for vlan multicast contexts. The first patch enables mcast ctx snooping when adding already existing master vlans to be consistent with the rest of the code. The second patch accounts for the mcast ctx router ports when allocating skb for notification. The third one fixes two suspicious rcu usages due to wrong vlan group helper, and the fourth updates host vlan mcast state along with port mcast state. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 2cb5942 + affce9a commit 4aefc79

File tree

5 files changed

+48
-17
lines changed

5 files changed

+48
-17
lines changed

net/bridge/br_mdb.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,36 @@ br_ip6_rports_get_timer(struct net_bridge_mcast_port *pmctx,
3737
#endif
3838
}
3939

40+
static size_t __br_rports_one_size(void)
41+
{
42+
return nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PORT */
43+
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_TIMER */
44+
nla_total_size(sizeof(u8)) + /* MDBA_ROUTER_PATTR_TYPE */
45+
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_INET_TIMER */
46+
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_INET6_TIMER */
47+
nla_total_size(sizeof(u32)); /* MDBA_ROUTER_PATTR_VID */
48+
}
49+
50+
size_t br_rports_size(const struct net_bridge_mcast *brmctx)
51+
{
52+
struct net_bridge_mcast_port *pmctx;
53+
size_t size = nla_total_size(0); /* MDBA_ROUTER */
54+
55+
rcu_read_lock();
56+
hlist_for_each_entry_rcu(pmctx, &brmctx->ip4_mc_router_list,
57+
ip4_rlist)
58+
size += __br_rports_one_size();
59+
60+
#if IS_ENABLED(CONFIG_IPV6)
61+
hlist_for_each_entry_rcu(pmctx, &brmctx->ip6_mc_router_list,
62+
ip6_rlist)
63+
size += __br_rports_one_size();
64+
#endif
65+
rcu_read_unlock();
66+
67+
return size;
68+
}
69+
4070
int br_rports_fill_info(struct sk_buff *skb,
4171
const struct net_bridge_mcast *brmctx)
4272
{

net/bridge/br_multicast.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ br_multicast_pg_to_port_ctx(const struct net_bridge_port_group *pg)
221221
* can safely be used on return
222222
*/
223223
rcu_read_lock();
224-
vlan = br_vlan_find(nbp_vlan_group(pg->key.port), pg->key.addr.vid);
224+
vlan = br_vlan_find(nbp_vlan_group_rcu(pg->key.port), pg->key.addr.vid);
225225
if (vlan && !br_multicast_port_ctx_vlan_disabled(&vlan->port_mcast_ctx))
226226
pmctx = &vlan->port_mcast_ctx;
227227
else
@@ -4074,7 +4074,7 @@ void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
40744074
}
40754075
}
40764076

4077-
void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan, bool on)
4077+
static void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan, bool on)
40784078
{
40794079
struct net_bridge_port *p;
40804080

@@ -4089,6 +4089,9 @@ void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan, bool on)
40894089
continue;
40904090
br_multicast_toggle_one_vlan(vport, on);
40914091
}
4092+
4093+
if (br_vlan_is_brentry(vlan))
4094+
br_multicast_toggle_one_vlan(vlan, on);
40924095
}
40934096

40944097
int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
@@ -4329,7 +4332,8 @@ static void br_multicast_start_querier(struct net_bridge_mcast *brmctx,
43294332
if (br_multicast_ctx_is_vlan(brmctx)) {
43304333
struct net_bridge_vlan *vlan;
43314334

4332-
vlan = br_vlan_find(nbp_vlan_group(port), brmctx->vlan->vid);
4335+
vlan = br_vlan_find(nbp_vlan_group_rcu(port),
4336+
brmctx->vlan->vid);
43334337
if (!vlan ||
43344338
br_multicast_port_ctx_state_stopped(&vlan->port_mcast_ctx))
43354339
continue;

net/bridge/br_private.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -938,7 +938,6 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,
938938
struct net_bridge_mcast_port *pmctx);
939939
void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx);
940940
void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on);
941-
void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan, bool on);
942941
int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
943942
struct netlink_ext_ack *extack);
944943
bool br_multicast_toggle_global_vlan(struct net_bridge_vlan *vlan, bool on);
@@ -952,6 +951,7 @@ int br_multicast_dump_querier_state(struct sk_buff *skb,
952951
const struct net_bridge_mcast *brmctx,
953952
int nest_attr);
954953
size_t br_multicast_querier_state_size(void);
954+
size_t br_rports_size(const struct net_bridge_mcast *brmctx);
955955

956956
static inline bool br_group_is_l2(const struct br_ip *group)
957957
{
@@ -1369,11 +1369,6 @@ static inline void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan,
13691369
{
13701370
}
13711371

1372-
static inline void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan,
1373-
bool on)
1374-
{
1375-
}
1376-
13771372
static inline int br_multicast_toggle_vlan_snooping(struct net_bridge *br,
13781373
bool on,
13791374
struct netlink_ext_ack *extack)

net/bridge/br_vlan.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,7 @@ static int br_vlan_add_existing(struct net_bridge *br,
694694
vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY;
695695
vg->num_vlans++;
696696
*changed = true;
697+
br_multicast_toggle_one_vlan(vlan, true);
697698
}
698699

699700
if (__vlan_add_flags(vlan, flags))

net/bridge/br_vlan_options.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
362362
return false;
363363
}
364364

365-
static size_t rtnl_vlan_global_opts_nlmsg_size(void)
365+
static size_t rtnl_vlan_global_opts_nlmsg_size(const struct net_bridge_vlan *v)
366366
{
367367
return NLMSG_ALIGN(sizeof(struct br_vlan_msg))
368368
+ nla_total_size(0) /* BRIDGE_VLANDB_GLOBAL_OPTIONS */
@@ -382,6 +382,8 @@ static size_t rtnl_vlan_global_opts_nlmsg_size(void)
382382
+ nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER */
383383
+ nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER */
384384
+ br_multicast_querier_state_size() /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE */
385+
+ nla_total_size(0) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */
386+
+ br_rports_size(&v->br_mcast_ctx) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */
385387
#endif
386388
+ nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */
387389
}
@@ -398,7 +400,12 @@ static void br_vlan_global_opts_notify(const struct net_bridge *br,
398400
/* right now notifications are done only with rtnl held */
399401
ASSERT_RTNL();
400402

401-
skb = nlmsg_new(rtnl_vlan_global_opts_nlmsg_size(), GFP_KERNEL);
403+
/* need to find the vlan due to flags/options */
404+
v = br_vlan_find(br_vlan_group(br), vid);
405+
if (!v)
406+
return;
407+
408+
skb = nlmsg_new(rtnl_vlan_global_opts_nlmsg_size(v), GFP_KERNEL);
402409
if (!skb)
403410
goto out_err;
404411

@@ -411,11 +418,6 @@ static void br_vlan_global_opts_notify(const struct net_bridge *br,
411418
bvm->family = AF_BRIDGE;
412419
bvm->ifindex = br->dev->ifindex;
413420

414-
/* need to find the vlan due to flags/options */
415-
v = br_vlan_find(br_vlan_group(br), vid);
416-
if (!v)
417-
goto out_kfree;
418-
419421
if (!br_vlan_global_opts_fill(skb, vid, vid_range, v))
420422
goto out_err;
421423

@@ -425,7 +427,6 @@ static void br_vlan_global_opts_notify(const struct net_bridge *br,
425427

426428
out_err:
427429
rtnl_set_sk_err(dev_net(br->dev), RTNLGRP_BRVLAN, err);
428-
out_kfree:
429430
kfree_skb(skb);
430431
}
431432

0 commit comments

Comments
 (0)