[PATCH] [RFC PATCH] bpf/xdp: propagate queue_index via xdp_frame for cpumap
From: Adith-Joshua
Date: Mon Apr 06 2026 - 13:13:04 EST
cpu_map_bpf_prog_run_xdp() currently lacks queue_index information in
xdp_rxq_info, as struct xdp_frame does not preserve it across the
xdp_buff -> xdp_frame conversion.
This results in loss of rx queue metadata when frames are redirected
via cpumap and later processed by XDP programs.
Propagate queue_index by storing it in struct xdp_frame during
conversion and restoring it when reconstructing xdp_buff. All
relevant xdp_frame constructors have been updated to ensure the field is consistently
initialized.
This introduces a new field in struct xdp_frame, which may have
implications for structure size and layout. Field reordering was
considered to minimize padding, but is not included here to keep the
change focused and avoid unrelated modifications.
Feedback is appreciated on whether this approach is acceptable or if a
different mechanism or struct layout would be preferred.
Signed-off-by: Adith-Joshua <adithalex29@xxxxxxxxx>
---
include/net/xdp.h | 4 ++++
kernel/bpf/cpumap.c | 2 +-
kernel/bpf/verifier.c | 12 ++++++++----
net/core/xdp.c | 1 +
4 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/include/net/xdp.h b/include/net/xdp.h
index aa742f413c35..11aecf84a896 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -301,6 +301,7 @@ struct xdp_frame {
*/
enum xdp_mem_type mem_type:32;
struct net_device *dev_rx; /* used by cpumap */
+ u32 queue_index;
u32 frame_sz;
u32 flags; /* supported values defined in xdp_buff_flags */
};
@@ -347,6 +348,7 @@ static inline void xdp_scrub_frame(struct xdp_frame *frame)
{
frame->data = NULL;
frame->dev_rx = NULL;
+ frame->queue_index = 0;
}
static inline void
@@ -392,6 +394,7 @@ void xdp_convert_frame_to_buff(const struct xdp_frame *frame,
xdp->data = frame->data;
xdp->data_end = frame->data + frame->len;
xdp->data_meta = frame->data - frame->metasize;
+ xdp->rxq->queue_index = frame->queue_index;
xdp->frame_sz = frame->frame_sz;
xdp->flags = frame->flags;
}
@@ -419,6 +422,7 @@ int xdp_update_frame_from_buff(const struct xdp_buff *xdp,
xdp_frame->len = xdp->data_end - xdp->data;
xdp_frame->headroom = headroom - sizeof(*xdp_frame);
xdp_frame->metasize = metasize;
+ xdp_frame->queue_index = xdp->rxq->queue_index;
xdp_frame->frame_sz = xdp->frame_sz;
xdp_frame->flags = xdp->flags;
diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c
index 32b43cb9061b..e475a732ceca 100644
--- a/kernel/bpf/cpumap.c
+++ b/kernel/bpf/cpumap.c
@@ -197,7 +197,7 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
rxq.dev = xdpf->dev_rx;
rxq.mem.type = xdpf->mem_type;
- /* TODO: report queue_index to xdp_rxq_info */
+ rxq.queue_index = xdpf->queue_index;
xdp_convert_frame_to_buff(xdpf, &xdp);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index e3814152b52f..e2583dfd7bf2 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -18693,12 +18693,16 @@ static struct bpf_iarray *jt_from_subprog(struct bpf_verifier_env *env,
int i;
for (i = 0; i < env->insn_array_map_cnt; i++) {
- /*
- * TODO (when needed): collect only jump tables, not static keys
- * or maps for indirect calls
- */
map = env->insn_array_maps[i];
+ /* Only consider instruction array maps with multiple entries.
+ * These correspond to jump tables. Skip others (e.g. static keys,
+ * indirect call maps).
+ */
+ if (map->map_type != BPF_MAP_TYPE_INSN_ARRAY ||
+ map->max_entries <= 1)
+ continue;
+
jt_cur = jt_from_map(map);
if (IS_ERR(jt_cur)) {
kvfree(jt);
diff --git a/net/core/xdp.c b/net/core/xdp.c
index 9890a30584ba..995f48e35310 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -604,6 +604,7 @@ struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp)
xdpf->len = totsize - metasize;
xdpf->headroom = 0;
xdpf->metasize = metasize;
+ xdpf->queue_index = xdp->rxq->queue_index;
xdpf->frame_sz = PAGE_SIZE;
xdpf->mem_type = MEM_TYPE_PAGE_ORDER0;
--
2.53.0