selftests/bpf: Test global bpf_list_head arrays.
authorKui-Feng Lee <thinker.li@gmail.com>
Thu, 23 May 2024 17:42:02 +0000 (10:42 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 4 Jun 2024 03:52:43 +0000 (20:52 -0700)
Make sure global arrays of bpf_list_heads and fields of bpf_list_heads in
nested struct types work correctly.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Kui-Feng Lee <thinker.li@gmail.com>
Link: https://lore.kernel.org/r/20240523174202.461236-10-thinker.li@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/linked_list.c
tools/testing/selftests/bpf/progs/linked_list.c

index 2fb89de..77d07e0 100644 (file)
@@ -183,6 +183,18 @@ static void test_linked_list_success(int mode, bool leave_in_map)
        if (!leave_in_map)
                clear_fields(skel->maps.bss_A);
 
+       ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_push_pop_nested), &opts);
+       ASSERT_OK(ret, "global_list_push_pop_nested");
+       ASSERT_OK(opts.retval, "global_list_push_pop_nested retval");
+       if (!leave_in_map)
+               clear_fields(skel->maps.bss_A);
+
+       ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.global_list_array_push_pop), &opts);
+       ASSERT_OK(ret, "global_list_array_push_pop");
+       ASSERT_OK(opts.retval, "global_list_array_push_pop retval");
+       if (!leave_in_map)
+               clear_fields(skel->maps.bss_A);
+
        if (mode == PUSH_POP)
                goto end;
 
index 26205ca..f69bf3e 100644 (file)
 
 #include "linked_list.h"
 
+struct head_nested_inner {
+       struct bpf_spin_lock lock;
+       struct bpf_list_head head __contains(foo, node2);
+};
+
+struct head_nested {
+       int dummy;
+       struct head_nested_inner inner;
+};
+
+private(C) struct bpf_spin_lock glock_c;
+private(C) struct bpf_list_head ghead_array[2] __contains(foo, node2);
+private(C) struct bpf_list_head ghead_array_one[1] __contains(foo, node2);
+
+private(D) struct head_nested ghead_nested;
+
 static __always_inline
 int list_push_pop(struct bpf_spin_lock *lock, struct bpf_list_head *head, bool leave_in_map)
 {
@@ -309,6 +325,32 @@ int global_list_push_pop(void *ctx)
        return test_list_push_pop(&glock, &ghead);
 }
 
+SEC("tc")
+int global_list_push_pop_nested(void *ctx)
+{
+       return test_list_push_pop(&ghead_nested.inner.lock, &ghead_nested.inner.head);
+}
+
+SEC("tc")
+int global_list_array_push_pop(void *ctx)
+{
+       int r;
+
+       r = test_list_push_pop(&glock_c, &ghead_array[0]);
+       if (r)
+               return r;
+
+       r = test_list_push_pop(&glock_c, &ghead_array[1]);
+       if (r)
+               return r;
+
+       /* Arrays with only one element is a special case, being treated
+        * just like a bpf_list_head variable by the verifier, not an
+        * array.
+        */
+       return test_list_push_pop(&glock_c, &ghead_array_one[0]);
+}
+
 SEC("tc")
 int map_list_push_pop_multiple(void *ctx)
 {