The test_tunnel.c file defines small fonctions to easily attach eBPF
programs to tc hooks, either on egress, ingress or both.
Move those helpers in a dedicated file so that other tests can benefit
from it.
Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
---
tools/testing/selftests/bpf/Makefile | 1 +
.../testing/selftests/bpf/prog_tests/test_tunnel.c | 80 +-------------------
tools/testing/selftests/bpf/tc_helpers.c | 87 ++++++++++++++++++++++
tools/testing/selftests/bpf/tc_helpers.h | 9 +++
4 files changed, 98 insertions(+), 79 deletions(-)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index f00587d4ede68ef08419bdd545f0ce8e6c3fcfd2..2f248dab922f57e2c14053cb0bdfbb547efe1292 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -737,6 +737,7 @@ TRUNNER_EXTRA_SOURCES := test_progs.c \
netlink_helpers.c \
jit_disasm_helpers.c \
io_helpers.c \
+ tc_helpers.c \
test_loader.c \
xsk.c \
disasm.c \
diff --git a/tools/testing/selftests/bpf/prog_tests/test_tunnel.c b/tools/testing/selftests/bpf/prog_tests/test_tunnel.c
index bae0e9de277d24c34938de30b42f3418ecb6fba8..9e5577c74d60b02a7d39158967112805111b69d8 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_tunnel.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_tunnel.c
@@ -64,6 +64,7 @@
#include "test_progs.h"
#include "network_helpers.h"
+#include "tc_helpers.h"
#include "test_tunnel_kern.skel.h"
#define IP4_ADDR_VETH0 "172.16.1.100"
@@ -534,85 +535,6 @@ static void ping6_dev1(void)
close_netns(nstoken);
}
-static int attach_tc_prog(int ifindex, int igr_fd, int egr_fd)
-{
- DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .ifindex = ifindex,
- .attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS);
- DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
- .priority = 1, .prog_fd = igr_fd);
- DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
- .priority = 1, .prog_fd = egr_fd);
- int ret;
-
- ret = bpf_tc_hook_create(&hook);
- if (!ASSERT_OK(ret, "create tc hook"))
- return ret;
-
- if (igr_fd >= 0) {
- hook.attach_point = BPF_TC_INGRESS;
- ret = bpf_tc_attach(&hook, &opts1);
- if (!ASSERT_OK(ret, "bpf_tc_attach")) {
- bpf_tc_hook_destroy(&hook);
- return ret;
- }
- }
-
- if (egr_fd >= 0) {
- hook.attach_point = BPF_TC_EGRESS;
- ret = bpf_tc_attach(&hook, &opts2);
- if (!ASSERT_OK(ret, "bpf_tc_attach")) {
- bpf_tc_hook_destroy(&hook);
- return ret;
- }
- }
-
- return 0;
-}
-
-static int generic_attach(const char *dev, int igr_fd, int egr_fd)
-{
- int ifindex;
-
- if (!ASSERT_OK_FD(igr_fd, "check ingress fd"))
- return -1;
- if (!ASSERT_OK_FD(egr_fd, "check egress fd"))
- return -1;
-
- ifindex = if_nametoindex(dev);
- if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
- return -1;
-
- return attach_tc_prog(ifindex, igr_fd, egr_fd);
-}
-
-static int generic_attach_igr(const char *dev, int igr_fd)
-{
- int ifindex;
-
- if (!ASSERT_OK_FD(igr_fd, "check ingress fd"))
- return -1;
-
- ifindex = if_nametoindex(dev);
- if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
- return -1;
-
- return attach_tc_prog(ifindex, igr_fd, -1);
-}
-
-static int generic_attach_egr(const char *dev, int egr_fd)
-{
- int ifindex;
-
- if (!ASSERT_OK_FD(egr_fd, "check egress fd"))
- return -1;
-
- ifindex = if_nametoindex(dev);
- if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
- return -1;
-
- return attach_tc_prog(ifindex, -1, egr_fd);
-}
-
static void test_vxlan_tunnel(void)
{
struct test_tunnel_kern *skel = NULL;
diff --git a/tools/testing/selftests/bpf/tc_helpers.c b/tools/testing/selftests/bpf/tc_helpers.c
new file mode 100644
index 0000000000000000000000000000000000000000..d668e10e3ebad8f8e04862f5c2b3ccd487fe8fa6
--- /dev/null
+++ b/tools/testing/selftests/bpf/tc_helpers.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#define _GNU_SOURCE
+
+#include <net/if.h>
+#include "tc_helpers.h"
+#include "test_progs.h"
+
+static int attach_tc_prog(int ifindex, int igr_fd, int egr_fd)
+{
+ DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .ifindex = ifindex,
+ .attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS);
+ DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
+ .priority = 1, .prog_fd = igr_fd);
+ DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
+ .priority = 1, .prog_fd = egr_fd);
+ int ret;
+
+ ret = bpf_tc_hook_create(&hook);
+ if (!ASSERT_OK(ret, "create tc hook"))
+ return ret;
+
+ if (igr_fd >= 0) {
+ hook.attach_point = BPF_TC_INGRESS;
+ ret = bpf_tc_attach(&hook, &opts1);
+ if (!ASSERT_OK(ret, "bpf_tc_attach")) {
+ bpf_tc_hook_destroy(&hook);
+ return ret;
+ }
+ }
+
+ if (egr_fd >= 0) {
+ hook.attach_point = BPF_TC_EGRESS;
+ ret = bpf_tc_attach(&hook, &opts2);
+ if (!ASSERT_OK(ret, "bpf_tc_attach")) {
+ bpf_tc_hook_destroy(&hook);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+int generic_attach(const char *dev, int igr_fd, int egr_fd)
+{
+ int ifindex;
+
+ if (!ASSERT_OK_FD(igr_fd, "check ingress fd"))
+ return -1;
+ if (!ASSERT_OK_FD(egr_fd, "check egress fd"))
+ return -1;
+
+ ifindex = if_nametoindex(dev);
+ if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
+ return -1;
+
+ return attach_tc_prog(ifindex, igr_fd, egr_fd);
+}
+
+int generic_attach_igr(const char *dev, int igr_fd)
+{
+ int ifindex;
+
+ if (!ASSERT_OK_FD(igr_fd, "check ingress fd"))
+ return -1;
+
+ ifindex = if_nametoindex(dev);
+ if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
+ return -1;
+
+ return attach_tc_prog(ifindex, igr_fd, -1);
+}
+
+int generic_attach_egr(const char *dev, int egr_fd)
+{
+ int ifindex;
+
+ if (!ASSERT_OK_FD(egr_fd, "check egress fd"))
+ return -1;
+
+ ifindex = if_nametoindex(dev);
+ if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
+ return -1;
+
+ return attach_tc_prog(ifindex, -1, egr_fd);
+}
+
+
diff --git a/tools/testing/selftests/bpf/tc_helpers.h b/tools/testing/selftests/bpf/tc_helpers.h
new file mode 100644
index 0000000000000000000000000000000000000000..d31abe33f9d80dadd8f829bcf9a68cfd744c3b99
--- /dev/null
+++ b/tools/testing/selftests/bpf/tc_helpers.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __TC_HELPERS_H
+#define __TC_HELPERS_H
+
+
+int generic_attach(const char *dev, int igr_fd, int egr_fd);
+int generic_attach_igr(const char *dev, int igr_fd);
+int generic_attach_egr(const char *dev, int egr_fd);
+#endif
--
2.51.0
On 10/17/25 7:29 AM, Alexis Lothoré (eBPF Foundation) wrote:
> diff --git a/tools/testing/selftests/bpf/tc_helpers.c b/tools/testing/selftests/bpf/tc_helpers.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..d668e10e3ebad8f8e04862f5c2b3ccd487fe8fa6
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/tc_helpers.c
> @@ -0,0 +1,87 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +#define _GNU_SOURCE
> +
> +#include <net/if.h>
> +#include "tc_helpers.h"
> +#include "test_progs.h"
> +
> +static int attach_tc_prog(int ifindex, int igr_fd, int egr_fd)
This one looks good but change it to "int tc_prog_attach(const char
*dev, int ingress_fd, int egress_fd)". Remove static. Take "const char
*dev" as the arg. Add it to network_helpers.[ch] instead of creating a
new source file.
> +{
> + DECLARE_LIBBPF_OPTS(bpf_tc_hook, hook, .ifindex = ifindex,
> + .attach_point = BPF_TC_INGRESS | BPF_TC_EGRESS);
> + DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts1, .handle = 1,
> + .priority = 1, .prog_fd = igr_fd);
> + DECLARE_LIBBPF_OPTS(bpf_tc_opts, opts2, .handle = 1,
> + .priority = 1, .prog_fd = egr_fd);
> + int ret;
> +
> + ret = bpf_tc_hook_create(&hook);
> + if (!ASSERT_OK(ret, "create tc hook"))
> + return ret;
> +
> + if (igr_fd >= 0) {
> + hook.attach_point = BPF_TC_INGRESS;
> + ret = bpf_tc_attach(&hook, &opts1);
> + if (!ASSERT_OK(ret, "bpf_tc_attach")) {
> + bpf_tc_hook_destroy(&hook);
> + return ret;
> + }
> + }
> +
> + if (egr_fd >= 0) {
> + hook.attach_point = BPF_TC_EGRESS;
> + ret = bpf_tc_attach(&hook, &opts2);
> + if (!ASSERT_OK(ret, "bpf_tc_attach")) {
> + bpf_tc_hook_destroy(&hook);
> + return ret;
> + }
> + }
> +
> + return 0;
> +}
> +
> +int generic_attach(const char *dev, int igr_fd, int egr_fd)
> +{
> + int ifindex;
> +
> + if (!ASSERT_OK_FD(igr_fd, "check ingress fd"))
> + return -1;
> + if (!ASSERT_OK_FD(egr_fd, "check egress fd"))
> + return -1;
> +
> + ifindex = if_nametoindex(dev);
> + if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
> + return -1;
> +
> + return attach_tc_prog(ifindex, igr_fd, egr_fd);
> +}
> +
> +int generic_attach_igr(const char *dev, int igr_fd)
> +{
> + int ifindex;
> +
> + if (!ASSERT_OK_FD(igr_fd, "check ingress fd"))
> + return -1;
> +
> + ifindex = if_nametoindex(dev);
> + if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
> + return -1;
> +
> + return attach_tc_prog(ifindex, igr_fd, -1);
> +}
> +
> +int generic_attach_egr(const char *dev, int egr_fd)
> +{
> + int ifindex;
> +
> + if (!ASSERT_OK_FD(egr_fd, "check egress fd"))
> + return -1;
> +
> + ifindex = if_nametoindex(dev);
> + if (!ASSERT_NEQ(ifindex, 0, "get ifindex"))
> + return -1;
> +
> + return attach_tc_prog(ifindex, -1, egr_fd);
> +}
These three generic_attach_* is a bit overkill for network_helpers.c.
Change test_tunnel.c to directly use tc_prog_attach().
> +
> +
> diff --git a/tools/testing/selftests/bpf/tc_helpers.h b/tools/testing/selftests/bpf/tc_helpers.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..d31abe33f9d80dadd8f829bcf9a68cfd744c3b99
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/tc_helpers.h
This new file is not needed also. Use the network_helpers.h.
On Sat Oct 18, 2025 at 1:26 AM CEST, Martin KaFai Lau wrote: > > > On 10/17/25 7:29 AM, Alexis Lothoré (eBPF Foundation) wrote: >> diff --git a/tools/testing/selftests/bpf/tc_helpers.c b/tools/testing/selftests/bpf/tc_helpers.c >> new file mode 100644 >> index 0000000000000000000000000000000000000000..d668e10e3ebad8f8e04862f5c2b3ccd487fe8fa6 >> --- /dev/null >> +++ b/tools/testing/selftests/bpf/tc_helpers.c >> @@ -0,0 +1,87 @@ >> +// SPDX-License-Identifier: GPL-2.0-only >> +#define _GNU_SOURCE >> + >> +#include <net/if.h> >> +#include "tc_helpers.h" >> +#include "test_progs.h" >> + >> +static int attach_tc_prog(int ifindex, int igr_fd, int egr_fd) > > This one looks good but change it to "int tc_prog_attach(const char > *dev, int ingress_fd, int egress_fd)". Remove static. Take "const char > *dev" as the arg. Add it to network_helpers.[ch] instead of creating a > new source file. Nice, thanks for the hint, I missed this header Alexis -- Alexis Lothoré, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
© 2016 - 2026 Red Hat, Inc.