Skip to content

Commit

Permalink
Merge branch 'bridge-vlan-fixes'
Browse files Browse the repository at this point in the history
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 <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 17, 2021
2 parents 2cb5942 + affce9a commit 4aefc79
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 17 deletions.
30 changes: 30 additions & 0 deletions net/bridge/br_mdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,36 @@ br_ip6_rports_get_timer(struct net_bridge_mcast_port *pmctx,
#endif
}

static size_t __br_rports_one_size(void)
{
return nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PORT */
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_TIMER */
nla_total_size(sizeof(u8)) + /* MDBA_ROUTER_PATTR_TYPE */
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_INET_TIMER */
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_INET6_TIMER */
nla_total_size(sizeof(u32)); /* MDBA_ROUTER_PATTR_VID */
}

size_t br_rports_size(const struct net_bridge_mcast *brmctx)
{
struct net_bridge_mcast_port *pmctx;
size_t size = nla_total_size(0); /* MDBA_ROUTER */

rcu_read_lock();
hlist_for_each_entry_rcu(pmctx, &brmctx->ip4_mc_router_list,
ip4_rlist)
size += __br_rports_one_size();

#if IS_ENABLED(CONFIG_IPV6)
hlist_for_each_entry_rcu(pmctx, &brmctx->ip6_mc_router_list,
ip6_rlist)
size += __br_rports_one_size();
#endif
rcu_read_unlock();

return size;
}

int br_rports_fill_info(struct sk_buff *skb,
const struct net_bridge_mcast *brmctx)
{
Expand Down
10 changes: 7 additions & 3 deletions net/bridge/br_multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ br_multicast_pg_to_port_ctx(const struct net_bridge_port_group *pg)
* can safely be used on return
*/
rcu_read_lock();
vlan = br_vlan_find(nbp_vlan_group(pg->key.port), pg->key.addr.vid);
vlan = br_vlan_find(nbp_vlan_group_rcu(pg->key.port), pg->key.addr.vid);
if (vlan && !br_multicast_port_ctx_vlan_disabled(&vlan->port_mcast_ctx))
pmctx = &vlan->port_mcast_ctx;
else
Expand Down Expand Up @@ -4074,7 +4074,7 @@ void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on)
}
}

void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan, bool on)
static void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan, bool on)
{
struct net_bridge_port *p;

Expand All @@ -4089,6 +4089,9 @@ void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan, bool on)
continue;
br_multicast_toggle_one_vlan(vport, on);
}

if (br_vlan_is_brentry(vlan))
br_multicast_toggle_one_vlan(vlan, on);
}

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

vlan = br_vlan_find(nbp_vlan_group(port), brmctx->vlan->vid);
vlan = br_vlan_find(nbp_vlan_group_rcu(port),
brmctx->vlan->vid);
if (!vlan ||
br_multicast_port_ctx_state_stopped(&vlan->port_mcast_ctx))
continue;
Expand Down
7 changes: 1 addition & 6 deletions net/bridge/br_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -938,7 +938,6 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,
struct net_bridge_mcast_port *pmctx);
void br_multicast_port_ctx_deinit(struct net_bridge_mcast_port *pmctx);
void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan, bool on);
void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan, bool on);
int br_multicast_toggle_vlan_snooping(struct net_bridge *br, bool on,
struct netlink_ext_ack *extack);
bool br_multicast_toggle_global_vlan(struct net_bridge_vlan *vlan, bool on);
Expand All @@ -952,6 +951,7 @@ int br_multicast_dump_querier_state(struct sk_buff *skb,
const struct net_bridge_mcast *brmctx,
int nest_attr);
size_t br_multicast_querier_state_size(void);
size_t br_rports_size(const struct net_bridge_mcast *brmctx);

static inline bool br_group_is_l2(const struct br_ip *group)
{
Expand Down Expand Up @@ -1369,11 +1369,6 @@ static inline void br_multicast_toggle_one_vlan(struct net_bridge_vlan *vlan,
{
}

static inline void br_multicast_toggle_vlan(struct net_bridge_vlan *vlan,
bool on)
{
}

static inline int br_multicast_toggle_vlan_snooping(struct net_bridge *br,
bool on,
struct netlink_ext_ack *extack)
Expand Down
1 change: 1 addition & 0 deletions net/bridge/br_vlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,7 @@ static int br_vlan_add_existing(struct net_bridge *br,
vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY;
vg->num_vlans++;
*changed = true;
br_multicast_toggle_one_vlan(vlan, true);
}

if (__vlan_add_flags(vlan, flags))
Expand Down
17 changes: 9 additions & 8 deletions net/bridge/br_vlan_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
return false;
}

static size_t rtnl_vlan_global_opts_nlmsg_size(void)
static size_t rtnl_vlan_global_opts_nlmsg_size(const struct net_bridge_vlan *v)
{
return NLMSG_ALIGN(sizeof(struct br_vlan_msg))
+ nla_total_size(0) /* BRIDGE_VLANDB_GLOBAL_OPTIONS */
Expand All @@ -382,6 +382,8 @@ static size_t rtnl_vlan_global_opts_nlmsg_size(void)
+ nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER */
+ nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER */
+ br_multicast_querier_state_size() /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE */
+ nla_total_size(0) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */
+ br_rports_size(&v->br_mcast_ctx) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */
#endif
+ nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */
}
Expand All @@ -398,7 +400,12 @@ static void br_vlan_global_opts_notify(const struct net_bridge *br,
/* right now notifications are done only with rtnl held */
ASSERT_RTNL();

skb = nlmsg_new(rtnl_vlan_global_opts_nlmsg_size(), GFP_KERNEL);
/* need to find the vlan due to flags/options */
v = br_vlan_find(br_vlan_group(br), vid);
if (!v)
return;

skb = nlmsg_new(rtnl_vlan_global_opts_nlmsg_size(v), GFP_KERNEL);
if (!skb)
goto out_err;

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

/* need to find the vlan due to flags/options */
v = br_vlan_find(br_vlan_group(br), vid);
if (!v)
goto out_kfree;

if (!br_vlan_global_opts_fill(skb, vid, vid_range, v))
goto out_err;

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

out_err:
rtnl_set_sk_err(dev_net(br->dev), RTNLGRP_BRVLAN, err);
out_kfree:
kfree_skb(skb);
}

Expand Down

0 comments on commit 4aefc79

Please sign in to comment.