Linux Kernel Selftest development
 help / color / mirror / Atom feed
From: "Alexis Lothoré" <alexis.lothore@bootlin.com>
To: "Ihor Solodrai" <ihor.solodrai@linux.dev>,
	"Alexis Lothoré" <alexis.lothore@bootlin.com>,
	"Jiayuan Chen" <jiayuan.chen@linux.dev>,
	"Alexei Starovoitov" <ast@kernel.org>,
	"Daniel Borkmann" <daniel@iogearbox.net>,
	"Andrii Nakryiko" <andrii@kernel.org>,
	"Eduard Zingerman" <eddyz87@gmail.com>,
	"Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
	"Martin KaFai Lau" <martin.lau@linux.dev>,
	"Song Liu" <song@kernel.org>,
	"Yonghong Song" <yonghong.song@linux.dev>,
	"Jiri Olsa" <jolsa@kernel.org>,
	"Emil Tsalapatis" <emil@etsalapatis.com>,
	"Shuah Khan" <shuah@kernel.org>
Cc: <ebpf@linuxfoundation.org>,
	"Bastien Curutchet" <bastien.curutchet@bootlin.com>,
	"Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
	<bpf@vger.kernel.org>, <linux-kselftest@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH bpf v3 1/2] selftests/bpf: keep polling connection that is still in progress
Date: Thu, 13 Aug 2026 09:29:14 +0200	[thread overview]
Message-ID: <DKNN0WMD9XW8.MCJAMGS5NPYR@bootlin.com> (raw)
In-Reply-To: <d92da576-4930-4b10-b8bd-ea1158ec08bc@linux.dev>

Hi Ihor,
thanks for the extensive investigation

On Wed Aug 12, 2026 at 8:46 PM CEST, Ihor Solodrai wrote:
> On 8/11/26 9:25 AM, Alexis Lothoré wrote:
>> On Tue Aug 11, 2026 at 5:05 PM CEST, Jiayuan Chen wrote:
>>>
>>> On 8/11/26 10:26 PM, Alexis Lothoré (eBPF Foundation) wrote:

[...]

>>> So IIUC this patch doesn't actually fix the flakiness: connect() on a 
>>> blocking socket only
>>> returns EINPROGRESS after SO_SNDTIMEO is fully consumed, so remaining_ms 
>>> is always ~0 and the
>>> overall time budget is still 1s, same as before. Am I missing something?
>> 
>> Hmmm, I have been assuming that this EINPROGRESS could be returned
>> _before_ the configured timeout depletion, but I may have been mistaken,
>> it indeed happens only  the socket is O_NONBLOCK, which is not the case
>> here. So indeed, it does not fix anything for the blocking case, as the
>> budget is already depleted when getting EINPROGRESS...
>> 
>> I added this budget mechanism to follow up on Ihor's suggestion, so I
>> either got it wrong, or it can not work.
>
> Hi Alexis,
>
> Looks like my suggestion was bad, sorry. Jiayuan is right. I didn't
> realize what -EINPROGRESS actually means here.
>
> See __inet_stream_connect() in net/ipv4/af_inet.c:697
>
> 	err = -EINPROGRESS;
> 	...
> 	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
> 	...
> 	if (!timeo || !inet_wait_for_connect(sk, timeo, writebias))
> 		goto out;
>
> -EINPROGRESS is a default that reaches userspace only when the wait
> expires. Every other exit sets a different error code. So on a
> blocking socket -EINPROGRESS does not mean "connection started", it
> means "waited the whole budget, gave up in SYN_SENT". On a nonblocking
> socket it means the opposite, and man 2 connect seems to only document
> the nonblocking case.
>
>> An intermediate solution could
>> be to exceptionally raise the budget by 1s when getting EINPROGRESS.
>
> I believe you're right that the flakiness can be addressed with bigger
> timeout, which is why v2 fixed it for you. But +1s may not be enough.
>
> IIUC the way the helpers are written cause -EINPROGRESS instead of
> -ETIMEDOUT. If SO_SNDTIMEO is not set before connect(), the kernel
> reports plain ETIMEDOUT, but it is set in settimeo().
>
> I vibe-coded a userspace repro: loopback listener with a full accept
> queue drained at t=1500ms, so the handshake completes at ~2040ms.
> Caller asks for timeout_ms=1000, like tc_tunnel:
>
>   mainline (blocking)                     budget 1000   FAIL at 1016ms
>   v3 (blocking + leftover poll)           budget 1000   FAIL at 1015ms # my suggestion
>   O_NONBLOCK + poll(timeout_ms)           budget 1000   FAIL at 1001ms # Jiayuan's suggestion
>   O_NONBLOCK + poll(3500)                 budget 3500   OK   at 2031ms
>   blocking, SO_SNDTIMEO raised to 3500    budget 3500   OK   at 2040ms
>   v2 (blocking 1000 + fixed 3000 grace)   budget 4046   OK   at 2067ms
>
> Everything that gave the handshake more than ~2040ms passed. Blocking
> vs nonblocking makes no difference, poll() vs no poll() makes no
> difference. We just need to increase the budget for connect().

