From nobody Sat Feb 7 21:15:01 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 2B6BB321420 for ; Mon, 19 Jan 2026 05:40:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801238; cv=none; b=JZ9EGk7m0as4eoFypvQHeeqIoZvTXvIE6ELYuYgdL6EPeTU8FbqMMgIWNfk8t8hPHNTPh+CDEtLz5z7bt2amaIVLSFAN0Hw47WSUYKcQriRGuuIIKoUiAY4ezZ3Sex8PxolDClhppJtrJsPrX1VNR4wAt1yQ9Q/tYYWyQqNUZIQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801238; c=relaxed/simple; bh=me4c50WXRR8xB8plkzzqIpolCR7qnDaoGIMH+/D8XeQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DLehTzNt31EazhyWmFn0LHFQtWJWa5DU60eKuDuHXznL9J+mDxC4n6TssZs/SjmutpFOlkFHsHXu1GJ127EFGJDNRXUcY8NaI2MEWGW7yxQdmbLj9iv5PlvMD00rZL3+4mPZZ9yHrK8SM5juKvvIivYIEtyK22o5IF6gBtiw2Jw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=PWzqRKEW; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="PWzqRKEW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768801236; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PctFfq/i0IRXmLnYYIwYR3vyYfcgXhxwyeKnIEI44lM=; b=PWzqRKEWb79yi/vmtUj4DaeBWLbaVIO8Nst0hv3VbzWj2+Y2zajZIzxBDPGPXYIl43kx20 1gf9+WwDE0cz8isEqUgbyctAlViJX0TTPsqxfGO3RbBqsPcYrxkwmNAHZnnyzFdxJhwi2L aece58+jXM68vGcxRAG/FotVnHW7TDk= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-606-xABdwAj9MZCCFoBHMrhdsA-1; Mon, 19 Jan 2026 00:40:31 -0500 X-MC-Unique: xABdwAj9MZCCFoBHMrhdsA-1 X-Mimecast-MFC-AGG-ID: xABdwAj9MZCCFoBHMrhdsA_1768801230 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E1F591800473; Mon, 19 Jan 2026 05:40:29 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.72.116.28]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0969B18004D8; Mon, 19 Jan 2026 05:40:18 +0000 (UTC) From: Xu Du To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v5 1/7] selftest: tun: Format tun.c existing code Date: Mon, 19 Jan 2026 13:39:58 +0800 Message-ID: <0d83416b59dcd5f2f8cdae6a1ca744cc4f3a7ccc.1768800198.git.xudu@redhat.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" In preparation for adding new tests for GSO over UDP tunnels, apply consistently the kernel style to the existing code. Signed-off-by: Xu Du --- tools/testing/selftests/net/tun.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index 0efc67b0357a..128b0a5327d4 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -25,7 +25,7 @@ static int tun_attach(int fd, char *dev) strcpy(ifr.ifr_name, dev); ifr.ifr_flags =3D IFF_ATTACH_QUEUE; =20 - return ioctl(fd, TUNSETQUEUE, (void *) &ifr); + return ioctl(fd, TUNSETQUEUE, (void *)&ifr); } =20 static int tun_detach(int fd, char *dev) @@ -36,7 +36,7 @@ static int tun_detach(int fd, char *dev) strcpy(ifr.ifr_name, dev); ifr.ifr_flags =3D IFF_DETACH_QUEUE; =20 - return ioctl(fd, TUNSETQUEUE, (void *) &ifr); + return ioctl(fd, TUNSETQUEUE, (void *)&ifr); } =20 static int tun_alloc(char *dev) @@ -54,7 +54,7 @@ static int tun_alloc(char *dev) strcpy(ifr.ifr_name, dev); ifr.ifr_flags =3D IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE; =20 - err =3D ioctl(fd, TUNSETIFF, (void *) &ifr); + err =3D ioctl(fd, TUNSETIFF, (void *)&ifr); if (err < 0) { fprintf(stderr, "can't TUNSETIFF: %s\n", strerror(errno)); close(fd); @@ -67,9 +67,9 @@ static int tun_alloc(char *dev) static int tun_delete(char *dev) { struct { - struct nlmsghdr nh; + struct nlmsghdr nh; struct ifinfomsg ifm; - unsigned char data[64]; + unsigned char data[64]; } req; struct rtattr *rta; int ret, rtnl; @@ -127,31 +127,36 @@ FIXTURE_TEARDOWN(tun) close(self->fd2); } =20 -TEST_F(tun, delete_detach_close) { +TEST_F(tun, delete_detach_close) +{ EXPECT_EQ(tun_delete(self->ifname), 0); EXPECT_EQ(tun_detach(self->fd, self->ifname), -1); EXPECT_EQ(errno, 22); } =20 -TEST_F(tun, detach_delete_close) { +TEST_F(tun, detach_delete_close) +{ EXPECT_EQ(tun_detach(self->fd, self->ifname), 0); EXPECT_EQ(tun_delete(self->ifname), 0); } =20 -TEST_F(tun, detach_close_delete) { +TEST_F(tun, detach_close_delete) +{ EXPECT_EQ(tun_detach(self->fd, self->ifname), 0); close(self->fd); self->fd =3D -1; EXPECT_EQ(tun_delete(self->ifname), 0); } =20 -TEST_F(tun, reattach_delete_close) { +TEST_F(tun, reattach_delete_close) +{ EXPECT_EQ(tun_detach(self->fd, self->ifname), 0); EXPECT_EQ(tun_attach(self->fd, self->ifname), 0); EXPECT_EQ(tun_delete(self->ifname), 0); } =20 -TEST_F(tun, reattach_close_delete) { +TEST_F(tun, reattach_close_delete) +{ EXPECT_EQ(tun_detach(self->fd, self->ifname), 0); EXPECT_EQ(tun_attach(self->fd, self->ifname), 0); close(self->fd); --=20 2.49.0 From nobody Sat Feb 7 21:15:01 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 A5A45258EFF for ; Mon, 19 Jan 2026 05:40:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801247; cv=none; b=QGi2ytLGLElY5cv/1wutwVPj4XhtSXmXHitWMX3bMF5XSMee2TfLS1qQsCxXye/fyMVG/DCT7dpupIKfqCbaXR+dretS5XvrHsA0kFV+dWmRxUYiS6600Ok1OzOBTN8xdmTM1Zj0dTkdEICQud4AmqeCdcm9IqE/8qGguKx4B2M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801247; c=relaxed/simple; bh=hDQ8EfPIyKNMLLbuPjZiYEDmTppVQJ6Rr3xDbEWjy0Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=OowkeZIuCPkM6YH7B791KOXl84AzAwtKP7e1iH5qoAz7EF5ZYNA6ogNzgQ+PBuKxFxgwz3jprckK+Vi+0nUMWP58GFGLuUyctXErxwoscrPU5vDn68SkHUs5wZgXv3fBh5SDEfrs9rSmJ/4GTq1Et79QPvWVc2Nlfa7eKm6Mz+Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Smm/h5Ko; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Smm/h5Ko" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768801244; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=o+zGQzCvke5yMLsplXDXRTcm2GeK+suemLUkBOqvWU8=; b=Smm/h5KoBdCW72ziSMUw8Xl97eJtlXh55wkcO40TEFMR1kmjU35H9plf64ZqwMVbv09Txc eMairA8pwYiWW6UVkqnbGgFtvKCG9Iak7U+a6JD2LI3w9MDEqcdQ0F1HDigh+ASNKlkdDE LVRs6T9e75tSa4OiIYJaYhUVucG4OeI= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-695-JqTJdTDFPVq1JaIejXVN6w-1; Mon, 19 Jan 2026 00:40:39 -0500 X-MC-Unique: JqTJdTDFPVq1JaIejXVN6w-1 X-Mimecast-MFC-AGG-ID: JqTJdTDFPVq1JaIejXVN6w_1768801238 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0E78B18005B2; Mon, 19 Jan 2026 05:40:38 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.72.116.28]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5EDF61800285; Mon, 19 Jan 2026 05:40:30 +0000 (UTC) From: Xu Du To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v5 2/7] selftest: tun: Introduce tuntap_helpers.h header for TUN/TAP testing Date: Mon, 19 Jan 2026 13:39:59 +0800 Message-ID: <85973e012b9b046a09a26cb16ae544e65afb2009.1768800198.git.xudu@redhat.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Introduce rtnetlink manipulation and packet construction helpers that will simplify the later creation of more related test cases. This avoids duplicating logic across different test cases. This new header will contain: - YNL-based netlink management utilities. - Helpers for ip link, ip address, ip neighbor and ip route operations. - Packet construction and manipulation helpers. Signed-off-by: Xu Du --- v4 -> v5: - Add YNL-based helpers for rtnetlink operations. v3 -> v4: - Fold the "tap.c buffer overflow detected" fix into the current commit. v1 -> v2: - Add support for route manipulation operations. - Add support for querying individual entries. tools/testing/selftests/net/tuntap_helpers.h | 391 +++++++++++++++++++ 1 file changed, 391 insertions(+) create mode 100644 tools/testing/selftests/net/tuntap_helpers.h diff --git a/tools/testing/selftests/net/tuntap_helpers.h b/tools/testing/s= elftests/net/tuntap_helpers.h new file mode 100644 index 000000000000..fa098d479ac9 --- /dev/null +++ b/tools/testing/selftests/net/tuntap_helpers.h @@ -0,0 +1,391 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _TUNTAP_HELPERS1_H +#define _TUNTAP_HELPERS1_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt-route-user.h" +#include "rt-addr-user.h" +#include "rt-neigh-user.h" +#include "rt-link-user.h" + +#define GENEVE_HLEN 8 +#define PKT_DATA 0xCB + +unsigned int if_nametoindex(const char *__ifname); + +static inline int ip_addr_len(int family) +{ + return (family =3D=3D AF_INET) ? sizeof(struct in_addr) : + sizeof(struct in6_addr); +} + +static inline void fill_ifaddr_msg(struct ifaddrmsg *ifam, int family, + int prefix, int flags, const char *intf) +{ + ifam->ifa_family =3D family; + ifam->ifa_prefixlen =3D prefix; + ifam->ifa_index =3D if_nametoindex(intf); + ifam->ifa_flags =3D flags; + ifam->ifa_scope =3D RT_SCOPE_UNIVERSE; +} + +static inline int ip_addr_add(const char *intf, int family, void *addr, + uint8_t prefix) +{ + int nl_flags =3D NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + int ifa_flags =3D IFA_F_PERMANENT | IFA_F_NODAD; + int ret =3D -1, ipalen =3D ip_addr_len(family); + struct rt_addr_newaddr_req *req; + struct ynl_sock *ys; + + ys =3D ynl_sock_create(&ynl_rt_addr_family, NULL); + if (!ys) + return -1; + + req =3D rt_addr_newaddr_req_alloc(); + if (!req) + goto err_req_alloc; + + fill_ifaddr_msg(&req->_hdr, family, prefix, ifa_flags, intf); + rt_addr_newaddr_req_set_nlflags(req, nl_flags); + rt_addr_newaddr_req_set_local(req, addr, ipalen); + + ret =3D rt_addr_newaddr(ys, req); + rt_addr_newaddr_req_free(req); +err_req_alloc: + ynl_sock_destroy(ys); + return ret; +} + +static inline void fill_neigh_req_header(struct ndmsg *ndm, int family, + int state, const char *intf) +{ + ndm->ndm_family =3D family; + ndm->ndm_ifindex =3D if_nametoindex(intf); + ndm->ndm_state =3D state; + ndm->ndm_flags =3D 0; + ndm->ndm_type =3D RTN_UNICAST; +} + +static inline int ip_neigh_add(const char *intf, int family, void *addr, + unsigned char *lladdr) +{ + int nl_flags =3D NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + int ret =3D -1, ipalen =3D ip_addr_len(family); + struct rt_neigh_newneigh_req *req; + struct ynl_sock *ys; + + ys =3D ynl_sock_create(&ynl_rt_neigh_family, NULL); + if (!ys) + return -1; + + req =3D rt_neigh_newneigh_req_alloc(); + if (!req) + goto err_req_alloc; + + fill_neigh_req_header(&req->_hdr, family, NUD_PERMANENT, intf); + rt_neigh_newneigh_req_set_nlflags(req, nl_flags); + rt_neigh_newneigh_req_set_dst(req, addr, ipalen); + rt_neigh_newneigh_req_set_lladdr(req, lladdr, ETH_ALEN); + rt_neigh_newneigh_req_set_ifindex(req, if_nametoindex(intf)); + + ret =3D rt_neigh_newneigh(ys, req); + rt_neigh_newneigh_req_free(req); +err_req_alloc: + ynl_sock_destroy(ys); + return ret; +} + +static inline void fill_route_req_header(struct rtmsg *rtm, int family, + int table) +{ + rtm->rtm_family =3D family; + rtm->rtm_table =3D table; +} + +static inline int +ip_route_get(const char *intf, int family, int table, void *dst, + void (*parse_rsp)(struct rt_route_getroute_rsp *rsp, void *out), + void *out) +{ + int ret =3D -1, ipalen =3D ip_addr_len(family); + struct rt_route_getroute_req *req; + struct rt_route_getroute_rsp *rsp; + struct ynl_sock *ys; + + ys =3D ynl_sock_create(&ynl_rt_route_family, NULL); + if (!ys) + return -1; + + req =3D rt_route_getroute_req_alloc(); + if (!req) + goto err_req_alloc; + + fill_route_req_header(&req->_hdr, family, table); + rt_route_getroute_req_set_nlflags(req, NLM_F_REQUEST); + rt_route_getroute_req_set_dst(req, dst, ipalen); + rt_route_getroute_req_set_oif(req, if_nametoindex(intf)); + + rsp =3D rt_route_getroute(ys, req); + if (!rsp) + goto err_rsp_get; + + ret =3D 0; + if (parse_rsp) + parse_rsp(rsp, out); + + rt_route_getroute_rsp_free(rsp); +err_rsp_get: + rt_route_getroute_req_free(req); +err_req_alloc: + ynl_sock_destroy(ys); + return ret; +} + +static inline int +ip_link_add(const char *dev, char *link_type, + int (*fill_link_attr)(struct rt_link_newlink_req *req, void *data), + void *data) +{ + int nl_flags =3D NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + struct rt_link_newlink_req *req; + struct ynl_sock *ys; + int ret =3D -1; + + ys =3D ynl_sock_create(&ynl_rt_link_family, NULL); + if (!ys) + return -1; + + req =3D rt_link_newlink_req_alloc(); + if (!req) + goto err_req_alloc; + + req->_hdr.ifi_flags =3D IFF_UP; + rt_link_newlink_req_set_nlflags(req, nl_flags); + rt_link_newlink_req_set_ifname(req, dev); + rt_link_newlink_req_set_linkinfo_kind(req, link_type); + + if (fill_link_attr && fill_link_attr(req, data) < 0) + goto err_attr_fill; + + ret =3D rt_link_newlink(ys, req); + if (ret < 0) + fprintf(stderr, "%s: req failed:%s\n", __func__, ys->err.msg); + +err_attr_fill: + rt_link_newlink_req_free(req); +err_req_alloc: + ynl_sock_destroy(ys); + return ret; +} + +static inline int ip_link_del(const char *dev) +{ + struct rt_link_dellink_req *req; + struct ynl_sock *ys; + int ret =3D -1; + + ys =3D ynl_sock_create(&ynl_rt_link_family, NULL); + if (!ys) + return -1; + + req =3D rt_link_dellink_req_alloc(); + if (!req) + goto err_req_alloc; + + rt_link_dellink_req_set_nlflags(req, NLM_F_REQUEST); + rt_link_dellink_req_set_ifname(req, dev); + + ret =3D rt_link_dellink(ys, req); + rt_link_dellink_req_free(req); +err_req_alloc: + ynl_sock_destroy(ys); + return ret; +} + +static inline size_t build_eth(uint8_t *buf, uint16_t proto, unsigned char= *src, + unsigned char *dest) +{ + struct ethhdr *eth =3D (struct ethhdr *)buf; + + eth->h_proto =3D htons(proto); + memcpy(eth->h_source, src, ETH_ALEN); + memcpy(eth->h_dest, dest, ETH_ALEN); + + return ETH_HLEN; +} + +static inline uint32_t add_csum(const uint8_t *buf, int len) +{ + uint16_t *sbuf =3D (uint16_t *)buf; + uint32_t sum =3D 0; + + while (len > 1) { + sum +=3D *sbuf++; + len -=3D 2; + } + + if (len) + sum +=3D *(uint8_t *)sbuf; + + return sum; +} + +static inline uint16_t finish_ip_csum(uint32_t sum) +{ + while (sum >> 16) + sum =3D (sum & 0xffff) + (sum >> 16); + return ~((uint16_t)sum); +} + +static inline uint16_t build_ip_csum(const uint8_t *buf, int len, uint32_t= sum) +{ + sum +=3D add_csum(buf, len); + return finish_ip_csum(sum); +} + +static inline int build_ipv4_header(uint8_t *buf, uint8_t proto, + int payload_len, struct in_addr *src, + struct in_addr *dst) +{ + struct iphdr *iph =3D (struct iphdr *)buf; + + iph->ihl =3D 5; + iph->version =3D 4; + iph->ttl =3D 8; + iph->tot_len =3D htons(sizeof(*iph) + payload_len); + iph->id =3D htons(1337); + iph->protocol =3D proto; + iph->saddr =3D src->s_addr; + iph->daddr =3D dst->s_addr; + iph->check =3D build_ip_csum(buf, iph->ihl << 2, 0); + + return iph->ihl << 2; +} + +static inline void ipv6_set_dsfield(struct ipv6hdr *ip6h, uint8_t dsfield) +{ + uint16_t val, *ptr =3D (uint16_t *)ip6h; + + val =3D ntohs(*ptr); + val &=3D 0xF00F; + val |=3D ((uint16_t)dsfield) << 4; + *ptr =3D htons(val); +} + +static inline int build_ipv6_header(uint8_t *buf, uint8_t proto, + uint8_t dsfield, int payload_len, + struct in6_addr *src, struct in6_addr *dst) +{ + struct ipv6hdr *ip6h =3D (struct ipv6hdr *)buf; + + ip6h->version =3D 6; + ip6h->payload_len =3D htons(payload_len); + ip6h->nexthdr =3D proto; + ip6h->hop_limit =3D 8; + ipv6_set_dsfield(ip6h, dsfield); + memcpy(&ip6h->saddr, src, sizeof(ip6h->saddr)); + memcpy(&ip6h->daddr, dst, sizeof(ip6h->daddr)); + + return sizeof(struct ipv6hdr); +} + +static inline int build_geneve_header(uint8_t *buf, uint32_t vni) +{ + uint16_t protocol =3D htons(ETH_P_TEB); + uint32_t geneve_vni =3D htonl((vni << 8) & 0xffffff00); + + memcpy(buf + 2, &protocol, 2); + memcpy(buf + 4, &geneve_vni, 4); + return GENEVE_HLEN; +} + +static inline int build_udp_header(uint8_t *buf, uint16_t sport, uint16_t = dport, + int payload_len) +{ + struct udphdr *udph =3D (struct udphdr *)buf; + + udph->source =3D htons(sport); + udph->dest =3D htons(dport); + udph->len =3D htons(sizeof(*udph) + payload_len); + return sizeof(*udph); +} + +static inline void build_udp_packet_csum(uint8_t *buf, int family, + bool csum_off) +{ + struct udphdr *udph =3D (struct udphdr *)buf; + size_t ipalen =3D ip_addr_len(family); + uint32_t sum; + + /* No extension IPv4 and IPv6 headers addresses are the last fields */ + sum =3D add_csum(buf - 2 * ipalen, 2 * ipalen); + sum +=3D htons(IPPROTO_UDP) + udph->len; + + if (!csum_off) + sum +=3D add_csum(buf, udph->len); + + udph->check =3D finish_ip_csum(sum); +} + +static inline int build_udp_packet(uint8_t *buf, uint16_t sport, uint16_t = dport, + int payload_len, int family, bool csum_off) +{ + struct udphdr *udph =3D (struct udphdr *)buf; + + build_udp_header(buf, sport, dport, payload_len); + memset(buf + sizeof(*udph), PKT_DATA, payload_len); + build_udp_packet_csum(buf, family, csum_off); + + return sizeof(*udph) + payload_len; +} + +static inline int build_virtio_net_hdr_v1_hash_tunnel(uint8_t *buf, bool i= s_tap, + int hdr_len, int gso_size, + int outer_family, + int inner_family) +{ + struct virtio_net_hdr_v1_hash_tunnel *vh_tunnel =3D (void *)buf; + struct virtio_net_hdr_v1 *vh =3D &vh_tunnel->hash_hdr.hdr; + int outer_iphlen, inner_iphlen, eth_hlen, gso_type; + + eth_hlen =3D is_tap ? ETH_HLEN : 0; + outer_iphlen =3D (outer_family =3D=3D AF_INET) ? sizeof(struct iphdr) : + sizeof(struct ipv6hdr); + inner_iphlen =3D (inner_family =3D=3D AF_INET) ? sizeof(struct iphdr) : + sizeof(struct ipv6hdr); + + vh_tunnel->outer_th_offset =3D eth_hlen + outer_iphlen; + vh_tunnel->inner_nh_offset =3D vh_tunnel->outer_th_offset + ETH_HLEN + + GENEVE_HLEN + sizeof(struct udphdr); + + vh->csum_start =3D vh_tunnel->inner_nh_offset + inner_iphlen; + vh->csum_offset =3D __builtin_offsetof(struct udphdr, check); + vh->flags =3D VIRTIO_NET_HDR_F_NEEDS_CSUM; + vh->hdr_len =3D hdr_len; + vh->gso_size =3D gso_size; + + if (gso_size) { + gso_type =3D outer_family =3D=3D AF_INET ? + VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4 : + VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6; + vh->gso_type =3D VIRTIO_NET_HDR_GSO_UDP_L4 | gso_type; + } + + return sizeof(struct virtio_net_hdr_v1_hash_tunnel); +} + +#endif /* _TUNTAP_HELPERS1_H */ --=20 2.49.0 From nobody Sat Feb 7 21:15:01 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 CD94C258EFF for ; Mon, 19 Jan 2026 05:40:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801255; cv=none; b=mcpcuuYizikqWS+wQSWGcCwNUGOkyVVfQvjnlPt4HYkcpHlk9u1Hao6VKErb0irgBEjB+GuRUbHYwqPgEnBI2QHIw3JHVohD5KKJGJkfJF/CZdSZHfDQACIR1gujo8oE7saOcrl+KHqO7w677QbwXJuURjmz/CTUjSXGRsVdjzM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801255; c=relaxed/simple; bh=YAvQxpdgt1WKlRFO7jvB0fVvQE9KxlMsOksUbfY7JkM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Hs73lME5adwl7yf8JF3Y94Vp4TbBeZgfYLpxAw2jtzMd5jFvMvKnQkD3NsIQlfMRyLkWghIcO5919nP9v8VV0f/wr7fdYLYOBQQZ+GWVMgsB5QYPoDibsGzVWBucwiZ7mV9F4NOJ95EnxPwYVVSAN70OvWQoWpLTc1Rc+NE6Fco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=SMKI6WUV; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="SMKI6WUV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768801251; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TSymtOAz4BKjHE60zeB8jOJnB2lXibwng+Q6/NjtkGw=; b=SMKI6WUVW0gk90wiQuEXPW2fMA0O6pgF+L1Py4ZlabUUNV4hqJAB+LcYcnBCP6rMcuOlLD fkovL8GzAmNB6XV74fzOqbWYdkZ181alyaK5RFrvxcxggQSd+IQEubBn8xPu3yHVN3g8Zr efq0XzyeL3lkzRmQSjlEoszkPNey6c4= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-106-jK19atPxOFq02Fkrudv-UA-1; Mon, 19 Jan 2026 00:40:46 -0500 X-MC-Unique: jK19atPxOFq02Fkrudv-UA-1 X-Mimecast-MFC-AGG-ID: jK19atPxOFq02Fkrudv-UA_1768801245 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D21EA1800350; Mon, 19 Jan 2026 05:40:44 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.72.116.28]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4261818004D8; Mon, 19 Jan 2026 05:40:38 +0000 (UTC) From: Xu Du To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v5 3/7] selftest: tun: Refactor tun_delete to use tuntap_helpers Date: Mon, 19 Jan 2026 13:40:00 +0800 Message-ID: <58c5767a8a82352fb784d8d51ec844055b6d7ff2.1768800198.git.xudu@redhat.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" The previous patch introduced common tuntap helpers to simplify tun test code. This patch refactors the tun_delete function to use these new helpers. Signed-off-by: Xu Du --- v4 -> v5: - Delete device using the new ip link YNL API. - Linked YNL library to the tun program. tools/testing/selftests/net/Makefile | 7 ++--- tools/testing/selftests/net/tun.c | 39 ++-------------------------- 2 files changed, 6 insertions(+), 40 deletions(-) diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests= /net/Makefile index b66ba04f19d9..64e941e6a88f 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -180,7 +180,6 @@ TEST_GEN_PROGS :=3D \ tap \ tcp_port_share \ tls \ - tun \ # end of TEST_GEN_PROGS =20 TEST_FILES :=3D \ @@ -192,7 +191,9 @@ TEST_FILES :=3D \ =20 # YNL files, must be before "include ..lib.mk" YNL_GEN_FILES :=3D busy_poller -YNL_GEN_PROGS :=3D netlink-dumps +YNL_GEN_PROGS :=3D \ + netlink-dumps \ + tun \ TEST_GEN_FILES +=3D $(YNL_GEN_FILES) TEST_GEN_PROGS +=3D $(YNL_GEN_PROGS) =20 @@ -203,7 +204,7 @@ TEST_INCLUDES :=3D forwarding/lib.sh include ../lib.mk =20 # YNL build -YNL_GENS :=3D netdev +YNL_GENS :=3D netdev rt-route rt-addr rt-neigh rt-link include ynl.mk =20 $(OUTPUT)/epoll_busy_poll: LDLIBS +=3D -lcap diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index 128b0a5327d4..d9030bdd2e06 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -8,14 +8,12 @@ #include #include #include -#include #include -#include -#include #include #include =20 #include "kselftest_harness.h" +#include "tuntap_helpers.h" =20 static int tun_attach(int fd, char *dev) { @@ -66,40 +64,7 @@ static int tun_alloc(char *dev) =20 static int tun_delete(char *dev) { - struct { - struct nlmsghdr nh; - struct ifinfomsg ifm; - unsigned char data[64]; - } req; - struct rtattr *rta; - int ret, rtnl; - - rtnl =3D socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (rtnl < 0) { - fprintf(stderr, "can't open rtnl: %s\n", strerror(errno)); - return 1; - } - - memset(&req, 0, sizeof(req)); - req.nh.nlmsg_len =3D NLMSG_ALIGN(NLMSG_LENGTH(sizeof(req.ifm))); - req.nh.nlmsg_flags =3D NLM_F_REQUEST; - req.nh.nlmsg_type =3D RTM_DELLINK; - - req.ifm.ifi_family =3D AF_UNSPEC; - - rta =3D (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.nh.nlmsg_len)); - rta->rta_type =3D IFLA_IFNAME; - rta->rta_len =3D RTA_LENGTH(IFNAMSIZ); - req.nh.nlmsg_len +=3D rta->rta_len; - memcpy(RTA_DATA(rta), dev, IFNAMSIZ); - - ret =3D send(rtnl, &req, req.nh.nlmsg_len, 0); - if (ret < 0) - fprintf(stderr, "can't send: %s\n", strerror(errno)); - ret =3D (unsigned int)ret !=3D req.nh.nlmsg_len; - - close(rtnl); - return ret; + return ip_link_del(dev); } =20 FIXTURE(tun) --=20 2.49.0 From nobody Sat Feb 7 21:15:01 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 4E309331202 for ; Mon, 19 Jan 2026 05:40:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801261; cv=none; b=CABiaTRlhqs8yhEtUyMo5ppFWrQkHYCPPd4mpQDQAWm0vRVAw6k9y0L0V0CyVTZ/pKW2LjiIxcd81U4CQmrtxJfM+UzJAzHdoZ54ORX8JZPn+E6jmafoIuf6hMaddKmG8iPCknQMM8g8sFF+S9r7pVPYsBFdUp3Va3z1OY0CT70= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801261; c=relaxed/simple; bh=j88S8UVMF4UN7ODSbM06V5kHCjacP62bjwVGVI7CEOg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AkHbEuPqVm/tRugKN62omaJLNtFr+SsDsC8uDQv41xZ6oT/Rx9kLyLC2ELFE9k98u43VSRgvz0lavSR6a9HFlqHiECU6TRt06huCi/vjyxP/cpklgrLUc7ZaN0rW9q6wc2FsnJeglNCVWOdPnWjcpK6KYgElTCglZZuMQMWrUUY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=IWRp6qhT; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="IWRp6qhT" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768801255; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WvZgwvJeGyGBpLubrY0OttguapRc1gPc0WNHWvn2/cU=; b=IWRp6qhTJSugoQq3vnoYwz14SIxwBvrXDnttnQ2zyrmw6E0PKlfvE1Qzj92n0tyTM5H4Mf eC43i+ZRNmfh2hlCwJk9BdormBO8PlRDBYikv0IiD72nqnp+q8C+ItvBQ0O8d+Pflz+RXy q0cLJsZ6kJqKtNmwcJ5slTi0dOmmavs= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-313-RubMhR79MlerTRDX_QIAEg-1; Mon, 19 Jan 2026 00:40:53 -0500 X-MC-Unique: RubMhR79MlerTRDX_QIAEg-1 X-Mimecast-MFC-AGG-ID: RubMhR79MlerTRDX_QIAEg_1768801252 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id F36131956080; Mon, 19 Jan 2026 05:40:51 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.72.116.28]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id CD5A718004D8; Mon, 19 Jan 2026 05:40:45 +0000 (UTC) From: Xu Du To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v5 4/7] selftest: tun: Add helpers for GSO over UDP tunnel Date: Mon, 19 Jan 2026 13:40:01 +0800 Message-ID: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" In preparation for testing GSO over UDP tunnels, enhance the test infrastructure to support a more complex data path involving a TUN device and a GENEVE udp tunnel. This patch introduces a dedicated setup/teardown topology that creates both a GENEVE tunnel interface and a TUN interface. The TUN device acts as the VTEP (Virtual Tunnel Endpoint), allowing it to send and receive virtio-net packets. This setup effectively tests the kernel's data path for encapsulated traffic. Note that after adding a new address to the UDP tunnel, we need to wait a bit until the associated route is available. Additionally, a new data structure is defined to manage test parameters. This structure is designed to be extensible, allowing different test data and configurations to be easily added in subsequent patches. Signed-off-by: Xu Du --- v4 -> v5: - Use Geneve instead of VXLAN due to missing YNL support. v1 -> v2: - Explicitly wait for successful target route lookup before transmitting the packets. - Add UDP connect() to verify remote reachability. - Abstract address assignment logic into helpers. tools/testing/selftests/net/tun.c | 425 ++++++++++++++++++++++++++++++ 1 file changed, 425 insertions(+) diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index d9030bdd2e06..ec089355312b 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -15,6 +15,80 @@ #include "kselftest_harness.h" #include "tuntap_helpers.h" =20 +static const char param_dev_geneve_name[] =3D "geneve1"; +static unsigned char param_hwaddr_outer_dst[] =3D { 0x00, 0xfe, 0x98, + 0x14, 0x22, 0x42 }; +static unsigned char param_hwaddr_outer_src[] =3D { 0x00, 0xfe, 0x98, + 0x94, 0xd2, 0x43 }; +static unsigned char param_hwaddr_inner_dst[] =3D { 0x00, 0xfe, 0x98, + 0x94, 0x22, 0xcc }; +static unsigned char param_hwaddr_inner_src[] =3D { 0x00, 0xfe, 0x98, + 0x94, 0xd2, 0xdd }; + +static struct in_addr param_ipaddr4_outer_dst =3D { + __constant_htonl(0xac100001), +}; + +static struct in_addr param_ipaddr4_outer_src =3D { + __constant_htonl(0xac100002), +}; + +static struct in_addr param_ipaddr4_inner_dst =3D { + __constant_htonl(0xac100101), +}; + +static struct in_addr param_ipaddr4_inner_src =3D { + __constant_htonl(0xac100102), +}; + +static struct in6_addr param_ipaddr6_outer_dst =3D { + { { 0x20, 0x02, 0x0d, 0xb8, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } }, +}; + +static struct in6_addr param_ipaddr6_outer_src =3D { + { { 0x20, 0x02, 0x0d, 0xb8, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } }, +}; + +static struct in6_addr param_ipaddr6_inner_dst =3D { + { { 0x20, 0x02, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } }, +}; + +static struct in6_addr param_ipaddr6_inner_src =3D { + { { 0x20, 0x02, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } }, +}; + +#define VN_ID 1 +#define VN_PORT 4789 +#define UDP_SRC_PORT 22 +#define UDP_DST_PORT 48878 +#define IPPREFIX_LEN 24 +#define IP6PREFIX_LEN 64 +#define TIMEOUT_SEC 10 +#define TIMEOUT_USEC 100000 +#define MAX_RETRIES 20 + +#define UDP_TUNNEL_GENEVE_4IN4 0x01 +#define UDP_TUNNEL_GENEVE_6IN4 0x02 +#define UDP_TUNNEL_GENEVE_4IN6 0x04 +#define UDP_TUNNEL_GENEVE_6IN6 0x08 + +#define UDP_TUNNEL_OUTER_IPV4 (UDP_TUNNEL_GENEVE_4IN4 | UDP_TUNNEL_GENEVE_= 6IN4) +#define UDP_TUNNEL_INNER_IPV4 (UDP_TUNNEL_GENEVE_4IN4 | UDP_TUNNEL_GENEVE_= 4IN6) + +#define TUN_VNET_TNL_SIZE sizeof(struct virtio_net_hdr_v1_hash_tunnel) + +struct geneve_setup_config { + int family; + union { + struct in_addr r4; + struct in6_addr r6; + } remote; + __be32 vnid; + __be16 vnport; + unsigned char hwaddr[6]; + uint8_t csum; +}; + static int tun_attach(int fd, char *dev) { struct ifreq ifr; @@ -67,6 +141,202 @@ static int tun_delete(char *dev) return ip_link_del(dev); } =20 +static int tun_open(char *dev, const int flags, const int hdrlen, + const int features, const unsigned char *mac_addr) +{ + struct ifreq ifr =3D { 0 }; + int fd, sk =3D -1; + + fd =3D open("/dev/net/tun", O_RDWR); + if (fd < 0) { + perror("open"); + return -1; + } + + ifr.ifr_flags =3D flags; + if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) { + perror("ioctl(TUNSETIFF)"); + goto err; + } + strcpy(dev, ifr.ifr_name); + + if (hdrlen > 0) { + if (ioctl(fd, TUNSETVNETHDRSZ, &hdrlen) < 0) { + perror("ioctl(TUNSETVNETHDRSZ)"); + goto err; + } + } + + if (features) { + if (ioctl(fd, TUNSETOFFLOAD, features) < 0) { + perror("ioctl(TUNSETOFFLOAD)"); + goto err; + } + } + + sk =3D socket(PF_INET, SOCK_DGRAM, 0); + if (sk < 0) { + perror("socket"); + goto err; + } + + if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) { + perror("ioctl(SIOCGIFFLAGS)"); + goto err; + } + + ifr.ifr_flags |=3D (IFF_UP | IFF_RUNNING); + if (ioctl(sk, SIOCSIFFLAGS, &ifr) < 0) { + perror("ioctl(SIOCSIFFLAGS)"); + goto err; + } + + if (mac_addr && flags & IFF_TAP) { + ifr.ifr_hwaddr.sa_family =3D ARPHRD_ETHER; + memcpy(ifr.ifr_hwaddr.sa_data, mac_addr, ETH_ALEN); + + if (ioctl(sk, SIOCSIFHWADDR, &ifr) < 0) { + perror("ioctl(SIOCSIFHWADDR)"); + goto err; + } + } + +out: + if (sk >=3D 0) + close(sk); + return fd; + +err: + close(fd); + fd =3D -1; + goto out; +} + +static size_t sockaddr_len(int family) +{ + return (family =3D=3D AF_INET) ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6); +} + +static int geneve_fill_newlink(struct rt_link_newlink_req *req, void *data) +{ + struct geneve_setup_config *cfg =3D data; + +#define SET_GENEVE_REMOTE rt_link_newlink_req_set_linkinfo_data_geneve_rem= ote +#define SET_GENEVE_REMOTE6 rt_link_newlink_req_set_linkinfo_data_geneve_re= mote6 + + rt_link_newlink_req_set_address(req, cfg->hwaddr, ETH_ALEN); + rt_link_newlink_req_set_linkinfo_data_geneve_id(req, cfg->vnid); + rt_link_newlink_req_set_linkinfo_data_geneve_port(req, cfg->vnport); + rt_link_newlink_req_set_linkinfo_data_geneve_udp_csum(req, cfg->csum); + + if (cfg->family =3D=3D AF_INET) + SET_GENEVE_REMOTE(req, cfg->remote.r4.s_addr); + else + SET_GENEVE_REMOTE6(req, &cfg->remote.r6, + sizeof(cfg->remote.r6)); + + return 0; +} + +static int geneve_create(const char *dev, int family, void *remote, + void *hwaddr) +{ + struct geneve_setup_config geneve; + + memset(&geneve, 0, sizeof(geneve)); + geneve.vnid =3D VN_ID; + geneve.vnport =3D htons(VN_PORT); + geneve.csum =3D 1; + geneve.family =3D family; + if (family =3D=3D AF_INET) + memcpy(&geneve.remote.r4, remote, sizeof(struct in_addr)); + else + memcpy(&geneve.remote.r6, remote, sizeof(struct in6_addr)); + memcpy(geneve.hwaddr, hwaddr, ETH_ALEN); + + return ip_link_add(dev, "geneve", geneve_fill_newlink, (void *)&geneve); +} + +static int set_pmtu_discover(int fd, bool is_ipv4) +{ + int level, name, val; + + if (is_ipv4) { + level =3D SOL_IP; + name =3D IP_MTU_DISCOVER; + val =3D IP_PMTUDISC_DO; + } else { + level =3D SOL_IPV6; + name =3D IPV6_MTU_DISCOVER; + val =3D IPV6_PMTUDISC_DO; + } + + return setsockopt(fd, level, name, &val, sizeof(val)); +} + +static int udp_socket_open(struct sockaddr_storage *ssa, bool do_frag, + bool do_connect, struct sockaddr_storage *dsa) +{ + struct timeval to =3D { .tv_sec =3D TIMEOUT_SEC }; + int fd, family =3D ssa->ss_family; + int salen =3D sockaddr_len(family); + + fd =3D socket(family, SOCK_DGRAM, 0); + if (fd < 0) + return -1; + + if (bind(fd, (struct sockaddr *)ssa, salen) < 0) { + perror("bind"); + goto err; + } + + if (do_connect && connect(fd, (struct sockaddr *)dsa, salen) < 0) { + perror("connect"); + goto err; + } + + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)) < 0) { + perror("setsockopt(SO_RCVTIMEO)"); + goto err; + } + + if (!do_frag && set_pmtu_discover(fd, family =3D=3D AF_INET) < 0) { + perror("set_pmtu_discover"); + goto err; + } + return fd; + +err: + close(fd); + return -1; +} + +static void parse_route_rsp(struct rt_route_getroute_rsp *rsp, void *rtm_t= ype) +{ + *(uint8_t *)rtm_type =3D rsp->_hdr.rtm_type; +} + +static int ip_route_check(const char *intf, int family, void *addr) +{ + uint8_t rtm_type, table =3D RT_TABLE_LOCAL; + int retries =3D MAX_RETRIES; + + while (retries-- > 0) { + if (ip_route_get(intf, family, table, addr, parse_route_rsp, + &rtm_type) =3D=3D 0 && + rtm_type =3D=3D RTN_LOCAL) + break; + + usleep(TIMEOUT_USEC); + } + + if (retries < 0) + return -1; + + return 0; +} + FIXTURE(tun) { char ifname[IFNAMSIZ]; @@ -129,4 +399,159 @@ TEST_F(tun, reattach_close_delete) EXPECT_EQ(tun_delete(self->ifname), 0); } =20 +FIXTURE(tun_vnet_udptnl) +{ + char ifname[IFNAMSIZ]; + int fd, sock; +}; + +FIXTURE_VARIANT(tun_vnet_udptnl) +{ + int tunnel_type; + bool is_tap; +}; + +/* clang-format off */ +#define TUN_VNET_UDPTNL_VARIANT_ADD(type, desc) = \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##udptnl) { \ + .tunnel_type =3D type, \ + .is_tap =3D true, \ + } +/* clang-format on */ + +TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_4IN4, 4in4); +TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_6IN4, 6in4); +TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_4IN6, 4in6); +TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_6IN6, 6in6); + +static void assign_ifaddr_vars(int family, int is_outer, void **srcip, + void **dstip, void **srcmac, void **dstmac) +{ + if (is_outer) { + if (family =3D=3D AF_INET) { + *srcip =3D (void *)¶m_ipaddr4_outer_src; + *dstip =3D (void *)¶m_ipaddr4_outer_dst; + } else { + *srcip =3D (void *)¶m_ipaddr6_outer_src; + *dstip =3D (void *)¶m_ipaddr6_outer_dst; + } + *srcmac =3D param_hwaddr_outer_src; + *dstmac =3D param_hwaddr_outer_dst; + } else { + if (family =3D=3D AF_INET) { + *srcip =3D (void *)¶m_ipaddr4_inner_src; + *dstip =3D (void *)¶m_ipaddr4_inner_dst; + } else { + *srcip =3D (void *)¶m_ipaddr6_inner_src; + *dstip =3D (void *)¶m_ipaddr6_inner_dst; + } + *srcmac =3D param_hwaddr_inner_src; + *dstmac =3D param_hwaddr_inner_dst; + } +} + +static void assign_sockaddr_vars(int family, int is_outer, + struct sockaddr_storage *src, + struct sockaddr_storage *dst) +{ + src->ss_family =3D family; + dst->ss_family =3D family; + + if (family =3D=3D AF_INET) { + struct sockaddr_in *s4 =3D (struct sockaddr_in *)src; + struct sockaddr_in *d4 =3D (struct sockaddr_in *)dst; + + s4->sin_addr =3D is_outer ? param_ipaddr4_outer_src : + param_ipaddr4_inner_src; + d4->sin_addr =3D is_outer ? param_ipaddr4_outer_dst : + param_ipaddr4_inner_dst; + if (!is_outer) { + s4->sin_port =3D htons(UDP_SRC_PORT); + d4->sin_port =3D htons(UDP_DST_PORT); + } + } else { + struct sockaddr_in6 *s6 =3D (struct sockaddr_in6 *)src; + struct sockaddr_in6 *d6 =3D (struct sockaddr_in6 *)dst; + + s6->sin6_addr =3D is_outer ? param_ipaddr6_outer_src : + param_ipaddr6_inner_src; + d6->sin6_addr =3D is_outer ? param_ipaddr6_outer_dst : + param_ipaddr6_inner_dst; + if (!is_outer) { + s6->sin6_port =3D htons(UDP_SRC_PORT); + d6->sin6_port =3D htons(UDP_DST_PORT); + } + } +} + +FIXTURE_SETUP(tun_vnet_udptnl) +{ + int ret, family, prefix, flags, features; + int tunnel_type =3D variant->tunnel_type; + struct sockaddr_storage ssa, dsa; + void *sip, *dip, *smac, *dmac; + + flags =3D (variant->is_tap ? IFF_TAP : IFF_TUN) | IFF_VNET_HDR | + IFF_MULTI_QUEUE | IFF_NO_PI; + features =3D TUN_F_CSUM | TUN_F_UDP_TUNNEL_GSO | + TUN_F_UDP_TUNNEL_GSO_CSUM | TUN_F_USO4 | TUN_F_USO6; + self->fd =3D tun_open(self->ifname, flags, TUN_VNET_TNL_SIZE, features, + param_hwaddr_outer_src); + ASSERT_GE(self->fd, 0); + + family =3D (tunnel_type & UDP_TUNNEL_OUTER_IPV4) ? AF_INET : AF_INET6; + prefix =3D (family =3D=3D AF_INET) ? IPPREFIX_LEN : IP6PREFIX_LEN; + assign_ifaddr_vars(family, 1, &sip, &dip, &smac, &dmac); + + ret =3D ip_addr_add(self->ifname, family, sip, prefix); + ASSERT_EQ(ret, 0); + ret =3D ip_neigh_add(self->ifname, family, dip, dmac); + ASSERT_EQ(ret, 0); + ret =3D ip_route_check(self->ifname, family, sip); + ASSERT_EQ(ret, 0); + + ret =3D geneve_create(param_dev_geneve_name, family, dip, + param_hwaddr_inner_src); + ASSERT_EQ(ret, 0); + + family =3D (tunnel_type & UDP_TUNNEL_INNER_IPV4) ? AF_INET : AF_INET6; + prefix =3D (family =3D=3D AF_INET) ? IPPREFIX_LEN : IP6PREFIX_LEN; + assign_ifaddr_vars(family, 0, &sip, &dip, &smac, &dmac); + + ret =3D ip_addr_add(param_dev_geneve_name, family, sip, prefix); + ASSERT_EQ(ret, 0); + ret =3D ip_neigh_add(param_dev_geneve_name, family, dip, dmac); + ASSERT_EQ(ret, 0); + ret =3D ip_route_check(param_dev_geneve_name, family, sip); + ASSERT_EQ(ret, 0); + + assign_sockaddr_vars(family, 0, &ssa, &dsa); + self->sock =3D udp_socket_open(&ssa, false, true, &dsa); + ASSERT_GE(self->sock, 0); +} + +FIXTURE_TEARDOWN(tun_vnet_udptnl) +{ + int ret; + + if (self->sock !=3D -1) + close(self->sock); + + ret =3D ip_link_del(param_dev_geneve_name); + EXPECT_EQ(ret, 0); + + ret =3D tun_delete(self->ifname); + EXPECT_EQ(ret, 0); +} + +TEST_F(tun_vnet_udptnl, basic) +{ + int ret; + char cmd[256] =3D { 0 }; + + sprintf(cmd, "ip addr show %s > /dev/null 2>&1", param_dev_geneve_name); + ret =3D system(cmd); + ASSERT_EQ(ret, 0); +} + TEST_HARNESS_MAIN --=20 2.49.0 From nobody Sat Feb 7 21:15:01 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 D6036330B2C for ; Mon, 19 Jan 2026 05:41:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801269; cv=none; b=sRSVYLFzx2s5p3mNtD2RIAQI1vxUlQzM/IGH/J2KLg/p3WNaEUWyUdYrpFUpjQ1wf3yFJtMtmwJEW1JvUg1zo8WZ+eojva6nn+HfXbpRUaM54UB9jiZQq7Sm8pr0HhRJjVNa6t9MQ7f2z5geW99i4l4tZ4noYFRkQfEybFJFBV0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801269; c=relaxed/simple; bh=r1GIHPsQXqh4NzWIRRAFxrdy8aRnIFNORBQkE2f8a20=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=arrOJv4ShW8Su1YBcixu/jY3hP5ltdtAjEVizfjW1DtSqFFJidqkWXeZOmk3cm2D9NtgP/3evIoe5twJYaRiYRBEPOGbWu4OqV7xYflJ3EPvBagr6zE0XnNdgNnD9Kl3Ji9q3AU8xWqkpKAWzIltynnKPhBieJzHHjHh4tzHJ3s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=JIzC7aUw; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="JIzC7aUw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768801267; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=+jVfxCv38JtbRl/2k2l0lZedi5OEIHN4mUj3DSEDDH4=; b=JIzC7aUwKUFcwxfFdf7n5cN8ufgz53ZrqrR7Qw1nUNmBoy2Wwp0WAplazJzinIt4c+lO8O +RbFpcqvjMWYHdMzc75I68lYrZfh9zhsKspGAyYWGm2H5xf4yEKijQKJNpXJYGus7u6SbZ f/J48+Tke5Yr3nJZNokOmwLyRY0VErk= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-581-kirIsUZmMg-63DiUr7Jqew-1; Mon, 19 Jan 2026 00:41:03 -0500 X-MC-Unique: kirIsUZmMg-63DiUr7Jqew-1 X-Mimecast-MFC-AGG-ID: kirIsUZmMg-63DiUr7Jqew_1768801261 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C264F1954B0B; Mon, 19 Jan 2026 05:41:01 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.72.116.28]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3BA2E18004D8; Mon, 19 Jan 2026 05:40:52 +0000 (UTC) From: Xu Du To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v5 5/7] selftest: tun: Add test for sending gso packet into tun Date: Mon, 19 Jan 2026 13:40:02 +0800 Message-ID: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" The test constructs a raw packet, prepends a virtio_net_hdr, and writes the result to the TUN device. This mimics the behavior of a vm forwarding a guest's packet to the host networking stack. Signed-off-by: Xu Du --- v4 -> v5: - Use Geneve instead of VXLAN due to missing YNL support. v3 -> v4: - Expand the buffer to accommodate the maximum length of test packets. v1 -> v2: - Correct spelling of 'recieve' to 'receive'. - Avoid busy waiting caused by recv() returning empty. tools/testing/selftests/net/tun.c | 144 ++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index ec089355312b..f0ddb5d37683 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -75,7 +75,34 @@ static struct in6_addr param_ipaddr6_inner_src =3D { #define UDP_TUNNEL_OUTER_IPV4 (UDP_TUNNEL_GENEVE_4IN4 | UDP_TUNNEL_GENEVE_= 6IN4) #define UDP_TUNNEL_INNER_IPV4 (UDP_TUNNEL_GENEVE_4IN4 | UDP_TUNNEL_GENEVE_= 4IN6) =20 +#define UDP_TUNNEL_GENEVE_4IN4_HDRLEN \ + (ETH_HLEN + 2 * sizeof(struct iphdr) + GENEVE_HLEN + \ + 2 * sizeof(struct udphdr)) +#define UDP_TUNNEL_GENEVE_6IN6_HDRLEN \ + (ETH_HLEN + 2 * sizeof(struct ipv6hdr) + GENEVE_HLEN + \ + 2 * sizeof(struct udphdr)) +#define UDP_TUNNEL_GENEVE_4IN6_HDRLEN \ + (ETH_HLEN + sizeof(struct iphdr) + sizeof(struct ipv6hdr) + \ + GENEVE_HLEN + 2 * sizeof(struct udphdr)) +#define UDP_TUNNEL_GENEVE_6IN4_HDRLEN \ + (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct iphdr) + \ + GENEVE_HLEN + 2 * sizeof(struct udphdr)) + +#define UDP_TUNNEL_HDRLEN(type) = \ + ((type) =3D=3D UDP_TUNNEL_GENEVE_4IN4 ? UDP_TUNNEL_GENEVE_4IN4_HDRLEN : \ + (type) =3D=3D UDP_TUNNEL_GENEVE_6IN6 ? UDP_TUNNEL_GENEVE_6IN6_HDRLEN : \ + (type) =3D=3D UDP_TUNNEL_GENEVE_4IN6 ? UDP_TUNNEL_GENEVE_4IN6_HDRLEN : \ + (type) =3D=3D UDP_TUNNEL_GENEVE_6IN4 ? UDP_TUNNEL_GENEVE_6IN4_HDRLEN : \ + 0) + +#define UDP_TUNNEL_MSS(type) (ETH_DATA_LEN - UDP_TUNNEL_HDRLEN(type)) +#define UDP_TUNNEL_MAX(type, is_tap) \ + (ETH_MAX_MTU - UDP_TUNNEL_HDRLEN(type) - ((is_tap) ? ETH_HLEN : 0)) + #define TUN_VNET_TNL_SIZE sizeof(struct virtio_net_hdr_v1_hash_tunnel) +#define MAX_VNET_TUNNEL_PACKET_SZ \ + (TUN_VNET_TNL_SIZE + ETH_HLEN + UDP_TUNNEL_GENEVE_6IN6_HDRLEN + \ + ETH_MAX_MTU) =20 struct geneve_setup_config { int family; @@ -408,15 +435,23 @@ FIXTURE(tun_vnet_udptnl) FIXTURE_VARIANT(tun_vnet_udptnl) { int tunnel_type; - bool is_tap; + int gso_size; + int data_size; + int r_num_mss; + bool is_tap, no_gso; }; =20 /* clang-format off */ #define TUN_VNET_UDPTNL_VARIANT_ADD(type, desc) = \ - FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##udptnl) { \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_1mss) { \ + /* send a single MSS: fall back to no GSO */ \ .tunnel_type =3D type, \ + .gso_size =3D UDP_TUNNEL_MSS(type), \ + .data_size =3D UDP_TUNNEL_MSS(type), \ + .r_num_mss =3D 1, \ .is_tap =3D true, \ - } + .no_gso =3D true, \ + }; /* clang-format on */ =20 TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_4IN4, 4in4); @@ -544,14 +579,105 @@ FIXTURE_TEARDOWN(tun_vnet_udptnl) EXPECT_EQ(ret, 0); } =20 -TEST_F(tun_vnet_udptnl, basic) +static int build_gso_packet_into_tun(const FIXTURE_VARIANT(tun_vnet_udptnl= ) * + variant, + uint8_t *buf) { - int ret; - char cmd[256] =3D { 0 }; + int pktlen, hlen, proto, inner_family, outer_family; + int tunnel_type =3D variant->tunnel_type; + int payload_len =3D variant->data_size; + int gso_size =3D variant->gso_size; + uint8_t *outer_udph, *cur =3D buf; + void *sip, *dip, *smac, *dmac; + bool is_tap =3D variant->is_tap; =20 - sprintf(cmd, "ip addr show %s > /dev/null 2>&1", param_dev_geneve_name); - ret =3D system(cmd); - ASSERT_EQ(ret, 0); + hlen =3D (is_tap ? ETH_HLEN : 0) + UDP_TUNNEL_HDRLEN(tunnel_type); + inner_family =3D (tunnel_type & UDP_TUNNEL_INNER_IPV4) ? AF_INET : + AF_INET6; + outer_family =3D (tunnel_type & UDP_TUNNEL_OUTER_IPV4) ? AF_INET : + AF_INET6; + + cur +=3D build_virtio_net_hdr_v1_hash_tunnel(cur, is_tap, hlen, gso_size, + outer_family, inner_family); + + pktlen =3D hlen + payload_len; + assign_ifaddr_vars(outer_family, 1, &sip, &dip, &smac, &dmac); + + if (is_tap) { + proto =3D outer_family =3D=3D AF_INET ? ETH_P_IP : ETH_P_IPV6; + pktlen -=3D ETH_HLEN; + cur +=3D build_eth(cur, proto, dmac, smac); + } + + if (outer_family =3D=3D AF_INET) { + pktlen =3D pktlen - sizeof(struct iphdr); + cur +=3D build_ipv4_header(cur, IPPROTO_UDP, pktlen, dip, sip); + } else { + pktlen =3D pktlen - sizeof(struct ipv6hdr); + cur +=3D build_ipv6_header(cur, IPPROTO_UDP, 0, pktlen, dip, sip); + } + + outer_udph =3D cur; + assign_ifaddr_vars(inner_family, 0, &sip, &dip, &smac, &dmac); + + pktlen -=3D sizeof(struct udphdr); + proto =3D inner_family =3D=3D AF_INET ? ETH_P_IP : ETH_P_IPV6; + cur +=3D build_udp_header(cur, UDP_SRC_PORT, VN_PORT, pktlen); + cur +=3D build_geneve_header(cur, VN_ID); + cur +=3D build_eth(cur, proto, dmac, smac); + + pktlen =3D sizeof(struct udphdr) + payload_len; + if (inner_family =3D=3D AF_INET) + cur +=3D build_ipv4_header(cur, IPPROTO_UDP, pktlen, dip, sip); + else + cur +=3D build_ipv6_header(cur, IPPROTO_UDP, 0, pktlen, dip, sip); + + cur +=3D build_udp_packet(cur, UDP_DST_PORT, UDP_SRC_PORT, payload_len, + inner_family, false); + + build_udp_packet_csum(outer_udph, outer_family, false); + + return cur - buf; +} + +static int +receive_gso_packet_from_tunnel(FIXTURE_DATA(tun_vnet_udptnl) * self, + const FIXTURE_VARIANT(tun_vnet_udptnl) * variant, + int *r_num_mss) +{ + uint8_t packet_buf[MAX_VNET_TUNNEL_PACKET_SZ]; + int len, total_len =3D 0, socket =3D self->sock; + int payload_len =3D variant->data_size; + + while (total_len < payload_len) { + len =3D recv(socket, packet_buf, sizeof(packet_buf), 0); + if (len <=3D 0) { + if (len < 0 && errno !=3D EAGAIN && errno !=3D EWOULDBLOCK) + perror("recv"); + break; + } + + (*r_num_mss)++; + total_len +=3D len; + } + + return total_len; +} + +TEST_F(tun_vnet_udptnl, send_gso_packet) +{ + uint8_t pkt[MAX_VNET_TUNNEL_PACKET_SZ]; + int r_num_mss =3D 0; + int ret, off; + + memset(pkt, 0, sizeof(pkt)); + off =3D build_gso_packet_into_tun(variant, pkt); + ret =3D write(self->fd, pkt, off); + ASSERT_EQ(ret, off); + + ret =3D receive_gso_packet_from_tunnel(self, variant, &r_num_mss); + ASSERT_EQ(ret, variant->data_size); + ASSERT_EQ(r_num_mss, variant->r_num_mss); } =20 TEST_HARNESS_MAIN --=20 2.49.0 From nobody Sat Feb 7 21:15:01 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 9ABEC258EFF for ; Mon, 19 Jan 2026 05:41:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801277; cv=none; b=etHzlybY+fJ8zLNHiE4Zq+6md+mfBGXOcb9+GSbRKLz0shHll3/0aT4j1oOKh6LlaokyKdElkUD1MBInaCZAZylILl+cQtr3ekoUM2EWrUkmwC7UK3AYLgxi8CiyKjcWts+F9S4u70iyRxogPlASc6V7OhWFlYPEPeKxOfxQ7Cc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801277; c=relaxed/simple; bh=g38DlUZkRdlJ0ZSnW67GBayP+2oMQoROgzlN1EpP/Y0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CDO/I9LzrIWCYGVllspU2MUQ8c4RMisyosk/s/EyOkHnCaBiimGqOBXn34fmEzrxjk+bqYee+gRslsSIzIgSB+g/vx1nP+IifpqqoDCW7rEKHd3PzF5q4snbS3trrRKELL1QrJ0v0RS/ZL+azWd9+gci1eYe+oDDFzlw74ZZDDU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Um9LG8hh; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Um9LG8hh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768801274; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=w+LmLXkMXMaFHSZYvpj4ayHWC8ZNpzFMrhh3QdVkU7o=; b=Um9LG8hhB5qWCp7kKzGm8SVcxuD9+EcCedrBTjWHnKC/eio6vg4hSzsnq5K2uuHFfraqGc jfEuT1PFLhapcxbCdMoJ+hWgAO5uegd0QKXfVKDfK+HLsP6iYC1DDdtpFjSbeaKKGpYmCX FA2O5f81oqbi4ZVhODpffotBseeN7y0= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-657-SWdWfrV5POCJzviLI3Aaww-1; Mon, 19 Jan 2026 00:41:11 -0500 X-MC-Unique: SWdWfrV5POCJzviLI3Aaww-1 X-Mimecast-MFC-AGG-ID: SWdWfrV5POCJzviLI3Aaww_1768801269 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C800918003FD; Mon, 19 Jan 2026 05:41:09 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.72.116.28]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C55C61800994; Mon, 19 Jan 2026 05:41:02 +0000 (UTC) From: Xu Du To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v5 6/7] selftest: tun: Add test for receiving gso packet from tun Date: Mon, 19 Jan 2026 13:40:03 +0800 Message-ID: <2e77843bfa9f6b89168436631309eac12ee70cca.1768800198.git.xudu@redhat.com> In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" The test validate that GSO information are correctly exposed when reading packets from a TUN device. Signed-off-by: Xu Du --- v1 -> v2: - Use previous helper to simplify tunnel packet sending. - Treat read timeout (EAGAIN) as assertion failure. - Correct spelling of 'recieve' to 'receive'. tools/testing/selftests/net/tun.c | 194 ++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index f0ddb5d37683..628ae2caf6f4 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -364,6 +364,116 @@ static int ip_route_check(const char *intf, int famil= y, void *addr) return 0; } =20 +static int send_gso_udp_msg(int socket, struct sockaddr_storage *addr, + uint8_t *send_buf, int send_len, int gso_size) +{ + char control[CMSG_SPACE(sizeof(uint16_t))] =3D { 0 }; + int alen =3D sockaddr_len(addr->ss_family); + struct msghdr msg =3D { 0 }; + struct iovec iov =3D { 0 }; + int ret; + + iov.iov_base =3D send_buf; + iov.iov_len =3D send_len; + + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_name =3D addr; + msg.msg_namelen =3D alen; + + if (gso_size > 0) { + struct cmsghdr *cmsg; + + msg.msg_control =3D control; + msg.msg_controllen =3D sizeof(control); + + cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_UDP; + cmsg->cmsg_type =3D UDP_SEGMENT; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(uint16_t)); + *(uint16_t *)CMSG_DATA(cmsg) =3D gso_size; + } + + ret =3D sendmsg(socket, &msg, 0); + if (ret < 0) + perror("sendmsg"); + + return ret; +} + +static int validate_hdrlen(uint8_t **cur, int *len, int x) +{ + if (*len < x) + return -1; + *cur +=3D x; + *len -=3D x; + return 0; +} + +static int parse_udp_tunnel_vnet_packet(uint8_t *buf, int len, int tunnel_= type, + bool is_tap) +{ + struct ipv6hdr *iph6; + struct udphdr *udph; + struct iphdr *iph4; + uint8_t *cur =3D buf; + + if (validate_hdrlen(&cur, &len, TUN_VNET_TNL_SIZE)) + return -1; + + if (is_tap) { + if (validate_hdrlen(&cur, &len, ETH_HLEN)) + return -1; + } + + if (tunnel_type & UDP_TUNNEL_OUTER_IPV4) { + iph4 =3D (struct iphdr *)cur; + if (validate_hdrlen(&cur, &len, sizeof(struct iphdr))) + return -1; + if (iph4->version !=3D 4 || iph4->protocol !=3D IPPROTO_UDP) + return -1; + } else { + iph6 =3D (struct ipv6hdr *)cur; + if (validate_hdrlen(&cur, &len, sizeof(struct ipv6hdr))) + return -1; + if (iph6->version !=3D 6 || iph6->nexthdr !=3D IPPROTO_UDP) + return -1; + } + + udph =3D (struct udphdr *)cur; + if (validate_hdrlen(&cur, &len, sizeof(struct udphdr))) + return -1; + if (ntohs(udph->dest) !=3D VN_PORT) + return -1; + + if (validate_hdrlen(&cur, &len, GENEVE_HLEN)) + return -1; + if (validate_hdrlen(&cur, &len, ETH_HLEN)) + return -1; + + if (tunnel_type & UDP_TUNNEL_INNER_IPV4) { + iph4 =3D (struct iphdr *)cur; + if (validate_hdrlen(&cur, &len, sizeof(struct iphdr))) + return -1; + if (iph4->version !=3D 4 || iph4->protocol !=3D IPPROTO_UDP) + return -1; + } else { + iph6 =3D (struct ipv6hdr *)cur; + if (validate_hdrlen(&cur, &len, sizeof(struct ipv6hdr))) + return -1; + if (iph6->version !=3D 6 || iph6->nexthdr !=3D IPPROTO_UDP) + return -1; + } + + udph =3D (struct udphdr *)cur; + if (validate_hdrlen(&cur, &len, sizeof(struct udphdr))) + return -1; + if (ntohs(udph->dest) !=3D UDP_DST_PORT) + return -1; + + return len; +} + FIXTURE(tun) { char ifname[IFNAMSIZ]; @@ -664,6 +774,68 @@ receive_gso_packet_from_tunnel(FIXTURE_DATA(tun_vnet_u= dptnl) * self, return total_len; } =20 +static int send_gso_packet_into_tunnel(FIXTURE_DATA(tun_vnet_udptnl) * sel= f, + const FIXTURE_VARIANT(tun_vnet_udptnl) * + variant) +{ + int family =3D (variant->tunnel_type & UDP_TUNNEL_INNER_IPV4) ? AF_INET : + AF_INET6; + uint8_t buf[MAX_VNET_TUNNEL_PACKET_SZ] =3D { 0 }; + int payload_len =3D variant->data_size; + int gso_size =3D variant->gso_size; + struct sockaddr_storage ssa, dsa; + + assign_sockaddr_vars(family, 0, &ssa, &dsa); + return send_gso_udp_msg(self->sock, &dsa, buf, payload_len, gso_size); +} + +static int +receive_gso_packet_from_tun(FIXTURE_DATA(tun_vnet_udptnl) * self, + const FIXTURE_VARIANT(tun_vnet_udptnl) * variant, + struct virtio_net_hdr_v1_hash_tunnel *vnet_hdr) +{ + struct timeval timeout =3D { .tv_sec =3D TIMEOUT_SEC }; + uint8_t buf[MAX_VNET_TUNNEL_PACKET_SZ]; + int tunnel_type =3D variant->tunnel_type; + int payload_len =3D variant->data_size; + bool is_tap =3D variant->is_tap; + int ret, len, total_len =3D 0; + int tun_fd =3D self->fd; + fd_set fdset; + + while (total_len < payload_len) { + FD_ZERO(&fdset); + FD_SET(tun_fd, &fdset); + + ret =3D select(tun_fd + 1, &fdset, NULL, NULL, &timeout); + if (ret <=3D 0) { + perror("select"); + break; + } + if (!FD_ISSET(tun_fd, &fdset)) + continue; + + len =3D read(tun_fd, buf, sizeof(buf)); + if (len <=3D 0) { + if (len < 0 && errno !=3D EAGAIN && errno !=3D EWOULDBLOCK) + perror("read"); + break; + } + + len =3D parse_udp_tunnel_vnet_packet(buf, len, tunnel_type, + is_tap); + if (len < 0) + continue; + + if (total_len =3D=3D 0) + memcpy(vnet_hdr, buf, TUN_VNET_TNL_SIZE); + + total_len +=3D len; + } + + return total_len; +} + TEST_F(tun_vnet_udptnl, send_gso_packet) { uint8_t pkt[MAX_VNET_TUNNEL_PACKET_SZ]; @@ -680,4 +852,26 @@ TEST_F(tun_vnet_udptnl, send_gso_packet) ASSERT_EQ(r_num_mss, variant->r_num_mss); } =20 +TEST_F(tun_vnet_udptnl, recv_gso_packet) +{ + struct virtio_net_hdr_v1_hash_tunnel vnet_hdr =3D { 0 }; + struct virtio_net_hdr_v1 *vh =3D &vnet_hdr.hash_hdr.hdr; + int ret, gso_type =3D VIRTIO_NET_HDR_GSO_UDP_L4; + + ret =3D send_gso_packet_into_tunnel(self, variant); + ASSERT_EQ(ret, variant->data_size); + + memset(&vnet_hdr, 0, sizeof(vnet_hdr)); + ret =3D receive_gso_packet_from_tun(self, variant, &vnet_hdr); + ASSERT_EQ(ret, variant->data_size); + + if (!variant->no_gso) { + ASSERT_EQ(vh->gso_size, variant->gso_size); + gso_type |=3D (variant->tunnel_type & UDP_TUNNEL_OUTER_IPV4) ? + (VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV4) : + (VIRTIO_NET_HDR_GSO_UDP_TUNNEL_IPV6); + ASSERT_EQ(vh->gso_type, gso_type); + } +} + TEST_HARNESS_MAIN --=20 2.49.0 From nobody Sat Feb 7 21:15:01 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 7B3B223D7E0 for ; Mon, 19 Jan 2026 05:41:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801286; cv=none; b=eoBY+4+wSFxejasJatvPYLj9mop+0x7JEeVifS9qSrce3IX1eCsltI6O+jhiv89Se3I73z1SqGFvl3YZ4sjl1iWtEDHA9XMmOHSvi/BEPmAddhnaBUXYF4zSP8Vv/1+5/OKnbCMHTDj0SqUksBupAzFc3aFOEFZ1UBbk9k0fteY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768801286; c=relaxed/simple; bh=lwwLjp60OEUmhJHmuz2OY+YTpljD4C1dOySM558JRa4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZHviy7jeYsafg9f50L5Dt8A/eyVl8bECtxj/wf3aza0IhGQPECXTQZzZM++ilOimZEUaD6J0AJhUBOTCy054d1/1DZesknIeIPeeKGCBOdW9bPfp72pv8sT0r0h2SleoFBYFOmMjQ2nbjlTh2TQ2LQ3V/ih+xUirkPNd1e6XBgg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=ZPx1gOna; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="ZPx1gOna" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768801284; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uIAxAdI8wZ+RP/CtpnS3XudX6INzowa2DYXcOdGUSDw=; b=ZPx1gOnazBrrd/h5KMYJODYtEGi5ySCi8p0/eWaWGOV2EkO/WCh1TUTthpyoTypVo0Th95 nK7QL0KNcVy516oIds9LX6+LWq0rXeVajuVvXbYg/OJqxqPT8GrI9D7LgqFpbY0jokehCX 2cIci2FHVEOZdNHYG8unZms3+jARDTE= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-130-NABk8D5hNzOGQIpgtp4JXg-1; Mon, 19 Jan 2026 00:41:20 -0500 X-MC-Unique: NABk8D5hNzOGQIpgtp4JXg-1 X-Mimecast-MFC-AGG-ID: NABk8D5hNzOGQIpgtp4JXg_1768801279 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 005401956052; Mon, 19 Jan 2026 05:41:19 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.72.116.28]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C7EEC18004D8; Mon, 19 Jan 2026 05:41:10 +0000 (UTC) From: Xu Du To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org Cc: netdev@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v5 7/7] selftest: tun: Add test data for success and failure paths Date: Mon, 19 Jan 2026 13:40:04 +0800 Message-ID: In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" To improve the robustness and coverage of the TUN selftests, this patch expands the set of test data. Signed-off-by: Xu Du --- tools/testing/selftests/net/tun.c | 115 +++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index 628ae2caf6f4..8a5cd5cb5472 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -57,6 +57,10 @@ static struct in6_addr param_ipaddr6_inner_src =3D { { { 0x20, 0x02, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } }, }; =20 +#ifndef BIT +#define BIT(nr) (1UL << (nr)) +#endif + #define VN_ID 1 #define VN_PORT 4789 #define UDP_SRC_PORT 22 @@ -72,6 +76,8 @@ static struct in6_addr param_ipaddr6_inner_src =3D { #define UDP_TUNNEL_GENEVE_4IN6 0x04 #define UDP_TUNNEL_GENEVE_6IN6 0x08 =20 +#define UDP_TUNNEL_MAX_SEGMENTS BIT(7) + #define UDP_TUNNEL_OUTER_IPV4 (UDP_TUNNEL_GENEVE_4IN4 | UDP_TUNNEL_GENEVE_= 6IN4) #define UDP_TUNNEL_INNER_IPV4 (UDP_TUNNEL_GENEVE_4IN4 | UDP_TUNNEL_GENEVE_= 4IN6) =20 @@ -553,6 +559,39 @@ FIXTURE_VARIANT(tun_vnet_udptnl) =20 /* clang-format off */ #define TUN_VNET_UDPTNL_VARIANT_ADD(type, desc) = \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_nogsosz_1byte) { \ + /* no GSO: send a single byte */ \ + .tunnel_type =3D type, \ + .data_size =3D 1, \ + .r_num_mss =3D 1, \ + .is_tap =3D true, \ + .no_gso =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_nogsosz_1mss) { \ + /* no GSO: send a single MSS, fall back to no GSO */ \ + .tunnel_type =3D type, \ + .data_size =3D UDP_TUNNEL_MSS(type), \ + .r_num_mss =3D 1, \ + .is_tap =3D true, \ + .no_gso =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_nogsosz_gtmss) { \ + /* no GSO: send a single MSS + 1B: fail */ \ + .tunnel_type =3D type, \ + .data_size =3D UDP_TUNNEL_MSS(type) + 1, \ + .r_num_mss =3D 1, \ + .is_tap =3D true, \ + .no_gso =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_1byte) { \ + /* GSO: send 1 byte, gso 1 byte, fall back to no GSO */ \ + .tunnel_type =3D type, \ + .gso_size =3D 1, \ + .data_size =3D 1, \ + .r_num_mss =3D 1, \ + .is_tap =3D true, \ + .no_gso =3D true, \ + }; \ FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_1mss) { \ /* send a single MSS: fall back to no GSO */ \ .tunnel_type =3D type, \ @@ -561,8 +600,65 @@ FIXTURE_VARIANT(tun_vnet_udptnl) .r_num_mss =3D 1, \ .is_tap =3D true, \ .no_gso =3D true, \ - }; -/* clang-format on */ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_ltgso) { \ + /* data <=3D MSS < gso: will fall back to no GSO */ \ + .tunnel_type =3D type, \ + .gso_size =3D UDP_TUNNEL_MSS(type) + 1, \ + .data_size =3D UDP_TUNNEL_MSS(type), \ + .r_num_mss =3D 1, \ + .is_tap =3D true, \ + .no_gso =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_gtgso) { \ + /* GSO: a single MSS + 1B */ \ + .tunnel_type =3D type, \ + .gso_size =3D UDP_TUNNEL_MSS(type), \ + .data_size =3D UDP_TUNNEL_MSS(type) + 1, \ + .r_num_mss =3D 2, \ + .is_tap =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_2mss) { \ + /* no GSO: send exactly 2 MSS */ \ + .tunnel_type =3D type, \ + .gso_size =3D UDP_TUNNEL_MSS(type), \ + .data_size =3D UDP_TUNNEL_MSS(type) * 2, \ + .r_num_mss =3D 2, \ + .is_tap =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_maxbytes) { \ + /* GSO: send max bytes */ \ + .tunnel_type =3D type, \ + .gso_size =3D UDP_TUNNEL_MSS(type), \ + .data_size =3D UDP_TUNNEL_MAX(type, true), \ + .r_num_mss =3D UDP_TUNNEL_MAX(type, true) / \ + UDP_TUNNEL_MSS(type) + 1, \ + .is_tap =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_over_maxbytes) { \ + /* GSO: send oversize max bytes: fail */ \ + .tunnel_type =3D type, \ + .gso_size =3D UDP_TUNNEL_MSS(type), \ + .data_size =3D ETH_MAX_MTU, \ + .r_num_mss =3D ETH_MAX_MTU / UDP_TUNNEL_MSS(type) + 1, \ + .is_tap =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_maxsegs) { \ + /* GSO: send max number of min sized segments */ \ + .tunnel_type =3D type, \ + .gso_size =3D 1, \ + .data_size =3D UDP_TUNNEL_MAX_SEGMENTS, \ + .r_num_mss =3D UDP_TUNNEL_MAX_SEGMENTS, \ + .is_tap =3D true, \ + }; \ + FIXTURE_VARIANT_ADD(tun_vnet_udptnl, desc##_5byte) { \ + /* GSO: send 5 bytes, gso 2 bytes */ \ + .tunnel_type =3D type, \ + .gso_size =3D 2, \ + .data_size =3D 5, \ + .r_num_mss =3D 3, \ + .is_tap =3D true, \ + } /* clang-format on */ =20 TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_4IN4, 4in4); TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_GENEVE_6IN4, 6in4); @@ -874,4 +970,19 @@ TEST_F(tun_vnet_udptnl, recv_gso_packet) } } =20 +XFAIL_ADD(tun_vnet_udptnl, 4in4_nogsosz_gtmss, recv_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 6in4_nogsosz_gtmss, recv_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 4in6_nogsosz_gtmss, recv_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 6in6_nogsosz_gtmss, recv_gso_packet); + +XFAIL_ADD(tun_vnet_udptnl, 4in4_over_maxbytes, send_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 6in4_over_maxbytes, send_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 4in6_over_maxbytes, send_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 6in6_over_maxbytes, send_gso_packet); + +XFAIL_ADD(tun_vnet_udptnl, 4in4_over_maxbytes, recv_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 6in4_over_maxbytes, recv_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 4in6_over_maxbytes, recv_gso_packet); +XFAIL_ADD(tun_vnet_udptnl, 6in6_over_maxbytes, recv_gso_packet); + TEST_HARNESS_MAIN --=20 2.49.0