[PATCH 1/2] xdp: propagate queue_index through xdp_frame
From: Anand Kumar Shaw
Date: Tue Feb 17 2026 - 09:34:00 EST
When an XDP frame is redirected via cpumap or devmap, the original RX
queue index from xdp_rxq_info is lost during the xdp_buff to xdp_frame
conversion. This causes BPF programs running on the remote CPU to always
see rx_queue_index as 0, and SKBs built from xdp_frame to lack proper
RX queue metadata.
Add a queue_index field to struct xdp_frame and populate it from
xdp->rxq->queue_index in both the normal conversion path
(xdp_convert_buff_to_frame) and the zero-copy path
(xdp_convert_zc_to_xdp_frame).
Additionally, call skb_record_rx_queue() in __xdp_build_skb_from_frame()
to set the RX queue on SKBs built from xdp_frame, resolving a
documented gap in the function.
Signed-off-by: Anand Kumar Shaw <anandkrshawheritage@xxxxxxxxx>
---
include/net/xdp.h | 2 ++
net/core/xdp.c | 3 ++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/include/net/xdp.h b/include/net/xdp.h
index aa742f413c35..4912e132ff84 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -303,6 +303,7 @@ struct xdp_frame {
struct net_device *dev_rx; /* used by cpumap */
u32 frame_sz;
u32 flags; /* supported values defined in xdp_buff_flags */
+ u32 queue_index;
};
static __always_inline bool xdp_frame_has_frags(const struct xdp_frame *frame)
@@ -441,6 +442,7 @@ struct xdp_frame *xdp_convert_buff_to_frame(struct xdp_buff *xdp)
/* rxq only valid until napi_schedule ends, convert to xdp_mem_type */
xdp_frame->mem_type = xdp->rxq->mem.type;
+ xdp_frame->queue_index = xdp->rxq->queue_index;
return xdp_frame;
}
diff --git a/net/core/xdp.c b/net/core/xdp.c
index fee6d080ee85..2d6a3f2c9584 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -606,6 +606,7 @@ struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp)
xdpf->metasize = metasize;
xdpf->frame_sz = PAGE_SIZE;
xdpf->mem_type = MEM_TYPE_PAGE_ORDER0;
+ xdpf->queue_index = xdp->rxq->queue_index;
xsk_buff_free(xdp);
return xdpf;
@@ -833,8 +834,8 @@ struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
/* Optional SKB info, currently missing:
* - HW checksum info (skb->ip_summed)
* - HW RX hash (skb_set_hash)
- * - RX ring dev queue index (skb_record_rx_queue)
*/
+ skb_record_rx_queue(skb, xdpf->queue_index);
if (xdpf->mem_type == MEM_TYPE_PAGE_POOL)
skb_mark_for_recycle(skb);
--
2.39.5 (Apple Git-154)