Move upstreamed patches to backports. Move the others to pending. Signed-off-by: Rosen Penev <rosenp@gmail.com> Link: https://github.com/openwrt/openwrt/pull/24013 Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
72 lines
2.9 KiB
Diff
72 lines
2.9 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Olaf Marzocchi <lists@marzocchi.net>
|
|
Date: Fri, 26 Jun 2026 00:00:00 +0000
|
|
Subject: [PATCH] net: dsa: qca8k: don't program unicast host FDB entries on
|
|
CPU ports
|
|
|
|
DSA installs host FDB entries for the same {MAC, VID} once per CPU port
|
|
in use. qca8k used to overwrite the single ATU entry, so the last CPU
|
|
port won and host reachability broke for user ports served by the other
|
|
CPU port (e.g. Netgear R7800 with wan bridged into br-lan). Merging the
|
|
CPU port bits into the destination mask instead is no better: the ATU
|
|
forwards a unicast hit to every port set in the mask, so a host entry
|
|
spanning both CPU ports makes the switch deliver one copy of each
|
|
host-bound frame per CPU port. This duplicated nearly all host traffic
|
|
and halved throughput on TP-Link TGR1900, Archer C2600 and ASUS
|
|
RT-AX89X, with "failed to delete ... from fdb: -22" log spam from the
|
|
asymmetric delete path.
|
|
|
|
Host FDB entries are a pure optimization on this switch: the unknown
|
|
unicast forward mask in GLOBAL_FW_CTRL1 already contains all CPU ports
|
|
and is filtered per ingress port by PORT_LOOKUP_CTRL members, so a
|
|
host-bound frame with no ATU entry reaches exactly one CPU port, the
|
|
conduit of its ingress port, and the tag parser delivers it to the
|
|
correct user netdevice from either conduit. The conduits run in
|
|
promiscuous mode (qca8k does not implement FDB isolation), so no RX
|
|
filtering relies on these entries either.
|
|
|
|
Skip programming unicast host FDB entries on CPU ports entirely. This
|
|
fixes the multi-CPU bridged setups without ever creating a unicast
|
|
destination mask with more than one CPU port bit, regardless of how a
|
|
board assigns its conduits.
|
|
|
|
Disclaimer: patch generated via Fable 5 and tested by @xback
|
|
|
|
Fixes: openwrt/openwrt#21317
|
|
Signed-off-by: Olaf Marzocchi <lists@marzocchi.net>
|
|
|
|
---
|
|
drivers/net/dsa/qca/qca8k-common.c | 14 ++++++++++++++
|
|
1 file changed, 14 insertions(+)
|
|
|
|
--- a/drivers/net/dsa/qca/qca8k-common.c
|
|
+++ b/drivers/net/dsa/qca/qca8k-common.c
|
|
@@ -836,6 +836,17 @@ int qca8k_port_fdb_add(struct dsa_switch
|
|
struct qca8k_priv *priv = ds->priv;
|
|
u16 port_mask = BIT(port);
|
|
|
|
+ /* The ATU forwards a unicast hit to every port set in the
|
|
+ * destination mask, so a host entry spanning multiple CPU ports
|
|
+ * would deliver one copy of each host-bound frame per CPU port.
|
|
+ * Skip host entries entirely: unknown unicast is already forwarded
|
|
+ * to all CPU ports by GLOBAL_FW_CTRL1 and filtered by the ingress
|
|
+ * port LOOKUP_MEMBER, so host-bound frames reach exactly one CPU
|
|
+ * port, the conduit of the ingress port.
|
|
+ */
|
|
+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
|
|
+ return 0;
|
|
+
|
|
return qca8k_port_fdb_insert(priv, addr, port_mask, vid);
|
|
}
|
|
|
|
@@ -846,6 +857,9 @@ int qca8k_port_fdb_del(struct dsa_switch
|
|
struct qca8k_priv *priv = ds->priv;
|
|
u16 port_mask = BIT(port);
|
|
|
|
+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
|
|
+ return 0;
|
|
+
|
|
if (!vid)
|
|
vid = QCA8K_PORT_VID_DEF;
|
|
|