]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/bpf: Add BPF iterator tests for resizable hash map
authorMykyta Yatsenko <yatsenko@meta.com>
Fri, 5 Jun 2026 11:41:27 +0000 (04:41 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 5 Jun 2026 15:00:08 +0000 (08:00 -0700)
Test basic BPF iterator functionality for BPF_MAP_TYPE_RHASH,
verifying all elements are visited.

Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Link: https://lore.kernel.org/r/20260605-rhash-v7-10-5b8e05f8630d@meta.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/rhash.c
tools/testing/selftests/bpf/progs/bpf_iter_bpf_rhash_map.c [new file with mode: 0644]

index 69686bf69ba57a88ac67822299524ca116adcd6c..98bb66907b7f7780c216141e24cec36466cd5206 100644 (file)
@@ -4,6 +4,7 @@
 #include <string.h>
 #include <stdio.h>
 #include "rhash.skel.h"
+#include "bpf_iter_bpf_rhash_map.skel.h"
 #include <linux/bpf.h>
 #include <linux/perf_event.h>
 #include <sys/syscall.h>
@@ -89,6 +90,65 @@ static void rhash_map_extra_too_big(void)
                close(fd);
 }
 
+static void rhash_iter_test(void)
+{
+       DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts);
+       struct bpf_iter_bpf_rhash_map *skel;
+       int err, i, len, map_fd, iter_fd;
+       union bpf_iter_link_info linfo;
+       u32 expected_key_sum = 0, key;
+       struct bpf_link *link;
+       u64 val = 0;
+       char buf[64];
+
+       skel = bpf_iter_bpf_rhash_map__open();
+       if (!ASSERT_OK_PTR(skel, "bpf_iter_bpf_rhash_map__open"))
+               return;
+
+       err = bpf_iter_bpf_rhash_map__load(skel);
+       if (!ASSERT_OK(err, "bpf_iter_bpf_rhash_map__load"))
+               goto out;
+
+       map_fd = bpf_map__fd(skel->maps.rhashmap);
+
+       /* Populate map with test data */
+       for (i = 0; i < 64; i++) {
+               key = i + 1;
+               expected_key_sum += key;
+
+               err = bpf_map_update_elem(map_fd, &key, &val, BPF_NOEXIST);
+               if (!ASSERT_OK(err, "map_update"))
+                       goto out;
+       }
+
+       memset(&linfo, 0, sizeof(linfo));
+       linfo.map.map_fd = map_fd;
+       opts.link_info = &linfo;
+       opts.link_info_len = sizeof(linfo);
+
+       link = bpf_program__attach_iter(skel->progs.dump_bpf_rhash_map, &opts);
+       if (!ASSERT_OK_PTR(link, "attach_iter"))
+               goto out;
+
+       iter_fd = bpf_iter_create(bpf_link__fd(link));
+       if (!ASSERT_GE(iter_fd, 0, "create_iter"))
+               goto free_link;
+
+       do {
+               len = read(iter_fd, buf, sizeof(buf));
+       } while (len > 0);
+
+       ASSERT_EQ(skel->bss->key_sum, expected_key_sum, "key_sum");
+       ASSERT_EQ(skel->bss->elem_count, 64, "elem_count");
+
+       close(iter_fd);
+
+free_link:
+       bpf_link__destroy(link);
+out:
+       bpf_iter_bpf_rhash_map__destroy(skel);
+}
+
 void test_rhash(void)
 {
        if (test__start_subtest("test_rhash_lookup_update"))
@@ -117,4 +177,7 @@ void test_rhash(void)
 
        if (test__start_subtest("test_rhash_map_extra_too_big"))
                rhash_map_extra_too_big();
+
+       if (test__start_subtest("test_rhash_iter"))
+               rhash_iter_test();
 }
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_bpf_rhash_map.c b/tools/testing/selftests/bpf/progs/bpf_iter_bpf_rhash_map.c
new file mode 100644 (file)
index 0000000..86f6c0d
--- /dev/null
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+
+char _license[] SEC("license") = "GPL";
+
+struct {
+       __uint(type, BPF_MAP_TYPE_RHASH);
+       __uint(map_flags, BPF_F_NO_PREALLOC);
+       __uint(max_entries, 64);
+       __type(key, __u32);
+       __type(value, __u64);
+} rhashmap SEC(".maps");
+
+__u32 key_sum = 0;
+__u64 val_sum = 0;
+__u32 elem_count = 0;
+__u32 err = 0;
+
+SEC("iter/bpf_map_elem")
+int dump_bpf_rhash_map(struct bpf_iter__bpf_map_elem *ctx)
+{
+       __u32 *key = ctx->key;
+       __u64 *val = ctx->value;
+
+       if (!key || !val)
+               return 0;
+
+       key_sum += *key;
+       val_sum += *val;
+       elem_count++;
+       return 0;
+}