Commit ee87c63f authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by Jakub Kicinski
Browse files

net: bridge: fix MST static key usage



As Ido pointed out, the static key usage in MST is buggy and should use
inc/dec instead of enable/disable because we can have multiple bridges
with MST enabled which means a single bridge can disable MST for all.
Use static_branch_inc/dec to avoid that. When destroying a bridge decrement
the key if MST was enabled.

Fixes: ec7328b5 ("net: bridge: mst: Multiple Spanning Tree (MST) mode")
Reported-by: default avatarIdo Schimmel <idosch@nvidia.com>
Closes: https://lore.kernel.org/netdev/20251104120313.1306566-1-razor@blackwall.org/T/#m6888d87658f94ed1725433940f4f4ebb00b5a68b


Signed-off-by: default avatarNikolay Aleksandrov <razor@blackwall.org>
Reviewed-by: default avatarIdo Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20251105111919.1499702-3-razor@blackwall.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 8dca3697
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -386,6 +386,7 @@ void br_dev_delete(struct net_device *dev, struct list_head *head)
		del_nbp(p);
	}

	br_mst_uninit(br);
	br_recalculate_neigh_suppress_enabled(br);

	br_fdb_delete_by_port(br, NULL, 0, 1);
+8 −2
Original line number Diff line number Diff line
@@ -22,6 +22,12 @@ bool br_mst_enabled(const struct net_device *dev)
}
EXPORT_SYMBOL_GPL(br_mst_enabled);

void br_mst_uninit(struct net_bridge *br)
{
	if (br_opt_get(br, BROPT_MST_ENABLED))
		static_branch_dec(&br_mst_used);
}

int br_mst_get_info(const struct net_device *dev, u16 msti, unsigned long *vids)
{
	const struct net_bridge_vlan_group *vg;
@@ -225,9 +231,9 @@ int br_mst_set_enabled(struct net_bridge *br, bool on,
		return err;

	if (on)
		static_branch_enable(&br_mst_used);
		static_branch_inc(&br_mst_used);
	else
		static_branch_disable(&br_mst_used);
		static_branch_dec(&br_mst_used);

	br_opt_toggle(br, BROPT_MST_ENABLED, on);
	return 0;
+5 −0
Original line number Diff line number Diff line
@@ -1954,6 +1954,7 @@ int br_mst_fill_info(struct sk_buff *skb,
		     const struct net_bridge_vlan_group *vg);
int br_mst_process(struct net_bridge_port *p, const struct nlattr *mst_attr,
		   struct netlink_ext_ack *extack);
void br_mst_uninit(struct net_bridge *br);
#else
static inline bool br_mst_is_enabled(const struct net_bridge_port *p)
{
@@ -1989,6 +1990,10 @@ static inline int br_mst_process(struct net_bridge_port *p,
{
	return -EOPNOTSUPP;
}

static inline void br_mst_uninit(struct net_bridge *br)
{
}
#endif

struct nf_br_ops {