Re: [PATCH net-next 21/33] virtio_net: add XDP frame size in two code paths
flat view
From: Jason Wang <hidden>
Date: 2020-04-28 09:51:02
Also in:
bpf
On 2020/4/27 下午10:32, Jesper Dangaard Brouer wrote:
On Mon, 27 Apr 2020 15:21:02 +0800 Jason Wang[off-list ref] wrote:quoted
On 2020/4/23 上午12:09, Jesper Dangaard Brouer wrote:quoted
The virtio_net driver is running inside the guest-OS. There are two XDP receive code-paths in virtio_net, namely receive_small() and receive_mergeable(). The receive_big() function does not support XDP. In receive_small() the frame size is available in buflen. The buffer backing these frames are allocated in add_recvbuf_small() with same size, except for the headroom, but tailroom have reserved room for skb_shared_info. The headroom is encoded in ctx pointer as a value. In receive_mergeable() the frame size is more dynamic. There are two basic cases: (1) buffer size is based on a exponentially weighted moving average (see DECLARE_EWMA) of packet length. Or (2) in case virtnet_get_headroom() have any headroom then buffer size is PAGE_SIZE. The ctx pointer is this time used for encoding two values; the buffer len "truesize" and headroom. In case (1) if the rx buffer size is underestimated, the packet will have been split over more buffers (num_buf info in virtio_net_hdr_mrg_rxbuf placed in top of buffer area). If that happens the XDP path does a xdp_linearize_page operation. Cc: Jason Wang<redacted> Signed-off-by: Jesper Dangaard Brouer<redacted> --- drivers/net/virtio_net.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 11f722460513..1df3676da185 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c@@ -689,6 +689,7 @@ static struct sk_buff *receive_small(struct net_device *dev, xdp.data_end = xdp.data + len; xdp.data_meta = xdp.data; xdp.rxq = &rq->xdp_rxq; + xdp.frame_sz = buflen; orig_data = xdp.data; act = bpf_prog_run_xdp(xdp_prog, &xdp); stats->xdp_packets++;@@ -797,10 +798,11 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, int offset = buf - page_address(page); struct sk_buff *head_skb, *curr_skb; struct bpf_prog *xdp_prog; - unsigned int truesize; + unsigned int truesize = mergeable_ctx_to_truesize(ctx); unsigned int headroom = mergeable_ctx_to_headroom(ctx); - int err; unsigned int metasize = 0; + unsigned int frame_sz; + int err; head_skb = NULL; stats->bytes += len - vi->hdr_len;@@ -821,6 +823,11 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, if (unlikely(hdr->hdr.gso_type)) goto err_xdp; + /* Buffers with headroom use PAGE_SIZE as alloc size, + * see add_recvbuf_mergeable() + get_mergeable_buf_len() + */ + frame_sz = headroom ? PAGE_SIZE : truesize; + /* This happens when rx buffer size is underestimated * or headroom is not enough because of the buffer * was refilled before XDP is set. This should only@@ -834,6 +841,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, page, offset, VIRTIO_XDP_HEADROOM, &len); + frame_sz = PAGE_SIZE;Should this be PAGE_SIZE - SKB_DATA_ALIGN(sizeof(struct skb_shared_info))?No, frame_sz include the SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) length.
Ok, consider mergeable buffer path depends on the truesize which is encoded in ctx. It looks to the the calculation in add_recvfbuf_mergeable() is wrong, we need count both headroom and tailroom there. We probably need the attached 2 patches to fix this. (untested, will test it tomorrow). Thanks
Attachments
- 0002-virtio-net-fix-the-XDP-truesize-calculation-for-merg.patch [text/x-patch] 1825 bytes · preview
- 0001-virtio-net-don-t-reserve-space-for-vnet-header-for-X.patch [text/x-patch] 1738 bytes · preview