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 <j...@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 _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel