A multi-queue conduit records its RX queue in skb->queue_mapping with skb_record_rx_queue(), as stmmac, mtk_eth_soc, fec and dpaa2 do. dsa_switch_rcv() passes the skb to the user port with that value unchanged, but user ports have a single RX queue. For a packet that arrived on conduit queue 1 or above, get_rps_cpu() finds the index past the user port's real_num_rx_queues and returns without steering. The WARN_ONCE() there stays silent because the port has only one queue. As a result, rps_cpus on a user port takes effect only for packets that arrived on conduit queue 0. Clear the queue mapping when the skb is handed to the user port. TX queue selection is unaffected: the user port's own netdev_pick_tx() sets queue_mapping again before the conduit transmits. Found on an IPQ8074 board (OpenWrt, Linux 6.18, conduit with four RX rings): with rps_cpus set on the LAN and WAN user ports, /proc/net/softnet_stat showed no RPS for traffic hashed to conduit rings 1-3. With this change, that traffic is steered to the configured CPUs. Fixes: 91da11f870f0 ("net: Distributed Switch Architecture protocol support") Assisted-by: LLM Signed-off-by: John Macias --- The Fixes tag points at the commit that added the DSA receive path. The problem shows up once RPS is used on a user port, since get_rps_cpu() checks the recorded queue against the port's own queue count. This was found and fixed with an AI coding assistant (Claude, from Anthropic). It traced the missing RPS to the stale queue_mapping, wrote the change and this changelog, and ran the tests on my hardware. I have reviewed the change. Testing: the same change on OpenWrt's Linux 6.18 on a Netgear RAX120 v1 (IPQ8074, out-of-tree qca_edma conduit with four RX rings, RSS over all four). Before, received_rps stayed at 0 on every CPU over 8 runs of bidirectional UDP with rps_cpus set on lan1 and wan. After, it rises on the configured CPUs for traffic from rings 1-3. On this tree (net, 7076f684d) the change is build-tested only (x86_64 defconfig with NET_DSA, W=1, WERROR). I have not tested it with a mainline conduit driver. net/dsa/tag.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/dsa/tag.c b/net/dsa/tag.c index 6a5aa7fc3..ecd4d8669 100644 --- a/net/dsa/tag.c +++ b/net/dsa/tag.c @@ -115,6 +115,12 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, skb = nskb; } + /* The conduit's RX queue index means nothing on the user port, which + * has a single RX queue, and get_rps_cpu() skips RPS when the index + * is out of range. + */ + skb_set_queue_mapping(skb, 0); + dev_sw_netstats_rx_add(skb->dev, skb->len + ETH_HLEN); if (dsa_skb_defer_rx_timestamp(p, skb)) -- 2.47.3