[PATCH net-next 06/14] selftests/bpf: Test skb_ext survival across veth and GRE
From: Jakub Sitnicki <jakub@cloudflare.com>
Date: 2026-08-14 08:14:35
Also in:
bpf
Subsystem:
bpf [general] (safe dynamic programs and tools), bpf [selftests] (test runners & infrastructure), kernel selftest framework, the rest, xdp (express data path) · Maintainers:
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Shuah Khan, Shuah Khan, Linus Torvalds, David S. Miller, Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend
Write skb_ext at TC egress and read it back at TC ingress after the packet crosses device boundaries: - survives_veth: veth forwarding between two netns - survives_gre: GRE encap/decap between two gretap endpoints over loopback in a single netns Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> --- .../bpf/prog_tests/xdp_context_test_run.c | 154 +++++++++++++++++++++ 1 file changed, 154 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
index 58b793cf14e5..de6030302536 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c@@ -783,6 +783,156 @@ static void test_mirred_clone_ext_cow(struct test_xdp_meta *skel) bpf_link__destroy(tp_link); } +/* Test if skb_ext survives veth cross-netns forward */ +static void test_skb_ext_scrub_veth(struct test_xdp_meta *skel) +{ + LIBBPF_OPTS(bpf_tc_hook, tx_hook, .attach_point = BPF_TC_EGRESS); + LIBBPF_OPTS(bpf_tc_opts, tx_opts, .handle = 1, .priority = 1); + LIBBPF_OPTS(bpf_tc_hook, rx_hook, .attach_point = BPF_TC_INGRESS); + LIBBPF_OPTS(bpf_tc_opts, rx_opts, .handle = 1, .priority = 1); + struct netns_obj *rx_ns = NULL, *tx_ns = NULL; + struct nstoken *nstoken = NULL; + int rx_ifindex, tx_ifindex; + int ret; + + tx_ns = netns_new(TX_NETNS, false); + if (!ASSERT_OK_PTR(tx_ns, "create tx_ns")) + return; + + rx_ns = netns_new(RX_NETNS, false); + if (!ASSERT_OK_PTR(rx_ns, "create rx_ns")) + goto close; + + SYS(close, "ip link add " RX_NAME " netns " RX_NETNS + " type veth peer name " TX_NAME " netns " TX_NETNS); + + /* Setup RX side: TC ingress reader */ + nstoken = open_netns(RX_NETNS); + if (!ASSERT_OK_PTR(nstoken, "setns rx_ns")) + goto close; + + SYS(close, "ip link set dev " RX_NAME " up"); + + rx_ifindex = if_nametoindex(RX_NAME); + if (!ASSERT_GE(rx_ifindex, 0, "if_nametoindex rx")) + goto close; + + rx_hook.ifindex = rx_ifindex; + ret = bpf_tc_hook_create(&rx_hook); + if (!ASSERT_OK(ret, "bpf_tc_hook_create rx")) + goto close; + + rx_opts.prog_fd = bpf_program__fd(skel->progs.tc_skb_ext_read); + ret = bpf_tc_attach(&rx_hook, &rx_opts); + if (!ASSERT_OK(ret, "bpf_tc_attach rx")) + goto close; + + close_netns(nstoken); + + /* Setup TX side: TC egress writer */ + nstoken = open_netns(TX_NETNS); + if (!ASSERT_OK_PTR(nstoken, "setns tx_ns")) + goto close; + + SYS(close, "ip link set dev " TX_NAME " up"); + + tx_ifindex = if_nametoindex(TX_NAME); + if (!ASSERT_GE(tx_ifindex, 0, "if_nametoindex tx")) + goto close; + + tx_hook.ifindex = tx_ifindex; + ret = bpf_tc_hook_create(&tx_hook); + if (!ASSERT_OK(ret, "bpf_tc_hook_create tx")) + goto close; + + tx_opts.prog_fd = bpf_program__fd(skel->progs.tc_skb_ext_write); + ret = bpf_tc_attach(&tx_hook, &tx_opts); + if (!ASSERT_OK(ret, "bpf_tc_attach tx")) + goto close; + + skel->bss->test_pass = false; + + ret = send_test_packet(tx_ifindex); + if (!ASSERT_OK(ret, "send_test_packet")) + goto close; + + ASSERT_TRUE(skel->bss->test_pass, "test_pass"); + +close: + close_netns(nstoken); + netns_free(rx_ns); + netns_free(tx_ns); +} + +/* Test if skb_ext survives GRE tunnel encap+decap */ +static void test_skb_ext_scrub_gre(struct test_xdp_meta *skel) +{ + LIBBPF_OPTS(bpf_tc_hook, tx_hook, .attach_point = BPF_TC_EGRESS); + LIBBPF_OPTS(bpf_tc_opts, tx_opts, .handle = 1, .priority = 1); + LIBBPF_OPTS(bpf_tc_hook, rx_hook, .attach_point = BPF_TC_INGRESS); + LIBBPF_OPTS(bpf_tc_opts, rx_opts, .handle = 1, .priority = 1); + struct netns_obj *ns = NULL; + int tx_ifindex; + int rx_ifindex; + int ret; + + skel->bss->test_pass = false; + + ns = netns_new("gre_test", true); + if (!ASSERT_OK_PTR(ns, "netns_new")) + return; + + /* Setup: gre_tx -> lo -> gre_rx */ + SYS(close, "ip link set lo up"); + SYS(close, "ip link add gre_tx type gretap" + " local 127.0.0.1 remote 127.0.0.2"); + SYS(close, "ip link set gre_tx up"); + SYS(close, "ip addr add 127.0.0.2/8 dev lo"); + SYS(close, "ip link add gre_rx type gretap" + " local 127.0.0.2 remote 127.0.0.1"); + SYS(close, "ip link set gre_rx up"); + + /* Write skb_ext on TC egress on GRE tx */ + tx_ifindex = if_nametoindex("gre_tx"); + if (!ASSERT_GE(tx_ifindex, 0, "tx_ifindex")) + goto close; + + tx_hook.ifindex = tx_ifindex; + ret = bpf_tc_hook_create(&tx_hook); + if (!ASSERT_OK(ret, "tx_hook_create")) + goto close; + + tx_opts.prog_fd = bpf_program__fd(skel->progs.tc_skb_ext_write); + ret = bpf_tc_attach(&tx_hook, &tx_opts); + if (!ASSERT_OK(ret, "tx_attach")) + goto close; + + /* Read skb_ext on TC ingress on GRE rx */ + rx_ifindex = if_nametoindex("gre_rx"); + if (!ASSERT_GE(rx_ifindex, 0, "rx_ifindex")) + goto close; + + rx_hook.ifindex = rx_ifindex; + ret = bpf_tc_hook_create(&rx_hook); + if (!ASSERT_OK(ret, "rx_hook_create")) + goto close; + + rx_opts.prog_fd = bpf_program__fd(skel->progs.tc_skb_ext_read); + ret = bpf_tc_attach(&rx_hook, &rx_opts); + if (!ASSERT_OK(ret, "rx_attach")) + goto close; + + /* Then use send_test_packet on GRE tx */ + ret = send_test_packet(tx_ifindex); + if (!ASSERT_OK(ret, "send_test_packet")) + goto close; + + ASSERT_TRUE(skel->bss->test_pass, "test_pass"); + +close: + netns_free(ns); +} + void test_skb_ext_basic(void) { struct test_xdp_meta *skel = NULL;
@@ -835,6 +985,10 @@ void test_skb_ext_basic(void) test_mirred_clone_ext(skel, skel->progs.tc_skb_ext_read); if (test__start_subtest("clone_ext_cow")) test_mirred_clone_ext_cow(skel); + if (test__start_subtest("survives_veth")) + test_skb_ext_scrub_veth(skel); + if (test__start_subtest("survives_gre")) + test_skb_ext_scrub_gre(skel); test_xdp_meta__destroy(skel); }
--
2.43.0