On Tue, Sep 10, 2024 at 11:36:36AM GMT, Alexei Starovoitov wrote: > On Mon, Sep 9, 2024 at 5:55 PM Daniel Xu <dxu@xxxxxxxxx> wrote: > > > > Right now there exists prog produce / userspace consume and userspace > > produce / prog consume support. But it is also useful to have prog > > produce / prog consume. > > > > For example, we want to track the latency overhead of cpumap in > > production. Since we need to store enqueue timestamps somewhere and > > cpumap is MPSC, we need an MPSC data structure to shadow cpumap. BPF > > ringbuf is such a data structure. Rather than reimplement (possibly > > poorly) a custom ringbuffer in BPF, extend the existing interface to > > allow the final quadrant of ringbuf usecases to be filled. Note we > > ignore userspace to userspace use case - there is no need to involve > > kernel for that. > > > > Signed-off-by: Daniel Xu <dxu@xxxxxxxxx> > > --- > > kernel/bpf/verifier.c | 6 +- > > tools/testing/selftests/bpf/Makefile | 3 +- > > .../selftests/bpf/prog_tests/ringbuf.c | 50 +++++++++++++++ > > .../bpf/progs/test_ringbuf_bpf_to_bpf.c | 64 +++++++++++++++++++ > > 4 files changed, 120 insertions(+), 3 deletions(-) > > create mode 100644 tools/testing/selftests/bpf/progs/test_ringbuf_bpf_to_bpf.c > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > index 53d0556fbbf3..56bfe559f228 100644 > > --- a/kernel/bpf/verifier.c > > +++ b/kernel/bpf/verifier.c > > @@ -9142,7 +9142,8 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, > > func_id != BPF_FUNC_ringbuf_query && > > func_id != BPF_FUNC_ringbuf_reserve_dynptr && > > func_id != BPF_FUNC_ringbuf_submit_dynptr && > > - func_id != BPF_FUNC_ringbuf_discard_dynptr) > > + func_id != BPF_FUNC_ringbuf_discard_dynptr && > > + func_id != BPF_FUNC_user_ringbuf_drain) > > goto error; > > break; > > case BPF_MAP_TYPE_USER_RINGBUF: > > @@ -9276,7 +9277,8 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env, > > goto error; > > break; > > case BPF_FUNC_user_ringbuf_drain: > > - if (map->map_type != BPF_MAP_TYPE_USER_RINGBUF) > > + if (map->map_type != BPF_MAP_TYPE_USER_RINGBUF && > > + map->map_type != BPF_MAP_TYPE_RINGBUF) > > goto error; > > I think it should work. > > Andrii, > > do you see any issues with such use? > > > break; > > case BPF_FUNC_get_stackid: > > diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile > > index 9905e3739dd0..233109843d4d 100644 > > --- a/tools/testing/selftests/bpf/Makefile > > +++ b/tools/testing/selftests/bpf/Makefile > > @@ -503,7 +503,8 @@ LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \ > > LSKELS := fentry_test.c fexit_test.c fexit_sleep.c atomics.c \ > > trace_printk.c trace_vprintk.c map_ptr_kern.c \ > > core_kern.c core_kern_overflow.c test_ringbuf.c \ > > - test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c > > + test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c \ > > + test_ringbuf_bpf_to_bpf.c > > Do you need it to be lskel ? > > Regular skels are either to debug. I'm actually unsure the difference, still. But all the other tests in the file were using lskel so I just copy/pasted. > > Also pls split selftest into a separate patch. Ack. > > > > > # Generate both light skeleton and libbpf skeleton for these > > LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \ > > diff --git a/tools/testing/selftests/bpf/prog_tests/ringbuf.c b/tools/testing/selftests/bpf/prog_tests/ringbuf.c > > index da430df45aa4..3e7955573ac5 100644 > > --- a/tools/testing/selftests/bpf/prog_tests/ringbuf.c > > +++ b/tools/testing/selftests/bpf/prog_tests/ringbuf.c > > @@ -17,6 +17,7 @@ > > #include "test_ringbuf_n.lskel.h" > > #include "test_ringbuf_map_key.lskel.h" > > #include "test_ringbuf_write.lskel.h" > > +#include "test_ringbuf_bpf_to_bpf.lskel.h" > > > > #define EDONE 7777 > > > > @@ -497,6 +498,53 @@ static void ringbuf_map_key_subtest(void) > > test_ringbuf_map_key_lskel__destroy(skel_map_key); > > } > > > > +static void ringbuf_bpf_to_bpf_subtest(void) > > +{ > > + struct test_ringbuf_bpf_to_bpf_lskel *skel; > > + int err, i; > > + > > + skel = test_ringbuf_bpf_to_bpf_lskel__open(); > > + if (!ASSERT_OK_PTR(skel, "test_ringbuf_bpf_to_bpf_lskel__open")) > > + return; > > + > > + skel->maps.ringbuf.max_entries = getpagesize(); > > + skel->bss->pid = getpid(); > > + > > + err = test_ringbuf_bpf_to_bpf_lskel__load(skel); > > + if (!ASSERT_OK(err, "test_ringbuf_bpf_to_bpf_lskel__load")) > > + goto cleanup; > > + > > + ringbuf = ring_buffer__new(skel->maps.ringbuf.map_fd, NULL, NULL, NULL); > > + if (!ASSERT_OK_PTR(ringbuf, "ring_buffer__new")) > > + goto cleanup; > > + > > + err = test_ringbuf_bpf_to_bpf_lskel__attach(skel); > > + if (!ASSERT_OK(err, "test_ringbuf_bpf_to_bpf_lskel__attach")) > > + goto cleanup_ringbuf; > > + > > + /* Produce N_SAMPLES samples in the ring buffer by calling getpid() */ > > + skel->bss->value = SAMPLE_VALUE; > > + for (i = 0; i < N_SAMPLES; i++) > > + syscall(__NR_getpgid); > > + > > + /* Trigger bpf-side consumption */ > > + syscall(__NR_prctl); > > This might conflict with other selftests that run in parallel. > > Just load the skel and bpf_prog_run(prog_fd). > No need to attach anywhere in the kernel. Ack. > > pw-bot: cr