[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251204025003.3162056-5-wusamuel@google.com>
Date: Wed, 3 Dec 2025 18:50:01 -0800
From: Samuel Wu <wusamuel@...gle.com>
To: Alexei Starovoitov <ast@...nel.org>, Daniel Borkmann <daniel@...earbox.net>,
Andrii Nakryiko <andrii@...nel.org>, Martin KaFai Lau <martin.lau@...ux.dev>,
Eduard Zingerman <eddyz87@...il.com>, Song Liu <song@...nel.org>,
Yonghong Song <yonghong.song@...ux.dev>, John Fastabend <john.fastabend@...il.com>,
KP Singh <kpsingh@...nel.org>, Stanislav Fomichev <sdf@...ichev.me>, Hao Luo <haoluo@...gle.com>,
Jiri Olsa <jolsa@...nel.org>, Shuah Khan <shuah@...nel.org>
Cc: rafael.j.wysocki@...el.com, Samuel Wu <wusamuel@...gle.com>,
kernel-team@...roid.com, linux-kernel@...r.kernel.org, bpf@...r.kernel.org,
linux-kselftest@...r.kernel.org
Subject: [PATCH v1 4/4] selftests/bpf: Open coded BPF wakeup_sources test
This commit introduces a new selftest for the BPF wakeup_source iterator
to verify the functionality of open-coded iteration.
The test adds:
- A new BPF map `test_ws_hash` to track iterated wakeup source names.
- A BPF program `iter_ws_for_each` that iterates over wakeup sources and
updates the `test_ws_hash` map with the names of found sources.
- A new subtest `subtest_ws_iter_check_open_coded` to trigger the BPF
program and assert that the expected wakeup sources are marked in the
map.
Signed-off-by: Samuel Wu <wusamuel@...gle.com>
---
.../testing/selftests/bpf/bpf_experimental.h | 5 ++
.../bpf/prog_tests/wakeup_source_iter.c | 42 +++++++++++++++++
.../selftests/bpf/progs/wakeup_source_iter.c | 47 +++++++++++++++++++
3 files changed, 94 insertions(+)
diff --git a/tools/testing/selftests/bpf/bpf_experimental.h b/tools/testing/selftests/bpf/bpf_experimental.h
index 2cd9165c7348..e532999b91ca 100644
--- a/tools/testing/selftests/bpf/bpf_experimental.h
+++ b/tools/testing/selftests/bpf/bpf_experimental.h
@@ -598,6 +598,11 @@ extern void bpf_iter_dmabuf_destroy(struct bpf_iter_dmabuf *it) __weak __ksym;
extern int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__str,
struct bpf_dynptr *value_p) __weak __ksym;
+struct bpf_iter_wakeup_source;
+extern int bpf_iter_wakeup_source_new(struct bpf_iter_wakeup_source *it) __weak __ksym;
+extern struct wakeup_source *bpf_iter_wakeup_source_next(
+ struct bpf_iter_wakeup_source *it) __weak __ksym;
+extern void bpf_iter_wakeup_source_destroy(struct bpf_iter_wakeup_source *it) __weak __ksym;
#define PREEMPT_BITS 8
#define SOFTIRQ_BITS 8
diff --git a/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c b/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c
index 5cea4d4458f3..b2eaba38cc68 100644
--- a/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c
@@ -241,9 +241,37 @@ static void subtest_ws_iter_check_no_infinite_reads(
close(iter_fd);
}
+static void subtest_ws_iter_check_open_coded(struct wakeup_source_iter *skel,
+ int map_fd)
+{
+ LIBBPF_OPTS(bpf_test_run_opts, topts);
+ char key[WAKEUP_SOURCE_NAME_LEN] = {0};
+ int err, fd;
+ bool found = false;
+
+ fd = bpf_program__fd(skel->progs.iter_ws_for_each);
+
+ err = bpf_prog_test_run_opts(fd, &topts);
+ if (!ASSERT_OK(err, "test_run_opts err"))
+ return;
+ if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+ return;
+
+ strncpy(key, test_ws_name, WAKEUP_SOURCE_NAME_LEN - 1);
+
+ if (!ASSERT_OK(bpf_map_lookup_elem(map_fd, key, &found),
+ "lookup test_ws_name"))
+ return;
+
+ ASSERT_TRUE(found, "found test ws via bpf_for_each");
+}
+
void test_wakeup_source_iter(void)
{
struct wakeup_source_iter *skel = NULL;
+ int map_fd;
+ const bool found_val = false;
+ char key[WAKEUP_SOURCE_NAME_LEN] = {0};
if (geteuid() != 0) {
fprintf(stderr,
@@ -256,6 +284,17 @@ void test_wakeup_source_iter(void)
if (!ASSERT_OK_PTR(skel, "wakeup_source_iter__open_and_load"))
return;
+ map_fd = bpf_map__fd(skel->maps.test_ws_hash);
+ if (!ASSERT_OK_FD(map_fd, "map_fd"))
+ goto destroy_skel;
+
+ /* Copy test name to key buffer, ensuring it's zero-padded */
+ strncpy(key, test_ws_name, WAKEUP_SOURCE_NAME_LEN - 1);
+
+ if (!ASSERT_OK(bpf_map_update_elem(map_fd, key, &found_val, BPF_ANY),
+ "insert test_ws_name"))
+ goto destroy_skel;
+
if (!ASSERT_OK(setup_test_ws(), "setup_test_ws"))
goto destroy;
@@ -274,8 +313,11 @@ void test_wakeup_source_iter(void)
subtest_ws_iter_check_sleep_times(skel);
if (test__start_subtest("no_infinite_reads"))
subtest_ws_iter_check_no_infinite_reads(skel);
+ if (test__start_subtest("open_coded"))
+ subtest_ws_iter_check_open_coded(skel, map_fd);
destroy:
teardown_test_ws();
+destroy_skel:
wakeup_source_iter__destroy(skel);
}
diff --git a/tools/testing/selftests/bpf/progs/wakeup_source_iter.c b/tools/testing/selftests/bpf/progs/wakeup_source_iter.c
index 8c1470f06740..7812e773aa0c 100644
--- a/tools/testing/selftests/bpf/progs/wakeup_source_iter.c
+++ b/tools/testing/selftests/bpf/progs/wakeup_source_iter.c
@@ -9,6 +9,13 @@
char _license[] SEC("license") = "GPL";
+struct {
+ __uint(type, BPF_MAP_TYPE_HASH);
+ __uint(key_size, WAKEUP_SOURCE_NAME_LEN);
+ __type(value, bool);
+ __uint(max_entries, 5);
+} test_ws_hash SEC(".maps");
+
SEC("iter/wakeup_source")
int wakeup_source_collector(struct bpf_iter__wakeup_source *ctx)
{
@@ -68,3 +75,43 @@ int wakeup_source_collector(struct bpf_iter__wakeup_source *ctx)
wakeup_count);
return 0;
}
+
+SEC("syscall")
+int iter_ws_for_each(const void *ctx)
+{
+ struct wakeup_source *ws;
+
+ bpf_for_each(wakeup_source, ws) {
+ char name[WAKEUP_SOURCE_NAME_LEN];
+ const char *pname;
+ bool *found;
+ long len;
+ int i;
+
+ if (bpf_core_read(&pname, sizeof(pname), &ws->name))
+ return 1;
+
+ if (!pname)
+ continue;
+
+ len = bpf_probe_read_kernel_str(name, sizeof(name), pname);
+ if (len < 0)
+ return 1;
+
+ /*
+ * Clear the remainder of the buffer to ensure a stable key for
+ * the map lookup.
+ */
+ bpf_for(i, len, WAKEUP_SOURCE_NAME_LEN)
+ name[i] = 0;
+
+ found = bpf_map_lookup_elem(&test_ws_hash, name);
+ if (found) {
+ bool t = true;
+
+ bpf_map_update_elem(&test_ws_hash, name, &t, BPF_EXIST);
+ }
+ }
+
+ return 0;
+}
--
2.52.0.177.g9f829587af-goog
Powered by blists - more mailing lists