From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
To: Eric Dumazet <edumazet@kernel.org>,
netdev@vger.kernel.org, "David S. Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: "Eric Dumazet" <edumazet@kernel.org>,
"Simon Horman" <horms@kernel.org>,
"Willem de Bruijn" <willemb@google.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
"Eugenio Pérez" <eperezma@redhat.com>,
"Hassan Sultan" <hassansultan@google.com>,
virtualization@lists.linux.dev
Subject: Re: [PATCH net 3/3] selftests: net: tun: test outer protocol of UDP tunnel GSO packets
Date: Tue, 03 Nov 2026 21:19:49 -0500 [thread overview]
Message-ID: <willemdebruijn.kernel.2bcc7ca0e8623@gmail.com> (raw)
In-Reply-To: <20261103203113.550604-4-edumazet@kernel.org>
Eric Dumazet wrote:
> Add a tun_vnet_udptnl_proto fixture writing single 4in4 Geneve GSO
> frames to a tap device with UDP tunnel offloads enabled:
>
> - outer_proto_ok: an outer IPv4 header, with or without an 802.1Q tag,
> is accepted.
> - outer_proto_bad: an outer ethertype that does not match the declared
> tunnel type (IPv6 on an IPv4 tunnel, or NSH, with or without a VLAN
> tag) is rejected with EINVAL.
>
> Without the previous virtio_net patch, outer_proto_bad fails because
> the kernel accepts the frames.
>
> Signed-off-by: Eric Dumazet <edumazet@kernel.org>
> ---
> tools/testing/selftests/net/tun.c | 130 ++++++++++++++++++++++++++++++
> 1 file changed, 130 insertions(+)
>
> diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c
> index 34de2580e32e..47a24b9c477b 100644
> --- a/tools/testing/selftests/net/tun.c
> +++ b/tools/testing/selftests/net/tun.c
> @@ -683,6 +683,136 @@ TEST_F(tun_vnet_gso, vlan_tcpv4_gso_no_csum_64k)
> ASSERT_EQ(ret, len);
> }
>
> +#ifndef ETH_P_NSH
> +#define ETH_P_NSH 0x894F
> +#endif
> +
> +FIXTURE(tun_vnet_udptnl_proto)
> +{
> + char ifname[IFNAMSIZ];
> + uint8_t *pkt;
> + int fd;
> +};
> +
> +FIXTURE_SETUP(tun_vnet_udptnl_proto)
> +{
> + int flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
> + int features = TUN_F_CSUM | TUN_F_UDP_TUNNEL_GSO |
> + TUN_F_UDP_TUNNEL_GSO_CSUM | TUN_F_USO4 | TUN_F_USO6;
> +
> + self->fd = -1;
> + if (unshare(CLONE_NEWNET))
> + SKIP(return, "Cannot create network namespace: %s",
> + strerror(errno));
> +
> + self->pkt = calloc(1, MAX_VNET_TUNNEL_PACKET_SZ);
> + ASSERT_NE(self->pkt, NULL);
> +
> + memset(self->ifname, 0, sizeof(self->ifname));
> + self->fd = tun_open(self->ifname, flags, TUN_VNET_TNL_SIZE, features,
> + param_hwaddr_outer_src);
> + ASSERT_GE(self->fd, 0);
> +}
> +
> +FIXTURE_TEARDOWN(tun_vnet_udptnl_proto)
> +{
> + if (self->fd >= 0)
> + close(self->fd);
> + free(self->pkt);
> +}
> +
> +/* Build a 4in4 Geneve GSO frame whose outer ethertype is @l3proto,
> + * optionally behind an 802.1Q tag.
> + */
> +static int build_udptnl_frame(uint8_t *buf, bool vlan, uint16_t l3proto,
> + int payload_len)
> +{
> + struct virtio_net_hdr_v1_hash_tunnel *vh = (void *)buf;
> + int vlan_len = vlan ? 4 : 0;
> + int hlen = ETH_HLEN + vlan_len + UDP_TUNNEL_GENEVE_4IN4_HDRLEN;
> + uint8_t *outer_udph, *cur = buf;
> + int pktlen;
> +
zero buffer. It is zeroed by calloc, but reused for multiple packets.
> + cur += build_virtio_net_hdr_v1_hash_tunnel(cur, true, hlen, 1400,
> + AF_INET, AF_INET);
> + vh->outer_th_offset += vlan_len;
> + vh->inner_nh_offset += vlan_len;
> + vh->hash_hdr.hdr.csum_start += vlan_len;
> +
> + if (vlan) {
> + uint16_t vlan_tag[2] = { htons(100), htons(l3proto) };
> +
> + cur += build_eth(cur, ETH_P_8021Q, param_hwaddr_outer_dst,
> + param_hwaddr_outer_src);
> + memcpy(cur, vlan_tag, sizeof(vlan_tag));
> + cur += sizeof(vlan_tag);
> + } else {
> + cur += build_eth(cur, l3proto, param_hwaddr_outer_dst,
> + param_hwaddr_outer_src);
> + }
> +
> + pktlen = UDP_TUNNEL_GENEVE_4IN4_HDRLEN - sizeof(struct iphdr) +
> + payload_len;
> + cur += build_ipv4_header(cur, IPPROTO_UDP, pktlen,
> + ¶m_ipaddr4_outer_dst,
> + ¶m_ipaddr4_outer_src);
> +
> + outer_udph = cur;
> + cur += build_udp_header(cur, UDP_SRC_PORT, VN_PORT,
> + pktlen - sizeof(struct udphdr));
> + cur += build_geneve_header(cur, VN_ID);
> + cur += build_eth(cur, ETH_P_IP, param_hwaddr_inner_dst,
> + param_hwaddr_inner_src);
> + cur += build_ipv4_header(cur, IPPROTO_UDP,
> + sizeof(struct udphdr) + payload_len,
> + ¶m_ipaddr4_inner_dst,
> + ¶m_ipaddr4_inner_src);
> + cur += build_udp_packet(cur, UDP_DST_PORT, UDP_SRC_PORT, payload_len,
> + AF_INET, false);
> + build_udp_packet_csum(outer_udph, AF_INET, false);
> +
> + return cur - buf;
> +}
> +
> +TEST_F(tun_vnet_udptnl_proto, outer_proto_ok)
> +{
> + uint8_t *pkt = self->pkt;
> + int len, ret;
> +
> + len = build_udptnl_frame(pkt, false, ETH_P_IP, 2800);
> + ret = write(self->fd, pkt, len);
> + ASSERT_EQ(ret, len);
> +
> + /* The outer IPv4 header can follow a VLAN tag. */
> + len = build_udptnl_frame(pkt, true, ETH_P_IP, 2800);
> + ret = write(self->fd, pkt, len);
> + ASSERT_EQ(ret, len);
> +}
> +
> +TEST_F(tun_vnet_udptnl_proto, outer_proto_bad)
> +{
> + uint8_t *pkt = self->pkt;
> + int len, ret;
> +
> + /* Outer ethertype does not match the declared IPv4 tunnel. */
> + len = build_udptnl_frame(pkt, false, ETH_P_IPV6, 2800);
> + ret = write(self->fd, pkt, len);
> + ASSERT_EQ(ret, -1);
> + ASSERT_EQ(errno, EINVAL);
> +
> + /* Outer header is not IP at all. */
> + len = build_udptnl_frame(pkt, false, ETH_P_NSH, 2800);
> + ret = write(self->fd, pkt, len);
> + ASSERT_EQ(ret, -1);
> + ASSERT_EQ(errno, EINVAL);
> +
> + /* Same, behind a VLAN tag. */
> + len = build_udptnl_frame(pkt, true, ETH_P_NSH, 2800);
> + ret = write(self->fd, pkt, len);
> + ASSERT_EQ(ret, -1);
> + ASSERT_EQ(errno, EINVAL);
> +}
> +
> FIXTURE(tun_vnet_udptnl)
> {
> char ifname[IFNAMSIZ];
> --
> 2.53.0
>
next prev parent reply other threads:[~2026-11-04 2:19 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 20:31 [PATCH net 0/3] net: virtio: validate outer protocol of UDP tunnel GSO packets Eric Dumazet
2026-11-03 20:31 ` [PATCH net 1/3] " Eric Dumazet
2026-11-04 2:01 ` Willem de Bruijn
2026-11-04 4:49 ` Eric Dumazet
2026-11-04 20:31 ` sashiko-bot
2026-11-05 8:32 ` netdev-bot+sashiko
2026-11-03 20:31 ` [PATCH net 2/3] selftests: net: tuntap: fix UDP checksum length in build_udp_packet_csum() Eric Dumazet
2026-11-04 2:10 ` Willem de Bruijn
2026-11-04 20:31 ` sashiko-bot
2026-11-03 20:31 ` [PATCH net 3/3] selftests: net: tun: test outer protocol of UDP tunnel GSO packets Eric Dumazet
2026-11-04 2:19 ` Willem de Bruijn [this message]
2026-11-04 20:31 ` sashiko-bot
2026-11-05 8:32 ` netdev-bot+sashiko
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=willemdebruijn.kernel.2bcc7ca0e8623@gmail.com \
--to=willemdebruijn.kernel@gmail.com \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=eperezma@redhat.com \
--cc=hassansultan@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=mst@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=virtualization@lists.linux.dev \
--cc=willemb@google.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.