[PATCH RFC v4 4/6] vhost-net: support VIRTIO_NET_F_RX_TSTAMP
From: Steffen Trumtrar
Date: Mon Oct 26 2026 - 04:33:29 EST
Advertise VIRTIO_NET_F_RX_TSTAMP to userspace and size the vnet header
for it, so a guest can negotiate the feature with a vhost-net backed
tap device.
The header is 40 bytes if the feature is negotiated. Whoever writes
the header (tun, or vhost itself with VHOST_NET_F_VIRTIO_NET_HDR) has
to fill in the timestamp; vhost only reserves the room. If vhost
writes the header, it zeroes everything behind num_buffers, so the
timestamp is 0, which the guest ignores.
Signed-off-by: Steffen Trumtrar <s.trumtrar@xxxxxxxxxxxxxx>
Assisted-by: Claude:claude-opus-5-5
---
drivers/vhost/net.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 2cc730729e08a..2a38ad0ea1af2 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -77,7 +77,8 @@ static const int vhost_net_bits[] = {
VIRTIO_F_RING_RESET,
VIRTIO_F_IN_ORDER,
VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO,
- VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO
+ VIRTIO_NET_F_HOST_UDP_TUNNEL_GSO,
+ VIRTIO_NET_F_RX_TSTAMP
};
enum {
@@ -1282,6 +1283,16 @@ static void handle_rx(struct vhost_net *net)
vhost_discard_vq_desc(vq, headcount, ndesc);
goto out;
}
+ /* Zero the rest of a header supplied by vhost, e.g. tstamp */
+ if (unlikely(vhost_hlen > sizeof(hdr) + sizeof(num_buffers))) {
+ size_t rest = vhost_hlen - sizeof(hdr) - sizeof(num_buffers);
+
+ if (iov_iter_zero(rest, &fixup) != rest) {
+ vq_err(vq, "Failed vnet_hdr zeroing");
+ vhost_discard_vq_desc(vq, headcount, ndesc);
+ goto out;
+ }
+ }
nvq->done_idx += headcount;
count += in_order ? 1 : headcount;
if (nvq->done_idx > VHOST_NET_BATCH) {
@@ -1688,6 +1699,10 @@ static int vhost_net_set_features(struct vhost_net *n, const u64 *features)
VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO))
hdr_len = sizeof(struct virtio_net_hdr_v1_hash_tunnel);
+ /* The header layout is cumulative, tstamp sits behind all other fields. */
+ if (virtio_features_test_bit(features, VIRTIO_NET_F_RX_TSTAMP))
+ hdr_len = offsetofend(struct virtio_net_common_hdr, tstamp);
+
if (virtio_features_test_bit(features, VHOST_NET_F_VIRTIO_NET_HDR)) {
/* vhost provides vnet_hdr */
vhost_hlen = hdr_len;
--
2.52.0