Skip to content

Commit 51ee71d

Browse files
davemarchevskyAlexei Starovoitov
authored andcommitted
selftests/bpf: Add test verifying bpf_ringbuf_reserve retval use in map ops
Add a test_ringbuf_map_key test prog, borrowing heavily from extant test_ringbuf.c. The program tries to use the result of bpf_ringbuf_reserve as map_key, which was not possible before previouis commits in this series. The test runner added to prog_tests/ringbuf.c verifies that the program loads and does basic sanity checks to confirm that it runs as expected. Also, refactor test_ringbuf such that runners for existing test_ringbuf and newly-added test_ringbuf_map_key are subtests of 'ringbuf' top-level test. Signed-off-by: Dave Marchevsky <[email protected]> Acked-by: Yonghong Song <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent d167330 commit 51ee71d

File tree

3 files changed

+140
-4
lines changed

3 files changed

+140
-4
lines changed

tools/testing/selftests/bpf/Makefile

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,11 @@ LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \
359359
test_subskeleton.skel.h test_subskeleton_lib.skel.h \
360360
test_usdt.skel.h
361361

362-
LSKELS := fentry_test.c fexit_test.c fexit_sleep.c \
363-
test_ringbuf.c atomics.c trace_printk.c trace_vprintk.c \
364-
map_ptr_kern.c core_kern.c core_kern_overflow.c
362+
LSKELS := fentry_test.c fexit_test.c fexit_sleep.c atomics.c \
363+
trace_printk.c trace_vprintk.c map_ptr_kern.c \
364+
core_kern.c core_kern_overflow.c test_ringbuf.c \
365+
test_ringbuf_map_key.c
366+
365367
# Generate both light skeleton and libbpf skeleton for these
366368
LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \
367369
kfunc_call_test_subprog.c

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

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/perf_event.h>
1414
#include <linux/ring_buffer.h>
1515
#include "test_ringbuf.lskel.h"
16+
#include "test_ringbuf_map_key.lskel.h"
1617

1718
#define EDONE 7777
1819

@@ -58,6 +59,7 @@ static int process_sample(void *ctx, void *data, size_t len)
5859
}
5960
}
6061

62+
static struct test_ringbuf_map_key_lskel *skel_map_key;
6163
static struct test_ringbuf_lskel *skel;
6264
static struct ring_buffer *ringbuf;
6365

@@ -81,7 +83,7 @@ static void *poll_thread(void *input)
8183
return (void *)(long)ring_buffer__poll(ringbuf, timeout);
8284
}
8385

