* [PATCH bpf-next v2] selftests/bpf: Time tc_edt from its first packet with data
@ 2026-10-19 6:35 Qiliang Yuan
2026-10-20 8:48 ` Alexis Lothoré
0 siblings, 1 reply; 2+ messages in thread
From: Qiliang Yuan @ 2026-10-19 6:35 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Ihor Solodrai, Shuah Khan, Alexis Lothoré (eBPF Foundation)
Cc: bpf, linux-kselftest, linux-kernel, Qiliang Yuan
tc_edt sends 1MB over a TCP connection that a BPF program shapes with
EDT, and checks that the rate it measures is within 2% of the target
rate. The transfer takes about 200ms, so the margin is about 4ms.
The measurement starts before send_recv_data(), which first creates the
sender thread and accepts the connection. On a KASAN kernel, x86_64 VM
with 32 vCPUs, that takes 0.7ms when idle and up to 4.7ms with all
CPUs busy, while the BPF program spreads the data over 200.08ms in the
median. The test also fails without test_progs -j where everything runs
slower, e.g. on s390x and with ASAN in BPF CI.
Have the BPF program note when the first packet with data goes out, and
start the measurement there.
tc_edt run 100 times on the same VM, idle and with 32 busy loops in the
background, before and after this patch:
before after
idle 0 of 100 failed 0 of 100 failed
busy loops 3 of 100 failed 0 of 100 failed
Fixes: b0f82e7ab6fb ("selftests/bpf: integrate test_tc_edt into test_progs")
Signed-off-by: Qiliang Yuan <odys.yuan@gmail.com>
---
V1 -> V2:
- Start the measurement at the first packet with data instead of running
tc_edt serially, as it also fails without -j (Alexei)
- Add before/after data
v1: https://lore.kernel.org/r/20261009-selftests-bpf-tc-edt-serial-v1-1-f72e045f2465@gmail.com
---
tools/testing/selftests/bpf/prog_tests/test_tc_edt.c | 13 ++++++++++---
tools/testing/selftests/bpf/progs/test_tc_edt.c | 13 ++++++++++---
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/test_tc_edt.c b/tools/testing/selftests/bpf/prog_tests/test_tc_edt.c
index 462512fb191f1..1391978a3e309 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_tc_edt.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_tc_edt.c
@@ -90,7 +90,7 @@ static void cleanup(void)
remove_netns(SERVER_NS);
}
-static void run_test(void)
+static void run_test(struct test_tc_edt *skel)
{
int server_fd, client_fd, err;
double rate_mbps, rate_error;
@@ -113,12 +113,19 @@ static void run_test(void)
if (!ASSERT_OK_FD(client_fd, "connect client"))
return;
- ts_start = get_time_ns();
err = send_recv_data(server_fd, client_fd, TX_BYTES_COUNT);
ts_end = get_time_ns();
close_netns(nstoken);
ASSERT_OK(err, "send_recv_data");
+ /*
+ * Start from the first packet with data rather than before
+ * send_recv_data(), which also sets up the sender.
+ */
+ ts_start = skel->bss->tx_start_ns;
+ if (!ASSERT_GT(ts_start, 0, "tx_start_ns"))
+ return;
+
rate_mbps = TX_BYTES_COUNT / ((ts_end - ts_start) / 1000.0);
rate_error =
fabs((rate_mbps - TARGET_RATE_MBPS) * 100.0 / TARGET_RATE_MBPS);
@@ -138,7 +145,7 @@ void test_tc_edt(void)
if (!ASSERT_OK(setup(skel), "global setup"))
return;
- run_test();
+ run_test(skel);
cleanup();
test_tc_edt__destroy(skel);
diff --git a/tools/testing/selftests/bpf/progs/test_tc_edt.c b/tools/testing/selftests/bpf/progs/test_tc_edt.c
index 4f6f03122d61d..69f4b16acbef6 100644
--- a/tools/testing/selftests/bpf/progs/test_tc_edt.c
+++ b/tools/testing/selftests/bpf/progs/test_tc_edt.c
@@ -24,6 +24,7 @@ struct {
} flow_map SEC(".maps");
__uint64_t target_rate;
+__uint64_t tx_start_ns;
static inline int throttle_flow(struct __sk_buff *skb)
{
@@ -62,7 +63,8 @@ static inline int throttle_flow(struct __sk_buff *skb)
return TC_ACT_OK;
}
-static inline int handle_tcp(struct __sk_buff *skb, struct tcphdr *tcp)
+static inline int handle_tcp(struct __sk_buff *skb, struct tcphdr *tcp,
+ uint32_t hdr_len)
{
void *data_end = (void *)(long)skb->data_end;
@@ -70,8 +72,12 @@ static inline int handle_tcp(struct __sk_buff *skb, struct tcphdr *tcp)
if ((void *)(tcp + 1) > data_end)
return TC_ACT_SHOT;
- if (tcp->source == bpf_htons(9000))
+ if (tcp->source == bpf_htons(9000)) {
+ /* Note when the first packet with data goes out */
+ if (!tx_start_ns && skb->len > hdr_len + tcp->doff * 4)
+ tx_start_ns = bpf_ktime_get_ns();
return throttle_flow(skb);
+ }
return TC_ACT_OK;
}
@@ -94,7 +100,8 @@ static inline int handle_ipv4(struct __sk_buff *skb)
return TC_ACT_SHOT;
if (iph->protocol == IPPROTO_TCP)
- return handle_tcp(skb, (struct tcphdr *)(((void *)iph) + ihl));
+ return handle_tcp(skb, (struct tcphdr *)(((void *)iph) + ihl),
+ sizeof(struct ethhdr) + ihl);
return TC_ACT_OK;
}
---
base-commit: e1d84a37cba984388988d2f1ddc84561413f0db2
change-id: 20261009-selftests-bpf-tc-edt-serial-9c65af71f845
Best regards,
--
Qiliang Yuan <odys.yuan@gmail.com>
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH bpf-next v2] selftests/bpf: Time tc_edt from its first packet with data
2026-10-19 6:35 [PATCH bpf-next v2] selftests/bpf: Time tc_edt from its first packet with data Qiliang Yuan
@ 2026-10-20 8:48 ` Alexis Lothoré
0 siblings, 0 replies; 2+ messages in thread
From: Alexis Lothoré @ 2026-10-20 8:48 UTC (permalink / raw)
To: Qiliang Yuan, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan,
Alexis Lothoré (eBPF Foundation)
Cc: bpf, linux-kselftest, linux-kernel
Hi Qiliang,
On Mon Oct 19, 2026 at 8:35 AM CEST, Qiliang Yuan wrote:
> tc_edt sends 1MB over a TCP connection that a BPF program shapes with
> EDT, and checks that the rate it measures is within 2% of the target
> rate. The transfer takes about 200ms, so the margin is about 4ms.
>
> The measurement starts before send_recv_data(), which first creates the
> sender thread and accepts the connection. On a KASAN kernel, x86_64 VM
> with 32 vCPUs, that takes 0.7ms when idle and up to 4.7ms with all
> CPUs busy, while the BPF program spreads the data over 200.08ms in the
> median. The test also fails without test_progs -j where everything runs
> slower, e.g. on s390x and with ASAN in BPF CI.
>
> Have the BPF program note when the first packet with data goes out, and
> start the measurement there.
>
> tc_edt run 100 times on the same VM, idle and with 32 busy loops in the
> background, before and after this patch:
>
> before after
> idle 0 of 100 failed 0 of 100 failed
> busy loops 3 of 100 failed 0 of 100 failed
>
> Fixes: b0f82e7ab6fb ("selftests/bpf: integrate test_tc_edt into test_progs")
> Signed-off-by: Qiliang Yuan <odys.yuan@gmail.com>
I still suspect that it will not solve the flakyness for every setup and
that it probably deserves a margin increase anyway, but the updated
measurement looks like a reasonable improvement to me.
Reviewed-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
--
Alexis Lothoré, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-20 8:48 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-19 6:35 [PATCH bpf-next v2] selftests/bpf: Time tc_edt from its first packet with data Qiliang Yuan
2026-10-20 8:48 ` Alexis Lothoré
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®