From nobody Fri Jan 9 01:02:32 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 D6A13316184 for ; Tue, 6 Jan 2026 01:35:40 +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=1767663342; cv=none; b=mabrFA4rggG25aR2roNXWzziq6hI9uzjrmVWpDfXXpUs5ORszxmvTC3mp/RjNUO1hTrNuX+lLTQ+piGVEfzX0IHHag8WADBtQz9E4/ea8NAqp3Ma0yWkrhynInW++/TkALQOYSadruhpQq6FKzOsYFto9CqkpYW3FcqarLPgMFs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767663342; c=relaxed/simple; bh=me4c50WXRR8xB8plkzzqIpolCR7qnDaoGIMH+/D8XeQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=etjjiHZtpOCAqm3z3X/tIJtnWVE1ODYnckeDJ5DPm4+D2HH1rQV7y+Y9IqwlCVbqRTFu+CVUtfsr0V6IgKA0rE2xs6+L2ajdaMM4PkYIwCqOKTZIsVuwRZ+4AlwpkXTN++Jpk9K8GJStTlp7DiE9nXFiPrxQcv0OTBVHoR7gutc= 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=NGCGpm6o; 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="NGCGpm6o" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767663339; 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=NGCGpm6oyzrCep4TYs6RJU8xhcVUFAcBLPoVPO2tySKJOqrpb10a4fxLmGFBO4UoSX1GRx yUxwvaFdFc9NkfKw2qHr7YxalEBtrKuagZNCR5jz9892rLLimwylq6DY/UtMnY8lcM+1+e 656n8t+cx2bH93aKxumfm18j3cAS95Q= 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-388-R8GL0tDHMvOUdf0sIRgGGA-1; Mon, 05 Jan 2026 20:35:35 -0500 X-MC-Unique: R8GL0tDHMvOUdf0sIRgGGA-1 X-Mimecast-MFC-AGG-ID: R8GL0tDHMvOUdf0sIRgGGA_1767663334 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 C8BD21800622; Tue, 6 Jan 2026 01:35:33 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.66.60.72]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id DD6FC180044F; Tue, 6 Jan 2026 01:35:29 +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 v4 1/8] selftest: tun: Format tun.c existing code Date: Tue, 6 Jan 2026 09:35:14 +0800 Message-ID: <177c8d3d1e496a871c294f78ca8febfefda4ad93.1767597114.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.111 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 Fri Jan 9 01:02:32 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 66A9B31619B for ; Tue, 6 Jan 2026 01:35:44 +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=1767663346; cv=none; b=deDR3elr/DDvJKTmigZsIGk9I/BvNb7/SEhX3MWsQA1evJX7J6YadDlmnEjFC+h+K4tSO9ZKG+uv7yVyXp0cCortcd4nwe9UZm/ZoSA8Kb5XFe/UWA3/+C/a5Q90yoTaZbZDWJuEr4Rv+AUvJ6SDN+w+9jVCMKQPdL5s32onhqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767663346; c=relaxed/simple; bh=8Q9RwB0fyOeWvZeOxgOM42dlEb8yEANB2crTOQLnt9o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rz9706oJsv79xyAQdZTdwrytg/VbpBoWQF2Xspclpv48VprNfIttBjB8LcefG7ORRuMEfmh8SJOK1IgkkpOssos6HLsYSYmOyqAfOQ7uT0pH3FvsUWeOR04GyU9O//zS7k2enqGUjynAjtidiPgUSwMHggd97G9lF8G6w4SFoNc= 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=gWoIprCc; 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="gWoIprCc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767663343; 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=ySvbfuM2pgv7wb1MkQlLWPaxhoxol89u6j/dVVCslo4=; b=gWoIprCczt095ax9OVj1+LwUxjtJWSVMo6i+9Hf+vwL4iaigdKDejulUNzzYfUj4jWd9S7 hbkD/FaC/sVdL/YTOAnSgmEcpUTjB/BFyt2bLnUBx1K/Pd6EqvSl6uxhcasVA1N4SuyUqL 4k7WGsDNbsh/QehKCkp8Tpsx0XLoIG8= 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-413-xNYZcRyhPP-HBPx0vmF0eg-1; Mon, 05 Jan 2026 20:35:40 -0500 X-MC-Unique: xNYZcRyhPP-HBPx0vmF0eg-1 X-Mimecast-MFC-AGG-ID: xNYZcRyhPP-HBPx0vmF0eg_1767663338 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 7B2A9180035A; Tue, 6 Jan 2026 01:35:38 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.66.60.72]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7CB09180045B; Tue, 6 Jan 2026 01:35:34 +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 v4 2/8] selftest: tun: Introduce tuntap_helpers.h header for TUN/TAP testing Date: Tue, 6 Jan 2026 09:35:15 +0800 Message-ID: <139afe2b511cd67c4aea98c72fd1f792ba147e4d.1767597114.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.111 Content-Type: text/plain; charset="utf-8" Introduce netlink 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: - Netlink socket management utilities. - Helpers for net device, ip address, ip neighbor and ip route operations. - Packet construction and manipulation helpers. Signed-off-by: Xu Du --- 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 | 602 +++++++++++++++++++ 1 file changed, 602 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..4604008a5a5a --- /dev/null +++ b/tools/testing/selftests/net/tuntap_helpers.h @@ -0,0 +1,602 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _TUNTAP_HELPERS_H +#define _TUNTAP_HELPERS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_RTNL_PAYLOAD 4096 +#define VXLAN_HLEN 8 +#define PKT_DATA 0xCB + +enum nl_op { + NL_NEW, + NL_DEL, + NL_GET, + NL_OP_MAX, +}; + +enum nl_type { + NL_ADDR, + NL_NEIGH, + NL_ROUTE, + NL_DEV, +}; + +struct nl_req_msg { + struct nlmsghdr nh; + union { + struct ifaddrmsg addr_info; + struct ndmsg neigh_info; + struct rtmsg route_info; + struct ifinfomsg dev_info; + }; + unsigned char data[MAX_RTNL_PAYLOAD]; +}; + +struct nl_req_cb { + int (*fill_rtattr)(struct nlmsghdr *nh, void *data); + void *cb_data; +}; + +struct nl_req_entry { + int type[NL_OP_MAX]; + size_t msgsize; + int (*fill_req)(int nl_op, void *params, struct nl_req_msg *req, + struct nl_req_cb *cb); + int (*check_answer)(void *params, struct nlmsghdr *nh); +}; + +struct nl_addr { + const char *intf; + int family; + void *addr; + uint8_t prefix; +}; + +struct nl_neigh { + const char *intf; + int family; + void *addr; + unsigned char *lladdr; +}; + +struct nl_route { + const char *intf; + int family; + int type; + int table; + void *dst; + uint8_t dst_len; + void *gateway; +}; + +struct nl_dev { + const char *intf; + char *link_type; + int (*fill_rtattr)(struct nlmsghdr *nh, void *cb_data); + int (*fill_info_data)(struct nlmsghdr *nh, void *cb_data); + void *cb_data; +}; + +static inline size_t ip_addr_len(int family) +{ + return (family =3D=3D AF_INET) ? sizeof(struct in_addr) : + sizeof(struct in6_addr); +} + +static inline struct rtattr *rtattr_add(struct nlmsghdr *nh, + unsigned short type, unsigned short len) +{ + struct rtattr *rta =3D + (struct rtattr *)((uint8_t *)nh + RTA_ALIGN(nh->nlmsg_len)); + + rta->rta_type =3D type; + rta->rta_len =3D RTA_LENGTH(len); + nh->nlmsg_len =3D RTA_ALIGN(nh->nlmsg_len) + RTA_ALIGN(rta->rta_len); + return rta; +} + +static inline struct rtattr *rtattr_begin(struct nlmsghdr *nh, + unsigned short type) +{ + return rtattr_add(nh, type, 0); +} + +static inline void rtattr_end(struct nlmsghdr *nh, struct rtattr *attr) +{ + uint8_t *end =3D (uint8_t *)nh + nh->nlmsg_len; + + attr->rta_len =3D end - (uint8_t *)attr; +} + +static struct rtattr *rtattr_add_str(struct nlmsghdr *nh, unsigned short t= ype, + const char *s) +{ + unsigned int strsz =3D strlen(s) + 1; + struct rtattr *rta; + + rta =3D rtattr_add(nh, type, strsz); + + memcpy(RTA_DATA(rta), s, strsz); + return rta; +} + +static inline struct rtattr *rtattr_add_any(struct nlmsghdr *nh, + unsigned short type, + const void *arr, size_t len) +{ + struct rtattr *rta =3D rtattr_add(nh, type, len); + + memcpy(RTA_DATA(rta), arr, len); + return rta; +} + +static inline int fill_addr_req(int nl_op, void *params, struct nl_req_msg= *req, + struct nl_req_cb *cb) +{ + struct nl_addr *addrp =3D params; + size_t ipalen; + + ipalen =3D ip_addr_len(addrp->family); + req->addr_info.ifa_family =3D addrp->family; + req->addr_info.ifa_index =3D if_nametoindex(addrp->intf); + req->addr_info.ifa_flags =3D (nl_op =3D=3D NL_NEW) ? IFA_F_NODAD : 0; + req->nh.nlmsg_flags |=3D (nl_op =3D=3D NL_GET) ? NLM_F_DUMP : 0; + + if (nl_op !=3D NL_GET) { + req->addr_info.ifa_prefixlen =3D addrp->prefix; + rtattr_add_any(&req->nh, IFA_LOCAL, addrp->addr, ipalen); + } + return 0; +} + +static inline int check_addr_answer(void *params, struct nlmsghdr *nh) +{ + struct rtattr *rta =3D (struct rtattr *)IFA_RTA(NLMSG_DATA(nh)); + struct nl_addr *addrp =3D params; + size_t ipalen; + int rtlen; + + ipalen =3D ip_addr_len(addrp->family); + rtlen =3D nh->nlmsg_len - NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + + while (RTA_OK(rta, rtlen)) { + if (rta->rta_type =3D=3D IFA_ADDRESS && + memcmp(RTA_DATA(rta), addrp->addr, ipalen) =3D=3D 0) + return 1; + rta =3D RTA_NEXT(rta, rtlen); + } + return 0; +} + +static inline int fill_neigh_req(int nl_op, void *params, + struct nl_req_msg *req, struct nl_req_cb *cb) +{ + struct nl_neigh *neighp =3D params; + size_t ipalen; + + ipalen =3D ip_addr_len(neighp->family); + req->neigh_info.ndm_family =3D neighp->family; + req->neigh_info.ndm_ifindex =3D if_nametoindex(neighp->intf); + req->neigh_info.ndm_state =3D (nl_op =3D=3D NL_NEW) ? NUD_PERMANENT : 0; + + rtattr_add_any(&req->nh, NDA_DST, neighp->addr, ipalen); + if (nl_op =3D=3D NL_NEW) + rtattr_add_any(&req->nh, NDA_LLADDR, neighp->lladdr, ETH_ALEN); + return 0; +} + +static inline int fill_route_req(int nl_op, void *params, + struct nl_req_msg *req, struct nl_req_cb *cb) +{ + struct nl_route *routep =3D params; + size_t ipalen; + int oif; + + ipalen =3D ip_addr_len(routep->family); + oif =3D if_nametoindex(routep->intf); + req->route_info.rtm_family =3D routep->family; + req->route_info.rtm_dst_len =3D routep->dst_len; + req->route_info.rtm_table =3D routep->table; + req->route_info.rtm_type =3D routep->type; + req->route_info.rtm_protocol =3D RTPROT_BOOT; + req->route_info.rtm_scope =3D RT_SCOPE_UNIVERSE; + + rtattr_add_any(&req->nh, RTA_DST, routep->dst, ipalen); + + if (nl_op !=3D NL_GET) { + rtattr_add_any(&req->nh, RTA_GATEWAY, routep->gateway, ipalen); + rtattr_add_any(&req->nh, RTA_OIF, &oif, sizeof(int)); + } + return 0; +} + +static inline int check_route_answer(void *params, struct nlmsghdr *nh) +{ + struct rtmsg *rtm =3D NLMSG_DATA(nh); + struct nl_route *routep =3D params; + + return (rtm->rtm_type =3D=3D routep->type) ? 1 : 0; +} + +static inline int fill_dev_req(int nl_op, void *params, struct nl_req_msg = *req, + struct nl_req_cb *cb) +{ + struct rtattr *link_info, *info_data; + struct nl_dev *devp =3D params; + int ret; + + cb->fill_rtattr =3D devp->fill_rtattr; + cb->cb_data =3D devp->cb_data; + + req->dev_info.ifi_family =3D AF_UNSPEC; + req->dev_info.ifi_type =3D 1; + req->dev_info.ifi_index =3D 0; + req->dev_info.ifi_flags =3D (nl_op =3D=3D NL_NEW) ? (IFF_BROADCAST | IFF_= UP) : + 0; + req->dev_info.ifi_change =3D 0xffffffff; + + rtattr_add_str(&req->nh, IFLA_IFNAME, devp->intf); + + if (nl_op =3D=3D NL_NEW) { + link_info =3D rtattr_begin(&req->nh, IFLA_LINKINFO); + rtattr_add_str(&req->nh, IFLA_INFO_KIND, devp->link_type); + + if (devp->fill_info_data) { + info_data =3D rtattr_begin(&req->nh, IFLA_INFO_DATA); + ret =3D devp->fill_info_data(&req->nh, devp->cb_data); + if (ret < 0) + return ret; + rtattr_end(&req->nh, info_data); + } + rtattr_end(&req->nh, link_info); + } + return 0; +} + +static const struct nl_req_entry nl_req_tbl[] =3D { + [NL_ADDR] =3D { { RTM_NEWADDR, RTM_DELADDR, RTM_GETADDR }, + sizeof(struct ifaddrmsg), + fill_addr_req, + check_addr_answer }, + [NL_NEIGH] =3D { { RTM_NEWNEIGH, RTM_DELNEIGH, RTM_GETNEIGH }, + sizeof(struct ndmsg), + fill_neigh_req, + NULL }, + [NL_ROUTE] =3D { { RTM_NEWROUTE, RTM_DELROUTE, RTM_GETROUTE }, + sizeof(struct rtmsg), + fill_route_req, + check_route_answer }, + [NL_DEV] =3D { { RTM_NEWLINK, RTM_DELLINK, RTM_GETLINK }, + sizeof(struct ifinfomsg), + fill_dev_req, + NULL }, +}; + +static inline int fill_nl_req_msg(int nl_op, int nl_type, void *params, + struct nl_req_msg *req, struct nl_req_cb *cb) +{ + int ret; + + req->nh.nlmsg_type =3D nl_req_tbl[nl_type].type[nl_op]; + req->nh.nlmsg_flags =3D NLM_F_REQUEST | NLM_F_ACK; + req->nh.nlmsg_flags |=3D nl_op =3D=3D NL_NEW ? (NLM_F_CREATE | NLM_F_EXCL= ) : + 0; + req->nh.nlmsg_len =3D NLMSG_LENGTH(nl_req_tbl[nl_type].msgsize); + + ret =3D nl_req_tbl[nl_type].fill_req(nl_op, params, req, cb); + if (ret < 0) + return ret; + + if (cb->fill_rtattr) { + ret =3D cb->fill_rtattr(&req->nh, cb->cb_data); + if (ret < 0) + return ret; + } + + return 0; +} + +static inline int check_nl_resp_msg(int rtnl, int nl_op, int nl_type, + void *params, struct nl_req_msg *req) +{ + int (*check_answer)(void *, struct nlmsghdr *) =3D + nl_req_tbl[nl_type].check_answer; + char answer[MAX_RTNL_PAYLOAD]; + int len, done, ret =3D 0; + struct nlmsgerr *err; + struct nlmsghdr *nh; + + do { + len =3D recv(rtnl, answer, sizeof(answer), 0); + if (len < 0) + return -1; + + for (nh =3D (struct nlmsghdr *)answer; NLMSG_OK(nh, len); + nh =3D NLMSG_NEXT(nh, len)) { + done =3D !(nh->nlmsg_flags & NLM_F_MULTI); + + if (nh->nlmsg_type =3D=3D NLMSG_DONE) + goto out; + + if (nh->nlmsg_type =3D=3D NLMSG_ERROR) { + err =3D (struct nlmsgerr *)NLMSG_DATA(nh); + ret =3D err->error; + goto out; + } + + if (nl_op !=3D NL_GET || !check_answer) { + /* treat new/del non-error msg as error */ + ret =3D -1; + goto out; + } + + if (check_answer(params, nh)) { + ret =3D 1; + goto out; + } + } + } while (!done); + +out: + return ret; +} + +static inline int netlink_op(int nl_op, int nl_type, void *params) +{ + struct nl_req_cb cb =3D { 0 }; + struct nl_req_msg req; + int rtnl, ret; + + rtnl =3D socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); + if (rtnl < 0) + return -1; + + ret =3D fill_nl_req_msg(nl_op, nl_type, params, &req, &cb); + if (ret < 0) + goto out; + + ret =3D send(rtnl, &req, req.nh.nlmsg_len, 0); + if (ret < 0) + goto out; + + /* return 1 if found, 0 if request msg successful, < 0 if error */ + ret =3D check_nl_resp_msg(rtnl, nl_op, nl_type, params, &req); +out: + close(rtnl); + return ret; +} + +static inline int ip_addr_add(const char *intf, int family, void *addr, + uint8_t prefix) +{ + struct nl_addr param =3D { intf, family, addr, prefix }; + + return netlink_op(NL_NEW, NL_ADDR, ¶m); +} + +static inline int ip_neigh_add(const char *intf, int family, void *addr, + unsigned char *lladdr) +{ + struct nl_neigh param =3D { intf, family, addr, lladdr }; + + return netlink_op(NL_NEW, NL_NEIGH, ¶m); +} + +static inline int ip_route_get(const char *intf, int family, void *dst, + uint8_t dst_len, int type, int table) +{ + struct nl_route param =3D { + intf, family, type, table, dst, dst_len, NULL + }; + + return netlink_op(NL_GET, NL_ROUTE, ¶m); +} + +static inline int +dev_create(const char *dev, char *link_type, + int (*fill_rtattr)(struct nlmsghdr *nh, void *cb_data), + int (*fill_info_data)(struct nlmsghdr *nh, void *cb_data), + void *cb_data) +{ + struct nl_dev param =3D { dev, link_type, fill_rtattr, fill_info_data, + cb_data }; + + return netlink_op(NL_NEW, NL_DEV, ¶m); +} + +static inline int dev_delete(const char *dev) +{ + struct nl_dev param =3D { dev, NULL, NULL, NULL, NULL }; + + return netlink_op(NL_DEL, NL_DEV, ¶m); +} + +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_vxlan_header(uint8_t *buf, uint32_t vni) +{ + uint32_t vx_vni =3D htonl((vni << 8) & 0xffffff00); + uint32_t vx_flags =3D htonl(0x08000000); + + memcpy(buf, &vx_flags, 4); + memcpy(buf + 4, &vx_vni, 4); + return VXLAN_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 + + VXLAN_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_HELPERS_H */ --=20 2.49.0 From nobody Fri Jan 9 01:02:32 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 050223148DF for ; Tue, 6 Jan 2026 01:35:46 +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=1767663348; cv=none; b=n9jmjh9hwG8HoIu0Byvl6CwuYExbSGqOAmRhsdUbJw1LUi+tFqTjpVTgsB/8N98wVC+ITsWcmz0k4CvTdlAZNDe/QI1CxmDrZLeenMQv2et7uUcqcvoJQagod9opJRODBYXtCKsaPE4kmGPLs+UY8nk6VuXRnsPvq9WR/yamWEc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767663348; c=relaxed/simple; bh=uRFxgVVwz4SIzsd58nKVZfi6jcW33M/juIg8syiwhW0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PVdOYFPqRfi/fblEhA01klmoTgamQpSGvMnrmPe1hPdnQ02KFt/eqcNEECcNotQo72Vs96T2j3iQSPuL+E2V3+DDaRWsgJ4nADv+kN6mGUMSqH4YJGxRJMig6yr+S0Q3CDMSCi70Qi77lGW5u6JCy9qNjV8r3aqnwb7ntEqM1rY= 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=h4SRsuUW; 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="h4SRsuUW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767663346; 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=g+m7vsuXPa0IEo+bxmHFD7Tx24Sxf6E+9tEfv8GQStw=; b=h4SRsuUWLLSABuHZwilYwh8tMddfTK2nhoQA8uYiSwg7wITgjNUmUsqa6itP0GBBZoPyNj YGlWTVIpMamFNvamtvIpaxfUU3W3TnXezTGP2Yn6RDknLIB31bKsfleG4eEjqC1AhSy/i3 P3T2/a7w694a1zRZ0CqbfyqbUpPWp3M= 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-60-OrcdJtIFNPCWxw4FzyPDMw-1; Mon, 05 Jan 2026 20:35:44 -0500 X-MC-Unique: OrcdJtIFNPCWxw4FzyPDMw-1 X-Mimecast-MFC-AGG-ID: OrcdJtIFNPCWxw4FzyPDMw_1767663343 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 4855E1800365; Tue, 6 Jan 2026 01:35:43 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.66.60.72]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4E8DD180044F; Tue, 6 Jan 2026 01:35: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 v4 3/8] selftest: tun: Refactor tun_delete to use tuntap_helpers Date: Tue, 6 Jan 2026 09:35:16 +0800 Message-ID: <4bcf3c4d30d6338c6f1224620e85e2fa4cf4ca35.1767597114.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.111 Content-Type: text/plain; charset="utf-8" The previous patch introduced common tuntap helpers to simplify tuntap test code. This patch refactors the tun_delete function to use these new helpers. Signed-off-by: Xu Du --- tools/testing/selftests/net/tun.c | 39 ++----------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index 128b0a5327d4..08e760fa5d15 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 dev_delete(dev); } =20 FIXTURE(tun) --=20 2.49.0 From nobody Fri Jan 9 01:02:32 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 AEFD32868B2 for ; Tue, 6 Jan 2026 01:35:55 +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=1767663357; cv=none; b=MKY1cjB6PUxG8zLQ87cB+k5QEgUmPciTBazN1J9K+BL7JaRNZOuYZfruaCxWOfX42to8YF5bGRw1SmRSdieLako6f2TWl3yfVwvDjynB6O9dioGa+OOL/LAt7yDIzD5tyq8d6qmr97X9XHuj7EhpHnHqkSDtDy4YNkEKMph4rYo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767663357; c=relaxed/simple; bh=Zq1Setti4rHsB3+ThqaDAQ01swL11cF1fNxgGM0PHeo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GOXd0zIqZJYHlF/zSD4wBnZVRcSQRCBTcsbYe4qqRVwpgzLVkt2XBQs9ir8ieei1EtaitXjJOwdXQiXu2gwzeZBhTHAd5kjyxqbCkeRDlddIW0MdW7ArVmpUhqOkwlqGSpMPEauGAefEXtXJ5rk0WM8y6j8lK330vgs0SwieEes= 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=YAYFpxkN; 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="YAYFpxkN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767663354; 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=LRz+JUHDJPTQK9o/T4QW/5UA/qmHHVcBln6aFBJ9uxQ=; b=YAYFpxkNTye3gkDRc2SNeUUr+IIDJFNpr0LDg7Jdi7K2LmLGw7WYopJHWeFtNb+AJjsliX LxrrrGu/ZicRcEMJvVuhkH7ZCuejK1KpO588eQB7BoiYQD4cyralFZ/veAWjgbajqI12vV 5lyjE2WzWc41iJdboCD/dmC+qNfqZxI= 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-384-Frkikj4sMBun2xyuv6aUTg-1; Mon, 05 Jan 2026 20:35:49 -0500 X-MC-Unique: Frkikj4sMBun2xyuv6aUTg-1 X-Mimecast-MFC-AGG-ID: Frkikj4sMBun2xyuv6aUTg_1767663348 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 CB8971800365; Tue, 6 Jan 2026 01:35:47 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.66.60.72]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D817018004D4; Tue, 6 Jan 2026 01:35:43 +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 v4 4/8] selftest: tap: Refactor tap test to use tuntap_helpers Date: Tue, 6 Jan 2026 09:35:17 +0800 Message-ID: <02a1295475c7218510e9a808ad8f97bb6005cdfc.1767597114.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.111 Content-Type: text/plain; charset="utf-8" Refactor existing TAP test cases to use the previously introduced tuntap_helpers from tuntap_helpers.h for device setup, packet construction, and cleanup. This reduces code duplication, improves test maintainability, and ensures consistent behavior across test scenarios. Signed-off-by: Xu Du --- v1 -> v2: - Add mactap IFLA_ADDRESS attribute. - Fix incorrect argument order in build_eth and build_ipv4_header. tools/testing/selftests/net/tap.c | 281 +++++------------------------- 1 file changed, 41 insertions(+), 240 deletions(-) diff --git a/tools/testing/selftests/net/tap.c b/tools/testing/selftests/ne= t/tap.c index a0c9418132c8..6793e47d67a7 100644 --- a/tools/testing/selftests/net/tap.c +++ b/tools/testing/selftests/net/tap.c @@ -10,14 +10,13 @@ #include #include #include -#include -#include #include #include #include #include #include #include "kselftest_harness.h" +#include "tuntap_helpers.h" =20 static const char param_dev_tap_name[] =3D "xmacvtap0"; static const char param_dev_dummy_name[] =3D "xdummy0"; @@ -26,161 +25,36 @@ static unsigned char param_hwaddr_dest[] =3D { 0x00, 0xfe, 0x98, 0x94, 0xd2, 0x43 }; =20 -#define MAX_RTNL_PAYLOAD (2048) -#define PKT_DATA 0xCB -#define TEST_PACKET_SZ (sizeof(struct virtio_net_hdr) + ETH_HLEN + ETH_MAX= _MTU) - -static struct rtattr *rtattr_add(struct nlmsghdr *nh, unsigned short type, - unsigned short len) -{ - struct rtattr *rta =3D - (struct rtattr *)((uint8_t *)nh + RTA_ALIGN(nh->nlmsg_len)); - rta->rta_type =3D type; - rta->rta_len =3D RTA_LENGTH(len); - nh->nlmsg_len =3D RTA_ALIGN(nh->nlmsg_len) + RTA_ALIGN(rta->rta_len); - return rta; -} - -static struct rtattr *rtattr_begin(struct nlmsghdr *nh, unsigned short typ= e) -{ - return rtattr_add(nh, type, 0); -} - -static void rtattr_end(struct nlmsghdr *nh, struct rtattr *attr) -{ - uint8_t *end =3D (uint8_t *)nh + nh->nlmsg_len; - - attr->rta_len =3D end - (uint8_t *)attr; -} - -static struct rtattr *rtattr_add_str(struct nlmsghdr *nh, unsigned short t= ype, - const char *s) -{ - unsigned int strsz =3D strlen(s) + 1; - struct rtattr *rta; - - rta =3D rtattr_add(nh, type, strsz); - - memcpy(RTA_DATA(rta), s, strsz); - return rta; -} - -static struct rtattr *rtattr_add_any(struct nlmsghdr *nh, unsigned short t= ype, - const void *arr, size_t len) -{ - struct rtattr *rta =3D rtattr_add(nh, type, len); - - memcpy(RTA_DATA(rta), arr, len); - return rta; -} - -static int dev_create(const char *dev, const char *link_type, - int (*fill_rtattr)(struct nlmsghdr *nh), - int (*fill_info_data)(struct nlmsghdr *nh)) -{ - struct { - struct nlmsghdr nh; - struct ifinfomsg info; - unsigned char data[MAX_RTNL_PAYLOAD]; - } req; - struct rtattr *link_info, *info_data; - int ret, rtnl; - - rtnl =3D socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (rtnl < 0) { - fprintf(stderr, "%s: socket %s\n", __func__, strerror(errno)); - return 1; - } - - memset(&req, 0, sizeof(req)); - req.nh.nlmsg_len =3D NLMSG_LENGTH(sizeof(req.info)); - req.nh.nlmsg_flags =3D NLM_F_REQUEST | NLM_F_CREATE; - req.nh.nlmsg_type =3D RTM_NEWLINK; - - req.info.ifi_family =3D AF_UNSPEC; - req.info.ifi_type =3D 1; - req.info.ifi_index =3D 0; - req.info.ifi_flags =3D IFF_BROADCAST | IFF_UP; - req.info.ifi_change =3D 0xffffffff; - - rtattr_add_str(&req.nh, IFLA_IFNAME, dev); - - if (fill_rtattr) { - ret =3D fill_rtattr(&req.nh); - if (ret) - return ret; - } - - link_info =3D rtattr_begin(&req.nh, IFLA_LINKINFO); - - rtattr_add_str(&req.nh, IFLA_INFO_KIND, link_type); - - if (fill_info_data) { - info_data =3D rtattr_begin(&req.nh, IFLA_INFO_DATA); - ret =3D fill_info_data(&req.nh); - if (ret) - return ret; - rtattr_end(&req.nh, info_data); - } - - rtattr_end(&req.nh, link_info); - - ret =3D send(rtnl, &req, req.nh.nlmsg_len, 0); - if (ret < 0) - fprintf(stderr, "%s: send %s\n", __func__, strerror(errno)); - ret =3D (unsigned int)ret !=3D req.nh.nlmsg_len; - - close(rtnl); - return ret; -} - -static int dev_delete(const char *dev) -{ - struct { - struct nlmsghdr nh; - struct ifinfomsg info; - unsigned char data[MAX_RTNL_PAYLOAD]; - } req; - int ret, rtnl; - - rtnl =3D socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (rtnl < 0) { - fprintf(stderr, "%s: socket %s\n", __func__, strerror(errno)); - return 1; - } - - memset(&req, 0, sizeof(req)); - req.nh.nlmsg_len =3D NLMSG_LENGTH(sizeof(req.info)); - req.nh.nlmsg_flags =3D NLM_F_REQUEST; - req.nh.nlmsg_type =3D RTM_DELLINK; - - req.info.ifi_family =3D AF_UNSPEC; - - rtattr_add_str(&req.nh, IFLA_IFNAME, dev); +static struct in_addr param_ipaddr_src =3D { + __constant_htonl(0xac110002), +}; =20 - ret =3D send(rtnl, &req, req.nh.nlmsg_len, 0); - if (ret < 0) - fprintf(stderr, "%s: send %s\n", __func__, strerror(errno)); +static struct in_addr param_ipaddr_dst =3D { + __constant_htonl(0xac110001), +}; =20 - ret =3D (unsigned int)ret !=3D req.nh.nlmsg_len; +#define UDP_SRC_PORT 22 +#define UDP_DST_PORT 58822 +#define TEST_PACKET_SZ (sizeof(struct virtio_net_hdr) + ETH_HLEN + ETH_MAX= _MTU) =20 - close(rtnl); - return ret; -} +struct mactap_setup_config { + char name[IFNAMSIZ]; + unsigned char hwaddr[ETH_ALEN]; +}; =20 -static int macvtap_fill_rtattr(struct nlmsghdr *nh) +static int macvtap_fill_rtattr(struct nlmsghdr *nh, void *data) { + struct mactap_setup_config *mactap =3D data; int ifindex; =20 - ifindex =3D if_nametoindex(param_dev_dummy_name); + ifindex =3D if_nametoindex(mactap->name); if (ifindex =3D=3D 0) { fprintf(stderr, "%s: ifindex %s\n", __func__, strerror(errno)); return -errno; } =20 rtattr_add_any(nh, IFLA_LINK, &ifindex, sizeof(ifindex)); - rtattr_add_any(nh, IFLA_ADDRESS, param_hwaddr_src, ETH_ALEN); - + rtattr_add_any(nh, IFLA_ADDRESS, mactap->hwaddr, ETH_ALEN); return 0; } =20 @@ -212,91 +86,6 @@ static int opentap(const char *devname) return fd; } =20 -size_t build_eth(uint8_t *buf, uint16_t proto) -{ - struct ethhdr *eth =3D (struct ethhdr *)buf; - - eth->h_proto =3D htons(proto); - memcpy(eth->h_source, param_hwaddr_src, ETH_ALEN); - memcpy(eth->h_dest, param_hwaddr_dest, ETH_ALEN); - - return ETH_HLEN; -} - -static uint32_t add_csum(const uint8_t *buf, int len) -{ - uint32_t sum =3D 0; - uint16_t *sbuf =3D (uint16_t *)buf; - - while (len > 1) { - sum +=3D *sbuf++; - len -=3D 2; - } - - if (len) - sum +=3D *(uint8_t *)sbuf; - - return sum; -} - -static uint16_t finish_ip_csum(uint32_t sum) -{ - uint16_t lo =3D sum & 0xffff; - uint16_t hi =3D sum >> 16; - - return ~(lo + hi); - -} - -static 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 int build_ipv4_header(uint8_t *buf, int payload_len) -{ - 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) + sizeof(struct udphdr) + payload_len); - iph->id =3D htons(1337); - iph->protocol =3D IPPROTO_UDP; - iph->saddr =3D htonl((172 << 24) | (17 << 16) | 2); - iph->daddr =3D htonl((172 << 24) | (17 << 16) | 1); - iph->check =3D build_ip_csum(buf, iph->ihl << 2, 0); - - return iph->ihl << 2; -} - -static int build_udp_packet(uint8_t *buf, int payload_len, bool csum_off) -{ - const int ip4alen =3D sizeof(uint32_t); - struct udphdr *udph =3D (struct udphdr *)buf; - int len =3D sizeof(*udph) + payload_len; - uint32_t sum =3D 0; - - udph->source =3D htons(22); - udph->dest =3D htons(58822); - udph->len =3D htons(len); - - memset(buf + sizeof(struct udphdr), PKT_DATA, payload_len); - - sum =3D add_csum(buf - 2 * ip4alen, 2 * ip4alen); - sum +=3D htons(IPPROTO_UDP) + udph->len; - - if (!csum_off) - sum +=3D add_csum(buf, len); - - udph->check =3D finish_ip_csum(sum); - - return sizeof(*udph) + payload_len; -} - size_t build_test_packet_valid_udp_gso(uint8_t *buf, size_t payload_len) { uint8_t *cur =3D buf; @@ -310,9 +99,12 @@ size_t build_test_packet_valid_udp_gso(uint8_t *buf, si= ze_t payload_len) vh->gso_size =3D ETH_DATA_LEN - sizeof(struct iphdr); cur +=3D sizeof(*vh); =20 - cur +=3D build_eth(cur, ETH_P_IP); - cur +=3D build_ipv4_header(cur, payload_len); - cur +=3D build_udp_packet(cur, payload_len, true); + cur +=3D build_eth(cur, ETH_P_IP, param_hwaddr_src, param_hwaddr_dest); + cur +=3D build_ipv4_header(cur, IPPROTO_UDP, + payload_len + sizeof(struct udphdr), + ¶m_ipaddr_src, ¶m_ipaddr_dst); + cur +=3D build_udp_packet(cur, UDP_SRC_PORT, UDP_DST_PORT, payload_len, + AF_INET, true); =20 return cur - buf; } @@ -326,9 +118,12 @@ size_t build_test_packet_valid_udp_csum(uint8_t *buf, = size_t payload_len) vh->gso_type =3D VIRTIO_NET_HDR_GSO_NONE; cur +=3D sizeof(*vh); =20 - cur +=3D build_eth(cur, ETH_P_IP); - cur +=3D build_ipv4_header(cur, payload_len); - cur +=3D build_udp_packet(cur, payload_len, false); + cur +=3D build_eth(cur, ETH_P_IP, param_hwaddr_src, param_hwaddr_dest); + cur +=3D build_ipv4_header(cur, IPPROTO_UDP, + payload_len + sizeof(struct udphdr), + ¶m_ipaddr_src, ¶m_ipaddr_dst); + cur +=3D build_udp_packet(cur, UDP_SRC_PORT, UDP_DST_PORT, payload_len, + AF_INET, false); =20 return cur - buf; } @@ -345,10 +140,13 @@ size_t build_test_packet_crash_tap_invalid_eth_proto(= uint8_t *buf, vh->gso_size =3D ETH_DATA_LEN - sizeof(struct iphdr); cur +=3D sizeof(*vh); =20 - cur +=3D build_eth(cur, 0); + cur +=3D build_eth(cur, ETH_P_IP, param_hwaddr_src, param_hwaddr_dest); cur +=3D sizeof(struct iphdr) + sizeof(struct udphdr); - cur +=3D build_ipv4_header(cur, payload_len); - cur +=3D build_udp_packet(cur, payload_len, true); + cur +=3D build_ipv4_header(cur, IPPROTO_UDP, + payload_len + sizeof(struct udphdr), + ¶m_ipaddr_src, ¶m_ipaddr_dst); + cur +=3D build_udp_packet(cur, UDP_SRC_PORT, UDP_DST_PORT, payload_len, + AF_INET, true); cur +=3D payload_len; =20 return cur - buf; @@ -362,12 +160,15 @@ FIXTURE(tap) FIXTURE_SETUP(tap) { int ret; + struct mactap_setup_config mactap_config; =20 - ret =3D dev_create(param_dev_dummy_name, "dummy", NULL, NULL); + ret =3D dev_create(param_dev_dummy_name, "dummy", NULL, NULL, NULL); EXPECT_EQ(ret, 0); =20 + strcpy(mactap_config.name, param_dev_dummy_name); + memcpy(mactap_config.hwaddr, param_hwaddr_src, ETH_ALEN); ret =3D dev_create(param_dev_tap_name, "macvtap", macvtap_fill_rtattr, - NULL); + NULL, &mactap_config); EXPECT_EQ(ret, 0); =20 self->fd =3D opentap(param_dev_tap_name); --=20 2.49.0 From nobody Fri Jan 9 01:02:32 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 F389226F293 for ; Tue, 6 Jan 2026 01:35: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=1767663359; cv=none; b=HdUjIxPkmpWei4IjVVoV/FLNBfLZTZNKdbaYrzzxq8oXMxLcnhx5fxE/UJCyacNd4s8gB7Vw18g0tRpV2kArHAdL/KVGXEleJkuXDfn2KPiv6zwZMvGosVM3TPFhnAJnF6TGYPWavAah5gwsJVK1FVsfY+P54PXksFSsK0RA02Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767663359; c=relaxed/simple; bh=tAUYHEl6685CSsQlCLViu12gGje42jR1WClHXv8Kdc0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z9wqoiw8baoy9V2cRs28C+aiHg4xO73kSNKbrbTyCgatv0pRuaAJCOMfwSNXi8jA3kFFKAAms+g+G72M3vysI8WO5GIE0FcpNUI+E7D+FYOzYWhCBSnSOKoOsRfxIixxXQRQZ4UFAevokwLxllrkhyJdDO9UCEVnlen/hiGjQYI= 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=ZTLKNML9; 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="ZTLKNML9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767663356; 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=VpfI5p9F4UpUW06qF6WwOuqLV8kuSpKWxe//r7BovXA=; b=ZTLKNML9H4sB8ZMiYDkmyTHlXHFxeFMriliAstF/yWDFzGWNyRxfYq9EEvB8KZT+fkXtnD U0QZ5aqcbzikIuB2MjWiPbLTTtSgSr1lv+l+EtiTUysJu2jZ7ihQbPEIk59qVXpjqP59M4 mfX/mH0U4niL86VO0fsyuOw9YqB/WTk= 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-571-i598fBnkPpywaZXxDWHu8g-1; Mon, 05 Jan 2026 20:35:53 -0500 X-MC-Unique: i598fBnkPpywaZXxDWHu8g-1 X-Mimecast-MFC-AGG-ID: i598fBnkPpywaZXxDWHu8g_1767663352 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 62B451800657; Tue, 6 Jan 2026 01:35:52 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.66.60.72]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7F01E180049F; Tue, 6 Jan 2026 01:35:48 +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 v4 5/8] selftest: tun: Add helpers for GSO over UDP tunnel Date: Tue, 6 Jan 2026 09:35:18 +0800 Message-ID: <5a95d6bfc481e69307ef805d33b7aa5ab2d99865.1767597114.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.111 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 VXLAN tunnel. This patch introduces a dedicated setup/teardown topology that creates both a VXLAN 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. Note that after adding a new address to the UDP tunnel, we need to wait a bit until the associated route is available. This setup effectively tests the kernel's data path for encapsulated traffic. 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 --- 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 | 439 ++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index 08e760fa5d15..add5e91df6c9 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -15,6 +15,78 @@ #include "kselftest_harness.h" #include "tuntap_helpers.h" =20 +static const char param_dev_vxlan_name[] =3D "vxlan1"; +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_VXLAN_4IN4 0x01 +#define UDP_TUNNEL_VXLAN_6IN4 0x02 +#define UDP_TUNNEL_VXLAN_4IN6 0x04 +#define UDP_TUNNEL_VXLAN_6IN6 0x08 + +#define UDP_TUNNEL_OUTER_IPV4 (UDP_TUNNEL_VXLAN_4IN4 | UDP_TUNNEL_VXLAN_6I= N4) +#define UDP_TUNNEL_INNER_IPV4 (UDP_TUNNEL_VXLAN_4IN4 | UDP_TUNNEL_VXLAN_4I= N6) + +#define TUN_VNET_TNL_SIZE sizeof(struct virtio_net_hdr_v1_hash_tunnel) + +struct vxlan_setup_config { + struct sockaddr_storage local_ip; + struct sockaddr_storage remote_ip; + __be32 vni; + int remote_ifindex; + __be16 dst_port; + unsigned char hwaddr[6]; + uint8_t csum; +}; + static int tun_attach(int fd, char *dev) { struct ifreq ifr; @@ -67,6 +139,198 @@ static int tun_delete(char *dev) return dev_delete(dev); } =20 +static size_t sockaddr_len(int family) +{ + return (family =3D=3D AF_INET) ? sizeof(struct sockaddr_in) : + sizeof(struct sockaddr_in6); +} + +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 int vxlan_fill_rtattr(struct nlmsghdr *nh, void *data) +{ + struct vxlan_setup_config *vxlan =3D data; + + rtattr_add_any(nh, IFLA_ADDRESS, vxlan->hwaddr, ETH_ALEN); + return 0; +} + +static int vxlan_fill_info_data(struct nlmsghdr *nh, void *data) +{ + struct vxlan_setup_config *vxlan =3D data; + + rtattr_add_any(nh, IFLA_VXLAN_LINK, &vxlan->remote_ifindex, + sizeof(vxlan->remote_ifindex)); + rtattr_add_any(nh, IFLA_VXLAN_ID, &vxlan->vni, sizeof(vxlan->vni)); + rtattr_add_any(nh, IFLA_VXLAN_PORT, &vxlan->dst_port, + sizeof(vxlan->dst_port)); + rtattr_add_any(nh, IFLA_VXLAN_UDP_CSUM, &vxlan->csum, + sizeof(vxlan->csum)); + + if (vxlan->remote_ip.ss_family =3D=3D AF_INET) { + struct sockaddr_in *r =3D (struct sockaddr_in *)&vxlan->remote_ip; + struct sockaddr_in *l =3D (struct sockaddr_in *)&vxlan->local_ip; + + rtattr_add_any(nh, IFLA_VXLAN_GROUP, &r->sin_addr, + sizeof(struct in_addr)); + rtattr_add_any(nh, IFLA_VXLAN_LOCAL, &l->sin_addr, + sizeof(struct in_addr)); + } else { + struct sockaddr_in6 *r6 =3D + (struct sockaddr_in6 *)&vxlan->remote_ip; + struct sockaddr_in6 *l6 =3D + (struct sockaddr_in6 *)&vxlan->local_ip; + + rtattr_add_any(nh, IFLA_VXLAN_GROUP6, &r6->sin6_addr, + sizeof(struct in6_addr)); + rtattr_add_any(nh, IFLA_VXLAN_LOCAL6, &l6->sin6_addr, + sizeof(struct in6_addr)); + } + + return 0; +} + +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 int ip_route_check(const char *intf, int family, void *addr) +{ + int len =3D ip_addr_len(family) * 8; + int retries =3D MAX_RETRIES; + + while (retries-- > 0) { + if (ip_route_get(intf, family, addr, len, RTN_LOCAL, + RT_TABLE_LOCAL) > 0) + break; + usleep(TIMEOUT_USEC); + } + + if (retries < 0) + return -1; + + return 0; +} + FIXTURE(tun) { char ifname[IFNAMSIZ]; @@ -129,4 +393,179 @@ 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_VXLAN_4IN4, 4in4); +TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_VXLAN_6IN4, 6in4); +TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_VXLAN_4IN6, 4in6); +TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_VXLAN_6IN6, 6in6); + +static void assign_ifaddr_vars(int family, int is_outer, void **srcip, + void **dstip, void **lladdr, int *prefix) +{ + 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; + } + *lladdr =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; + } + *lladdr =3D param_hwaddr_inner_dst; + } + *prefix =3D (family =3D=3D AF_INET) ? IPPREFIX_LEN : IP6PREFIX_LEN; +} + +static void assign_sockaddr_vars(int family, int is_outer, + struct sockaddr_storage *src, + struct sockaddr_storage *dst) +{ + struct sockaddr_in6 *s6, *d6; + struct sockaddr_in *s4, *d4; + + if (is_outer) { + if (family =3D=3D AF_INET) { + s4 =3D (struct sockaddr_in *)src; + d4 =3D (struct sockaddr_in *)dst; + s4->sin_family =3D AF_INET; + d4->sin_family =3D AF_INET; + s4->sin_addr =3D param_ipaddr4_outer_src; + d4->sin_addr =3D param_ipaddr4_outer_dst; + } else { + s6 =3D (struct sockaddr_in6 *)src; + d6 =3D (struct sockaddr_in6 *)dst; + s6->sin6_family =3D AF_INET6; + d6->sin6_family =3D AF_INET6; + s6->sin6_addr =3D param_ipaddr6_outer_src; + d6->sin6_addr =3D param_ipaddr6_outer_dst; + } + } else { + if (family =3D=3D AF_INET) { + s4 =3D (struct sockaddr_in *)src; + d4 =3D (struct sockaddr_in *)dst; + s4->sin_family =3D AF_INET; + d4->sin_family =3D AF_INET; + s4->sin_addr =3D param_ipaddr4_inner_src; + d4->sin_addr =3D param_ipaddr4_inner_dst; + s4->sin_port =3D htons(UDP_SRC_PORT); + d4->sin_port =3D htons(UDP_DST_PORT); + } else { + s6 =3D (struct sockaddr_in6 *)src; + d6 =3D (struct sockaddr_in6 *)dst; + s6->sin6_family =3D AF_INET6; + d6->sin6_family =3D AF_INET6; + s6->sin6_addr =3D param_ipaddr6_inner_src; + d6->sin6_addr =3D param_ipaddr6_inner_dst; + 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; + struct vxlan_setup_config vxlan; + void *srcip, *dstip, *lladdr; + + 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; + assign_ifaddr_vars(family, 1, &srcip, &dstip, &lladdr, &prefix); + + ret =3D ip_addr_add(self->ifname, family, srcip, prefix); + ASSERT_EQ(ret, 0); + ret =3D ip_neigh_add(self->ifname, family, dstip, lladdr); + ASSERT_EQ(ret, 0); + ret =3D ip_route_check(self->ifname, family, srcip); + ASSERT_EQ(ret, 0); + + assign_sockaddr_vars(family, 1, &ssa, &dsa); + memset(&vxlan, 0, sizeof(vxlan)); + vxlan.vni =3D VN_ID; + vxlan.dst_port =3D htons(VN_PORT); + vxlan.csum =3D 1; + vxlan.remote_ifindex =3D if_nametoindex(self->ifname); + vxlan.local_ip =3D ssa; + vxlan.remote_ip =3D dsa; + memcpy(vxlan.hwaddr, param_hwaddr_inner_src, ETH_ALEN); + + ret =3D dev_create(param_dev_vxlan_name, "vxlan", vxlan_fill_rtattr, + vxlan_fill_info_data, (void *)&vxlan); + ASSERT_EQ(ret, 0); + + family =3D (tunnel_type & UDP_TUNNEL_INNER_IPV4) ? AF_INET : AF_INET6; + assign_ifaddr_vars(family, 0, &srcip, &dstip, &lladdr, &prefix); + + ret =3D ip_addr_add(param_dev_vxlan_name, family, srcip, prefix); + ASSERT_EQ(ret, 0); + ret =3D ip_neigh_add(param_dev_vxlan_name, family, dstip, lladdr); + ASSERT_EQ(ret, 0); + ret =3D ip_route_check(param_dev_vxlan_name, family, srcip); + 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 dev_delete(param_dev_vxlan_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_vxlan_name); + ret =3D system(cmd); + ASSERT_EQ(ret, 0); +} + TEST_HARNESS_MAIN --=20 2.49.0 From nobody Fri Jan 9 01:02:33 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 951CF3161A6 for ; Tue, 6 Jan 2026 01:36:02 +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=1767663365; cv=none; b=qQ0b40bafZ7vetBY6gNKrqvEeJU6Mv5SSY0FdizNdOv+Hq/K9T60vZ3gEDS9ezAIV1txMrgE5cgLa9GBu/VE7mFOFQgMopYljnhpxByuLgT0XVorbeNh1oi5Hf5Eg4xNkgoLawgae7gP4izCXDmSN3Z1LjzOadLDLsos4AOTpas= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767663365; c=relaxed/simple; bh=1Q1RiDIAFkCQpUf2Av+niR0MOVEyfWEtRaYvKQV0ctY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=o6BDXyDtc3VTxuVbE1OJ5J867HTjD2PkNH2nxE4gQ+GxyJ5JZ+f3VfBFqHIL4SLVjAH8vHStxc7kWtnRXF0FgW0PJFfj3e2CRTy/cULCjhsia0n4ZVEiMWU35IH1UzhlDQeOXrNdLbGZBLDXFb9A8umXaJXZc21PxA7iqtg9uu4= 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=LO52RI6T; 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="LO52RI6T" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767663361; 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=oVLA9fiklNQD9VQBuHy22IKHtUeJIXv5AwA+1ApaiNA=; b=LO52RI6Td3gLkpby2V/0IZE9dun01gXG9cjBX4LDpemdjl4eNA16tTaErJH9N6HhGCtd1t kcKd44jmMfn0s3ki4iWAlbjMqTXnU/11mwDp4CN72ZtZHIuuu7LVMcunfNRH3XoZXgqCik RuE2+I5B3AuS/JseEJoKqWDJROj3+90= 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-520-S3W0UybXMLuXhJ4K6z1OrQ-1; Mon, 05 Jan 2026 20:35:58 -0500 X-MC-Unique: S3W0UybXMLuXhJ4K6z1OrQ-1 X-Mimecast-MFC-AGG-ID: S3W0UybXMLuXhJ4K6z1OrQ_1767663357 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 EC554195DE48; Tue, 6 Jan 2026 01:35:56 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.66.60.72]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1555E180044F; Tue, 6 Jan 2026 01:35: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 v4 6/8] selftest: tun: Add test for sending gso packet into tun Date: Tue, 6 Jan 2026 09:35:19 +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.111 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 --- 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 | 151 ++++++++++++++++++++++++++++-- 1 file changed, 142 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/ne= t/tun.c index add5e91df6c9..ececc5ed4909 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -75,8 +75,35 @@ static struct in6_addr param_ipaddr6_inner_src =3D { #define UDP_TUNNEL_OUTER_IPV4 (UDP_TUNNEL_VXLAN_4IN4 | UDP_TUNNEL_VXLAN_6I= N4) #define UDP_TUNNEL_INNER_IPV4 (UDP_TUNNEL_VXLAN_4IN4 | UDP_TUNNEL_VXLAN_4I= N6) =20 +#define UDP_TUNNEL_VXLAN_4IN4_HDRLEN \ + (ETH_HLEN + 2 * sizeof(struct iphdr) + 8 + 2 * sizeof(struct udphdr)) +#define UDP_TUNNEL_VXLAN_6IN6_HDRLEN \ + (ETH_HLEN + 2 * sizeof(struct ipv6hdr) + 8 + 2 * sizeof(struct udphdr)) +#define UDP_TUNNEL_VXLAN_4IN6_HDRLEN \ + (ETH_HLEN + sizeof(struct iphdr) + sizeof(struct ipv6hdr) + 8 + \ + 2 * sizeof(struct udphdr)) +#define UDP_TUNNEL_VXLAN_6IN4_HDRLEN \ + (ETH_HLEN + sizeof(struct ipv6hdr) + sizeof(struct iphdr) + 8 + \ + 2 * sizeof(struct udphdr)) + +#define UDP_TUNNEL_HDRLEN(type) \ + ((type) =3D=3D UDP_TUNNEL_VXLAN_4IN4 ? UDP_TUNNEL_VXLAN_4IN4_HDRLEN : \ + (type) =3D=3D UDP_TUNNEL_VXLAN_6IN4 ? UDP_TUNNEL_VXLAN_6IN4_HDRLEN : \ + (type) =3D=3D UDP_TUNNEL_VXLAN_4IN6 ? UDP_TUNNEL_VXLAN_4IN6_HDRLEN : \ + (type) =3D=3D UDP_TUNNEL_VXLAN_6IN6 ? UDP_TUNNEL_VXLAN_6IN6_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) =20 +#define MAX_VNET_TUNNEL_PACKET_SZ \ + (TUN_VNET_TNL_SIZE + ETH_HLEN + UDP_TUNNEL_VXLAN_6IN6_HDRLEN + \ + ETH_MAX_MTU) + struct vxlan_setup_config { struct sockaddr_storage local_ip; struct sockaddr_storage remote_ip; @@ -402,15 +429,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_VXLAN_4IN4, 4in4); @@ -558,14 +593,112 @@ 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 tunnel_type =3D variant->tunnel_type; + int payload_len =3D variant->data_size; + int gso_size =3D variant->gso_size; + int inner_family, outer_family; + bool is_tap =3D variant->is_tap; + uint8_t *outer_udph =3D NULL; + uint8_t *cur =3D buf; + int len, proto; + + len =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, len, gso_size, + outer_family, inner_family); + + if (is_tap) { + proto =3D outer_family =3D=3D AF_INET ? ETH_P_IP : ETH_P_IPV6; + cur +=3D build_eth(cur, proto, param_hwaddr_outer_dst, + param_hwaddr_outer_src); + len -=3D ETH_HLEN; + } =20 - sprintf(cmd, "ip addr show %s > /dev/null 2>&1", param_dev_vxlan_name); - ret =3D system(cmd); - ASSERT_EQ(ret, 0); + if (outer_family =3D=3D AF_INET) { + len =3D len - sizeof(struct iphdr) + payload_len; + cur +=3D build_ipv4_header(cur, IPPROTO_UDP, len, + ¶m_ipaddr4_outer_dst, + ¶m_ipaddr4_outer_src); + } else { + len =3D len - sizeof(struct ipv6hdr) + payload_len; + cur +=3D build_ipv6_header(cur, IPPROTO_UDP, 0, len, + ¶m_ipaddr6_outer_dst, + ¶m_ipaddr6_outer_src); + } + + outer_udph =3D cur; + len -=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, len); + cur +=3D build_vxlan_header(cur, VN_ID); + cur +=3D build_eth(cur, proto, param_hwaddr_inner_dst, + param_hwaddr_inner_src); + + len =3D sizeof(struct udphdr) + payload_len; + if (inner_family =3D=3D AF_INET) { + cur +=3D build_ipv4_header(cur, IPPROTO_UDP, len, + ¶m_ipaddr4_inner_dst, + ¶m_ipaddr4_inner_src); + } else { + cur +=3D build_ipv6_header(cur, IPPROTO_UDP, 0, len, + ¶m_ipaddr6_inner_dst, + ¶m_ipaddr6_inner_src); + } + + 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 Fri Jan 9 01:02:33 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 1F38C3164D8 for ; Tue, 6 Jan 2026 01:36:06 +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=1767663368; cv=none; b=rUixg57BU4LTaC6sGpLQM3CY1vhTz+1aF21evLZM/OOHfPziOudHrMUkgU2DD+Cpgqp5nU0Pb7eVboP19nB5C/dk17/GIkFtsDd9ig9RZmwvHpKtzhOaPLF43MBeu27t1/B+3nK5ULO5q2RjArICgEYvH62wLafCTpDDCH2LxQY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767663368; c=relaxed/simple; bh=ZZciuq5Tf0LFi6IDgCo6befS/ZmflvQrWFLLhulQW1k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Z+qiQvUqEchB3blrm/7zBjTgoUCNS7aW7S0KJFsAqQnmlwrQYMnbaUiyKYO2tUL+414Geg87GPyCyUf7Lo63E3SO6NIlbV5DdltsRGXwDumjaTclnWiHZ5s3h5OT+ILOR+YVg0xYXWIusN6Kp6K3STyz+bQEenvKxw85VrMH2sI= 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=fe8cmkk0; 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="fe8cmkk0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767663366; 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=8VspJF4Fqgw1lmUXUVAn/WJv4En3EieXQ+eX82sdaQM=; b=fe8cmkk06u4CABUZuPsYFRYfFyUbiMjFmrDNetolyU5ycsmbvk41HRaibl+gtZFeW+zhst WdTyCXFco2sUv7T/1BTc9+feGcoKOYXMqfeGAWBjtHMt0AaafdisZkmShL/AVeOANgxAr+ HTErAbZCIPWJfc3smjTwKDCRHKA0n8c= 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-126-Lol2DfMbPRuN93KAc_N4Zg-1; Mon, 05 Jan 2026 20:36:02 -0500 X-MC-Unique: Lol2DfMbPRuN93KAc_N4Zg-1 X-Mimecast-MFC-AGG-ID: Lol2DfMbPRuN93KAc_N4Zg_1767663361 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 81047195608E; Tue, 6 Jan 2026 01:36:01 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.66.60.72]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9E099180044F; Tue, 6 Jan 2026 01:35:57 +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 v4 7/8] selftest: tun: Add test for receiving gso packet from tun Date: Tue, 6 Jan 2026 09:35:20 +0800 Message-ID: <0641b34b47b4ab0d612f0554c31bab068ee20e71.1767597114.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.111 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 ececc5ed4909..3a90e7c4bc5b 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -358,6 +358,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, 8)) + 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]; @@ -685,6 +795,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]; @@ -701,4 +873,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 Fri Jan 9 01:02:33 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 291A43191D0 for ; Tue, 6 Jan 2026 01:36:13 +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=1767663375; cv=none; b=TodSVFp3AOEFMixHJ1EKmOzCv1lv3Vp6D8Bbfp24f37KfYfydRHM7Pw/y8FSzWWjEgX31QXqbTySF/xh5X6pn/uUwUv36BVOjv9Z07+xWujDByEveS4NKPxgk/P5JHhS0awX5yLaEH6r+TUpSmZtUuDW2e2M/NXll/zJ4UX5uIo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767663375; c=relaxed/simple; bh=uL092dlJuSSJTGC3YnxkXxk3fogYnWG29PGHbQ5sLEE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IWO0NoPyPmiemA3qMgCzT5KGKt26elRVH61Vz1YH/aidwMTZeAHIn29wz3l5oQKovU14yHcw0xLMd7LXzKpRWJUoHdo97VBQUL6wTaTE1ovk0gomw4V+of7rq8vv39vGRjwbFbI6tx9YSGJUxneYp4rsP6wfX2F0oDc3aUGapog= 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=GiOWE3Qt; 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="GiOWE3Qt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767663373; 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=6zfvleqHF+vihvobQ9j/ZQshfIqfQXu1yeAQ6DhfoSA=; b=GiOWE3QtktKI/G3MTM1LFRe763oCTFV+3tSd6cPNbKC+795nECl7PH/WxeNHyG4BNNbJ8Q ufhCLUxftAF/etIW46xPxna947nu2029GZB67RTARLe/QHZQUzUO+3AQZr0J/fCNy2gUIF gWbmkxCUpPjPEaSB5UHHYovLGJnS4ro= 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-180-ci2DhOxrNR6k4G63VYV6WQ-1; Mon, 05 Jan 2026 20:36:07 -0500 X-MC-Unique: ci2DhOxrNR6k4G63VYV6WQ-1 X-Mimecast-MFC-AGG-ID: ci2DhOxrNR6k4G63VYV6WQ_1767663366 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 16EF51800343; Tue, 6 Jan 2026 01:36:06 +0000 (UTC) Received: from xudu-thinkpadx1carbongen9.nay.csb (unknown [10.66.60.72]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 343F3180044F; Tue, 6 Jan 2026 01:36:01 +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 v4 8/8] selftest: tun: Add test data for success and failure paths Date: Tue, 6 Jan 2026 09:35:21 +0800 Message-ID: <89100ed7d241df962e31ec84090c8b99d6fa7206.1767597114.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.111 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 3a90e7c4bc5b..1676996fbdd0 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_VXLAN_4IN6 0x04 #define UDP_TUNNEL_VXLAN_6IN6 0x08 =20 +#define UDP_TUNNEL_MAX_SEGMENTS BIT(7) + #define UDP_TUNNEL_OUTER_IPV4 (UDP_TUNNEL_VXLAN_4IN4 | UDP_TUNNEL_VXLAN_6I= N4) #define UDP_TUNNEL_INNER_IPV4 (UDP_TUNNEL_VXLAN_4IN4 | UDP_TUNNEL_VXLAN_4I= N6) =20 @@ -547,6 +553,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, \ @@ -555,8 +594,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_VXLAN_4IN4, 4in4); TUN_VNET_UDPTNL_VARIANT_ADD(UDP_TUNNEL_VXLAN_6IN4, 6in4); @@ -895,4 +991,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