Re: [PATCH net-next v6 09/10] virtio_net: xsk: rx: support recv merge mode
From: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
Date: 2024-06-28 05:56:54
Also in:
bpf, virtualization
On Fri, 28 Jun 2024 10:19:44 +0800, Jason Wang [off-list ref] wrote:
On Tue, Jun 18, 2024 at 3:57 PM Xuan Zhuo [off-list ref] wrote:quoted
Support AF-XDP for merge mode. Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com> --- drivers/net/virtio_net.c | 139 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+)diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 06608d696e2e..cfa106aa8039 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c@@ -504,6 +504,10 @@ static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp, struct net_device *dev, unsigned int *xdp_xmit, struct virtnet_rq_stats *stats); +static struct sk_buff *virtnet_skb_append_frag(struct sk_buff *head_skb, + struct sk_buff *curr_skb, + struct page *page, void *buf, + int len, int truesize); static bool is_xdp_frame(void *ptr) {@@ -1128,6 +1132,139 @@ static struct sk_buff *virtnet_receive_xsk_small(struct net_device *dev, struct } } +static void xsk_drop_follow_bufs(struct net_device *dev, + struct receive_queue *rq, + u32 num_buf, + struct virtnet_rq_stats *stats) +{ + struct xdp_buff *xdp; + u32 len; + + while (num_buf-- > 1) { + xdp = virtqueue_get_buf(rq->vq, &len); + if (unlikely(!xdp)) { + pr_debug("%s: rx error: %d buffers missing\n", + dev->name, num_buf); + DEV_STATS_INC(dev, rx_length_errors); + break; + } + u64_stats_add(&stats->bytes, len); + xsk_buff_free(xdp); + } +} + +static int xsk_append_merge_buffer(struct virtnet_info *vi, + struct receive_queue *rq, + struct sk_buff *head_skb, + u32 num_buf, + struct virtio_net_hdr_mrg_rxbuf *hdr, + struct virtnet_rq_stats *stats) +{ + struct sk_buff *curr_skb; + struct xdp_buff *xdp; + u32 len, truesize; + struct page *page; + void *buf; + + curr_skb = head_skb; + + while (--num_buf) { + buf = virtqueue_get_buf(rq->vq, &len); + if (unlikely(!buf)) { + pr_debug("%s: rx error: %d buffers out of %d missing\n", + vi->dev->name, num_buf, + virtio16_to_cpu(vi->vdev, + hdr->num_buffers)); + DEV_STATS_INC(vi->dev, rx_length_errors); + return -EINVAL; + } + + u64_stats_add(&stats->bytes, len); + + xdp = buf_to_xdp(vi, rq, buf, len); + if (!xdp) + goto err; + + buf = napi_alloc_frag(len);So we don't do this for non xsk paths. Any reason we can't reuse the existing codes?
Do you mean this code:
while (--num_buf) {
int num_skb_frags;
-> buf = virtnet_rq_get_buf(rq, &len, &ctx);
if (unlikely(!buf)) {
pr_debug("%s: rx error: %d buffers out of %d missing\n",
dev->name, num_buf,
virtio16_to_cpu(vi->vdev,
hdr->num_buffers));
DEV_STATS_INC(dev, rx_length_errors);
goto err_buf;
}
u64_stats_add(&stats->bytes, len);
page = virt_to_head_page(buf);
-> truesize = mergeable_ctx_to_truesize(ctx);
-> headroom = mergeable_ctx_to_headroom(ctx);
-> tailroom = headroom ? sizeof(struct skb_shared_info) : 0;
-> room = SKB_DATA_ALIGN(headroom + tailroom);
-> if (unlikely(len > truesize - room)) {
-> pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
-> dev->name, len, (unsigned long)(truesize - room));
-> DEV_STATS_INC(dev, rx_length_errors);
-> goto err_skb;
-> }
curr_skb = virtnet_skb_append_frag(head_skb, curr_skb, page,
buf, len, truesize);
if (!curr_skb)
goto err_skb;
}
The code lines that are marked are differ.
The same logic is separated to function virtnet_skb_append_frag().
So the code is similitude, but we can not merge them.
Thanks.
Thanks