From: Liang Chen <liangchen.linux@gmail.com>
To: mst@redhat.com, jasowang@redhat.com, hengqi@linux.alibaba.com,
xuanzhuo@linux.alibaba.com
Cc: virtualization@lists.linux-foundation.org,
linux-kernel@vger.kernel.org, liangchen.linux@gmail.com
Subject: [PATCH v2 1/3] virtio_net: Preserve virtio header before XDP program execution
Date: Wed, 24 Jan 2024 16:57:19 +0800 [thread overview]
Message-ID: <20240124085721.54442-2-liangchen.linux@gmail.com> (raw)
In-Reply-To: <20240124085721.54442-1-liangchen.linux@gmail.com>
The xdp program may overwrite the inline virtio header. To ensure the
integrity of the virtio header, it is saved in a data structure that
wraps both the xdp_buff and the header before running the xdp program.
Signed-off-by: Liang Chen <liangchen.linux@gmail.com>
---
drivers/net/virtio_net.c | 43 +++++++++++++++++++++++++++++-----------
1 file changed, 31 insertions(+), 12 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d7ce4a1011ea..b56828804e5f 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -349,6 +349,11 @@ struct virtio_net_common_hdr {
};
};
+struct virtnet_xdp_buff {
+ struct xdp_buff xdp;
+ struct virtio_net_common_hdr hdr;
+};
+
static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
static bool is_xdp_frame(void *ptr)
@@ -1199,9 +1204,10 @@ static struct sk_buff *receive_small_xdp(struct net_device *dev,
unsigned int headroom = vi->hdr_len + header_offset;
struct virtio_net_hdr_mrg_rxbuf *hdr = buf + header_offset;
struct page *page = virt_to_head_page(buf);
+ struct virtnet_xdp_buff virtnet_xdp;
struct page *xdp_page;
+ struct xdp_buff *xdp;
unsigned int buflen;
- struct xdp_buff xdp;
struct sk_buff *skb;
unsigned int metasize = 0;
u32 act;
@@ -1233,17 +1239,23 @@ static struct sk_buff *receive_small_xdp(struct net_device *dev,
page = xdp_page;
}
- xdp_init_buff(&xdp, buflen, &rq->xdp_rxq);
- xdp_prepare_buff(&xdp, buf + VIRTNET_RX_PAD + vi->hdr_len,
+ xdp = &virtnet_xdp.xdp;
+ xdp_init_buff(xdp, buflen, &rq->xdp_rxq);
+ xdp_prepare_buff(xdp, buf + VIRTNET_RX_PAD + vi->hdr_len,
xdp_headroom, len, true);
- act = virtnet_xdp_handler(xdp_prog, &xdp, dev, xdp_xmit, stats);
+ /* Copy out the virtio header, as it may be overwritten by the
+ * xdp program.
+ */
+ memcpy(&virtnet_xdp.hdr, hdr, vi->hdr_len);
+
+ act = virtnet_xdp_handler(xdp_prog, xdp, dev, xdp_xmit, stats);
switch (act) {
case XDP_PASS:
/* Recalculate length in case bpf program changed it */
- len = xdp.data_end - xdp.data;
- metasize = xdp.data - xdp.data_meta;
+ len = xdp->data_end - xdp->data;
+ metasize = xdp->data - xdp->data_meta;
break;
case XDP_TX:
@@ -1254,7 +1266,7 @@ static struct sk_buff *receive_small_xdp(struct net_device *dev,
goto err_xdp;
}
- skb = virtnet_build_skb(buf, buflen, xdp.data - buf, len);
+ skb = virtnet_build_skb(buf, buflen, xdp->data - buf, len);
if (unlikely(!skb))
goto err;
@@ -1591,10 +1603,11 @@ static struct sk_buff *receive_mergeable_xdp(struct net_device *dev,
int num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers);
struct page *page = virt_to_head_page(buf);
int offset = buf - page_address(page);
+ struct virtnet_xdp_buff virtnet_xdp;
unsigned int xdp_frags_truesz = 0;
struct sk_buff *head_skb;
unsigned int frame_sz;
- struct xdp_buff xdp;
+ struct xdp_buff *xdp;
void *data;
u32 act;
int err;
@@ -1604,16 +1617,22 @@ static struct sk_buff *receive_mergeable_xdp(struct net_device *dev,
if (unlikely(!data))
goto err_xdp;
- err = virtnet_build_xdp_buff_mrg(dev, vi, rq, &xdp, data, len, frame_sz,
+ xdp = &virtnet_xdp.xdp;
+ err = virtnet_build_xdp_buff_mrg(dev, vi, rq, xdp, data, len, frame_sz,
&num_buf, &xdp_frags_truesz, stats);
if (unlikely(err))
goto err_xdp;
- act = virtnet_xdp_handler(xdp_prog, &xdp, dev, xdp_xmit, stats);
+ /* Copy out the virtio header, as it may be overwritten by the
+ * xdp program.
+ */
+ memcpy(&virtnet_xdp.hdr, hdr, vi->hdr_len);
+
+ act = virtnet_xdp_handler(xdp_prog, xdp, dev, xdp_xmit, stats);
switch (act) {
case XDP_PASS:
- head_skb = build_skb_from_xdp_buff(dev, vi, &xdp, xdp_frags_truesz);
+ head_skb = build_skb_from_xdp_buff(dev, vi, xdp, xdp_frags_truesz);
if (unlikely(!head_skb))
break;
return head_skb;
@@ -1626,7 +1645,7 @@ static struct sk_buff *receive_mergeable_xdp(struct net_device *dev,
break;
}
- put_xdp_frags(&xdp);
+ put_xdp_frags(xdp);
err_xdp:
put_page(page);
--
2.40.1
next prev parent reply other threads:[~2024-01-24 8:58 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-24 8:57 [PATCH v2 0/3] virtio_net: Support the RX hash XDP hint Liang Chen
2024-01-24 8:57 ` Liang Chen [this message]
2024-01-24 9:06 ` [PATCH v2 1/3] virtio_net: Preserve virtio header before XDP program execution Xuan Zhuo
2024-01-25 10:17 ` Liang Chen
2024-01-24 8:57 ` [PATCH v2 2/3] virtio_net: Add missing virtio header in skb for XDP_PASS Liang Chen
2024-01-24 9:14 ` Xuan Zhuo
2024-01-25 3:48 ` Jason Wang
2024-01-25 6:41 ` Xuan Zhuo
2024-01-25 6:50 ` Liang Chen
2024-01-24 11:04 ` Heng Qi
2024-01-25 6:52 ` Liang Chen
2024-01-24 8:57 ` [PATCH v2 3/3] virtio_net: Support RX hash XDP hint Liang Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240124085721.54442-2-liangchen.linux@gmail.com \
--to=liangchen.linux@gmail.com \
--cc=hengqi@linux.alibaba.com \
--cc=jasowang@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mst@redhat.com \
--cc=virtualization@lists.linux-foundation.org \
--cc=xuanzhuo@linux.alibaba.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.