* [PATCH net] selftests/net: run tun tests in a dedicated network namespace
@ 2026-09-05 8:53 Edoardo Canepa
2026-09-10 0:56 ` netdev-bot+sashiko
0 siblings, 1 reply; 3+ messages in thread
From: Edoardo Canepa @ 2026-09-05 8:53 UTC (permalink / raw)
To: netdev
Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Shuah Khan, Xu Du, Po-Hsu Lin, linux-kselftest,
linux-kernel
The tun_vnet_udptnl fixture creates a fresh tap device and installs an
IPv6 outer neighbor entry as NUD_PERMANENT before sending packets. On
systems where systemd-udevd is running and a systemd .link file sets
MACAddressPolicy=persistent
(the default shipped by systemd in 99-default.link, so this is what
most systemd-based hosts inherit), systemd-udevd's net_setup_link
builtin asynchronously sends an RTM_SETLINK to reassign the freshly
created tap device's MAC to a machine-persistent value. When that
netlink message races the test's ip_neigh_add() call, the address
change kicks the following path:
do_setlink
-> netif_set_mac_address
-> call_netdevice_notifiers_info
-> ndisc_netdev_event
-> neigh_changeaddr
-> neigh_flush_dev(tbl, dev, /* skip_perm = */ false)
which flushes every neighbor entry on the interface, including the one
the test just installed as NUD_PERMANENT. The subsequent packet
therefore hits __neigh_create(), triggers NDISC, and times out with:
tun.c:947:send_gso_packet:Expected ret (0) == variant->data_size (1423)
tun.c:948:send_gso_packet:Expected r_num_mss (0) == variant->r_num_mss (2)
The failure is non-deterministic and can affect both directions. Both
recv_gso_packet and send_gso_packet variants can hit it; the failure
reproduces on a plain systemd-based VM with no containers, and is
triggered whenever the udev worker's RTM_SETLINK lands after the test
has installed its neighbor entry.
Fix by calling unshare(CLONE_NEWNET) once, from main(), before invoking
the kselftest_harness. All tap and geneve devices are then created in
a namespace that systemd-udevd (running in the init netns) does not
watch, so its RTM_SETLINK never fires against them. This mirrors the
approach used by selftests/net/ipsec.c, which also unshares from main()
rather than per-fixture; it keeps the harness output ordering intact
and avoids paying the netns-creation cost on every variant.
Verified on a plain systemd-based VM running the affected kernel:
1000 repeated invocations of
tun_vnet_udptnl.4in6_nogsosz_1byte.recv_gso_packet produce 7 failures
without the fix and zero failures with it. A 20-iteration run of the
full test binary produces 4 failed runs (across different variants,
all send_gso_packet) without the fix and zero failed runs with it.
Reported-by: Po-Hsu Lin <po-hsu.lin@canonical.com>
Closes: https://bugs.launchpad.net/bugs/2158217
Fixes: 24e59f26eef2 ("selftest: tun: Add helpers for GSO over UDP tunnel")
Assisted-by: LLM
Signed-off-by: Edoardo Canepa <edoardo.canepa@canonical.com>
---
tools/testing/selftests/net/tun.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c
index abe488bac50b..7f118ba3ae0b 100644
--- a/tools/testing/selftests/net/tun.c
+++ b/tools/testing/selftests/net/tun.c
@@ -4,6 +4,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -985,4 +986,12 @@ 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
+int main(int argc, char **argv)
+{
+ if (unshare(CLONE_NEWNET) < 0) {
+ perror("unshare(CLONE_NEWNET)");
+ return 1;
+ }
+
+ return test_harness_run(argc, argv);
+}
base-commit: 80dd7e754b3aa9637a0758ad93fa209f9650ec48
--
2.53.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net] selftests/net: run tun tests in a dedicated network namespace
2026-09-05 8:53 [PATCH net] selftests/net: run tun tests in a dedicated network namespace Edoardo Canepa
@ 2026-09-10 0:56 ` netdev-bot+sashiko
2026-09-11 0:28 ` Jakub Kicinski
0 siblings, 1 reply; 3+ messages in thread
From: netdev-bot+sashiko @ 2026-09-10 0:56 UTC (permalink / raw)
To: edoardo.canepa
Cc: netdev, davem, edumazet, kuba, pabeni, horms, shuah, xudu,
po-hsu.lin, linux-kselftest, linux-kernel
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 0 · Medium: 1 · Low: 0
- [Medium] In the newly added main() in tools/testing/selftests/net/tun.c
(lines 989-997), any failure of unshare(CLONE_NEWNET) is treated as a…
--
selftests/net: run tun tests in a dedicated network namespace
The patch replaces TEST_HARNESS_MAIN in tools/testing/selftests/net/tun.c
with a hand-written main() that calls unshare(CLONE_NEWNET) before running
the harness, so tap and geneve devices are created outside the init netns
that systemd-udevd watches.
Closes: https://bugs.launchpad.net/bugs/2158217
> diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c
> index abe488bac50bb..7f118ba3ae0bb 100644
> --- a/tools/testing/selftests/net/tun.c
> +++ b/tools/testing/selftests/net/tun.c
[ ... ]
> @@ -985,4 +986,12 @@ 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
> +int main(int argc, char **argv)
> +{
> + if (unshare(CLONE_NEWNET) < 0) {
> + perror("unshare(CLONE_NEWNET)");
> + return 1;
> + }
> +
> + return test_harness_run(argc, argv);
> +}
[Severity: Medium]
Should an unshare() failure here be reported as FAIL for the whole binary?
Returning 1 from main() is KSFT_FAIL, and since test_harness_run() is never
reached, ksft_print_header() and ksft_set_plan() never run either, so the
binary emits no "TAP version 13" line, no "1..N" plan and no per-test result
lines at all. Would a runner then be able to tell "network namespaces
unavailable" apart from a real tun/tap regression?
There appear to be two reachable ways to land in this path without any
actual tun/tap problem:
CONFIG_NET_NS=n, where the stub in include/net/net_namespace.h rejects the
flag outright:
static inline struct net *copy_net_ns(u64 flags,
struct user_namespace *user_ns, struct net *old_net)
{
if (flags & CLONE_NEWNET)
return ERR_PTR(-EINVAL);
return old_net;
}
and running with CAP_NET_ADMIN but without CAP_SYS_ADMIN (for example a
container started with --cap-add=NET_ADMIN), where unshare(CLONE_NEWNET)
fails with EPERM.
In both cases the pre-existing tun fixture is aborted too, even though
FIXTURE_SETUP(tun) only does:
self->fd = tun_alloc(self->ifname);
ASSERT_GE(self->fd, 0);
which needs /dev/net/tun and CAP_NET_ADMIN, but no network namespace. Was
losing that coverage intended?
Would returning KSFT_SKIP (4) fit the convention better here? The precedent
named in the changelog, "This mirrors the approach used by
selftests/net/ipsec.c, which also unshares from main()", handles the same
failure differently in selftests/net/ipsec.c:main():
if (init_namespaces())
ksft_exit_skip("Failed to create namespaces\n");
Other harness call sites do the same, for example
selftests/arm64/gcs/gcs-locking.c:main():
ksft_print_msg("GCS was enabled, test unsupported\n");
return KSFT_SKIP;
and selftests/net/icmp_rfc4884.c keeps the unshare inside
FIXTURE_SETUP(rfc4884) so the failure stays attributable inside the TAP
stream:
ret = unshare(CLONE_NEWNET);
ASSERT_EQ(ret, 0) {
TH_LOG("unshare(CLONE_NEWNET) failed: %s", strerror(errno));
}
One more question on the changelog: the patch adds CAP_SYS_ADMIN in the
current user namespace and CONFIG_NET_NS as new prerequisites for the entire
binary. Should that be mentioned in the commit message?
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260905085318.3416670-1-edoardo.canepa%40canonical.com
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH net] selftests/net: run tun tests in a dedicated network namespace
2026-09-10 0:56 ` netdev-bot+sashiko
@ 2026-09-11 0:28 ` Jakub Kicinski
0 siblings, 0 replies; 3+ messages in thread
From: Jakub Kicinski @ 2026-09-11 0:28 UTC (permalink / raw)
To: netdev-bot+sashiko
Cc: edoardo.canepa, netdev, davem, edumazet, pabeni, horms, shuah,
xudu, po-hsu.lin, linux-kselftest, linux-kernel
On Thu, 10 Sep 2026 00:56:15 +0000 netdev-bot+sashiko@kernel.org wrote:
> - [Medium] In the newly added main() in tools/testing/selftests/net/tun.c
> (lines 989-997), any failure of unshare(CLONE_NEWNET) is treated as a…
Seems fair, at a glance it seems like we just need to add this code to
two setup functions instead of creating a real main().
--
pw-bot: cr
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-11 0:28 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-05 8:53 [PATCH net] selftests/net: run tun tests in a dedicated network namespace Edoardo Canepa
2026-09-10 0:56 ` netdev-bot+sashiko
2026-09-11 0:28 ` Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®