Demonstrate support for new virtio-net features

VIRTIO_NET_HDR_F_TSTAMP

This is not intended to be merged.

A full feature test also requires a patched qemu binary that knows
these features and negotiates correct vnet_hdr_sz in
virtio_net_set_mrg_rx_bufs. See
https://github.com/strumtrar/qemu/tree/v10.2.0/virtio-rx-stamps

Not-yet-signed-off-by: Steffen Trumtrar <[email protected]>
---
 drivers/net/tun.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 8192740357a09..aa988a9c4bc99 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2065,23 +2065,29 @@ static ssize_t tun_put_user(struct tun_struct *tun,
        }
 
        if (vnet_hdr_sz) {
-               struct virtio_net_hdr_v1_hash_tunnel hdr;
-               struct virtio_net_hdr *gso;
+               struct virtio_net_hdr_v1_hash_tunnel_ts hdr;
+
+               memset(&hdr, 0, sizeof(hdr));
 
                ret = tun_vnet_hdr_tnl_from_skb(tun->flags, tun->dev, skb,
-                                               &hdr);
+                                               (struct 
virtio_net_hdr_v1_hash_tunnel *)&hdr);
                if (ret)
                        return ret;
 
-               /*
-                * Drop the packet if the configured header size is too small
-                * WRT the enabled offloads.
-                */
-               gso = (struct virtio_net_hdr *)&hdr;
-               ret = __tun_vnet_hdr_put(vnet_hdr_sz, tun->dev->features,
-                                        iter, gso);
-               if (ret)
-                       return ret;
+               if (vnet_hdr_sz >= sizeof(struct 
virtio_net_hdr_v1_hash_tunnel_ts)) {
+                       __le64 tstamp = cpu_to_le64(ktime_get_ns());
+
+                       hdr.tstamp_0 = (tstamp & 0x000000000000ffffULL) >> 0;
+                       hdr.tstamp_1 = (tstamp & 0x00000000ffff0000ULL) >> 16;
+                       hdr.tstamp_2 = (tstamp & 0x0000ffff00000000ULL) >> 32;
+                       hdr.tstamp_3 = (tstamp & 0xffff000000000000ULL) >> 48;
+               }
+
+               if (unlikely(iov_iter_count(iter) < vnet_hdr_sz))
+                       return -EINVAL;
+
+               if (unlikely(copy_to_iter(&hdr, vnet_hdr_sz, iter) != 
vnet_hdr_sz))
+                       return -EFAULT;
        }
 
        if (vlan_hlen) {

-- 
2.52.0


Reply via email to