Hi all,
Both tc_links.c and tc_opts.c do their tests on the loopback interface. It prevents from parallelizing their executions.
Add a new behaviour to the test_progs framework that creates and opens a new network namespace to run a test in it. This is done automatically on tests whose names start with 'ns_'.
One test already has a name starting with 'ns_', so PATCH 1 renames it to avoid conflicts. PATCH 2 introduces the test_progs 'feature'. PATCH 3 & 4 convert some tests to use these dedicated namespaces.
Signed-off-by: Bastien Curutchet (eBPF Foundation) bastien.curutchet@bootlin.com --- Changes in v2: - Handle the netns creation / opening directly in test_progs - Link to v1: https://lore.kernel.org/bpf/e3838d93-04e3-4e96-af53-e9e63550d7ba@bootlin.com
--- Bastien Curutchet (eBPF Foundation) (4): selftests/bpf: ns_current_pid_tgid: Rename the test function selftests/bpf: Optionally open a dedicated namespace to run test in it selftests/bpf: tc_links/tc_opts: Unserialize tests selftests/bpf: ns_current_pid_tgid: Use test_progs's ns_ feature
.../selftests/bpf/prog_tests/ns_current_pid_tgid.c | 47 ++++++++-------------- tools/testing/selftests/bpf/prog_tests/tc_links.c | 28 ++++++------- tools/testing/selftests/bpf/prog_tests/tc_opts.c | 40 +++++++++--------- tools/testing/selftests/bpf/test_progs.c | 12 ++++++ 4 files changed, 63 insertions(+), 64 deletions(-) --- base-commit: a814b9be27fb3c3f49343aee4b015b76f5875558 change-id: 20250219-b4-tc_links-b6d5bf709e1f
Best regards,
Next patch will add a new feature to test_prog to run tests in a dedicated namespace if the test name starts with 'ns_'. Here the test name already starts with 'ns_' and creates some namespaces which would conflict with the new feature.
Rename the test to avoid this conflict.
Signed-off-by: Bastien Curutchet (eBPF Foundation) bastien.curutchet@bootlin.com --- tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c b/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c index 761ce24bce38fd97d29ab9faf513d47459299e4d..78020ece6a29c3bec4600f4fd6fe88fdbd2a768b 100644 --- a/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +++ b/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c @@ -220,7 +220,7 @@ static void test_in_netns(int (*fn)(void *), void *arg) }
/* TODO: use a different tracepoint */ -void serial_test_ns_current_pid_tgid(void) +void serial_test_current_pid_tgid(void) { if (test__start_subtest("root_ns_tp")) test_current_pid_tgid_tp(NULL);
Some tests are serialized to prevent interference with others.
Open a dedicated network namespace when a test name starts with 'ns_' to allow more test parallelization. Use the test name as namespace name to avoid conflict between namespaces.
Signed-off-by: Bastien Curutchet (eBPF Foundation) bastien.curutchet@bootlin.com --- tools/testing/selftests/bpf/test_progs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index c9e745d49493e594b55d79ac26061b0466f9a039..0cb759632225d27ad8df7bc478bf1adb5651bf33 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -1365,10 +1365,19 @@ static int recv_message(int sock, struct msg *msg) return ret; }
+static bool ns_is_needed(const char *test_name) +{ + if (strlen(test_name) < 3) + return false; + + return !strncmp(test_name, "ns_", 3); +} + static void run_one_test(int test_num) { struct prog_test_def *test = &prog_test_defs[test_num]; struct test_state *state = &test_states[test_num]; + struct netns_obj *ns = NULL;
env.test = test; env.test_state = state; @@ -1376,10 +1385,13 @@ static void run_one_test(int test_num) stdio_hijack(&state->log_buf, &state->log_cnt);
watchdog_start(); + if (ns_is_needed(test->test_name)) + ns = netns_new(test->test_name, true); if (test->run_test) test->run_test(); else if (test->run_serial_test) test->run_serial_test(); + netns_free(ns); watchdog_stop();
/* ensure last sub-test is finalized properly */
Tests are serialized because they all use the loopback interface.
Replace the 'serial_test_' prefixes with 'test_ns_' to benefit from the new test_prog feature which creates a dedicated namespace for each test, allowing them to run in parallel.
Signed-off-by: Bastien Curutchet (eBPF Foundation) bastien.curutchet@bootlin.com --- tools/testing/selftests/bpf/prog_tests/tc_links.c | 28 ++++++++-------- tools/testing/selftests/bpf/prog_tests/tc_opts.c | 40 +++++++++++------------ 2 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/tc_links.c b/tools/testing/selftests/bpf/prog_tests/tc_links.c index 1af9ec1149aab6ca5ef6986fc16a650162266966..2186a24e7d8a948840532f9bb6263f68985583c8 100644 --- a/tools/testing/selftests/bpf/prog_tests/tc_links.c +++ b/tools/testing/selftests/bpf/prog_tests/tc_links.c @@ -13,7 +13,7 @@ #include "netlink_helpers.h" #include "tc_helpers.h"
-void serial_test_tc_links_basic(void) +void test_ns_tc_links_basic(void) { LIBBPF_OPTS(bpf_prog_query_opts, optq); LIBBPF_OPTS(bpf_tcx_opts, optl); @@ -260,7 +260,7 @@ static void test_tc_links_before_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_links_before(void) +void test_ns_tc_links_before(void) { test_tc_links_before_target(BPF_TCX_INGRESS); test_tc_links_before_target(BPF_TCX_EGRESS); @@ -414,7 +414,7 @@ static void test_tc_links_after_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_links_after(void) +void test_ns_tc_links_after(void) { test_tc_links_after_target(BPF_TCX_INGRESS); test_tc_links_after_target(BPF_TCX_EGRESS); @@ -514,7 +514,7 @@ static void test_tc_links_revision_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_links_revision(void) +void test_ns_tc_links_revision(void) { test_tc_links_revision_target(BPF_TCX_INGRESS); test_tc_links_revision_target(BPF_TCX_EGRESS); @@ -618,7 +618,7 @@ static void test_tc_chain_classic(int target, bool chain_tc_old) assert_mprog_count(target, 0); }
-void serial_test_tc_links_chain_classic(void) +void test_ns_tc_links_chain_classic(void) { test_tc_chain_classic(BPF_TCX_INGRESS, false); test_tc_chain_classic(BPF_TCX_EGRESS, false); @@ -846,7 +846,7 @@ static void test_tc_links_replace_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_links_replace(void) +void test_ns_tc_links_replace(void) { test_tc_links_replace_target(BPF_TCX_INGRESS); test_tc_links_replace_target(BPF_TCX_EGRESS); @@ -1158,7 +1158,7 @@ static void test_tc_links_invalid_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_links_invalid(void) +void test_ns_tc_links_invalid(void) { test_tc_links_invalid_target(BPF_TCX_INGRESS); test_tc_links_invalid_target(BPF_TCX_EGRESS); @@ -1314,7 +1314,7 @@ static void test_tc_links_prepend_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_links_prepend(void) +void test_ns_tc_links_prepend(void) { test_tc_links_prepend_target(BPF_TCX_INGRESS); test_tc_links_prepend_target(BPF_TCX_EGRESS); @@ -1470,7 +1470,7 @@ static void test_tc_links_append_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_links_append(void) +void test_ns_tc_links_append(void) { test_tc_links_append_target(BPF_TCX_INGRESS); test_tc_links_append_target(BPF_TCX_EGRESS); @@ -1568,7 +1568,7 @@ static void test_tc_links_dev_cleanup_target(int target) ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); }
-void serial_test_tc_links_dev_cleanup(void) +void test_ns_tc_links_dev_cleanup(void) { test_tc_links_dev_cleanup_target(BPF_TCX_INGRESS); test_tc_links_dev_cleanup_target(BPF_TCX_EGRESS); @@ -1672,7 +1672,7 @@ static void test_tc_chain_mixed(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_links_chain_mixed(void) +void test_ns_tc_links_chain_mixed(void) { test_tc_chain_mixed(BPF_TCX_INGRESS); test_tc_chain_mixed(BPF_TCX_EGRESS); @@ -1782,7 +1782,7 @@ static void test_tc_links_ingress(int target, bool chain_tc_old, assert_mprog_count(target, 0); }
-void serial_test_tc_links_ingress(void) +void test_ns_tc_links_ingress(void) { test_tc_links_ingress(BPF_TCX_INGRESS, true, true); test_tc_links_ingress(BPF_TCX_INGRESS, true, false); @@ -1823,7 +1823,7 @@ static int qdisc_replace(int ifindex, const char *kind, bool block) return err; }
-void serial_test_tc_links_dev_chain0(void) +void test_ns_tc_links_dev_chain0(void) { int err, ifindex;
@@ -1955,7 +1955,7 @@ static void test_tc_links_dev_mixed(int target) ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); }
-void serial_test_tc_links_dev_mixed(void) +void test_ns_tc_links_dev_mixed(void) { test_tc_links_dev_mixed(BPF_TCX_INGRESS); test_tc_links_dev_mixed(BPF_TCX_EGRESS); diff --git a/tools/testing/selftests/bpf/prog_tests/tc_opts.c b/tools/testing/selftests/bpf/prog_tests/tc_opts.c index f77f604389aabbc7afb71ac003dc952cba82c460..dd7a138d8c3dcef0db4d9e6831951db5306c0c04 100644 --- a/tools/testing/selftests/bpf/prog_tests/tc_opts.c +++ b/tools/testing/selftests/bpf/prog_tests/tc_opts.c @@ -10,7 +10,7 @@ #include "test_tc_link.skel.h" #include "tc_helpers.h"
-void serial_test_tc_opts_basic(void) +void test_ns_tc_opts_basic(void) { LIBBPF_OPTS(bpf_prog_attach_opts, opta); LIBBPF_OPTS(bpf_prog_detach_opts, optd); @@ -254,7 +254,7 @@ static void test_tc_opts_before_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_before(void) +void test_ns_tc_opts_before(void) { test_tc_opts_before_target(BPF_TCX_INGRESS); test_tc_opts_before_target(BPF_TCX_EGRESS); @@ -445,7 +445,7 @@ static void test_tc_opts_after_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_after(void) +void test_ns_tc_opts_after(void) { test_tc_opts_after_target(BPF_TCX_INGRESS); test_tc_opts_after_target(BPF_TCX_EGRESS); @@ -554,7 +554,7 @@ static void test_tc_opts_revision_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_revision(void) +void test_ns_tc_opts_revision(void) { test_tc_opts_revision_target(BPF_TCX_INGRESS); test_tc_opts_revision_target(BPF_TCX_EGRESS); @@ -655,7 +655,7 @@ static void test_tc_chain_classic(int target, bool chain_tc_old) assert_mprog_count(target, 0); }
-void serial_test_tc_opts_chain_classic(void) +void test_ns_tc_opts_chain_classic(void) { test_tc_chain_classic(BPF_TCX_INGRESS, false); test_tc_chain_classic(BPF_TCX_EGRESS, false); @@ -864,7 +864,7 @@ static void test_tc_opts_replace_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_replace(void) +void test_ns_tc_opts_replace(void) { test_tc_opts_replace_target(BPF_TCX_INGRESS); test_tc_opts_replace_target(BPF_TCX_EGRESS); @@ -1017,7 +1017,7 @@ static void test_tc_opts_invalid_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_invalid(void) +void test_ns_tc_opts_invalid(void) { test_tc_opts_invalid_target(BPF_TCX_INGRESS); test_tc_opts_invalid_target(BPF_TCX_EGRESS); @@ -1157,7 +1157,7 @@ static void test_tc_opts_prepend_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_prepend(void) +void test_ns_tc_opts_prepend(void) { test_tc_opts_prepend_target(BPF_TCX_INGRESS); test_tc_opts_prepend_target(BPF_TCX_EGRESS); @@ -1297,7 +1297,7 @@ static void test_tc_opts_append_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_append(void) +void test_ns_tc_opts_append(void) { test_tc_opts_append_target(BPF_TCX_INGRESS); test_tc_opts_append_target(BPF_TCX_EGRESS); @@ -1387,7 +1387,7 @@ static void test_tc_opts_dev_cleanup_target(int target) ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); }
-void serial_test_tc_opts_dev_cleanup(void) +void test_ns_tc_opts_dev_cleanup(void) { test_tc_opts_dev_cleanup_target(BPF_TCX_INGRESS); test_tc_opts_dev_cleanup_target(BPF_TCX_EGRESS); @@ -1563,7 +1563,7 @@ static void test_tc_opts_mixed_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_opts_mixed(void) +void test_ns_tc_opts_mixed(void) { test_tc_opts_mixed_target(BPF_TCX_INGRESS); test_tc_opts_mixed_target(BPF_TCX_EGRESS); @@ -1642,7 +1642,7 @@ static void test_tc_opts_demixed_target(int target) assert_mprog_count(target, 0); }
-void serial_test_tc_opts_demixed(void) +void test_ns_tc_opts_demixed(void) { test_tc_opts_demixed_target(BPF_TCX_INGRESS); test_tc_opts_demixed_target(BPF_TCX_EGRESS); @@ -1813,7 +1813,7 @@ static void test_tc_opts_detach_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_detach(void) +void test_ns_tc_opts_detach(void) { test_tc_opts_detach_target(BPF_TCX_INGRESS); test_tc_opts_detach_target(BPF_TCX_EGRESS); @@ -2020,7 +2020,7 @@ static void test_tc_opts_detach_before_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_detach_before(void) +void test_ns_tc_opts_detach_before(void) { test_tc_opts_detach_before_target(BPF_TCX_INGRESS); test_tc_opts_detach_before_target(BPF_TCX_EGRESS); @@ -2236,7 +2236,7 @@ static void test_tc_opts_detach_after_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_detach_after(void) +void test_ns_tc_opts_detach_after(void) { test_tc_opts_detach_after_target(BPF_TCX_INGRESS); test_tc_opts_detach_after_target(BPF_TCX_EGRESS); @@ -2265,7 +2265,7 @@ static void test_tc_opts_delete_empty(int target, bool chain_tc_old) assert_mprog_count(target, 0); }
-void serial_test_tc_opts_delete_empty(void) +void test_ns_tc_opts_delete_empty(void) { test_tc_opts_delete_empty(BPF_TCX_INGRESS, false); test_tc_opts_delete_empty(BPF_TCX_EGRESS, false); @@ -2372,7 +2372,7 @@ static void test_tc_chain_mixed(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_chain_mixed(void) +void test_ns_tc_opts_chain_mixed(void) { test_tc_chain_mixed(BPF_TCX_INGRESS); test_tc_chain_mixed(BPF_TCX_EGRESS); @@ -2446,7 +2446,7 @@ static void test_tc_opts_max_target(int target, int flags, bool relative) ASSERT_EQ(if_nametoindex("tcx_opts2"), 0, "dev2_removed"); }
-void serial_test_tc_opts_max(void) +void test_ns_tc_opts_max(void) { test_tc_opts_max_target(BPF_TCX_INGRESS, 0, false); test_tc_opts_max_target(BPF_TCX_EGRESS, 0, false); @@ -2748,7 +2748,7 @@ static void test_tc_opts_query_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_query(void) +void test_ns_tc_opts_query(void) { test_tc_opts_query_target(BPF_TCX_INGRESS); test_tc_opts_query_target(BPF_TCX_EGRESS); @@ -2807,7 +2807,7 @@ static void test_tc_opts_query_attach_target(int target) test_tc_link__destroy(skel); }
-void serial_test_tc_opts_query_attach(void) +void test_ns_tc_opts_query_attach(void) { test_tc_opts_query_attach_target(BPF_TCX_INGRESS); test_tc_opts_query_attach_target(BPF_TCX_EGRESS);
Two subtests use the test_in_netns() function to run the test in a dedicated network namespace. This can now be done directly through the test_progs framework with a test name starting with 'ns_'.
Replace the use of test_in_netns() by test_ns_* calls.
Signed-off-by: Bastien Curutchet (eBPF Foundation) bastien.curutchet@bootlin.com --- .../selftests/bpf/prog_tests/ns_current_pid_tgid.c | 45 ++++++++-------------- 1 file changed, 16 insertions(+), 29 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c b/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c index 78020ece6a29c3bec4600f4fd6fe88fdbd2a768b..99c953f2be21581f8362f6c9217d395c06e7b5b4 100644 --- a/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c +++ b/tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c @@ -200,25 +200,6 @@ static void test_ns_current_pid_tgid_new_ns(int (*fn)(void *), void *arg) return; }
-static void test_in_netns(int (*fn)(void *), void *arg) -{ - struct nstoken *nstoken = NULL; - - SYS(cleanup, "ip netns add ns_current_pid_tgid"); - SYS(cleanup, "ip -net ns_current_pid_tgid link set dev lo up"); - - nstoken = open_netns("ns_current_pid_tgid"); - if (!ASSERT_OK_PTR(nstoken, "open_netns")) - goto cleanup; - - test_ns_current_pid_tgid_new_ns(fn, arg); - -cleanup: - if (nstoken) - close_netns(nstoken); - SYS_NOFAIL("ip netns del ns_current_pid_tgid"); -} - /* TODO: use a different tracepoint */ void serial_test_current_pid_tgid(void) { @@ -226,15 +207,21 @@ void serial_test_current_pid_tgid(void) test_current_pid_tgid_tp(NULL); if (test__start_subtest("new_ns_tp")) test_ns_current_pid_tgid_new_ns(test_current_pid_tgid_tp, NULL); - if (test__start_subtest("new_ns_cgrp")) { - int cgroup_fd = -1; - - cgroup_fd = test__join_cgroup("/sock_addr"); - if (ASSERT_GE(cgroup_fd, 0, "join_cgroup")) { - test_in_netns(test_current_pid_tgid_cgrp, &cgroup_fd); - close(cgroup_fd); - } +} + +void test_ns_current_pid_tgid_cgrp(void) +{ + int cgroup_fd = test__join_cgroup("/sock_addr"); + + if (ASSERT_OK_FD(cgroup_fd, "join_cgroup")) { + test_ns_current_pid_tgid_new_ns(test_current_pid_tgid_cgrp, &cgroup_fd); + close(cgroup_fd); } - if (test__start_subtest("new_ns_sk_msg")) - test_in_netns(test_current_pid_tgid_sk_msg, NULL); } + +void test_ns_current_pid_tgid_sk_msg(void) +{ + test_ns_current_pid_tgid_new_ns(test_current_pid_tgid_sk_msg, NULL); +} + +
On 02/19, Bastien Curutchet (eBPF Foundation) wrote:
Hi all,
Both tc_links.c and tc_opts.c do their tests on the loopback interface. It prevents from parallelizing their executions.
Add a new behaviour to the test_progs framework that creates and opens a new network namespace to run a test in it. This is done automatically on tests whose names start with 'ns_'.
One test already has a name starting with 'ns_', so PATCH 1 renames it to avoid conflicts. PATCH 2 introduces the test_progs 'feature'. PATCH 3 & 4 convert some tests to use these dedicated namespaces.
Signed-off-by: Bastien Curutchet (eBPF Foundation) bastien.curutchet@bootlin.com
Changes in v2:
- Handle the netns creation / opening directly in test_progs
- Link to v1: https://lore.kernel.org/bpf/e3838d93-04e3-4e96-af53-e9e63550d7ba@bootlin.com
Acked-by: Stanislav Fomichev sdf@fomichev.me
Thanks, looks very nice!
Hello:
This series was applied to bpf/bpf-next.git (master) by Alexei Starovoitov ast@kernel.org:
On Wed, 19 Feb 2025 15:52:59 +0100 you wrote:
Hi all,
Both tc_links.c and tc_opts.c do their tests on the loopback interface. It prevents from parallelizing their executions.
Add a new behaviour to the test_progs framework that creates and opens a new network namespace to run a test in it. This is done automatically on tests whose names start with 'ns_'.
[...]
Here is the summary with links: - [bpf-next,v2,1/4] selftests/bpf: ns_current_pid_tgid: Rename the test function https://git.kernel.org/bpf/bpf-next/c/4a06c5251ae3 - [bpf-next,v2,2/4] selftests/bpf: Optionally open a dedicated namespace to run test in it https://git.kernel.org/bpf/bpf-next/c/c047e0e0e435 - [bpf-next,v2,3/4] selftests/bpf: tc_links/tc_opts: Unserialize tests https://git.kernel.org/bpf/bpf-next/c/207cd7578ad1 - [bpf-next,v2,4/4] selftests/bpf: ns_current_pid_tgid: Use test_progs's ns_ feature https://git.kernel.org/bpf/bpf-next/c/157feaaf18ce
You are awesome, thank you!
linux-kselftest-mirror@lists.linaro.org