Ok, so indeed the poll() loop complexifies the connection helpers
without much gain.

> I don't think swtiching to O_NONBLOCK makes sense. Apparently, it was
> nonblocking in the past, see 99126abec5e5 ("bpf: selftests: A few
> improvements to network_helpers.c")
>
> So I think we can introduce a separate connect() budget, similar to
> your v2. And then use opts->timeout_ms for everything after. Something
> like this:
>
> 	#define CONNECT_TIMEOUT_MS	5000
>
> 	static int connect_timeout_ms(const struct network_helper_opts *opts)
> 	{
> 		/* don't shorten what the caller asked for: tc_redirect
> 		 * and xdp_synproxy pass 10000
> 		 */
> 		return MAX(opts->timeout_ms, CONNECT_TIMEOUT_MS);
> 	}
>
> and in connect_to_addr():
>
> 	fd = client_socket(addr->ss_family, type, opts);
> 	if (fd < 0) {
> 		log_err("Failed to create client socket");
> 		return -1;
> 	}
>
> 	/* SO_SNDTIMEO is a ceiling, not a sleep: a wider handshake
> 	 * budget costs nothing on connections that succeed.
> 	 */
> 	if (settimeo(fd, connect_timeout_ms(opts)))
> 		goto close;
>
> 	if (connect(fd, (const struct sockaddr *)addr, addrlen)) {
> 		log_err("Failed to connect to server");
> 		goto close;
> 	}
>
> 	if (settimeo(fd, opts->timeout_ms))	/* data I/O budget */
> 		goto close;
>
> 	return fd;
>
> close:
> 	save_errno_close(fd);
> 	return -1;
>
> This is simpler than poll() and retry loops.

Ok, I'll give it a try with this simpler connect-only-extended-budget,
without the poll loop

> An entirely different alternative that Eduard brought up in an
> off-list discussion, is to drop all the timeout machinery from
> network_helpers.c altogether, and rely solely on the test_progs
> watchdog to kill the subtest processes: d9d4d127e813 ("selftests/bpf:
> watchdog timer for test_progs")
>
> I am not convinced it's a good idea, because I don't know what will
> happen with all the tc_* tests if there is no connection timeouts. If
> you're interested, you could try it and see.

Hmmm, I'm not very familiar with this mechanism, but aside from the
potential issues you are mentioning, wouldn't it make us loose a bit of
info here, when the watchdog kicks the runner out ? We may know from the
stacktrace that the subtest was in connect(), but we would loose any
formal error/errno on connection timeout I guess, and I am not sure how
confident we can get about any watchdog kick being a connect timeout.

>> That potentially brings back part of the issues he has been mentioning
>> with selftests duration possibly increasing by a non negligeable amount,
>> but maybe 1s is a better compromise, compared to my initial 3s proposal
>> ?
>> 




-- 
Alexis Lothoré, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


  reply	other threads:[~2026-08-13  7:29 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-11 14:26 [PATCH bpf v3 0/2] selftest/bpf: make test_tc_tunnel and test_tc_edt more robust to CI load Alexis Lothoré (eBPF Foundation)
2026-08-11 14:26 ` [PATCH bpf v3 1/2] selftests/bpf: keep polling connection that is still in progress Alexis Lothoré (eBPF Foundation)
2026-08-11 15:05   ` Jiayuan Chen
2026-08-11 16:25     ` Alexis Lothoré
2026-08-12 18:46       ` Ihor Solodrai
2026-08-13  7:29         ` Alexis Lothoré [this message]
2026-08-13 16:17           ` Ihor Solodrai
2026-08-11 15:30   ` bot+bpf-ci
2026-08-11 16:01     ` Alexis Lothoré
2026-08-11 14:26 ` [PATCH bpf v3 2/2] selftests/bpf: add connect timeout to test_tc_edt Alexis Lothoré (eBPF Foundation)

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=DKNN0WMD9XW8.MCJAMGS5NPYR@bootlin.com \
    --to=alexis.lothore@bootlin.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bastien.curutchet@bootlin.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=ebpf@linuxfoundation.org \
    --cc=eddyz87@gmail.com \
    --cc=emil@etsalapatis.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=jiayuan.chen@linux.dev \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=shuah@kernel.org \
    --cc=song@kernel.org \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox