summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolay Aleksandrov <razor@blackwall.org>2025-11-05 13:19:19 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-11-13 15:34:39 -0500
commit29d4429a993f10c5a9f55c265283c3fd4d0832f5 (patch)
treebf3433352db7bcc9933eaa553480caf14df36149
parentbf3843183bc3158e5821b46f330c438ae9bd6ddb (diff)
downloadlinux-29d4429a993f10c5a9f55c265283c3fd4d0832f5.tar.gz
linux-29d4429a993f10c5a9f55c265283c3fd4d0832f5.tar.bz2
linux-29d4429a993f10c5a9f55c265283c3fd4d0832f5.zip
net: bridge: fix MST static key usage
[ Upstream commit ee87c63f9b2a418f698d79c2991347e31a7d2c27 ] 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: ec7328b59176 ("net: bridge: mst: Multiple Spanning Tree (MST) mode") Reported-by: Ido Schimmel <idosch@nvidia.com> Closes: https://lore.kernel.org/netdev/20251104120313.1306566-1-razor@blackwall.org/T/#m6888d87658f94ed1725433940f4f4ebb00b5a68b Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Link: https://patch.msgid.link/20251105111919.1499702-3-razor@blackwall.org Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--net/bridge/br_if.c1
-rw-r--r--net/bridge/br_mst.c10
-rw-r--r--net/bridge/br_private.h5
3 files changed, 14 insertions, 2 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 2450690f98cf..6ffc81eedf07 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -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);
diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c
index 3f24b4ee49c2..43a300ae6bfa 100644
--- a/net/bridge/br_mst.c
+++ b/net/bridge/br_mst.c
@@ -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;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 40dcffc2132e..741b0b8c4bab 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1923,6 +1923,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)
{
@@ -1958,6 +1959,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 {