[PATCH] realtek: don't set L2LEARNING flag in rtl83xx TX header

Jan Hoffmann jan at 3e8.eu
Thu Oct 20 14:07:57 PDT 2022


Enabling L2 learning for packets forwarded by the CPU can result in
incorrect entries being written to the forwarding table.

If a packet that was trapped to the CPU port gets forwarded to another
port, the switch incorrectly learns the CPU port instead of the original
source port. If the packet is sent untagged, this entry is also created
for rvid 0 instead of the real VLAN.

Examples for packets which trigger this issue are Multicast Listener
Reports and IGMP membership reports.

On RTL839x, this change doesn't have any effect, as learning on the CPU
port appears to be disabled by default in RTL839X_L2_PORT_NEW_SALRN
(this is not explicitly configured by the driver).

On RTL838x, this may cause some traffic for the CPU port to be flooded.
However, this inefficiency is much less of an issue than misforwarding
traffic to the switch CPU every time a connected device sends an IGMP or
MLD report.

The severity of flooding is also somewhat limited, as the eth0 address
does not need an entry in the forwarding table (it is written to a
special MAC address register in the switch).

Fixes: 9eab76c84e31 ("realtek: Improve TX CPU-Tag usage")
Signed-off-by: Jan Hoffmann <jan at 3e8.eu>
---

RTL93xx may also be affected (the TX header doesn't have a field to
control learning), but I don't have a device to verify that.

Even with this patch, I have sometimes seen forwarding table entries
with rvid 0 being learned from the CPU port by the switch.

Maybe it would be a good idea to disable hardware learning for the CPU
port entirely (the SALEARN registers should allow that on all devices)
and let DSA handle it instead. Since kernel 5.12 (and backported to
OpenWrt), there is the assisted_learning_on_cpu_port (although that flag
doesn't really change anything in a typical switch configuration).

Kernel 5.14 adds syncing of local bridge addresses to DSA switches
(regardless of assisted learning), so flooding should no longer be an
issue after the next kernel update (the pending patches in OpenWrt
already contain variants of those changes which should enable this for
drivers with assisted learning, but that doesn't seem to work).

I'm currently looking into assisted learning and trying to figure out
why local/bridge addresses are not added to the forwarding table. But
that requires more work, and is probably better suited for a separate
patch series.

 .../realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c     | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
index d497b4cc8caa..89b296e03fed 100644
--- a/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-5.10/drivers/net/ethernet/rtl838x_eth.c
@@ -96,7 +96,7 @@ struct notify_b {
 static void rtl838x_create_tx_header(struct p_hdr *h, unsigned int dest_port, int prio)
 {
 	// cpu_tag[0] is reserved on the RTL83XX SoCs
-	h->cpu_tag[1] = 0x0401;  // BIT 10: RTL8380_CPU_TAG, BIT0: L2LEARNING on
+	h->cpu_tag[1] = 0x0400;  // BIT 10: RTL8380_CPU_TAG
 	h->cpu_tag[2] = 0x0200;  // Set only AS_DPM, to enable DPM settings below
 	h->cpu_tag[3] = 0x0000;
 	h->cpu_tag[4] = BIT(dest_port) >> 16;
@@ -111,7 +111,7 @@ static void rtl839x_create_tx_header(struct p_hdr *h, unsigned int dest_port, in
 {
 	// cpu_tag[0] is reserved on the RTL83XX SoCs
 	h->cpu_tag[1] = 0x0100; // RTL8390_CPU_TAG marker
-	h->cpu_tag[2] = BIT(4) | BIT(7); /* AS_DPM (4) and L2LEARNING (7) flags */
+	h->cpu_tag[2] = BIT(4); /* AS_DPM flag */
 	h->cpu_tag[3] = h->cpu_tag[4] = h->cpu_tag[5] = 0;
 	// h->cpu_tag[1] |= BIT(1) | BIT(0); // Bypass filter 1/2
 	if (dest_port >= 32) {
-- 
2.37.3




More information about the openwrt-devel mailing list