[...] >> @@ -393,34 +397,39 @@ static u32 do_xdp_prog(struct virtnet_info *vi, >> struct bpf_prog *xdp_prog, >> void *data, int len) >> { >> - int hdr_padded_len; >> struct xdp_buff xdp; >> - void *buf; >> unsigned int qp; >> u32 act; >> + >> if (vi->mergeable_rx_bufs) { >> - hdr_padded_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); >> - xdp.data = data + hdr_padded_len; >> + int desc_room = sizeof(struct virtio_net_hdr_mrg_rxbuf); >> + >> + /* Allow consuming headroom but reserve enough space to push >> + * the descriptor on if we get an XDP_TX return code. >> + */ >> + xdp.data_hard_start = data - vi->headroom + desc_room; >> + xdp.data = data + desc_room; >> xdp.data_end = xdp.data + (len - vi->hdr_len); >> - buf = data; >> } else { /* small buffers */ >> struct sk_buff *skb = data; >> - xdp.data = skb->data; >> + xdp.data_hard_start = skb->data; >> + xdp.data = skb->data + vi->headroom; >> xdp.data_end = xdp.data + len; >> - buf = skb->data; >> } >> act = bpf_prog_run_xdp(xdp_prog, &xdp); >> switch (act) { >> case XDP_PASS: >> + if (!vi->mergeable_rx_bufs) >> + __skb_pull((struct sk_buff *) data, >> + xdp.data - xdp.data_hard_start); > > Instead of doing things here and virtnet_xdp_xmit(). How about always making > skb->data point to the buffer head like: > > 1) reserve headroom in add_recvbuf_small() > 2) skb_push(xdp->data - xdp_data_hard_start, skb) if we detect xdp->data was > modified afer bpf_prog_run_xdp() > > Then there's no special code in either XDP_PASS or XDP_TX? >
Alternatively moving the pull into the receive_small XDP handler also removes the special case. I'll submit a patch shortly let me know what you think. >> return XDP_PASS; >> case XDP_TX: >> qp = vi->curr_queue_pairs - >> vi->xdp_queue_pairs + >> smp_processor_id(); > > [...] > .John