[PATCH] selftests/bpf: tc_tunnel - validate decap tunnel state without false-pass gaps

Nick Hudson <[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]>
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;
+	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;
-- 
2.34.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.