From: weimin xiong <15927021679@163.com>
To: mst@redhat.com
Cc: jasowang@redhat.com, virtualization@vger.kernel.org,
netdev@vger.kernel.org, xiongweimin <xiongweimin@kylinos.cn>
Subject: [PATCH] vhost/net: Fill virtio_net_hdr GSO/csum metadata on RX
Date: Mon, 13 Jul 2026 09:04:42 +0800 [thread overview]
Message-ID: <20260713010442.331109-1-15927021679@163.com> (raw)
From: xiongweimin <xiongweimin@kylinos.cn>
When VHOST_NET_F_VIRTIO_NET_HDR is set, vhost supplies virtio_net_hdr to
the guest but previously always wrote a zeroed header (GSO_NONE). Guests
that rely on GUEST_TSO*/GUEST_CSUM therefore never saw offload metadata.
Peek the socket skb before recvmsg and populate the header with
virtio_net_hdr_from_skb(). Also advertise the corresponding guest offload
feature bits from VHOST_GET_FEATURES.
TX TSO toward backends without IFF_VNET_HDR is intentionally left for a
follow-up series.
Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Jason Wang <jasowang@redhat.com>
Cc: virtualization@vger.kernel.org
Cc: netdev@vger.kernel.org
---
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -73,6 +73,10 @@
VHOST_FEATURES,
VHOST_NET_F_VIRTIO_NET_HDR,
VIRTIO_NET_F_MRG_RXBUF,
+ VIRTIO_NET_F_GUEST_CSUM,
+ VIRTIO_NET_F_GUEST_TSO4,
+ VIRTIO_NET_F_GUEST_TSO6,
+ VIRTIO_NET_F_GUEST_ECN,
VIRTIO_F_ACCESS_PLATFORM,
VIRTIO_F_RING_RESET,
VIRTIO_F_IN_ORDER,
@@ -644,7 +648,7 @@
static size_t init_iov_iter(struct vhost_virtqueue *vq, struct iov_iter *iter,
size_t hdr_size, int out)
{
- /* Skip header. TODO: support TSO. */
+ /* Skip guest virtio_net_hdr; TX TSO handled in a follow-up. */
size_t len = iov_length(vq->iov, out);
iov_iter_init(iter, ITER_SOURCE, vq->iov, out, len);
@@ -1025,6 +1029,35 @@
return len;
}
+/*
+ * When VHOST_NET_F_VIRTIO_NET_HDR is set, vhost supplies virtio_net_hdr.
+ * Populate GSO/checksum metadata from the socket skb so guests that
+ * negotiated GUEST_TSO*/GUEST_CSUM receive correct offload information.
+ */
+static int vhost_net_hdr_from_sock(struct vhost_virtqueue *vq, struct sock *sk,
+ struct virtio_net_hdr *hdr)
+{
+ struct sk_buff *skb;
+ unsigned long flags;
+ int vlan_hlen = 0;
+ int ret;
+
+ spin_lock_irqsave(&sk->sk_receive_queue.lock, flags);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (!skb) {
+ spin_unlock_irqrestore(&sk->sk_receive_queue.lock, flags);
+ memset(hdr, 0, sizeof(*hdr));
+ hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
+ return 0;
+ }
+ if (skb_vlan_tag_present(skb))
+ vlan_hlen = VLAN_HLEN;
+ ret = virtio_net_hdr_from_skb(skb, hdr, vhost_is_little_endian(vq),
+ true, vlan_hlen);
+ spin_unlock_irqrestore(&sk->sk_receive_queue.lock, flags);
+ return ret;
+}
+
static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk,
bool *busyloop_intr, unsigned int *count)
{
@@ -1239,10 +1272,18 @@
/* We don't need to be notified again. */
iov_iter_init(&msg.msg_iter, ITER_DEST, vq->iov, in, vhost_len);
fixup = msg.msg_iter;
- if (unlikely((vhost_hlen))) {
- /* We will supply the header ourselves
- * TODO: support TSO.
+ if (unlikely(vhost_hlen)) {
+ /*
+ * Build virtio_net_hdr from the socket skb before
+ * recvmsg consumes it. Skip for ptr_ring backends
+ * where the skb is not on sk_receive_queue.
*/
+ if (!nvq->rx_ring &&
+ vhost_net_hdr_from_sock(vq, sock->sk, &hdr)) {
+ vq_err(vq, "Failed to build vnet_hdr from skb\n");
+ vhost_discard_vq_desc(vq, headcount, ndesc);
+ continue;
+ }
iov_iter_advance(&msg.msg_iter, vhost_hlen);
}
err = sock->ops->recvmsg(sock, &msg,
@@ -1270,7 +1311,6 @@
*/
iov_iter_advance(&fixup, sizeof(hdr));
}
- /* TODO: Should check and handle checksum. */
num_buffers = cpu_to_vhost16(vq, headcount);
if (likely(set_num_buffers) &&
next reply other threads:[~2026-07-13 1:04 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-13 1:04 weimin xiong [this message]
2026-07-13 7:03 ` [PATCH] vhost/net: Fill virtio_net_hdr GSO/csum metadata on RX Michael S. Tsirkin
2026-07-13 8:04 ` Xiong Weimin
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=20260713010442.331109-1-15927021679@163.com \
--to=15927021679@163.com \
--cc=jasowang@redhat.com \
--cc=mst@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=virtualization@vger.kernel.org \
--cc=xiongweimin@kylinos.cn \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox