>From 033e3a8650a498de73cd202375b2e3f843e9a376 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Thu, 28 Jul 2022 02:07:08 +0300 Subject: [PATCH] ksz9477: force-disable address learning I suspect that what Brian Hutchinson experiences with the rx_discards counter incrementing is due to his setup, where 2 external switches connect together 2 bonded KSZ9567 switch ports, in such a way that one KSZ port is able to see packets sent by the other (this is probably aggravated by the multicast sent at a high data rate, which is treated as broadcast by the external switches and flooded). If we don't turn address learning off on standalone ports, this results in the switch learning that a packet with this MAC SA came from the outside world (when the MAC address actually belongs to Linux, and must be forwarded to Linux). Then when the outside world actually tries to reach Linux' MAC address, the KSZ switch finds that MAC address in the FDB, but it points towards the outside world port, from which the packet was received. 'Hey are you crazy, do you want me to loop back this packet? No, let me just drop it" - is what I suspect the KSZ switch would say, and a valid reason why it would increment rx_discards. To prove this, hack the ksz9477_port_stp_state_set() method from v5.10.69 such as to force-disable address learning on all KSZ ports. Ports that are standalone have their STP state set to FORWARDING by DSA through dsa_port_enable_rt() -> dsa_port_set_state_now(dp, BR_STATE_FORWARDING), so I find it reasonable that this patch takes effect if that is the problem. I've disabled learning for all STP states just to make sure the driver doesn't transition through some STP states in which it learns something, and then it doesn't get rid of those addresses, corrupting the test. Signed-off-by: Vladimir Oltean --- drivers/net/dsa/microchip/ksz9477.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index b3aa99eb6c2c..c20ee86c98c0 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -419,10 +419,10 @@ static void ksz9477_port_stp_state_set(struct dsa_switch *ds, int port, member = dev->host_mask | p->vid_member; break; case BR_STATE_LEARNING: - data |= PORT_RX_ENABLE; + data |= PORT_RX_ENABLE | PORT_LEARN_DISABLE; break; case BR_STATE_FORWARDING: - data |= (PORT_TX_ENABLE | PORT_RX_ENABLE); + data |= (PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE); /* This function is also used internally. */ if (port == dev->cpu_port) -- 2.34.1