Re: [PATCH] selftests/bpf: tc_tunnel - validate decap tunnel state without false-pass gaps
"Hudson, Nick" <[email protected]>
| Newsgroups | org.kernel.vger.linux-kselftest,org.kernel.vger.bpf,org.kernel.vger.linux-kernel,org.kernel.vger.netdev |
|---|---|
| Message-ID | <[email protected]> |
> On Aug 19, 2026, at 10:34 PM, Emil Tsalapatis <[email protected]> wrote: > > !-------------------------------------------------------------------| > This Message Is From an External Sender > This message came from outside your organization. > |-------------------------------------------------------------------! > > On Tue Aug 18, 2026 at 8:03 AM EDT, Nick Hudson wrote: >> This follow-up tightens the selftest to guard against false passes in >> GSO decap validation. >> >> It validates the expected post-decap state for both GSO and non-GSO >> packets: expected tunnel gso_type bits must be cleared and >> skb->encapsulation must match the remaining tunnel state. >> >> It also adds explicit assertions that the decap validation path was >> executed, including the large-send phase for GSO-marked subtests, and >> asserts that the large-send marker is reset after the send. >> >> This keeps the tc_tunnel decap checks meaningful and avoids false-pass >> regressions without over-constraining behavior across tunnel modes. >> >> Signed-off-by: Nick Hudson <[email protected]> >> --- >> .../selftests/bpf/prog_tests/test_tc_tunnel.c | 33 +++++++++++++++---- >> .../selftests/bpf/progs/test_tc_tunnel.c | 19 +++++++++++ >> 2 files changed, 46 insertions(+), 6 deletions(-) >> >> diff --git a/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c b/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c >> index 67ba27d69347..08d7d90f7772 100644 >> --- a/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c >> +++ b/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c >> @@ -206,7 +206,7 @@ static void disconnect_client_from_server(struct subtest_cfg *cfg, >> free(conn); >> } >> >> -static int send_and_test_data(struct subtest_cfg *cfg) >> +static int send_and_test_data(struct subtest_cfg *cfg, struct test_tc_tunnel *skel) >> { >> struct connection *conn; >> int err, res = -1; >> @@ -215,6 +215,7 @@ static int send_and_test_data(struct subtest_cfg *cfg) >> if (!ASSERT_OK_PTR(conn, "connect to server")) >> return -1; >> >> + skel->bss->decap_expect_large_send = 0; >> err = send(conn->client_fd, tx_buffer, DEFAULT_TEST_DATA_SIZE, 0); >> if (!ASSERT_EQ(err, DEFAULT_TEST_DATA_SIZE, "send data from client")) >> goto end; >> @@ -226,14 +227,17 @@ static int send_and_test_data(struct subtest_cfg *cfg) >> goto end; >> } >> >> + skel->bss->decap_expect_large_send = 1; >> err = send(conn->client_fd, tx_buffer, GSO_TEST_DATA_SIZE, 0); >> if (!ASSERT_EQ(err, GSO_TEST_DATA_SIZE, "send (large) data from client")) >> goto end; >> if (check_server_rx_data(cfg, conn, DEFAULT_TEST_DATA_SIZE)) >> goto end; >> + skel->bss->decap_expect_large_send = 0; >> >> res = 0; >> end: >> + skel->bss->decap_expect_large_send = 0; >> disconnect_client_from_server(cfg, conn); >> return res; >> } >> @@ -374,10 +378,15 @@ static int configure_ebpf_decapsulation(struct subtest_cfg *cfg) >> return ret; >> } >> >> -static void run_test(struct subtest_cfg *cfg) >> +static void run_test(struct subtest_cfg *cfg, struct test_tc_tunnel *skel) >> { >> struct nstoken *nstoken; >> >> + skel->bss->decap_validation_seen = 0; >> + skel->bss->decap_gso_validation_seen = 0; > > Sashiko points out correctly that gso_validation_seen is never checked. > Can we assert it with the others? > Yeah, I’m fixing this and removing decap_{large_send_validation_seen,expect_large_send} > The CI bot's point on the other hand doesn't matter that much imo, the > assert for the config variable is good in case we ever add any other > subtests. Which point, sorry? > > pw-bot: cr > >> + skel->bss->decap_large_send_validation_seen = 0; >> + skel->bss->decap_expect_large_send = 0; >> + >> if (!ASSERT_OK(run_server(cfg), "run server")) >> return; >> >> @@ -386,7 +395,7 @@ static void run_test(struct subtest_cfg *cfg) >> goto fail; >> >> /* Basic communication must work */ >> - if (!ASSERT_OK(send_and_test_data(cfg), "connect without any encap")) >> + if (!ASSERT_OK(send_and_test_data(cfg, skel), "connect without any encap")) >> goto fail; >> >> /* Attach encapsulation program to client */ >> @@ -398,7 +407,7 @@ static void run_test(struct subtest_cfg *cfg) >> if (!ASSERT_OK(configure_kernel_decapsulation(cfg), >> "configure kernel decapsulation")) >> goto fail; >> - if (!ASSERT_OK(send_and_test_data(cfg), >> + if (!ASSERT_OK(send_and_test_data(cfg, skel), >> "connect with encap prog and kern decap")) >> goto fail; >> } >> @@ -406,7 +415,18 @@ static void run_test(struct subtest_cfg *cfg) >> /* Replace kernel decapsulation with BPF decapsulation, test must pass */ >> if (!ASSERT_OK(configure_ebpf_decapsulation(cfg), "configure ebpf decapsulation")) >> goto fail; >> - ASSERT_OK(send_and_test_data(cfg), "connect with encap and decap progs"); >> + if (!ASSERT_OK(send_and_test_data(cfg, skel), "connect with encap and decap progs")) >> + goto fail; >> + if (!ASSERT_NEQ(skel->bss->decap_validation_seen, 0, >> + "decap validation executed")) >> + goto fail; >> + if (!ASSERT_EQ(skel->bss->decap_expect_large_send, 0, >> + "decap large-send marker reset")) >> + goto fail; >> + if (cfg->test_gso) { >> + ASSERT_NEQ(skel->bss->decap_large_send_validation_seen, 0, >> + "decap validation executed for large send"); >> + } >> >> fail: >> close_netns(nstoken); >> @@ -438,6 +458,7 @@ static int setup(void) >> SYS(fail_close_ns_client, "ip link add %s type veth peer name %s", >> "veth1 mtu 1500 netns " CLIENT_NS " address " MAC_ADDR_VETH1, >> "veth2 mtu 1500 netns " SERVER_NS " address " MAC_ADDR_VETH2); >> + SYS(fail_close_ns_client, "ethtool -K veth1 tso off"); >> SYS(fail_close_ns_client, "ip link set veth1 up"); >> nstoken_server = open_netns(SERVER_NS); >> if (!ASSERT_OK_PTR(nstoken_server, "open server ns")) >> @@ -701,7 +722,7 @@ void test_tc_tunnel(void) >> if (ret < 0 || !test__start_subtest(cfg->name)) >> continue; >> if (subtest_setup(skel, cfg) == 0) >> - run_test(cfg); >> + run_test(cfg, skel); >> subtest_cleanup(cfg); >> } >> cleanup(); >> diff --git a/tools/testing/selftests/bpf/progs/test_tc_tunnel.c b/tools/testing/selftests/bpf/progs/test_tc_tunnel.c >> index 853bca962910..e9bd1c9781f7 100644 >> --- a/tools/testing/selftests/bpf/progs/test_tc_tunnel.c >> +++ b/tools/testing/selftests/bpf/progs/test_tc_tunnel.c >> @@ -16,6 +16,11 @@ static const int cfg_port = 8000; >> >> static const int cfg_udp_src = 20000; >> >> +__u64 decap_validation_seen; >> +__u64 decap_gso_validation_seen; >> +__u64 decap_large_send_validation_seen; >> +__u32 decap_expect_large_send; >> + >> #define ETH_P_MPLS_UC 0x8847 >> #define ETH_P_TEB 0x6558 >> >> @@ -690,7 +695,21 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto, >> >> kskb = bpf_cast_to_kern_ctx(skb); >> shinfo = bpf_core_cast(kskb->head + kskb->end, struct skb_shared_info); >> + >> + if (flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK | >> + BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) >> + decap_validation_seen++; >> + >> + if ((flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK | >> + BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) && >> + decap_expect_large_send) >> + decap_large_send_validation_seen++; >> + >> if (shinfo->gso_size) { >> + if (flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK | >> + BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) >> + decap_gso_validation_seen++; >> + >> if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) && >> (shinfo->gso_type & SKB_GSO_UDP_TUNNEL_MASK)) >> return TC_ACT_SHOT; >
smime.p7s
(application/pkcs7-signature, 3 KB) - not displayed