From: Eric Dumazet <edumazet@kernel.org>
To: 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>,
"Jason Wang" <jasowangio@gmail.com>,
"Eugenio Pérez" <eperezma@redhat.com>,
"Hassan Sultan" <hassansultan@google.com>,
virtualization@lists.linux.dev
Subject: [PATCH net v3 7/8] selftests: net: tun: test more outer header mismatches of UDP tunnel GSO
Date: Thu, 5 Nov 2026 12:57:14 +0100 [thread overview]
Message-ID: <20261105115715.1466924-8-edumazet@kernel.org> (raw)
In-Reply-To: <20261105115715.1466924-1-edumazet@kernel.org>
Add tap tests for the outer header checks of UDP tunnel GSO packets
not covered yet:
- outer_proto_ok_ipv6: a 4in6 frame with an outer IPv6 header is
accepted.
- outer_proto_bad_family: an IPv4 ethertype on a declared IPv6 tunnel
is rejected.
- outer_proto_bad_vlan_ipv6: an IPv6 ethertype behind a VLAN tag on a
declared IPv4 tunnel is rejected.
- outer_proto_bad_vlan_offset: a VLAN tagged frame whose
outer_th_offset ignores the tag is rejected.
- outer_proto_bad_l4: an outer IPv4 header carrying GRE instead of UDP
is rejected.
Without the first patch of this series, the four outer_proto_bad
tests fail because the kernel accepts the frames.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/netdev/179386753718.488856.13433005125725728519@kernel.org/
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
---
tools/testing/selftests/net/tun.c | 97 +++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c
index cfeca53863ce..a135d3aa10d1 100644
--- a/tools/testing/selftests/net/tun.c
+++ b/tools/testing/selftests/net/tun.c
@@ -869,6 +869,103 @@ TEST_F(tun_vnet_udptnl_proto, outer_proto_link_type)
ASSERT_EQ(ret, len);
}
+/* Build a 4in6 Geneve GSO frame whose outer ethertype is @l3proto. */
+static int build_udptnl6_frame(uint8_t *buf, uint16_t l3proto,
+ int payload_len)
+{
+ int hlen = UDP_TUNNEL_GENEVE_4IN6_HDRLEN;
+ uint8_t *outer_udph, *cur = buf;
+ int pktlen;
+
+ memset(buf, 0, TUN_VNET_TNL_SIZE + hlen + payload_len);
+
+ cur += build_virtio_net_hdr_v1_hash_tunnel(cur, true, hlen, 1400,
+ AF_INET6, AF_INET);
+ cur += build_eth(cur, l3proto, param_hwaddr_outer_dst,
+ param_hwaddr_outer_src);
+
+ pktlen = UDP_TUNNEL_GENEVE_4IN6_HDRLEN - ETH_HLEN -
+ sizeof(struct ipv6hdr) + payload_len;
+ cur += build_ipv6_header(cur, IPPROTO_UDP, 0, pktlen,
+ ¶m_ipaddr6_outer_dst,
+ ¶m_ipaddr6_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_INET6, false);
+
+ return cur - buf;
+}
+
+TEST_F(tun_vnet_udptnl_proto, outer_proto_ok_ipv6)
+{
+ int len, ret;
+
+ len = build_udptnl6_frame(self->pkt, ETH_P_IPV6, 2800);
+ ret = write(self->fd, self->pkt, len);
+ ASSERT_EQ(ret, len);
+}
+
+/* An IPv4 ethertype on a declared IPv6 tunnel. */
+TEST_F(tun_vnet_udptnl_proto, outer_proto_bad_family)
+{
+ int len, ret;
+
+ len = build_udptnl6_frame(self->pkt, ETH_P_IP, 2800);
+ ret = write(self->fd, self->pkt, len);
+ ASSERT_EQ(ret, -1);
+ ASSERT_EQ(errno, EINVAL);
+}
+
+TEST_F(tun_vnet_udptnl_proto, outer_proto_bad_vlan_ipv6)
+{
+ int len, ret;
+
+ len = build_udptnl_frame(self->pkt, true, ETH_P_IPV6, 2800);
+ ret = write(self->fd, self->pkt, len);
+ ASSERT_EQ(ret, -1);
+ ASSERT_EQ(errno, EINVAL);
+}
+
+/* outer_th_offset does not account for the VLAN tag. */
+TEST_F(tun_vnet_udptnl_proto, outer_proto_bad_vlan_offset)
+{
+ struct virtio_net_hdr_v1_hash_tunnel *vh = (void *)self->pkt;
+ int len, ret;
+
+ len = build_udptnl_frame(self->pkt, true, ETH_P_IP, 2800);
+ vh->outer_th_offset -= 4;
+ ret = write(self->fd, self->pkt, len);
+ ASSERT_EQ(ret, -1);
+ ASSERT_EQ(errno, EINVAL);
+}
+
+/* The outer IPv4 header does not carry UDP. */
+TEST_F(tun_vnet_udptnl_proto, outer_proto_bad_l4)
+{
+ struct iphdr *iph;
+ int len, ret;
+
+ len = build_udptnl_frame(self->pkt, false, ETH_P_IP, 2800);
+ iph = (struct iphdr *)(self->pkt + TUN_VNET_TNL_SIZE + ETH_HLEN);
+ iph->protocol = IPPROTO_GRE;
+ iph->check = 0;
+ iph->check = build_ip_csum((uint8_t *)iph, iph->ihl << 2, 0);
+ ret = write(self->fd, self->pkt, len);
+ ASSERT_EQ(ret, -1);
+ ASSERT_EQ(errno, EINVAL);
+}
+
/* IFF_TUN device with a tun_pi header: skb->protocol comes from
* userspace, and there is no Ethernet header.
*/
--
2.53.0
next prev parent reply other threads:[~2026-11-05 11:57 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 11:57 [PATCH net v3 0/8] net: virtio: validate outer protocol of UDP tunnel GSO packets Eric Dumazet
2026-11-05 11:57 ` [PATCH net v3 1/8] " Eric Dumazet
2026-11-05 11:57 ` [PATCH net v3 2/8] net: virtio: do not use dev->type to find the outer L3 header Eric Dumazet
2026-11-05 11:57 ` [PATCH net v3 3/8] tun: clear stale skb->protocol of NAPI frags skbs Eric Dumazet
2026-11-05 11:57 ` [PATCH net v3 4/8] selftests: net: tuntap: fix UDP checksum length in build_udp_packet_csum() Eric Dumazet
2026-11-05 11:57 ` [PATCH net v3 5/8] selftests: net: tun: test outer protocol of UDP tunnel GSO packets Eric Dumazet
2026-11-05 11:57 ` [PATCH net v3 6/8] selftests: net: tun: test UDP tunnel GSO on retyped devices Eric Dumazet
2026-11-05 11:57 ` Eric Dumazet [this message]
2026-11-05 11:57 ` [PATCH net v3 8/8] selftests: net: tuntap: write UDP tunnel offsets in little endian Eric Dumazet
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=20261105115715.1466924-8-edumazet@kernel.org \
--to=edumazet@kernel.org \
--cc=davem@davemloft.net \
--cc=eperezma@redhat.com \
--cc=hassansultan@google.com \
--cc=horms@kernel.org \
--cc=jasowangio@gmail.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox