mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
selftests/bpf: Time tc_edt from its first packet with data
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: b0f82e7ab6 ("selftests/bpf: integrate test_tc_edt into test_progs")
Signed-off-by: Qiliang Yuan <odys.yuan@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Reviewed-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
Link: https://patch.msgid.link/20261019-selftests-bpf-tc-edt-serial-v2-1-41c3813e7916@gmail.com
This commit is contained in:
parent
cce4e11eea
commit
b116ac6087
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user