* [PATCH net 0/2] net: dsa: b53: fix 8021q uppers on standalone ports
@ 2026-08-06 7:31 Semih Baskan
2026-08-06 7:31 ` [PATCH net 1/2] net: dsa: let drivers offload " Semih Baskan
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Semih Baskan @ 2026-08-06 7:31 UTC (permalink / raw)
To: florian.fainelli, jonas.gorski, andrew, olteanv, davem, edumazet,
kuba, pabeni
Cc: vladimir.oltean, horms, netdev, linux-kernel
Since v5.15, a standalone port on a b53 switch cannot receive its own
tagged traffic: the switch VID lookup is always active, an 8021q
upper's VID never reaches the VLAN table, and every tagged frame
resolves to an empty member set and is discarded. The common victim is
a VLAN-tagged PPPoE WAN, where the PADI goes out and the tagged PADO
never reaches the CPU.
My first attempt disabled the VLAN table while not filtering:
https://lore.kernel.org/all/20260805072641.402-1-strst.gs@gmail.com/
Jonas pointed out that this moves the ARL to shared VLAN learning and
desynchronizes the hardware table from the bridge fdb, and I withdrew
it. I then measured the alternatives on an RT-N18U (BCM53011 rev 5),
with the outbound direction of the same link as a positive control on
every run:
- With the table enabled, no ingress VID check setting delivers the
frame: VC4_NO_ING_VID_CHK, VC4_ING_VID_VIO_FWD and
VC4_ING_VID_VIO_TO_IMP all give 0, and clearing VC0_DROP_VID_MISS
changes nothing. The frame does not die at ingress admission, it
dies when forwarding resolves the VID against an empty member set.
- With the table disabled, a static fdb entry with VID 100 is lost
from the hardware ARL no matter how the driver drives the ARL
registers: keeping ARLTBL_IVL_SVL_SELECT at IVL does not preserve
it, and neither does additionally keeping the VID learning bits in
VLAN_CTRL0 set.
So on this hardware, delivering the frame and keeping VID-keyed ARL
entries are mutually exclusive unless the VID is in the table. This
series therefore programs the table, narrowed to what is actually
needed: a standalone port only needs the VIDs its 8021q uppers use,
which is one table write per upper instead of entries for all 4096
VIDs.
I tried to keep the fix inside b53, but the driver cannot solve this
alone: without NETIF_F_HW_VLAN_CTAG_FILTER the 8021q layer never calls
.ndo_vlan_rx_add_vid, so the VIDs never reach the driver, and DSA
manages that feature bit. The one existing way to get it,
ds->needs_standalone_vlan_filtering, does not work here. It was
measured insufficient, because f089652b6b16 makes .port_vlan_add skip
the hardware write while not filtering, and its other effect is one
b53 cannot take: with vlan_filtering_is_global, the forced
vlan_filtering=1 in dsa_port_reset_vlan_filtering() would flip the
whole switch into VLAN filtering when any port leaves a VLAN-unaware
bridge. hellcreek relies on exactly those semantics, so patch 1 adds a
narrower opt-in that only delivers the VIDs and leaves vlan_filtering
alone, and patch 2 uses it in b53 and programs entries that carry
standalone members, masked so bridge VLANs stay without effect while
not filtering.
Tested on the RT-N18U: the standalone upper receives 7 of 7 probe
frames with vlan_filtering staying 0, the static fdb entry with a VID
now survives a vlan_filtering toggle since the table and the ARL mode
are never touched, uppers keep working across bridge join and leave
and across a vlan_filtering toggle including on ports that were
bridged while the toggle happened, deleting an upper or bridging its
port verifiably stops delivery of that VID to the CPU, and the PPPoE
session from the original report establishes. 802.1ad uppers keep
working as software VLANs, since this switch does not parse 0x88a8,
and stacked QinQ over an offloaded upper works too.
Semih Baskan (2):
net: dsa: let drivers offload 8021q uppers on standalone ports
net: dsa: b53: offload 8021q uppers on standalone ports
drivers/net/dsa/b53/b53_common.c | 118 ++++++++++++++++++++++++++-----
include/net/dsa.h | 3 +
net/dsa/port.c | 21 ++++--
net/dsa/user.c | 4 +-
4 files changed, 120 insertions(+), 26 deletions(-)
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net 1/2] net: dsa: let drivers offload 8021q uppers on standalone ports
2026-08-06 7:31 [PATCH net 0/2] net: dsa: b53: fix 8021q uppers on standalone ports Semih Baskan
@ 2026-08-06 7:31 ` Semih Baskan
2026-08-06 11:15 ` Vladimir Oltean
2026-08-06 7:31 ` [PATCH net 2/2] net: dsa: b53: " Semih Baskan
2026-08-06 8:39 ` [PATCH net 0/2] net: dsa: b53: fix " Jonas Gorski
2 siblings, 1 reply; 9+ messages in thread
From: Semih Baskan @ 2026-08-06 7:31 UTC (permalink / raw)
To: florian.fainelli, jonas.gorski, andrew, olteanv, davem, edumazet,
kuba, pabeni
Cc: vladimir.oltean, horms, netdev, linux-kernel
Some switches cannot deliver a tagged frame to the CPU while its VID is
absent from the VLAN table, not even with VLAN filtering turned off.
b53 is one of them: its VID lookup is always active, and disabling it
moves the ARL to shared VLAN learning, where ARL operations force VID 0
and the hardware table drifts away from the bridge fdb. On such
hardware a standalone port can only receive the traffic of its 8021q
uppers if their VIDs are programmed into the table.
The existing opt-in for this class of problem,
ds->needs_standalone_vlan_filtering, delivers those VIDs but does more:
dsa_port_reset_vlan_filtering() also forces vlan_filtering=1 on a port
that leaves a VLAN-unaware bridge. hellcreek wants exactly that. b53
must not have it, because it sets vlan_filtering_is_global, so the
forced flip would turn the whole switch into a VLAN filtering device
the first time any port leaves a VLAN-unaware bridge and change
behaviour for every other port.
Add ds->needs_standalone_vlan_offload for the narrower need. It
advertises NETIF_F_HW_VLAN_CTAG_FILTER on user ports, so the 8021q
layer reports upper VIDs to .port_vlan_add, and it leaves the
vlan_filtering state alone.
Upper offload of such a switch never depends on vlan_filtering: every
VID was already delivered when the upper was created, since the
feature bit is always on. dsa_port_vlan_filtering() therefore skips
its ports entirely when a bridge toggles VLAN awareness. Restoring
them on the way up would add VIDs that were never cleared, and
clearing them on the way down would strip the driver's record of a
bridged port's uppers and the feature bit, leaving a port that later
leaves the bridge with uppers that cannot receive and no way to
re-offload them. The conduit change path keeps its explicit teardown
and restore of standalone VLANs, and now also runs it for a standalone
port of such a switch while VLAN filtering is off, because that port
has VLANs on the CPU port too.
The Fixes tag is for backport dependency tracking: the b53 fix in the
next patch needs this flag to exist.
Fixes: 06cfb2df7eb0 ("net: dsa: don't advertise 'rx-vlan-filter' when not needed")
Cc: stable@vger.kernel.org
Signed-off-by: Semih Baskan <strst.gs@gmail.com>
---
include/net/dsa.h | 3 +++
net/dsa/port.c | 21 ++++++++++++++-------
net/dsa/user.c | 4 +++-
3 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 6f7f5c17b532..6f3a60c23d14 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -403,6 +403,9 @@ struct dsa_switch {
/* Keep VLAN filtering enabled on ports not offloading any upper */
u32 needs_standalone_vlan_filtering:1;
+ /* Offload 8021q uppers of standalone ports even when not filtering */
+ u32 needs_standalone_vlan_offload:1;
+
/* Pass .port_vlan_add and .port_vlan_del to drivers even for bridges
* that have vlan_filtering=0. All drivers should ideally set this (and
* then the option would get removed), but it is unknown whether this
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 1f5536c0dffc..23d1c5ae6934 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -831,6 +831,9 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
if (!user)
continue;
+ if (ds->needs_standalone_vlan_offload)
+ continue;
+
err = dsa_user_manage_vlan_filtering(user,
vlan_filtering);
if (err)
@@ -839,10 +842,12 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
} else {
dp->vlan_filtering = vlan_filtering;
- err = dsa_user_manage_vlan_filtering(dp->user,
- vlan_filtering);
- if (err)
- goto restore;
+ if (!ds->needs_standalone_vlan_offload) {
+ err = dsa_user_manage_vlan_filtering(dp->user,
+ vlan_filtering);
+ if (err)
+ goto restore;
+ }
}
return 0;
@@ -1445,10 +1450,12 @@ int dsa_port_change_conduit(struct dsa_port *dp, struct net_device *conduit,
/* The port might still be VLAN filtering even if it's no longer
* under a bridge, either due to ds->vlan_filtering_is_global or
- * ds->needs_standalone_vlan_filtering. In turn this means VLANs
- * on the CPU port.
+ * ds->needs_standalone_vlan_filtering, and standalone ports of a
+ * ds->needs_standalone_vlan_offload switch keep their VLANs without
+ * filtering. In turn this means VLANs on the CPU port.
*/
- vlan_filtering = dsa_port_is_vlan_filtering(dp);
+ vlan_filtering = dsa_port_is_vlan_filtering(dp) ||
+ (ds->needs_standalone_vlan_offload && !bridge_dev);
if (vlan_filtering) {
err = dsa_user_manage_vlan_filtering(dev, false);
if (err) {
diff --git a/net/dsa/user.c b/net/dsa/user.c
index 03c7af6abe18..2b1695b386ef 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -1946,6 +1946,7 @@ static int dsa_user_clear_vlan(struct net_device *vdev, int vid, void *arg)
*
* - If standalone (this includes software bridge, software LAG):
* - if ds->needs_standalone_vlan_filtering = true, OR if
+ * ds->needs_standalone_vlan_offload = true, OR if
* (ds->vlan_filtering_is_global = true AND there are bridges spanning
* this switch chip which have vlan_filtering=1)
* - the 8021q upper VLANs
@@ -2718,7 +2719,8 @@ void dsa_user_setup_tagger(struct net_device *user)
user->hw_features |= NETIF_F_HW_TC;
if (user->needed_tailroom)
user->features &= ~(NETIF_F_SG | NETIF_F_FRAGLIST);
- if (ds->needs_standalone_vlan_filtering)
+ if (ds->needs_standalone_vlan_filtering ||
+ ds->needs_standalone_vlan_offload)
user->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
user->lltx = true;
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH net 2/2] net: dsa: b53: offload 8021q uppers on standalone ports
2026-08-06 7:31 [PATCH net 0/2] net: dsa: b53: fix 8021q uppers on standalone ports Semih Baskan
2026-08-06 7:31 ` [PATCH net 1/2] net: dsa: let drivers offload " Semih Baskan
@ 2026-08-06 7:31 ` Semih Baskan
2026-08-06 8:39 ` [PATCH net 0/2] net: dsa: b53: fix " Jonas Gorski
2 siblings, 0 replies; 9+ messages in thread
From: Semih Baskan @ 2026-08-06 7:31 UTC (permalink / raw)
To: florian.fainelli, jonas.gorski, andrew, olteanv, davem, edumazet,
kuba, pabeni
Cc: vladimir.oltean, horms, netdev, linux-kernel
b53 keeps the hardware VID lookup enabled at all times:
b53_switch_alloc() sets dev->vlan_enabled and nothing ever clears it.
A VID that is absent from the VLAN table resolves to an empty member
set, so a tagged frame carrying it is discarded instead of reaching
the CPU. Disabling the lookup is not an option either, because that
moves the ARL to shared VLAN learning, where ARL operations force
VID 0 and the hardware table drifts away from the bridge fdb.
Commit 06cfb2df7eb0 ("net: dsa: don't advertise 'rx-vlan-filter' when
not needed") stopped advertising NETIF_F_HW_VLAN_CTAG_FILTER on ports
that do not offload a VLAN-aware bridge, so creating an 8021q upper on
a standalone port no longer reaches .ndo_vlan_rx_add_vid and the VID
is never offloaded. Commit f089652b6b16 ("net: dsa: b53: do not
program vlans when vlan filtering is off") then made .port_vlan_add
skip the hardware write while dev->vlan_filtering is false, which it
is for a standalone port. Together they leave standalone ports unable
to receive their own tagged traffic.
This breaks a common configuration, a VLAN-tagged WAN for a PPPoE ISP.
The PADI leaves the port correctly tagged, the concentrator answers,
and the switch discards the tagged PADO, so the session never
establishes. Reported on an Asus RT-N18U in 2023 and still
reproducible.
Take the new needs_standalone_vlan_offload opt-in so DSA reports upper
VIDs again, and program VLAN entries that carry a standalone port even
while not filtering. Only the standalone members and the CPU port are
written to such an entry. A VID used by both an 8021q upper and a
bridge VLAN therefore does not gain the bridged ports as members, so
bridge VLANs keep having no effect while filtering is off, which is
what Documentation/networking/switchdev.rst requires and what that
commit implements. The PVID register writes stay gated on
vlan_filtering for the same reason.
b53_configure_vlan() used to restore entries only while filtering, so
restore the standalone ones there as well, otherwise the next
b53_apply_config() wipes them. Bridge join and leave rewrite the
entries of the moved port, because its standalone state is part of the
masking decision: joining removes the port from its uppers' entries,
and leaving adds it back, including uppers that were created while the
port was still bridged. When the last standalone member leaves a VID,
the entry is written back empty, so deleting an upper or bridging its
port returns the hardware to the state it had before the upper
existed.
Creating an upper whose VID the hardware cannot serve now fails
loudly instead of producing an interface that cannot receive:
b53_vlan_prepare() rejects VIDs beyond the VLAN table size on
BCM5325/BCM5365, and any tagged VLAN on BCM7278 port 7, which
cannot receive tagged frames. Previously the ndo was never called,
so such uppers were silently created broken.
Measured on an Asus RT-N18U (BCM53011 rev 5) against a peer device. A
probe over an 8021q upper on the standalone WAN port received 0 frames
before and 7 of 7 after, with the outbound direction as a positive
control and vlan_filtering staying 0 throughout. A static fdb entry
with VID 100 survived a vlan_filtering 1->0 toggle in hardware, since
dev->vlan_enabled is never touched and the ARL keeps using independent
VLAN learning. The PPPoE session from the report establishes.
Fixes: 06cfb2df7eb0 ("net: dsa: don't advertise 'rx-vlan-filter' when not needed")
Cc: stable@vger.kernel.org
Signed-off-by: Semih Baskan <strst.gs@gmail.com>
---
drivers/net/dsa/b53/b53_common.c | 118 ++++++++++++++++++++++++++-----
1 file changed, 100 insertions(+), 18 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 3f5b9592794d..ba1266cd70c3 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -898,10 +898,52 @@ static bool b53_vlan_port_may_join_untagged(struct dsa_switch *ds, int port)
return dp->bridge == NULL;
}
+static bool b53_vlan_hw_entry(struct dsa_switch *ds, const struct b53_vlan *vl,
+ struct b53_vlan *hw)
+{
+ struct b53_device *dev = ds->priv;
+ bool standalone = false;
+ struct dsa_port *dp;
+ unsigned int port;
+
+ *hw = *vl;
+
+ if (dev->vlan_filtering)
+ return true;
+
+ hw->members = 0;
+ hw->untag = 0;
+
+ b53_for_each_port(dev, port) {
+ if (!(vl->members & BIT(port)))
+ continue;
+
+ dp = dsa_to_port(ds, port);
+
+ if (!dsa_port_is_cpu(dp)) {
+ if (dp->bridge)
+ continue;
+
+ standalone = true;
+ }
+
+ hw->members |= BIT(port);
+ hw->untag |= vl->untag & BIT(port);
+ }
+
+ if (!standalone) {
+ hw->members = 0;
+ hw->untag = 0;
+ }
+
+ return standalone;
+}
+
int b53_configure_vlan(struct dsa_switch *ds)
{
struct b53_device *dev = ds->priv;
struct b53_vlan vl = { 0 };
+ struct b53_vlan hw;
struct b53_vlan *v;
int i, def_vid;
u16 vid;
@@ -937,20 +979,23 @@ int b53_configure_vlan(struct dsa_switch *ds)
}
b53_set_vlan_entry(dev, def_vid, &vl);
- if (dev->vlan_filtering) {
- /* Upon initial call we have not set-up any VLANs, but upon
- * system resume, we need to restore all VLAN entries.
- */
- for (vid = def_vid + 1; vid < dev->num_vlans; vid++) {
- v = &dev->vlans[vid];
+ /* Upon initial call we have not set-up any VLANs, but upon
+ * system resume, we need to restore all VLAN entries.
+ */
+ for (vid = def_vid + 1; vid < dev->num_vlans; vid++) {
+ v = &dev->vlans[vid];
- if (!v->members)
- continue;
+ if (!v->members)
+ continue;
- b53_set_vlan_entry(dev, vid, v);
- b53_fast_age_vlan(dev, vid);
- }
+ if (!b53_vlan_hw_entry(ds, v, &hw))
+ continue;
+ b53_set_vlan_entry(dev, vid, &hw);
+ b53_fast_age_vlan(dev, vid);
+ }
+
+ if (dev->vlan_filtering) {
b53_for_each_port(dev, i) {
if (!dsa_is_cpu_port(ds, i))
b53_write16(dev, B53_VLAN_PAGE,
@@ -1720,6 +1765,7 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
struct b53_device *dev = ds->priv;
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+ struct b53_vlan hw;
struct b53_vlan *vl;
u16 old_pvid, new_pvid;
int err;
@@ -1751,13 +1797,14 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
else
vl->untag &= ~BIT(port);
- if (!dev->vlan_filtering)
+ if (!b53_vlan_hw_entry(ds, vl, &hw))
return 0;
- b53_set_vlan_entry(dev, vlan->vid, vl);
+ b53_set_vlan_entry(dev, vlan->vid, &hw);
b53_fast_age_vlan(dev, vlan->vid);
- if (!dsa_is_cpu_port(ds, port) && new_pvid != old_pvid) {
+ if (dev->vlan_filtering &&
+ !dsa_is_cpu_port(ds, port) && new_pvid != old_pvid) {
b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
new_pvid);
b53_fast_age_vlan(dev, old_pvid);
@@ -1772,7 +1819,9 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
{
struct b53_device *dev = ds->priv;
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+ struct b53_vlan hw;
struct b53_vlan *vl;
+ bool needs_hw;
u16 pvid;
if (vlan->vid == 0)
@@ -1782,6 +1831,8 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
vl = &dev->vlans[vlan->vid];
+ needs_hw = b53_vlan_hw_entry(ds, vl, &hw);
+
vl->members &= ~BIT(port);
if (pvid == vlan->vid)
@@ -1791,14 +1842,18 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
if (untagged && !b53_vlan_port_needs_forced_tagged(ds, port))
vl->untag &= ~(BIT(port));
- if (!dev->vlan_filtering)
+ if (!needs_hw)
return 0;
- b53_set_vlan_entry(dev, vlan->vid, vl);
+ b53_vlan_hw_entry(ds, vl, &hw);
+ b53_set_vlan_entry(dev, vlan->vid, &hw);
b53_fast_age_vlan(dev, vlan->vid);
- b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), pvid);
- b53_fast_age_vlan(dev, pvid);
+ if (dev->vlan_filtering) {
+ b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
+ pvid);
+ b53_fast_age_vlan(dev, pvid);
+ }
return 0;
}
@@ -2261,6 +2316,28 @@ int b53_mdb_del(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL(b53_mdb_del);
+static void b53_standalone_vlan_resync(struct dsa_switch *ds, int port)
+{
+ struct b53_device *dev = ds->priv;
+ struct b53_vlan hw;
+ struct b53_vlan *vl;
+ u16 vid;
+
+ if (dev->vlan_filtering)
+ return;
+
+ for (vid = b53_default_pvid(dev) + 1; vid < dev->num_vlans; vid++) {
+ vl = &dev->vlans[vid];
+
+ if (!(vl->members & BIT(port)))
+ continue;
+
+ b53_vlan_hw_entry(ds, vl, &hw);
+ b53_set_vlan_entry(dev, vid, &hw);
+ b53_fast_age_vlan(dev, vid);
+ }
+}
+
int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
bool *tx_fwd_offload, struct netlink_ext_ack *extack)
{
@@ -2324,6 +2401,8 @@ int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
dev->ports[port].vlan_ctl_mask = pvlan;
+ b53_standalone_vlan_resync(ds, port);
+
return 0;
}
EXPORT_SYMBOL(b53_br_join);
@@ -2376,6 +2455,8 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
vl->members |= BIT(port);
b53_set_vlan_entry(dev, pvid, vl);
}
+
+ b53_standalone_vlan_resync(ds, port);
}
EXPORT_SYMBOL(b53_br_leave);
@@ -3213,6 +3294,7 @@ struct b53_device *b53_switch_alloc(struct device *base,
* devices. (not hardware supported)
*/
ds->vlan_filtering_is_global = true;
+ ds->needs_standalone_vlan_offload = true;
mutex_init(&dev->reg_mutex);
mutex_init(&dev->stats_mutex);
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH net 0/2] net: dsa: b53: fix 8021q uppers on standalone ports
2026-08-06 7:31 [PATCH net 0/2] net: dsa: b53: fix 8021q uppers on standalone ports Semih Baskan
2026-08-06 7:31 ` [PATCH net 1/2] net: dsa: let drivers offload " Semih Baskan
2026-08-06 7:31 ` [PATCH net 2/2] net: dsa: b53: " Semih Baskan
@ 2026-08-06 8:39 ` Jonas Gorski
2026-08-06 11:06 ` Semih Baskan
2 siblings, 1 reply; 9+ messages in thread
From: Jonas Gorski @ 2026-08-06 8:39 UTC (permalink / raw)
To: Semih Baskan
Cc: florian.fainelli, andrew, olteanv, davem, edumazet, kuba, pabeni,
vladimir.oltean, horms, netdev, linux-kernel,
Rafał Miłecki
Hi,
On Thu, Aug 6, 2026 at 9:31 AM Semih Baskan <strst.gs@gmail.com> wrote:
>
> Since v5.15, a standalone port on a b53 switch cannot receive its own
> tagged traffic: the switch VID lookup is always active, an 8021q
> upper's VID never reaches the VLAN table, and every tagged frame
> resolves to an empty member set and is discarded. The common victim is
> a VLAN-tagged PPPoE WAN, where the PADI goes out and the tagged PADO
> never reaches the CPU.
>
> My first attempt disabled the VLAN table while not filtering:
>
> https://lore.kernel.org/all/20260805072641.402-1-strst.gs@gmail.com/
>
> Jonas pointed out that this moves the ARL to shared VLAN learning and
> desynchronizes the hardware table from the bridge fdb, and I withdrew
> it. I then measured the alternatives on an RT-N18U (BCM53011 rev 5),
> with the outbound direction of the same link as a positive control on
> every run:
>
> - With the table enabled, no ingress VID check setting delivers the
> frame: VC4_NO_ING_VID_CHK, VC4_ING_VID_VIO_FWD and
> VC4_ING_VID_VIO_TO_IMP all give 0, and clearing VC0_DROP_VID_MISS
> changes nothing. The frame does not die at ingress admission, it
> dies when forwarding resolves the VID against an empty member set.
Note that this is working on switches other than bcm5301x (at least on
bcm63268 and bcm53115), so this seems to be a bcm5301x specific issue.
Unfortunately I do not have a device with such a switch. Though it
only works for standalone ports, it does not allow forwarding between
ports.
Though this isn't the first time a bcm5310x issue showed up with
packets not properly trapped to CPU. Rafal, Florian, did you ever
figure out the issue?
It feels like there is something missing with the CPU port
configuration. Which port are you using as CPU port?
I see several device trees in-tree using port 5, but according to the
register definitions in OpenMDK, the only valid port for both BRCM_HDR
and GLOBAL_CONFIG's FRM_MGMT_PORT is imp0 / port 8 [1].
So I now wonder if using port 5 as CPU port only appears to work (i.e.
enabling the header does), but anything that is supposed to trap to
CPU tries to forward to 8, which is disabled. Or does not forward at
all, because the FRM_MGMT_PORT is configured to an invalid value.
In addition to that, I see that b53_brcm_hdr_setup() does not clear
GC_FRM_MGMT_PORT_M, so if it defaults/was programmed to anything
before, it may become a wrong value.
If you are using port 5 as CPU port, can you try switching to port 8 / gmac2?
> - With the table disabled, a static fdb entry with VID 100 is lost
> from the hardware ARL no matter how the driver drives the ARL
> registers: keeping ARLTBL_IVL_SVL_SELECT at IVL does not preserve
> it, and neither does additionally keeping the VID learning bits in
> VLAN_CTRL0 set.
ARLTBL_IVL_SVL_SELECT is only implemented on bcm5302x / bcm58xx /
bcm53134 (and maybe some other newer switches), so no wonder it
doesn't do anything for you (it also has some additional dependencies
which aren't implemented in b53, so this is essentially dead code).
[1] https://github.com/Broadcom/OpenMDK/blob/v2.11.0/cdk/PKG/chip/bcm53010/bcm53010_a0_defs.h
Best regards,
Jonas
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net 0/2] net: dsa: b53: fix 8021q uppers on standalone ports
2026-08-06 8:39 ` [PATCH net 0/2] net: dsa: b53: fix " Jonas Gorski
@ 2026-08-06 11:06 ` Semih Baskan
0 siblings, 0 replies; 9+ messages in thread
From: Semih Baskan @ 2026-08-06 11:06 UTC (permalink / raw)
To: Jonas Gorski
Cc: florian.fainelli, andrew, olteanv, davem, edumazet, kuba, pabeni,
vladimir.oltean, horms, netdev, linux-kernel,
Rafał Miłecki
Hi Jonas,
> If you are using port 5 as CPU port, can you try switching to port 8 / gmac2?
You are right. I tested it today on the RT-N18U and switching the CPU
port to port 8 makes tagged standalone RX work on an unpatched driver,
with nothing in the VLAN table. Details below.
User ports attach to port 5 (gmac0) here, as in every bcm5301x device
tree in-tree. I enabled port@8 (gmac2) as the only CPU port in the dts,
left the driver completely stock, and rebuilt:
- the board comes up with the whole management path over gmac2, so
the port 8 to gmac2 path works on BCM47081,
- the tagged probe that always failed on port 5 delivers 7 of 7
(outbound positive control 7 of 7, delivery attributed to eth2 by
interface counters, eth0 stayed at 0),
- the PPPoE session from the original report establishes.
I also instrumented b53_brcm_hdr_setup() to read back GLOBAL_CONFIG,
and the register documentation in OpenMDK explains the mechanism you
suspected. GMNGCFG.FRM_MNGP on bcm53010 [1]:
00 = no IMP port
01 = reserved
10 = IMP0 only: all traffic to CPU from LAN and WAN ports goes to IMP0
11 = dual IMP: LAN-port CPU traffic goes to IMP0, WAN-port traffic to
IMP1, and "In polar, IMP0 is Port 8 and IMP1 is Port 5."
With CPU port 5 the driver ORs GC_FRM_MGMT_PORT_M, which is the field
mask, so the register reads back 0xc2: FRM_MNGP=11, dual IMP. In that
mode the tagged frames reach the CPU on neither IMP: I also tested an
intermediate build with port@8 enabled as a second CPU port while the
user ports stayed on port 5, which is what plain bcm-ns.dtsi describes
since it does not disable port@7/8, and delivery still failed with the
gmac2 counters at zero. With port 8 as the only CPU port the driver
programs 0x82: FRM_MNGP=10, IMP0 only, and delivery works. So your
no-clear observation is correct and the value it produces is worse
than a stale leftover: the port 5 branch cannot program anything
better, because there is no "IMP1 only" encoding, and LAN-class
management traps can never arrive on port 5 on this chip.
One smaller register note: BRCM_HDR_CTRL on bcm53010 does have per-port
bits (bit0 port 8, bit1 port 5, bit2 port 7) [1], so the Broadcom header
itself is valid on port 5. That is why tagging works there at all; the
port-8-only limitation is in the IMP routing, not the header.
A data point that fits the same picture: with CPU on port 5, BPDUs sent
into switch port 0 do reach the CPU. Port 0 is WAN-class in the chip's
management routing, so its traps go to IMP1, port 5. The trap
destination depends on the port class, which is probably why this
half-works and has been so confusing historically.
> ARLTBL_IVL_SVL_SELECT is only implemented on bcm5302x / bcm58xx /
> bcm53134 (and maybe some other newer switches), so no wonder it
> doesn't do anything for you
Thanks, noted. That makes the second measurement stronger rather than
weaker: on this chip there is no knob at all that preserves VID-keyed
ARL entries with the table disabled.
One property of the port 8 setup worth knowing before anyone reads it
as the fix: delivery is indiscriminate. After deleting the 8021q upper
I still see the tagged frames of that VID on the CPU with tcpdump.
Every unknown VID from the wire reaches the CPU, always, which is the
pre-5.15 behavior with its unfiltered nature included. The series
delivers only the VIDs that uppers subscribe, and stops delivering when
they go away.
So as I see it there are two valid fixes on different timescales.
Moving bcm5301x device trees to gmac2 fixes the trap path at the root,
but it changes the conduit for every board, needs per-board validation,
and cannot go to stable. The series fixes the deployed port 5 topology
selectively and is backportable. They do not conflict; the VLAN entries
are correct and harmless under either CPU port. I am happy to help test
a device tree migration on the RT-N18U if you want to pursue that
separately.
Also for completeness: a runtime test of your suggestion via conduit
reassignment is not possible, b53 does not implement
port_change_conduit, so I tested through the device tree.
[1] https://github.com/Broadcom/OpenMDK/blob/v2.11.0/cdk/PKG/chip/bcm53010/bcm53010_a0_defs.h
Best regards,
Semih
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net 1/2] net: dsa: let drivers offload 8021q uppers on standalone ports
2026-08-06 7:31 ` [PATCH net 1/2] net: dsa: let drivers offload " Semih Baskan
@ 2026-08-06 11:15 ` Vladimir Oltean
2026-08-06 11:44 ` Semih Baskan
0 siblings, 1 reply; 9+ messages in thread
From: Vladimir Oltean @ 2026-08-06 11:15 UTC (permalink / raw)
To: Semih Baskan
Cc: florian.fainelli, jonas.gorski, andrew, davem, edumazet, kuba,
pabeni, vladimir.oltean, horms, netdev, linux-kernel
On Thu, Aug 06, 2026 at 10:31:18AM +0300, Semih Baskan wrote:
> Some switches cannot deliver a tagged frame to the CPU while its VID is
> absent from the VLAN table, not even with VLAN filtering turned off.
> b53 is one of them: its VID lookup is always active, and disabling it
> moves the ARL to shared VLAN learning, where ARL operations force VID 0
> and the hardware table drifts away from the bridge fdb. On such
> hardware a standalone port can only receive the traffic of its 8021q
> uppers if their VIDs are programmed into the table.
Then their "vlan_filtering off" implementation is broken.
BTW, how is the "standalone port" behaviour different than the
vlan_filtering=0 bridge port case? If as you say, the switch must have
the VID in the VLAN table to send the packet to the CPU, what is
different when that port is under a VLAN-unaware bridge such that this
presumably does work?
> The existing opt-in for this class of problem,
> ds->needs_standalone_vlan_filtering, delivers those VIDs but does more:
> dsa_port_reset_vlan_filtering() also forces vlan_filtering=1 on a port
> that leaves a VLAN-unaware bridge. hellcreek wants exactly that. b53
> must not have it, because it sets vlan_filtering_is_global, so the
> forced flip would turn the whole switch into a VLAN filtering device
> the first time any port leaves a VLAN-unaware bridge and change
> behaviour for every other port.
If there is a problem with the vlan_filtering_is_global +
needs_standalone_vlan_filtering combination, then hellcreek also suffers
from it, because it does set both flags as well.
> Add ds->needs_standalone_vlan_offload for the narrower need. It
> advertises NETIF_F_HW_VLAN_CTAG_FILTER on user ports, so the 8021q
> layer reports upper VIDs to .port_vlan_add, and it leaves the
> vlan_filtering state alone.
>
> Upper offload of such a switch never depends on vlan_filtering: every
> VID was already delivered when the upper was created, since the
> feature bit is always on. dsa_port_vlan_filtering() therefore skips
> its ports entirely when a bridge toggles VLAN awareness. Restoring
> them on the way up would add VIDs that were never cleared, and
> clearing them on the way down would strip the driver's record of a
> bridged port's uppers and the feature bit, leaving a port that later
> leaves the bridge with uppers that cannot receive and no way to
> re-offload them. The conduit change path keeps its explicit teardown
> and restore of standalone VLANs, and now also runs it for a standalone
> port of such a switch while VLAN filtering is off, because that port
> has VLANs on the CPU port too.
I don't really understand the rest of the explanation for the "narrower
need", as it relies on the false fact that hellcreek is somehow not in
the same boat.
Why can't standalone ports tolerate the .port_vlan_filtering() call?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net 1/2] net: dsa: let drivers offload 8021q uppers on standalone ports
2026-08-06 11:15 ` Vladimir Oltean
@ 2026-08-06 11:44 ` Semih Baskan
2026-08-06 12:43 ` Vladimir Oltean
0 siblings, 1 reply; 9+ messages in thread
From: Semih Baskan @ 2026-08-06 11:44 UTC (permalink / raw)
To: Vladimir Oltean
Cc: florian.fainelli, jonas.gorski, andrew, davem, edumazet, kuba,
pabeni, vladimir.oltean, horms, netdev, linux-kernel
Hi Vladimir,
> Then their "vlan_filtering off" implementation is broken.
In the sense that the hardware cannot forward an arbitrary tagged frame
transparently while the table is active, and the table cannot be
deactivated without the ARL cost from the other subthread, yes. The
flag exists so the driver can compensate for exactly that.
> BTW, how is the "standalone port" behaviour different than the
> vlan_filtering=0 bridge port case? If as you say, the switch must have
> the VID in the VLAN table to send the packet to the CPU, what is
> different when that port is under a VLAN-unaware bridge such that this
> presumably does work?
It is not different, and it does not work. A tagged frame whose VID is
not in the table dies the same way when the port is under a
VLAN-unaware bridge; this hardware cannot do transparent tagged
bridging since the same v5.15 change. Jonas observed the same
limitation earlier in this thread from the other direction: on the
chips where standalone RX still works, forwarding tagged frames
between ports does not.
The reason the fix scopes to standalone ports is that they have a
finite, well-defined VID source: the 8021q uppers, reported through
the feature bit. A VLAN-unaware bridge has no such source; making it
transparent would mean programming the whole VID space, which is the
several-seconds-per-toggle variant Jonas measured and rejected in the
first thread. So the series fixes the reported regression, the
standalone PPPoE/upper case, and does not pretend to fix transparent
tagged bridging, which this hardware has not done since v5.15 either.
> If there is a problem with the vlan_filtering_is_global +
> needs_standalone_vlan_filtering combination, then hellcreek also suffers
> from it, because it does set both flags as well.
You are right, and the commit message argues this badly; I will reword
it if a v2 is wanted. vlan_filtering_is_global is not the
differentiator, hellcreek sets it too. The difference is what the
forced vlan_filtering=1 means for each driver. For hellcreek,
switch-wide VLAN awareness is the intended operating state; its
standalone traffic depends on filtering being on, and hellcreek.c
documents that unmanaged setups are not supported. The forced flip
lands it in the state it wants. For b53, vlan_filtering=1 is a
different user-visible mode for every port on the switch: untagged
frames become PVID-classified against the table, egress untagging
applies, unknown VIDs are dropped at ingress. Forcing that globally
because one port left a VLAN-unaware bridge would change the behaviour
of every other port, including members of VLAN-unaware bridges that
expect transparent operation. b53 needs the VIDs delivered while
vlan_filtering stays wherever the user put it, which is the narrower
flag.
> Why can't standalone ports tolerate the .port_vlan_filtering() call?
They do tolerate and still receive it: the ds->ops->port_vlan_filtering
call is unchanged, b53 sees every toggle and rebuilds its hardware
state from its own records. What the flag skips is only the core's
dsa_user_manage_vlan_filtering(), whose two jobs are wrong for a
switch whose feature bit is permanently on. On the way to
vlan_filtering=1 it replays VIDs that were never cleared, so
vlan_vid_add() refcounts every upper VID twice. On the way to 0 it
clears the VIDs and drops NETIF_F_HW_VLAN_CTAG_FILTER on a port that
happens to be bridged at toggle time; I measured that case on the
RT-N18U: after the port later leaves the bridge, its uppers stay dead
until reboot, because nothing re-offloads them once the feature bit is
gone. With the skip, both effects are gone and the driver derives the
hardware state from the flip itself. hellcreek does not set the new
flag, so its path through dsa_user_manage_vlan_filtering() is
unchanged.
Best regards,
Semih
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net 1/2] net: dsa: let drivers offload 8021q uppers on standalone ports
2026-08-06 11:44 ` Semih Baskan
@ 2026-08-06 12:43 ` Vladimir Oltean
2026-08-06 13:39 ` Semih Baskan
0 siblings, 1 reply; 9+ messages in thread
From: Vladimir Oltean @ 2026-08-06 12:43 UTC (permalink / raw)
To: Semih Baskan
Cc: florian.fainelli, jonas.gorski, andrew, davem, edumazet, kuba,
pabeni, vladimir.oltean, horms, netdev, linux-kernel
On Thu, Aug 06, 2026 at 02:44:44PM +0300, Semih Baskan wrote:
> Hi Vladimir,
>
> > Then their "vlan_filtering off" implementation is broken.
>
> In the sense that the hardware cannot forward an arbitrary tagged frame
> transparently while the table is active, and the table cannot be
> deactivated without the ARL cost from the other subthread, yes. The
> flag exists so the driver can compensate for exactly that.
But it doesn't, at least not in a sane way. If it still only accepts
those VLANs that have been added to filters by higher layers, it's not
VLAN-unaware. If a solution is not found to the problem, the driver must
reject operation as VLAN-unaware.
> > BTW, how is the "standalone port" behaviour different than the
> > vlan_filtering=0 bridge port case? If as you say, the switch must have
> > the VID in the VLAN table to send the packet to the CPU, what is
> > different when that port is under a VLAN-unaware bridge such that this
> > presumably does work?
>
> It is not different, and it does not work. A tagged frame whose VID is
> not in the table dies the same way when the port is under a
> VLAN-unaware bridge; this hardware cannot do transparent tagged
> bridging since the same v5.15 change. Jonas observed the same
> limitation earlier in this thread from the other direction: on the
> chips where standalone RX still works, forwarding tagged frames
> between ports does not.
I fail to see how commit 06cfb2df7eb0 ("net: dsa: don't advertise
'rx-vlan-filter' when not needed") could have caused a regression in
VLAN-unaware bridging on your b53 switch. Only perhaps if VLAN-unaware
traffic worked by coincidence. If the switch drops packets with an
unmapped arbitrary VID=1234, it would do so regardless of whether
'rx-vlan-filter' is advertised or not - unless VID=1234 is not arbitrary
but was programmed somehow by higher layers. Which is *not* a
requirement for VLAN-unaware bridging.
>
> The reason the fix scopes to standalone ports is that they have a
> finite, well-defined VID source: the 8021q uppers, reported through
> the feature bit. A VLAN-unaware bridge has no such source; making it
> transparent would mean programming the whole VID space, which is the
> several-seconds-per-toggle variant Jonas measured and rejected in the
> first thread. So the series fixes the reported regression, the
> standalone PPPoE/upper case, and does not pretend to fix transparent
> tagged bridging, which this hardware has not done since v5.15 either.
>
> > If there is a problem with the vlan_filtering_is_global +
> > needs_standalone_vlan_filtering combination, then hellcreek also suffers
> > from it, because it does set both flags as well.
>
> You are right, and the commit message argues this badly; I will reword
> it if a v2 is wanted. vlan_filtering_is_global is not the
> differentiator, hellcreek sets it too. The difference is what the
> forced vlan_filtering=1 means for each driver. For hellcreek,
> switch-wide VLAN awareness is the intended operating state; its
> standalone traffic depends on filtering being on, and hellcreek.c
> documents that unmanaged setups are not supported. The forced flip
> lands it in the state it wants. For b53, vlan_filtering=1 is a
> different user-visible mode for every port on the switch: untagged
> frames become PVID-classified against the table, egress untagging
> applies, unknown VIDs are dropped at ingress. Forcing that globally
> because one port left a VLAN-unaware bridge would change the behaviour
> of every other port, including members of VLAN-unaware bridges that
> expect transparent operation.
..which you just said earlier that they don't work either way?!
> b53 needs the VIDs delivered while vlan_filtering stays wherever the
> user put it, which is the narrower flag.
Sorry, but I'm not able to make any sense of this explanation.
The only distinction I'm seeing is that in hellcreek, VLAN-unaware mode
works, and in your b53 model it doesn't.
> > Why can't standalone ports tolerate the .port_vlan_filtering() call?
>
> They do tolerate and still receive it: the ds->ops->port_vlan_filtering
> call is unchanged, b53 sees every toggle and rebuilds its hardware
> state from its own records.
Ok, my mistake.
> What the flag skips is only the core's
> dsa_user_manage_vlan_filtering(), whose two jobs are wrong for a
> switch whose feature bit is permanently on. On the way to
> vlan_filtering=1 it replays VIDs that were never cleared, so
> vlan_vid_add() refcounts every upper VID twice.
You are really explaining here what is needed for your hack to work, not
why your hack is needed.
You need to skip dsa_user_manage_vlan_filtering() because you want to
keep VLAN filters you need while lying to higher layers that you don't
need them. Just saying that you do need them and refusing to operate
otherwise is much more straightforward.
> On the way to 0 it
> clears the VIDs and drops NETIF_F_HW_VLAN_CTAG_FILTER on a port that
> happens to be bridged at toggle time; I measured that case on the
> RT-N18U: after the port later leaves the bridge, its uppers stay dead
> until reboot, because nothing re-offloads them once the feature bit is
> gone.
With vlan_filtering/NETIF_F_HW_VLAN_CTAG_FILTER set to 0, no one *has*
to reoffload the VLAN filters, because the hardware shouldn't need them.
Try the VID=1234 case with 2 veth interfaces in a software VLAN-unaware
bridge.
> With the skip, both effects are gone and the driver derives the
> hardware state from the flip itself. hellcreek does not set the new
> flag, so its path through dsa_user_manage_vlan_filtering() is
> unchanged.
>
> Best regards,
> Semih
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH net 1/2] net: dsa: let drivers offload 8021q uppers on standalone ports
2026-08-06 12:43 ` Vladimir Oltean
@ 2026-08-06 13:39 ` Semih Baskan
0 siblings, 0 replies; 9+ messages in thread
From: Semih Baskan @ 2026-08-06 13:39 UTC (permalink / raw)
To: Vladimir Oltean
Cc: florian.fainelli, jonas.gorski, andrew, davem, edumazet, kuba,
pabeni, vladimir.oltean, horms, netdev, linux-kernel
Hi Vladimir,
> But it doesn't, at least not in a sane way. If it still only accepts
> those VLANs that have been added to filters by higher layers, it's not
> VLAN-unaware. If a solution is not found to the problem, the driver must
> reject operation as VLAN-unaware.
You are right that the port is not VLAN-unaware. It cannot be: the VID
lookup on this silicon cannot be turned off without the ARL loss from
the other subthread. My mistake in the previous mail was arguing around
that instead of saying it.
Let me first correct a history error I made, because the accurate
version actually simplifies the discussion.
> I fail to see how commit 06cfb2df7eb0 ("net: dsa: don't advertise
> 'rx-vlan-filter' when not needed") could have caused a regression in
> VLAN-unaware bridging on your b53 switch.
Correct, it could not, and my sentence attributing transparent bridging
to the same change was wrong. b53 has had dev->vlan_enabled = true at
switch allocation since before v5.15, and b53_vlan_filtering() has
never turned the table off. So arbitrary-VID transparency was already
impossible in v5.14, the last working kernel of the bug report. There
was no coincidence and no bridging regression: what worked in v5.14
and stopped in v5.15 is exactly one pipeline, the standalone 8021q
upper. In v5.14 the feature bit was advertised unconditionally, the
VIDs were delivered, and .port_vlan_add programmed them into the
always-on table. 06cfb2df7eb0 stopped the delivery and f089652b6b16
stopped the programming. The series restores that v5.14 pipeline for
drivers that opt in, and nothing else. That is why the Fixes tag
points where it points.
> ..which you just said earlier that they don't work either way?!
You are right, that sentence conflated two things. Forcing
vlan_filtering=1 globally would not hurt tagged transparency, which is
dead either way. What it changes is what works today: untagged
forwarding becomes subject to bridge VLAN semantics the user never
configured, the reported vlan_filtering state of every bridge on the
switch flips under the user, and b53 switches its ingress mode to
VC4_ING_VID_VIO_DROP plus VC5_DROP_VTABLE_MISS chip-wide.
> The only distinction I'm seeing is that in hellcreek, VLAN-unaware mode
> works, and in your b53 model it doesn't.
Yes, and I think the three reasons you listed in 06cfb2df7eb0's commit
message describe the difference better than my commit message did.
hellcreek is case 3: its hardware can be VLAN-unaware, but standalone
separation depends on unique VLANs, so its flag also forces the
vlan_filtering state, and that forcing is correct there. b53 after
v5.14 is case 1, "the standalone ports would otherwise drop
VLAN-tagged traffic", with one difference: in case 1 the VLAN
awareness that causes the dropping is held on by a VLAN-aware bridge
elsewhere on the switch, while on b53 it is held on by the silicon
itself, permanently. The new flag registers exactly that: a driver
whose ports always satisfy case 1's condition, with no bridge
required. It deliberately does not force the vlan_filtering state the
way needs_standalone_vlan_filtering does, because that forcing solves
hellcreek's separation problem, which b53 does not have.
> You need to skip dsa_user_manage_vlan_filtering() because you want to
> keep VLAN filters you need while lying to higher layers that you don't
> need them.
I would describe it as the opposite. 'rx-vlan-filter: on' is the true
statement about this hardware: it filters, always, and cannot do
otherwise. What lies to higher layers is the current mainline
behaviour, which reports the port as not filtering and then drops
every unsubscribed VID in silicon. The flag makes the feature bit
match the silicon; the skip then only stops the core from toggling a
bit that describes an invariant property.
> With vlan_filtering/NETIF_F_HW_VLAN_CTAG_FILTER set to 0, no one *has*
> to reoffload the VLAN filters, because the hardware shouldn't need them.
Agreed, in the software model no one has to. The measurement was not an
argument that the software model is wrong; it shows what breaks
mechanically if the flag advertises the feature permanently but the
core still clears it on toggles. It is internal consistency of this
approach, not a requirement I claim the model imposes.
Which leaves the real question, what to do with hardware like this.
I see three options.
1. Reject VLAN-unaware operation, as you suggest. Honest, but on b53 it
refuses the default configuration of every deployed OpenWrt board on
this platform, where the LAN bridge is vlan_filtering=0. That turns
a working untagged setup into a broken one on a kernel update.
2. Force VLAN awareness, the hellcreek way. No new core code, but it
flips the reported vlan_filtering state under the user, changes
untagged handling switch-wide, and enables the drop modes above on
every port. Whether that cost is acceptable for this user base is
really a question for Jonas and Florian.
3. This series: report the filtering that the silicon actually does,
restore the v5.14 delivery pipeline behind an opt-in, and change
nothing else. Untagged setups keep working unchanged, VLAN-unaware
bridges keep their (already partial) behaviour unchanged, and the
one regression users actually reported is fixed in a way that can
go to stable.
I implemented 3 because it is the only one where no deployed
configuration changes behaviour. If the consensus is that 1 or 2 is
the right model for b53 despite the fallout, I will help make and test
that on the hardware I have, but I do not think it can be the net fix
for the regression.
Best regards,
Semih
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-08-06 13:39 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-06 7:31 [PATCH net 0/2] net: dsa: b53: fix 8021q uppers on standalone ports Semih Baskan
2026-08-06 7:31 ` [PATCH net 1/2] net: dsa: let drivers offload " Semih Baskan
2026-08-06 11:15 ` Vladimir Oltean
2026-08-06 11:44 ` Semih Baskan
2026-08-06 12:43 ` Vladimir Oltean
2026-08-06 13:39 ` Semih Baskan
2026-08-06 7:31 ` [PATCH net 2/2] net: dsa: b53: " Semih Baskan
2026-08-06 8:39 ` [PATCH net 0/2] net: dsa: b53: fix " Jonas Gorski
2026-08-06 11:06 ` Semih Baskan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox