Thread (32 messages) 32 messages, 4 authors, 2024-07-01

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help