From: Nikolay Aleksandrov <razor@blackwall.org>
To: netdev@vger.kernel.org
Cc: idosch@nvidia.com, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, horms@kernel.org,
bridge@lists.linux.dev, Nikolay Aleksandrov <razor@blackwall.org>
Subject: [PATCH net-next 08/12] net: bridge: vlan: quiesce readers before freeing port VLANs
Date: Wed, 30 Sep 2026 10:14:07 +0300 [thread overview]
Message-ID: <20260930071411.2786201-9-razor@blackwall.org> (raw)
In-Reply-To: <20260930071411.2786201-1-razor@blackwall.org>
Later fdb entries will cache port-VLAN pointers so unpublish a VLAN, wait
for a grace period (existing readers) and then purge or rewrite fdb
references before releasing it. Cached destinations can continue forwarding
until they are cleaned, that is acceptable so add a comment to document it.
During port teardown unpublish the complete VLAN group first, clean the
port fdbs and then release the VLANs. This lets all VLANs share one grace
period.
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
---
net/bridge/br_fdb.c | 20 ++++++++++++++++----
net/bridge/br_if.c | 7 +++++--
net/bridge/br_private.h | 12 ++++++++++--
net/bridge/br_vlan.c | 21 +++++++++++++++------
4 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 7c68b540b358..307f9c12914e 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -883,7 +883,9 @@ void br_fdb_cleanup_by_dst(struct net_bridge *br,
spin_lock_bh(&br->hash_lock);
hlist_for_each_entry_safe(f, tmp, &br->fdb_list, fdb_node) {
- if (br_fdb_dst_port(f) != p)
+ struct net_bridge_dst dst = br_fdb_dst_read(f);
+
+ if (br_dst_port(dst) != p)
continue;
if (vlan && f->key.vlan_id == vlan->vid &&
@@ -894,12 +896,22 @@ void br_fdb_cleanup_by_dst(struct net_bridge *br,
continue;
}
- if (!do_all)
+ if (!do_all) {
+ if (vid && f->key.vlan_id != vid)
+ continue;
+
if (test_bit(BR_FDB_STATIC, &f->flags) ||
(test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &f->flags) &&
- !test_bit(BR_FDB_OFFLOADED, &f->flags)) ||
- (vid && f->key.vlan_id != vid))
+ !test_bit(BR_FDB_OFFLOADED, &f->flags))) {
+ /* The entry outlives the VLAN, so it must fall
+ * back to the raw port destination
+ */
+ if (vlan && br_dst_vlan(dst) == vlan)
+ br_fdb_dst_write(f,
+ br_port_to_dst(p));
continue;
+ }
+ }
if (test_bit(BR_FDB_LOCAL, &f->flags))
fdb_delete_local(br, p, f);
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index d94558a5e3e9..2c05ebc1299d 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -333,8 +333,9 @@ static void update_headroom(struct net_bridge *br, int new_hr)
*/
static void del_nbp(struct net_bridge_port *p)
{
- struct net_bridge *br = p->br;
+ struct net_bridge_vlan_group *vg;
struct net_device *dev = p->dev;
+ struct net_bridge *br = p->br;
sysfs_remove_link(br->ifobj, p->dev->name);
@@ -354,8 +355,10 @@ static void del_nbp(struct net_bridge_port *p)
update_headroom(br, get_max_headroom(br));
netdev_reset_rx_headroom(dev);
- nbp_vlan_flush(p);
+ vg = nbp_vlan_group(p);
+ nbp_vlan_group_unpublish(p);
br_fdb_cleanup_by_dst(br, br_port_to_dst(p), 0, 1);
+ nbp_vlan_flush(p, vg);
switchdev_deferred_process();
nbp_backup_clear(p);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index a790368b69e9..951b6ac5f484 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1735,7 +1735,9 @@ int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid,
int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags,
bool *changed, struct netlink_ext_ack *extack);
int nbp_vlan_delete(struct net_bridge_port *port, u16 vid);
-void nbp_vlan_flush(struct net_bridge_port *port);
+void nbp_vlan_group_unpublish(struct net_bridge_port *port);
+void nbp_vlan_flush(struct net_bridge_port *port,
+ struct net_bridge_vlan_group *vg);
int nbp_vlan_init(struct net_bridge_port *port, struct netlink_ext_ack *extack);
int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask);
void br_vlan_get_stats(const struct net_bridge_vlan *v,
@@ -1894,7 +1896,13 @@ static inline int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
return -EOPNOTSUPP;
}
-static inline void nbp_vlan_flush(struct net_bridge_port *port)
+static inline void nbp_vlan_group_unpublish(struct net_bridge_port *port)
+{
+}
+
+static inline void
+nbp_vlan_flush(struct net_bridge_port *port,
+ struct net_bridge_vlan_group *vg)
{
}
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 8a914e249767..0675f74cf1b9 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1406,23 +1406,32 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
v = br_vlan_find(vg, vid);
if (!v)
return -ENOENT;
- br_fdb_cleanup_by_dst(port->br, br_vlan_to_dst(v), vid, 0);
__vlan_unpublish(vg, v);
+ synchronize_net();
+ /* Traffic may still use v through cached fdb dsts until they are
+ * cleaned below. This is acceptable during vlan deletion. Above we
+ * drain the readers that could republish the dst before cleaning it
+ */
+ br_fdb_cleanup_by_dst(port->br, br_vlan_to_dst(v), vid, 0);
__vlan_del(vg, v);
return 0;
}
-void nbp_vlan_flush(struct net_bridge_port *port)
+void nbp_vlan_group_unpublish(struct net_bridge_port *port)
{
- struct net_bridge_vlan_group *vg;
-
ASSERT_RTNL();
- vg = nbp_vlan_group(port);
- __vlan_flush(port->br, port, vg);
RCU_INIT_POINTER(port->vlgrp, NULL);
synchronize_net();
+}
+
+void nbp_vlan_flush(struct net_bridge_port *port,
+ struct net_bridge_vlan_group *vg)
+{
+ ASSERT_RTNL();
+
+ __vlan_flush(port->br, port, vg);
__vlan_group_free(vg);
}
--
2.47.3
next prev parent reply other threads:[~2026-09-30 7:15 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 7:13 [PATCH net-next 00/12] net: bridge: vlan: optimize standard fdb fwding path Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 01/12] net: bridge: introduce a bridge destination type Nikolay Aleksandrov
2026-10-01 7:24 ` Nikolay Aleksandrov
2026-10-02 19:45 ` Jakub Kicinski
2026-10-02 20:09 ` Nikolay Aleksandrov
2026-10-02 20:18 ` Jakub Kicinski
2026-09-30 7:14 ` [PATCH net-next 02/12] net: bridge: use net_bridge_dst for fdb destinations Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 03/12] net: bridge: add VLAN support to bridge destinations Nikolay Aleksandrov
2026-10-01 11:59 ` netdev-bot+sashiko
2026-10-01 12:03 ` Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 04/12] net: bridge: vlan: return VLAN entries from ingress helpers Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 05/12] net: bridge: fdb: pass VLAN entries to learning updates Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 06/12] net: bridge: fdb: consolidate port-VLAN cleanup Nikolay Aleksandrov
2026-10-01 11:59 ` netdev-bot+sashiko
2026-10-01 12:05 ` Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 07/12] net: bridge: vlan: split unpublishing from deletion Nikolay Aleksandrov
2026-09-30 7:14 ` Nikolay Aleksandrov [this message]
2026-10-01 7:28 ` [PATCH net-next 08/12] net: bridge: vlan: quiesce readers before freeing port VLANs Nikolay Aleksandrov
2026-10-01 11:59 ` netdev-bot+sashiko
2026-10-01 12:07 ` Nikolay Aleksandrov
2026-10-02 19:50 ` Jakub Kicinski
2026-10-02 19:59 ` Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 09/12] net: bridge: fdb: factor out existing entry updates Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 10/12] net: bridge: fdb: cache port VLANs in learned entries Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 11/12] net: bridge: fdb: cache VLAN destinations in configured entries Nikolay Aleksandrov
2026-10-01 7:36 ` Nikolay Aleksandrov
2026-09-30 7:14 ` [PATCH net-next 12/12] net: bridge: fdb: avoid VLAN lookups in unicast forwarding Nikolay Aleksandrov
2026-10-02 20:00 ` [PATCH net-next 00/12] net: bridge: vlan: optimize standard fdb fwding path patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260930071411.2786201-9-razor@blackwall.org \
--to=razor@blackwall.org \
--cc=bridge@lists.linux.dev \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).