84-
void test_ringbuf(void)
86+
static void ringbuf_subtest(void)
8587
{
8688
const size_t rec_sz = BPF_RINGBUF_HDR_SZ + sizeof(struct sample);
8789
pthread_t thread;
@@ -297,3 +299,65 @@ void test_ringbuf(void)
297299
ring_buffer__free(ringbuf);
298300
test_ringbuf_lskel__destroy(skel);
299301
}
302+
303+
static int process_map_key_sample(void *ctx, void *data, size_t len)
304+
{
305+
struct sample *s;
306+
int err, val;
307+
308+
s = data;
309+
switch (s->seq) {
310+
case 1:
311+
ASSERT_EQ(s->value, 42, "sample_value");
312+
err = bpf_map_lookup_elem(skel_map_key->maps.hash_map.map_fd,
313+
s, &val);
314+
ASSERT_OK(err, "hash_map bpf_map_lookup_elem");
315+
ASSERT_EQ(val, 1, "hash_map val");
316+
return -EDONE;
317+
default:
318+
return 0;
319+
}
320+
}
321+
322+
static void ringbuf_map_key_subtest(void)
323+
{
324+
int err;
325+
326+
skel_map_key = test_ringbuf_map_key_lskel__open();
327+
if (!ASSERT_OK_PTR(skel_map_key, "test_ringbuf_map_key_lskel__open"))
328+
return;
329+
330+
skel_map_key->maps.ringbuf.max_entries = getpagesize();
331+
skel_map_key->bss->pid = getpid();
332+
333+
err = test_ringbuf_map_key_lskel__load(skel_map_key);
334+
if (!ASSERT_OK(err, "test_ringbuf_map_key_lskel__load"))
335+
goto cleanup;
336+
337+
ringbuf = ring_buffer__new(skel_map_key->maps.ringbuf.map_fd,
338+
process_map_key_sample, NULL, NULL);
339+
if (!ASSERT_OK_PTR(ringbuf, "ring_buffer__new"))
340+
goto cleanup;
341+
342+
err = test_ringbuf_map_key_lskel__attach(skel_map_key);
343+
if (!ASSERT_OK(err, "test_ringbuf_map_key_lskel__attach"))
344+
goto cleanup_ringbuf;
345+
346+
syscall(__NR_getpgid);
347+
ASSERT_EQ(skel_map_key->bss->seq, 1, "skel_map_key->bss->seq");
348+
err = ring_buffer__poll(ringbuf, -1);
349+
ASSERT_EQ(err, -EDONE, "ring_buffer__poll");
350+
351+
cleanup_ringbuf:
352+
ring_buffer__free(ringbuf);
353+
cleanup:
354+
test_ringbuf_map_key_lskel__destroy(skel_map_key);
355+
}
356+
357+
void test_ringbuf(void)
358+
{
359+
if (test__start_subtest("ringbuf"))
360+
ringbuf_subtest();
361+
if (test__start_subtest("ringbuf_map_key"))
362+
ringbuf_map_key_subtest();
363+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
3+
4+
#include <linux/bpf.h>
5+
#include <bpf/bpf_helpers.h>
6+
#include "bpf_misc.h"
7+
8+
char _license[] SEC("license") = "GPL";
9+
10+
struct sample {
11+
int pid;
12+
int seq;
13+
long value;
14+
char comm[16];
15+
};
16+
17+
struct {
18+
__uint(type, BPF_MAP_TYPE_RINGBUF);
19+
} ringbuf SEC(".maps");
20+
21+
struct {
22+
__uint(type, BPF_MAP_TYPE_HASH);
23+
__uint(max_entries, 1000);
24+
__type(key, struct sample);
25+
__type(value, int);
26+
} hash_map SEC(".maps");
27+
28+
/* inputs */
29+
int pid = 0;
30+
31+
/* inner state */
32+
long seq = 0;
33+
34+
SEC("fentry/" SYS_PREFIX "sys_getpgid")
35+
int test_ringbuf_mem_map_key(void *ctx)
36+
{
37+
int cur_pid = bpf_get_current_pid_tgid() >> 32;
38+
struct sample *sample, sample_copy;
39+
int *lookup_val;
40+
41+
if (cur_pid != pid)
42+
return 0;
43+
44+
sample = bpf_ringbuf_reserve(&ringbuf, sizeof(*sample), 0);
45+
if (!sample)
46+
return 0;
47+
48+
sample->pid = pid;
49+
bpf_get_current_comm(sample->comm, sizeof(sample->comm));
50+
sample->seq = ++seq;
51+
sample->value = 42;
52+
53+
/* test using 'sample' (PTR_TO_MEM | MEM_ALLOC) as map key arg
54+
*/
55+
lookup_val = (int *)bpf_map_lookup_elem(&hash_map, sample);
56+
57+
/* workaround - memcpy is necessary so that verifier doesn't
58+
* complain with:
59+
* verifier internal error: more than one arg with ref_obj_id R3
60+
* when trying to do bpf_map_update_elem(&hash_map, sample, &sample->seq, BPF_ANY);
61+
*
62+
* Since bpf_map_lookup_elem above uses 'sample' as key, test using
63+
* sample field as value below
64+
*/
65+
__builtin_memcpy(&sample_copy, sample, sizeof(struct sample));
66+
bpf_map_update_elem(&hash_map, &sample_copy, &sample->seq, BPF_ANY);
67+
68+
bpf_ringbuf_submit(sample, 0);
69+
return 0;
70+
}

0 commit comments

Comments
 (0)