From: "Emil Tsalapatis" <emil@etsalapatis.com>
To: "Alexei Starovoitov" <alexei.starovoitov@gmail.com>,
<bpf@vger.kernel.org>
Cc: <daniel@iogearbox.net>, <andrii@kernel.org>, <eddyz87@gmail.com>,
<bastien.curutchet@bootlin.com>,
"Alexei Starovoitov" <ast@kernel.org>
Subject: Re: [PATCH bpf-next] selftests/bpf: Wait for links to come up in lwt_ip_encap
Date: Wed, 16 Sep 2026 23:51:41 +0000 [thread overview]
Message-ID: <DLH57NI97844.2XBZUZV378XNE@etsalapatis.com> (raw)
In-Reply-To: <20260916232407.764886-1-alexei.starovoitov@gmail.com>
On Wed Sep 16, 2026 at 11:24 PM UTC, Alexei Starovoitov wrote:
> From: Alexei Starovoitov <ast@kernel.org>
>
> lwt_ip_encap creates three fresh netns with veth pairs across them and
> then immediately pings over IPv6. The peer ends of the first veth pair
> end up with the same ifindex in their respective netns, so linkwatch
> does not treat the carrier-on as urgent and may deliver NETDEV_CHANGE up
> to one second later. Until that happens addrconf considers the link not
> ready: no ff00::/8 multicast route and no link-local address are
> installed, and the neighbour solicitation for the next hop is dropped
> as a no-route packet. The NS retransmit a second later succeeds, but
> ping -W1 has already given up:
>
> check_ping_ok:FAIL:ip netns exec ns-lwt-ip-encap-1-... ping -6 -c 1 -W1 -I veth1 fb04::1 > /dev/null unexpected error: 256 (errno 2)
> lwt_ip_encap:FAIL:ping OK unexpected error: -1 (errno 2)
> #226/1 lwt_ip_encap_ipv4/egress:FAIL
>
> This reproduces reliably when the test is run standalone on an idle
> system where setup completes well within a second. The original shell
> script had a "sleep 1 # reduce flakiness" after setup which was lost in
> the conversion to test_progs.
>
> Instead of sleeping, poll SIOCGIFFLAGS for IFF_RUNNING on all veths at
> the end of setup_network() so traffic is only sent once every link is
> operationally up.
>
> Fixes: f5e288943e2c ("selftests/bpf: Move test_lwt_ip_encap to test_progs")
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
> ---
> .../selftests/bpf/prog_tests/lwt_ip_encap.c | 53 +++++++++++++++++++
> 1 file changed, 53 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/lwt_ip_encap.c b/tools/testing/selftests/bpf/prog_tests/lwt_ip_encap.c
> index 39e8a3b8b6af..5c5560d45c5b 100644
> --- a/tools/testing/selftests/bpf/prog_tests/lwt_ip_encap.c
> +++ b/tools/testing/selftests/bpf/prog_tests/lwt_ip_encap.c
> @@ -1,5 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0-only
> +#include <net/if.h>
> #include <netinet/in.h>
> +#include <sys/ioctl.h>
>
> #include "network_helpers.h"
> #include "test_progs.h"
> @@ -141,6 +143,54 @@ static int set_bottom_addr(const char *ns1, const char *ns2, const char *ns3)
> return 1;
> }
>
> +/*
> + * A veth whose peer sits in another netns with the same ifindex gets its
> + * carrier-on handled as a non-urgent linkwatch event, i.e. up to 1s late.
> + * Until then IPv6 considers the link not ready (no ff00::/8 route, no
> + * link-local address) and silently drops neighbour solicitations, so wait
> + * for all links to be operationally up (IFF_RUNNING) before sending traffic.
> + */
> +static int wait_for_oper_up(const char *ns, const char *dev)
> +{
> + struct nstoken *nstoken;
> + struct ifreq ifr = {};
> + int i, fd, ret = -1;
> +
> + nstoken = open_netns(ns);
> + if (!ASSERT_OK_PTR(nstoken, "open ns"))
> + return -1;
> +
> + fd = socket(AF_INET, SOCK_DGRAM, 0);
> + if (!ASSERT_OK_FD(fd, "socket"))
> + goto out;
> +
> + strncpy(ifr.ifr_name, dev, IFNAMSIZ - 1);
> + for (i = 0; i < 50; i++) {
> + if (!ASSERT_OK(ioctl(fd, SIOCGIFFLAGS, &ifr), "SIOCGIFFLAGS"))
> + break;
> + if (ifr.ifr_flags & IFF_RUNNING) {
> + ret = 0;
> + break;
> + }
> + usleep(100000);
> + }
> + close(fd);
> +out:
> + ASSERT_OK(ret, dev);
> + close_netns(nstoken);
> + return ret;
> +}
> +
> +static int wait_for_links(const char *ns1, const char *ns2, const char *ns3)
> +{
> + if (wait_for_oper_up(ns1, "veth1") || wait_for_oper_up(ns1, "veth5") ||
> + wait_for_oper_up(ns2, "veth2") || wait_for_oper_up(ns2, "veth3") ||
> + wait_for_oper_up(ns2, "veth6") || wait_for_oper_up(ns2, "veth7") ||
> + wait_for_oper_up(ns3, "veth4") || wait_for_oper_up(ns3, "veth8"))
> + return -1;
> + return 0;
> +}
> +
> static int configure_vrf(const char *ns1, const char *ns2)
> {
> if (!ns1 || !ns2)
> @@ -304,6 +354,9 @@ static int setup_network(char *ns1, char *ns2, char *ns3, const char *vrf)
> if (!ASSERT_OK(configure_ns3(ns3), "configure ns3 routes"))
> goto fail;
>
> + if (!ASSERT_OK(wait_for_links(ns1, ns2, ns3), "wait for links"))
> + goto fail;
> +
> /* Link bottom route to the GRE tunnels */
> SYS(fail, "ip -n %s route add %s/32 dev veth5 via %s %s",
> ns1, IP4_ADDR_GRE, IP4_ADDR_6, vrf);
next prev parent reply other threads:[~2026-09-16 23:51 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-16 23:24 [PATCH bpf-next] selftests/bpf: Wait for links to come up in lwt_ip_encap Alexei Starovoitov
2026-09-16 23:51 ` Emil Tsalapatis [this message]
2026-09-17 3:50 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DLH57NI97844.2XBZUZV378XNE@etsalapatis.com \
--to=emil@etsalapatis.com \
--cc=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bastien.curutchet@bootlin.com \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.