From 2acaf1d8aca770c0c3110baa78559efa5d018037 Mon Sep 17 00:00:00 2001 From: Arthur Kiyanovski Date: Fri, 12 Sep 2025 20:29:38 +0000 Subject: [PATCH] af_xdp: Fix wakeup channel mismatch causing performance degradation When AF_XDP sockets are bound to non-zero hardware queues, applications experience severe throughput degradation (e.g., 9 Gbps drops to 20 Mbps). Problem: The efrm_vi_get_channel() function calculates wakeup channels using RSS modulo arithmetic: `instance % rss_channel_count`. For AF_XDP devices, rss_channel_count is hardcoded to 1, causing all VI instances to map to wakeup channel 0, regardless of their actual hardware queue binding. This creates a mismatch where: - AF_XDP socket correctly binds to hardware queue N - Packets arrive at hardware queue N - But application wakeup notifications are sent to event queue 0 - Application relies on periodic polling (90ms timeout) instead of immediate event-driven wakeups Root Cause: AF_XDP uses direct queue selection via ntuple rules rather than RSS distribution, making the RSS-based wakeup channel calculation incorrect. Solution: Add AF_XDP-specific logic to use direct 1:1 mapping where the wakeup channel equals the VI instance number, ensuring proper alignment between packet arrival queue and application wakeup channel. Testing: - Before: Queue 4 traffic = 20 Mbps (450x degradation) - After: Queue 4 traffic = 9 Gbps (full performance restored) - Queue 0 performance unaffected (was already working correctly) --- src/lib/efrm/vi_resource_info.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lib/efrm/vi_resource_info.c b/src/lib/efrm/vi_resource_info.c index a39234250..fdc2f94a5 100644 --- a/src/lib/efrm/vi_resource_info.c +++ b/src/lib/efrm/vi_resource_info.c @@ -103,10 +103,17 @@ EXPORT_SYMBOL(efrm_vi_get_dev); int efrm_vi_get_channel(struct efrm_vi *virs) { - struct efrm_nic *nic = efrm_nic(virs->rs.rs_client->nic); + struct efhw_nic *efhw_nic = efrm_client_get_nic(virs->rs.rs_client); + struct efrm_nic *nic = efrm_nic(efhw_nic); + /* interrupt is managed by us. */ if (virs->vec != NULL) return virs->vec->channel; + + /* For AF_XDP, wakeup channel must match the AF_XDP queue number */ + if (efhw_nic->devtype.arch == EFHW_ARCH_AF_XDP) + return virs->rs.rs_instance; + /* interrupt is managed by net driver. */ return virs->net_drv_wakeup_channel >= 0 ? virs->net_drv_wakeup_channel :