[PATCH v9 nf 06/15] bridge: Add filling forward path from port to port
From: Eric Woudstra <hidden>
Date: 2025-03-05 10:30:12
Also in:
bridge, linux-arm-kernel, linux-hardening, linux-mediatek, lkml, netfilter-devel
Subsystem:
ethernet bridge, networking [general], the rest · Maintainers:
Nikolay Aleksandrov, Ido Schimmel, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
If a port is passed as argument instead of the master, then: At br_fill_forward_path(): find the master and use it to fill the forward path. At br_vlan_fill_forward_path_pvid(): lookup vlan group from port instead. Changed call to br_vlan_group() into br_vlan_group_rcu() while at it. Acked-by: Nikolay Aleksandrov <razor@blackwall.org> Signed-off-by: Eric Woudstra <redacted> --- net/bridge/br_device.c | 19 ++++++++++++++----- net/bridge/br_private.h | 2 ++ net/bridge/br_vlan.c | 6 +++++- 3 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 9d8c72ed01ab..02eb23e8aab8 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c@@ -383,16 +383,25 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev) static int br_fill_forward_path(struct net_device_path_ctx *ctx, struct net_device_path *path) { + struct net_bridge_port *src, *dst; struct net_bridge_fdb_entry *f; - struct net_bridge_port *dst; struct net_bridge *br; - if (netif_is_bridge_port(ctx->dev)) - return -1; + if (netif_is_bridge_port(ctx->dev)) { + struct net_device *br_dev; + + br_dev = netdev_master_upper_dev_get_rcu((struct net_device *)ctx->dev); + if (!br_dev) + return -1; - br = netdev_priv(ctx->dev); + src = br_port_get_rcu(ctx->dev); + br = netdev_priv(br_dev); + } else { + src = NULL; + br = netdev_priv(ctx->dev); + } - br_vlan_fill_forward_path_pvid(br, ctx, path); + br_vlan_fill_forward_path_pvid(br, src, ctx, path); f = br_fdb_find_rcu(br, ctx->daddr, path->bridge.vlan_id); if (!f)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1054b8a88edc..a0b950390a16 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h@@ -1584,6 +1584,7 @@ bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, const struct net_bridge_vlan *range_end); void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_bridge_port *p, struct net_device_path_ctx *ctx, struct net_device_path *path); int br_vlan_fill_forward_path_mode(struct net_bridge *br,
@@ -1753,6 +1754,7 @@ static inline int nbp_get_num_vlan_infos(struct net_bridge_port *p, } static inline void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_bridge_port *p, struct net_device_path_ctx *ctx, struct net_device_path *path) {
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index d9a69ec9affe..a18c7da12ebd 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c@@ -1441,6 +1441,7 @@ int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid) EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu); void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_bridge_port *p, struct net_device_path_ctx *ctx, struct net_device_path *path) {
@@ -1453,7 +1454,10 @@ void br_vlan_fill_forward_path_pvid(struct net_bridge *br, if (!br_opt_get(br, BROPT_VLAN_ENABLED)) return; - vg = br_vlan_group(br); + if (p) + vg = nbp_vlan_group_rcu(p); + else + vg = br_vlan_group_rcu(br); if (idx >= 0 && ctx->vlan[idx].proto == br->vlan_proto) {
--
2.47.1