From nobody Thu Sep 24 18:44:24 2026 Received: from mx1.white.stw.pengutronix.de (mx1.white.stw.pengutronix.de [185.203.200.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DBE304A8FF7; Mon, 21 Sep 2026 14:46:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.200.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790001982; cv=none; b=tXhjuSon0ABYhxrVcdAxtjVs+i8Hyueixnh4nt8wNR6TpZsJrEWSWQCuEjQrAoNaVD0HNrmVXBn8igHg4cfsYsAS8P9vGVqlLy6v1miEAqqRtU86mkny1MjJfr680FmeNhQJf6w/POD1sCkfVOq8b1gQdOAP+DGhJyfs+X2eqag= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790001982; c=relaxed/simple; bh=9JEOL0jy1qSQHFHqo2htCvwnRH6aK2JI6t7iRw9IZrA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JxHyMDkqLDqHILla1cYJpsYhaioM6NRYgOpWIUxyBrG9DU7xdZqxoZOBz7RzRtxCHa6D6xEgVTbdXRtD+lDR/0l5JFjihgHGC4XR4MUtywzDtoXLw251Vz2S0oeAN/PCHZOpoBAz5PrQG+rM0FdWIDxxaYST3dEv4nwtmMCGeQw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.200.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from ratatoskr.trumtrar.info (unknown [IPv6:2a00:1f:f805:4b01:1e0e:d42d:4ec8:33b2]) (Authenticated sender: str@pengutronix.de) by mx1.white.stw.pengutronix.de (Postfix) with ESMTPSA id 905E2201F07; Mon, 21 Sep 2026 16:46:14 +0200 (CEST) From: Steffen Trumtrar Date: Mon, 21 Sep 2026 16:46:10 +0200 Subject: [PATCH RFC v3 1/2] virtio-net: support receive timestamp Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-v6-7-topic-virtio-net-ptp-v3-1-3350851c4f88@pengutronix.de> References: <20260921-v6-7-topic-virtio-net-ptp-v3-0-3350851c4f88@pengutronix.de> In-Reply-To: <20260921-v6-7-topic-virtio-net-ptp-v3-0-3350851c4f88@pengutronix.de> To: "Michael S. Tsirkin" , Xuan Zhuo , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Willem de Bruijn , Andrew Lunn , =?utf-8?q?Eugenio_P=C3=A9rez?= , Jason Wang , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Stanislav Fomichev , Jason Wang Cc: virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Steffen Trumtrar X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=8965; i=s.trumtrar@pengutronix.de; h=from:subject:message-id; bh=9JEOL0jy1qSQHFHqo2htCvwnRH6aK2JI6t7iRw9IZrA=; b=owGbwMvMwCUmtVehiCsuTInxtFoSQ9ZGZ9M5kmtOvjRZxm7wKzNqW7O8tUTuUtmQ/O6f55wup lnt0TbsKGVhEONikBVTZFFZWMEn6vHBM3KaCBfMHFYmkCEMXJwCMBGjX4wMswszi8W44uQXm119 G/N1g9i6aSI5R75reTMcKv1/MeSrAyPDm38LDq0xCS3x+rh4g1P/VWtNy7y7h6NPnfwgtUGr4pc KLwA= X-Developer-Key: i=s.trumtrar@pengutronix.de; a=openpgp; fpr=24A1780E1548F0495996140A1ABD20720A5E5622 Add optional hardware rx timestamp offload for virtio-net. Introduce virtio feature VIRTIO_NET_F_TSTAMP. If negotiated, the virtio-net header is expanded with room for a timestamp. To get and set the hwtstamp the functions ndo_hwtstamp_set/get are implemented. This allows filtering the packets and only time stamp the packets where the filter matches. This way, the timestamping can be en/disabled at runtime. Currently, timestamping is handled the same for all supported filters and therefore handled the same for all received packets. XDP packets are not supported and timestamping is skipped for the XDP path. Tested: guest: ./timestamping eth0 \ SOF_TIMESTAMPING_RAW_HARDWARE \ SOF_TIMESTAMPING_RX_HARDWARE host: nc -4 -u 192.168.1.1 319 Signed-off-by: Steffen Trumtrar -- Changes to v2: - update filter handling - move tstamp into virtio_net_common_hdr - remove new struct virtio_net_hdr_v1_hash_tunnel_ts Changes to v1: - rework series to use flow filters - add new struct virtio_net_hdr_v1_hash_tunnel_ts - original work done by: Willem de Bruijn --- drivers/net/virtio_net.c | 127 ++++++++++++++++++++++++++++++++++++= +++- include/uapi/linux/virtio_net.h | 1 + 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index e34c52d059d39..ef6238cb336b9 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -416,6 +416,12 @@ struct virtnet_info { u32 rss_hash_types_supported; u32 rss_hash_types_saved; =20 + /* Device passes time stamps to the driver */ + bool has_tstamp; + bool hwts_rx_en; + + struct kernel_hwtstamp_config tstamp_config; + /* Has control virtqueue */ bool has_cvq; =20 @@ -499,6 +505,8 @@ struct virtio_net_common_hdr { struct virtio_net_hdr_v1_hash hash_v1_hdr; struct virtio_net_hdr_v1_hash_tunnel tnl_hdr; }; + + __le16 tstamp[4]; /* 64-bit timestamp, 2-byte aligned */ }; =20 static struct virtio_net_common_hdr xsk_hdr; @@ -2468,6 +2476,15 @@ virtio_net_hash_value(const struct virtio_net_hdr_v1= _hash *hdr_hash) (__le16_to_cpu(hdr_hash->hash_value_hi) << 16); } =20 +static inline u64 +virtio_net_tstamp_value(const struct virtio_net_common_hdr *hdr) +{ + return (u64)__le16_to_cpu(hdr->tstamp[0]) | + ((u64)__le16_to_cpu(hdr->tstamp[1]) << 16) | + ((u64)__le16_to_cpu(hdr->tstamp[2]) << 32) | + ((u64)__le16_to_cpu(hdr->tstamp[3]) << 48); +} + static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_h= ash, struct sk_buff *skb) { @@ -2497,6 +2514,18 @@ static void virtio_skb_set_hash(const struct virtio_= net_hdr_v1_hash *hdr_hash, skb_set_hash(skb, virtio_net_hash_value(hdr_hash), rss_hash_type); } =20 +static inline void virtnet_record_rx_tstamp(const struct virtnet_info *vi, + struct sk_buff *skb) +{ + struct skb_shared_hwtstamps *shhwtstamps =3D skb_hwtstamps(skb); + const struct virtio_net_common_hdr *h =3D skb_vnet_common_hdr(skb); + u64 ts; + + ts =3D virtio_net_tstamp_value(h); + memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps)); + shhwtstamps->hwtstamp =3D ns_to_ktime(ts); +} + static void virtnet_receive_done(struct virtnet_info *vi, struct receive_q= ueue *rq, struct sk_buff *skb, u8 flags) { @@ -2590,6 +2619,9 @@ static void receive_buf(struct virtnet_info *vi, stru= ct receive_queue *rq, if (unlikely(!skb)) return; =20 + if (likely(skb) && likely(!vi->xdp_enabled) && READ_ONCE(vi->hwts_rx_en)) + virtnet_record_rx_tstamp(vi, skb); + virtnet_receive_done(vi, rq, skb, flags); } =20 @@ -5518,6 +5550,30 @@ static int virtnet_get_per_queue_coalesce(struct net= _device *dev, return 0; } =20 +static int virtnet_get_ts_info(struct net_device *dev, + struct kernel_ethtool_ts_info *info) +{ + struct virtnet_info *vi =3D netdev_priv(dev); + + /* setup default software timestamp */ + ethtool_op_get_ts_info(dev, info); + + if (vi->has_tstamp) { + info->so_timestamping |=3D + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + info->rx_filters =3D (BIT(HWTSTAMP_FILTER_NONE) | + BIT(HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | + BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | + BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ)); + } + + return 0; +} + static void virtnet_init_settings(struct net_device *dev) { struct virtnet_info *vi =3D netdev_priv(dev); @@ -5613,7 +5669,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = =3D { .get_ethtool_stats =3D virtnet_get_ethtool_stats, .set_channels =3D virtnet_set_channels, .get_channels =3D virtnet_get_channels, - .get_ts_info =3D ethtool_op_get_ts_info, + .get_ts_info =3D virtnet_get_ts_info, .get_link_ksettings =3D virtnet_get_link_ksettings, .set_link_ksettings =3D virtnet_set_link_ksettings, .set_coalesce =3D virtnet_set_coalesce, @@ -6212,6 +6268,61 @@ static void virtnet_tx_timeout(struct net_device *de= v, unsigned int txqueue) jiffies_to_usecs(jiffies - READ_ONCE(txq->trans_start))); } =20 +static int virtnet_hwtstamp_get(struct net_device *dev, + struct kernel_hwtstamp_config *config) +{ + struct virtnet_info *vi =3D netdev_priv(dev); + + if (!netif_running(dev)) + return -EINVAL; + + if (!vi->has_tstamp) + return -EOPNOTSUPP; + + *config =3D vi->tstamp_config; + + return 0; +} + +static int virtnet_hwtstamp_set(struct net_device *dev, + struct kernel_hwtstamp_config *config, + struct netlink_ext_ack *extack) +{ + struct virtnet_info *vi =3D netdev_priv(dev); + + if (!netif_running(dev)) + return -EINVAL; + + if (!vi->has_tstamp) + return -EOPNOTSUPP; + + config->tx_type =3D HWTSTAMP_TX_OFF; + + if (unlikely(vi->xdp_enabled)) + return -EOPNOTSUPP; + + switch (config->rx_filter) { + case HWTSTAMP_FILTER_NONE: + WRITE_ONCE(vi->hwts_rx_en, false); + break; + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + WRITE_ONCE(vi->hwts_rx_en, true); + break; + case HWTSTAMP_FILTER_ALL: + default: + config->rx_filter =3D HWTSTAMP_FILTER_NONE; + return -ERANGE; + } + + vi->tstamp_config =3D *config; + + return 0; +} + static int virtnet_init_irq_moder(struct virtnet_info *vi) { u8 profile_flags =3D 0, coal_flags =3D 0; @@ -6272,6 +6383,8 @@ static const struct net_device_ops virtnet_netdev =3D= { .ndo_get_phys_port_name =3D virtnet_get_phys_port_name, .ndo_set_features =3D virtnet_set_features, .ndo_tx_timeout =3D virtnet_tx_timeout, + .ndo_hwtstamp_set =3D virtnet_hwtstamp_set, + .ndo_hwtstamp_get =3D virtnet_hwtstamp_get, }; =20 static void virtnet_config_changed_work(struct work_struct *work) @@ -6878,6 +6991,9 @@ static int virtnet_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) vi->has_rss_hash_report =3D true; =20 + if (virtio_has_feature(vdev, VIRTIO_NET_F_TSTAMP)) + vi->has_tstamp =3D true; + if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) { vi->has_rss =3D true; =20 @@ -6922,6 +7038,12 @@ static int virtnet_probe(struct virtio_device *vdev) else vi->hdr_len =3D sizeof(struct virtio_net_hdr); =20 + if (vi->has_tstamp) + vi->hdr_len =3D offsetof(struct virtio_net_common_hdr, tstamp) + + sizeof_field(struct virtio_net_common_hdr, tstamp); + + vi->hwts_rx_en =3D false; + if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO_CSUM)) vi->rx_tnl_csum =3D true; if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UDP_TUNNEL_GSO)) @@ -7248,7 +7370,8 @@ static struct virtio_device_id id_table[] =3D { VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY, \ VIRTIO_NET_F_RSS, VIRTIO_NET_F_HASH_REPORT, VIRTIO_NET_F_NOTF_COAL, \ VIRTIO_NET_F_VQ_NOTF_COAL, \ - VIRTIO_NET_F_GUEST_HDRLEN, VIRTIO_NET_F_DEVICE_STATS + VIRTIO_NET_F_GUEST_HDRLEN, VIRTIO_NET_F_DEVICE_STATS, \ + VIRTIO_NET_F_TSTAMP =20 static unsigned int features[] =3D { VIRTNET_FEATURES, diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_ne= t.h index 1db45b01532b5..39977765b72aa 100644 --- a/include/uapi/linux/virtio_net.h +++ b/include/uapi/linux/virtio_net.h @@ -56,6 +56,7 @@ #define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow * Steering */ #define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ +#define VIRTIO_NET_F_TSTAMP 49 /* Device sends TAI receive time */ #define VIRTIO_NET_F_DEVICE_STATS 50 /* Device can provide device-level st= atistics. */ #define VIRTIO_NET_F_VQ_NOTF_COAL 52 /* Device supports virtqueue notifica= tion coalescing */ #define VIRTIO_NET_F_NOTF_COAL 53 /* Device supports notifications coalesc= ing */ --=20 2.52.0 From nobody Thu Sep 24 18:44:24 2026 Received: from mx1.white.stw.pengutronix.de (mx1.white.stw.pengutronix.de [185.203.200.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB1904A0937; Mon, 21 Sep 2026 14:46:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.200.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790001982; cv=none; b=HBhsA7pIcMGz1rs6C+zcW4E76hspsBPzb+2mkmqotg7Ded/b1NCU5o0fU1Mue3XwHJiYpGT/ntxfi0xx5PPAhDPJFyfq3ZlkcJK4PVCRGSJZmiDoTG4DlqG6uA9maPhgaS8RHA+ddpDdLdumWVe1JTmatmF5TYZCpXHkan5C8TM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790001982; c=relaxed/simple; bh=Xu5NNYUv3QkvPDO37s/spZC3Lcn7LkjLNqeHi6OeTnU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qGRn9gzJpSrSnRcpxd5eWEgwk4XevdooWUaFxEKJbQLWoJddgYsV5uQ/QEHWxCjvAt9SPREzYb7w2mg5bZ7tZLdPqWvAQRM8c4T0I6TcfP0lB5LMtVX3Yn+nbMyEFxZ6L8lGymly9j7UP9JkOSgHsAdR6plwZn6g6nTiCgpHI54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.200.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from ratatoskr.trumtrar.info (unknown [IPv6:2a00:1f:f805:4b01:1e0e:d42d:4ec8:33b2]) (Authenticated sender: str@pengutronix.de) by mx1.white.stw.pengutronix.de (Postfix) with ESMTPSA id 0410C201F08; Mon, 21 Sep 2026 16:46:15 +0200 (CEST) From: Steffen Trumtrar Date: Mon, 21 Sep 2026 16:46:11 +0200 Subject: [PATCH RFC v3 2/2] tun: support rx-tstamp Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-v6-7-topic-virtio-net-ptp-v3-2-3350851c4f88@pengutronix.de> References: <20260921-v6-7-topic-virtio-net-ptp-v3-0-3350851c4f88@pengutronix.de> In-Reply-To: <20260921-v6-7-topic-virtio-net-ptp-v3-0-3350851c4f88@pengutronix.de> To: "Michael S. Tsirkin" , Xuan Zhuo , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Richard Cochran , Willem de Bruijn , Andrew Lunn , =?utf-8?q?Eugenio_P=C3=A9rez?= , Jason Wang , Alexei Starovoitov , Daniel Borkmann , Jesper Dangaard Brouer , John Fastabend , Stanislav Fomichev , Jason Wang Cc: virtualization@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, bpf@vger.kernel.org, Steffen Trumtrar X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=6467; i=s.trumtrar@pengutronix.de; h=from:subject:message-id; bh=Xu5NNYUv3QkvPDO37s/spZC3Lcn7LkjLNqeHi6OeTnU=; b=owGbwMvMwCUmtVehiCsuTInxtFoSQ9ZGZ9N11vH8VR2y2dMebXspePtH586t6gz8s84caFG/p dtWr5rZUcrCIMbFICumyKKysIJP1OODZ+Q0ES6YOaxMIEMYuDgFYCKlIQz/bNbIzHrvu+tQ9vJH /P9/b+50DhGsd+tZbPU1kvO6i2DCSkaGiTPM6rZpXiw51xP38rBF2Q8VxZN7T59YXhG1RDpf3+I wJwA= X-Developer-Key: i=s.trumtrar@pengutronix.de; a=openpgp; fpr=24A1780E1548F0495996140A1ABD20720A5E5622 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/v11.0.1/virtio-rx-stamps Not-yet-signed-off-by: Steffen Trumtrar --- Changes since v2: - use tstamp from virtio_net_common_hdr - use the negotiated vnet_hdr_sz in __tun_vnet_hdr_get Signed-off-by: Steffen Trumtrar --- drivers/net/tun.c | 20 +++++++++++++++----- drivers/net/tun_vnet.h | 27 ++++++++++++++++----------- drivers/net/virtio_net.c | 11 ----------- include/uapi/linux/virtio_net.h | 11 +++++++++++ 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 5a302709a68aa..924784771b6b7 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2157,12 +2157,23 @@ static ssize_t tun_put_user(struct tun_struct *tun, } =20 if (vnet_hdr_sz) { - struct virtio_net_hdr_v1_hash_tunnel hdr; - struct virtio_net_hdr *gso; + struct virtio_net_common_hdr hdr; =20 memset(&hdr, 0, sizeof(hdr)); + + /* hdr has at least the size up to and including the tstamp field. */ + if (vnet_hdr_sz >=3D offsetof(struct virtio_net_common_hdr, tstamp) + + sizeof_field(struct virtio_net_common_hdr, tstamp)) { + u64 tstamp =3D ktime_get_clocktai_ns(); + + hdr.tstamp[0] =3D (tstamp & 0x000000000000ffffULL) >> 0; + hdr.tstamp[1] =3D (tstamp & 0x00000000ffff0000ULL) >> 16; + hdr.tstamp[2] =3D (tstamp & 0x0000ffff00000000ULL) >> 32; + hdr.tstamp[3] =3D (tstamp & 0xffff000000000000ULL) >> 48; + } + ret =3D tun_vnet_hdr_tnl_from_skb(tun->flags, tun->dev, skb, - &hdr); + (struct virtio_net_hdr_v1_hash_tunnel *)&hdr); if (ret) return ret; =20 @@ -2170,9 +2181,8 @@ static ssize_t tun_put_user(struct tun_struct *tun, * Drop the packet if the configured header size is too small * WRT the enabled offloads. */ - gso =3D (struct virtio_net_hdr *)&hdr; ret =3D __tun_vnet_hdr_put(vnet_hdr_sz, tun->dev->features, - iter, gso); + iter, &hdr); if (ret) return ret; } diff --git a/drivers/net/tun_vnet.h b/drivers/net/tun_vnet.h index f4c652b1fa44d..0a7fe1ce889b5 100644 --- a/drivers/net/tun_vnet.h +++ b/drivers/net/tun_vnet.h @@ -109,12 +109,9 @@ static inline long tun_vnet_ioctl(int *vnet_hdr_sz, un= signed int *flags, } } =20 -static inline unsigned int tun_vnet_parse_size(netdev_features_t features) +static inline unsigned int tun_vnet_parse_size(int vnet_hdr_sz) { - if (!(features & NETIF_F_GSO_UDP_TUNNEL)) - return sizeof(struct virtio_net_hdr); - - return TUN_VNET_TNL_SIZE; + return min_t(unsigned int, sizeof(struct virtio_net_common_hdr), vnet_hdr= _sz); } =20 static inline int __tun_vnet_hdr_get(int sz, unsigned int flags, @@ -122,15 +119,20 @@ static inline int __tun_vnet_hdr_get(int sz, unsigned= int flags, struct iov_iter *from, struct virtio_net_hdr *hdr) { - unsigned int parsed_size =3D tun_vnet_parse_size(features); + unsigned int parsed_size =3D tun_vnet_parse_size(sz); + u8 tmp[sizeof(struct virtio_net_common_hdr)]; // temp buffer with known s= ize u16 hdr_len; =20 if (iov_iter_count(from) < sz) return -EINVAL; =20 - if (!copy_from_iter_full(hdr, parsed_size, from)) + /* copy parsed size data to the tmp buffer, otherwise compiler will compl= ain */ + if (!copy_from_iter_full(tmp, parsed_size, from)) return -EFAULT; =20 + /* now copy the relevant data from tmp to hdr */ + memcpy(hdr, tmp, min(parsed_size, sizeof(*hdr))); + hdr_len =3D tun_vnet16_to_cpu(flags, hdr->hdr_len); =20 if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { @@ -155,14 +157,17 @@ static inline int tun_vnet_hdr_get(int sz, unsigned i= nt flags, =20 static inline int __tun_vnet_hdr_put(int sz, netdev_features_t features, struct iov_iter *iter, - const struct virtio_net_hdr *hdr) + const struct virtio_net_common_hdr *hdr) { - unsigned int parsed_size =3D tun_vnet_parse_size(features); + unsigned int parsed_size =3D tun_vnet_parse_size(sz); + u8 buf[sizeof(*hdr)]; =20 if (unlikely(iov_iter_count(iter) < sz)) return -EINVAL; =20 - if (unlikely(copy_to_iter(hdr, parsed_size, iter) !=3D parsed_size)) + memcpy(buf, hdr, parsed_size); + + if (unlikely(copy_to_iter(buf, parsed_size, iter) !=3D parsed_size)) return -EFAULT; =20 if (iov_iter_zero(sz - parsed_size, iter) !=3D sz - parsed_size) @@ -174,7 +179,7 @@ static inline int __tun_vnet_hdr_put(int sz, netdev_fea= tures_t features, static inline int tun_vnet_hdr_put(int sz, struct iov_iter *iter, const struct virtio_net_hdr *hdr) { - return __tun_vnet_hdr_put(sz, 0, iter, hdr); + return __tun_vnet_hdr_put(sz, 0, iter, (struct virtio_net_common_hdr *)hd= r); } =20 static inline int tun_vnet_hdr_to_skb(unsigned int flags, struct sk_buff *= skb, diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index ef6238cb336b9..60ae9392f9876 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -498,17 +498,6 @@ struct padded_vnet_hdr { char padding[12]; }; =20 -struct virtio_net_common_hdr { - union { - struct virtio_net_hdr hdr; - struct virtio_net_hdr_mrg_rxbuf mrg_hdr; - struct virtio_net_hdr_v1_hash hash_v1_hdr; - struct virtio_net_hdr_v1_hash_tunnel tnl_hdr; - }; - - __le16 tstamp[4]; /* 64-bit timestamp, 2-byte aligned */ -}; - static struct virtio_net_common_hdr xsk_hdr; =20 static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf); diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_ne= t.h index 39977765b72aa..8fed76755dcb1 100644 --- a/include/uapi/linux/virtio_net.h +++ b/include/uapi/linux/virtio_net.h @@ -238,6 +238,17 @@ struct virtio_net_hdr_mrg_rxbuf { struct virtio_net_hdr hdr; __virtio16 num_buffers; /* Number of merged rx buffers */ }; + +struct virtio_net_common_hdr { + union { + struct virtio_net_hdr hdr; + struct virtio_net_hdr_mrg_rxbuf mrg_hdr; + struct virtio_net_hdr_v1_hash hash_v1_hdr; + struct virtio_net_hdr_v1_hash_tunnel tnl_hdr; + }; + + __virtio16 tstamp[4]; /* 64-bit timestamp, 2-byte aligned */ +}; #endif /* ...VIRTIO_NET_NO_LEGACY */ =20 /* --=20 2.52.0