Skip to content

Commit 474c16e

Browse files
wusamuel6Kernel Patches Daemon
authored andcommitted
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 <[email protected]>
1 parent 6d1acc1 commit 474c16e

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

tools/testing/selftests/bpf/bpf_experimental.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,11 @@ extern void bpf_iter_dmabuf_destroy(struct bpf_iter_dmabuf *it) __weak __ksym;
598598

599599
extern int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__str,
600600
struct bpf_dynptr *value_p) __weak __ksym;
601+
struct bpf_iter_wakeup_source;
602+
extern int bpf_iter_wakeup_source_new(struct bpf_iter_wakeup_source *it) __weak __ksym;
603+
extern struct wakeup_source *bpf_iter_wakeup_source_next(
604+
struct bpf_iter_wakeup_source *it) __weak __ksym;
605+
extern void bpf_iter_wakeup_source_destroy(struct bpf_iter_wakeup_source *it) __weak __ksym;
601606

602607
#define PREEMPT_BITS 8
603608
#define SOFTIRQ_BITS 8

tools/testing/selftests/bpf/prog_tests/wakeup_source_iter.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,37 @@ static void subtest_ws_iter_check_no_infinite_reads(
241241
close(iter_fd);
242242
}
243243

244+
static void subtest_ws_iter_check_open_coded(struct wakeup_source_iter *skel,
245+
int map_fd)
246+
{
247+
LIBBPF_OPTS(bpf_test_run_opts, topts);
248+
char key[WAKEUP_SOURCE_NAME_LEN] = {0};
249+
int err, fd;
250+
bool found = false;
251+
252+
fd = bpf_program__fd(skel->progs.iter_ws_for_each);
253+
254+
err = bpf_prog_test_run_opts(fd, &topts);
255+
if (!ASSERT_OK(err, "test_run_opts err"))
256+
return;
257+
if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
258+
return;
259+
260+
strncpy(key, test_ws_name, WAKEUP_SOURCE_NAME_LEN - 1);
261+
262+
if (!ASSERT_OK(bpf_map_lookup_elem(map_fd, key, &found),
263+
"lookup test_ws_name"))
264+
return;
265+
266+
ASSERT_TRUE(found, "found test ws via bpf_for_each");
267+
}
268+
244269
void test_wakeup_source_iter(void)
245270
{
246271
struct wakeup_source_iter *skel = NULL;
272+
int map_fd;
273+
const bool found_val = false;
274+
char key[WAKEUP_SOURCE_NAME_LEN] = {0};
247275

248276
if (geteuid() != 0) {
249277
fprintf(stderr,
@@ -256,6 +284,17 @@ void test_wakeup_source_iter(void)
256284
if (!ASSERT_OK_PTR(skel, "wakeup_source_iter__open_and_load"))
257285
return;
258286

287+
map_fd = bpf_map__fd(skel->maps.test_ws_hash);
288+
if (!ASSERT_OK_FD(map_fd, "map_fd"))
289+
goto destroy_skel;
290+
291+
/* Copy test name to key buffer, ensuring it's zero-padded */
292+
strncpy(key, test_ws_name, WAKEUP_SOURCE_NAME_LEN - 1);
293+
294+
if (!ASSERT_OK(bpf_map_update_elem(map_fd, key, &found_val, BPF_ANY),
295+
"insert test_ws_name"))
296+
goto destroy_skel;
297+
259298
if (!ASSERT_OK(setup_test_ws(), "setup_test_ws"))
260299
goto destroy;
261300

@@ -274,8 +313,11 @@ void test_wakeup_source_iter(void)
274313
subtest_ws_iter_check_sleep_times(skel);
275314
if (test__start_subtest("no_infinite_reads"))
276315
subtest_ws_iter_check_no_infinite_reads(skel);
316+
if (test__start_subtest("open_coded"))
317+
subtest_ws_iter_check_open_coded(skel, map_fd);
277318

278319
destroy:
279320
teardown_test_ws();
321+
destroy_skel:
280322
wakeup_source_iter__destroy(skel);
281323
}

tools/testing/selftests/bpf/progs/wakeup_source_iter.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99

1010
char _license[] SEC("license") = "GPL";
1111

12+
struct {
13+
__uint(type, BPF_MAP_TYPE_HASH);
14+
__uint(key_size, WAKEUP_SOURCE_NAME_LEN);
15+
__type(value, bool);
16+
__uint(max_entries, 5);
17+
} test_ws_hash SEC(".maps");
18+
1219
SEC("iter/wakeup_source")
1320
int wakeup_source_collector(struct bpf_iter__wakeup_source *ctx)
1421
{
@@ -68,3 +75,43 @@ int wakeup_source_collector(struct bpf_iter__wakeup_source *ctx)
6875
wakeup_count);
6976
return 0;
7077
}
78+
79+
SEC("syscall")
80+
int iter_ws_for_each(const void *ctx)
81+
{
82+
struct wakeup_source *ws;
83+
84+
bpf_for_each(wakeup_source, ws) {
85+
char name[WAKEUP_SOURCE_NAME_LEN];
86+
const char *pname;
87+
bool *found;
88+
long len;
89+
int i;
90+
91+
if (bpf_core_read(&pname, sizeof(pname), &ws->name))
92+
return 1;
93+
94+
if (!pname)
95+
continue;
96+
97+
len = bpf_probe_read_kernel_str(name, sizeof(name), pname);
98+
if (len < 0)
99+
return 1;
100+
101+
/*
102+
* Clear the remainder of the buffer to ensure a stable key for
103+
* the map lookup.
104+
*/
105+
bpf_for(i, len, WAKEUP_SOURCE_NAME_LEN)
106+
name[i] = 0;
107+
108+
found = bpf_map_lookup_elem(&test_ws_hash, name);
109+
if (found) {
110+
bool t = true;
111+
112+
bpf_map_update_elem(&test_ws_hash, name, &t, BPF_EXIST);
113+
}
114+
}
115+
116+
return 0;
117+
}

0 commit comments

Comments
 (0)