On Mon, Jan 03, 2022 at 04:08:11PM +0100, Toke Høiland-Jørgensen wrote: > +static void xdp_test_run_init_page(struct page *page, void *arg) > +{ > + struct xdp_page_head *head = phys_to_virt(page_to_phys(page)); > + struct xdp_buff *new_ctx, *orig_ctx; > + u32 headroom = XDP_PACKET_HEADROOM; > + struct xdp_test_data *xdp = arg; > + size_t frm_len, meta_len; > + struct xdp_frame *frm; > + void *data; > + > + orig_ctx = xdp->orig_ctx; > + frm_len = orig_ctx->data_end - orig_ctx->data_meta; > + meta_len = orig_ctx->data - orig_ctx->data_meta; > + headroom -= meta_len; > + > + new_ctx = &head->ctx; > + frm = &head->frm; > + data = &head->data; > + memcpy(data + headroom, orig_ctx->data_meta, frm_len); > + > + xdp_init_buff(new_ctx, TEST_XDP_FRAME_SIZE, &xdp->rxq); > + xdp_prepare_buff(new_ctx, data, headroom, frm_len, true); > + new_ctx->data_meta = new_ctx->data + meta_len; data vs data_meta is the other way around, no? Probably needs a selftest to make sure. > +static int xdp_recv_frames(struct xdp_frame **frames, int nframes, > + struct net_device *dev) > +{ > + gfp_t gfp = __GFP_ZERO | GFP_ATOMIC; > + void *skbs[TEST_XDP_BATCH]; > + int i, n; > + LIST_HEAD(list); > + > + n = kmem_cache_alloc_bulk(skbuff_head_cache, gfp, nframes, skbs); > + if (unlikely(n == 0)) { > + for (i = 0; i < nframes; i++) > + xdp_return_frame(frames[i]); > + return -ENOMEM; > + } > + > + for (i = 0; i < nframes; i++) { > + struct xdp_frame *xdpf = frames[i]; > + struct sk_buff *skb = skbs[i]; > + > + skb = __xdp_build_skb_from_frame(xdpf, skb, dev); > + if (!skb) { > + xdp_return_frame(xdpf); > + continue; > + } > + > + list_add_tail(&skb->list, &list); > + } > + netif_receive_skb_list(&list); Does it need local_bh_disable() like cpumap does? I've applied patches 1 - 5.