Skip to content

Commit e4bbf50

Browse files
Xu KuohaiKernel Patches Daemon
authored andcommitted
selftests/bpf: Add test for overwrite ring buffer
Add test for overwiret mode ring buffer. The test creates a bpf ring buffer in overwrite mode, then repeatlly reserves and commits data to check if the ring buffer works as expected both before and after overwrite happens. Signed-off-by: Xu Kuohai <[email protected]>
1 parent 9c4d863 commit e4bbf50

File tree

3 files changed

+174
-1
lines changed

3 files changed

+174
-1
lines changed

tools/testing/selftests/bpf/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,8 @@ LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \
499499
LSKELS := fentry_test.c fexit_test.c fexit_sleep.c atomics.c \
500500
trace_printk.c trace_vprintk.c map_ptr_kern.c \
501501
core_kern.c core_kern_overflow.c test_ringbuf.c \
502-
test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c
502+
test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c \
503+
test_ringbuf_overwrite.c
503504

504505
# Generate both light skeleton and libbpf skeleton for these
505506
LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \

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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "test_ringbuf_n.lskel.h"
1818
#include "test_ringbuf_map_key.lskel.h"
1919
#include "test_ringbuf_write.lskel.h"
20+
#include "test_ringbuf_overwrite.lskel.h"
2021

2122
#define EDONE 7777
2223

@@ -497,6 +498,77 @@ static void ringbuf_map_key_subtest(void)
497498
test_ringbuf_map_key_lskel__destroy(skel_map_key);
498499
}
499500

501+
static void ringbuf_overwrite_mode_subtest(void)
502+
{
503+
unsigned long size, len1, len2, len3, len4, len5;
504+
unsigned long expect_avail_data, expect_prod_pos, expect_over_pos;
505+
struct test_ringbuf_overwrite_lskel *skel;
506+
int err;
507+
508+
skel = test_ringbuf_overwrite_lskel__open();
509+
if (!ASSERT_OK_PTR(skel, "skel_open"))
510+
return;
511+
512+
size = 0x1000;
513+
len1 = 0x800;
514+
len2 = 0x400;
515+
len3 = size - len1 - len2 - BPF_RINGBUF_HDR_SZ * 3; /* 0x3e8 */
516+
len4 = len3 - 8; /* 0x3e0 */
517+
len5 = len3; /* retry with len3 */
518+
519+
skel->maps.ringbuf.max_entries = size;
520+
skel->rodata->LEN1 = len1;
521+
skel->rodata->LEN2 = len2;
522+
skel->rodata->LEN3 = len3;
523+
skel->rodata->LEN4 = len4;
524+
skel->rodata->LEN5 = len5;
525+
526+
skel->bss->pid = getpid();
527+
528+
err = test_ringbuf_overwrite_lskel__load(skel);
529+
if (!ASSERT_OK(err, "skel_load"))
530+
goto cleanup;
531+
532+
err = test_ringbuf_overwrite_lskel__attach(skel);
533+
if (!ASSERT_OK(err, "skel_attach"))
534+
goto cleanup;
535+
536+
syscall(__NR_getpgid);
537+
538+
ASSERT_EQ(skel->bss->reserve1_fail, 0, "reserve 1");
539+
ASSERT_EQ(skel->bss->reserve2_fail, 0, "reserve 2");
540+
ASSERT_EQ(skel->bss->reserve3_fail, 1, "reserve 3");
541+
ASSERT_EQ(skel->bss->reserve4_fail, 0, "reserve 4");
542+
ASSERT_EQ(skel->bss->reserve5_fail, 0, "reserve 5");
543+
544+
CHECK(skel->bss->ring_size != size,
545+
"check_ring_size", "exp %lu, got %lu\n",
546+
size, skel->bss->ring_size);
547+
548+
expect_avail_data = len2 + len4 + len5 + 3 * BPF_RINGBUF_HDR_SZ;
549+
CHECK(skel->bss->avail_data != expect_avail_data,
550+
"check_avail_size", "exp %lu, got %lu\n",
551+
expect_avail_data, skel->bss->avail_data);
552+
553+
CHECK(skel->bss->cons_pos != 0,
554+
"check_cons_pos", "exp 0, got %lu\n",
555+
skel->bss->cons_pos);
556+
557+
expect_prod_pos = len1 + len2 + len4 + len5 + 4 * BPF_RINGBUF_HDR_SZ;
558+
CHECK(skel->bss->prod_pos != expect_prod_pos,
559+
"check_prod_pos", "exp %lu, got %lu\n",
560+
expect_prod_pos, skel->bss->prod_pos);
561+
562+
expect_over_pos = len1 + BPF_RINGBUF_HDR_SZ;
563+
CHECK(skel->bss->over_pos != expect_over_pos,
564+
"check_over_pos", "exp %lu, got %lu\n",
565+
(unsigned long)expect_over_pos, skel->bss->over_pos);
566+
567+
test_ringbuf_overwrite_lskel__detach(skel);
568+
cleanup:
569+
test_ringbuf_overwrite_lskel__destroy(skel);
570+
}
571+
500572
void test_ringbuf(void)
501573
{
502574
if (test__start_subtest("ringbuf"))
@@ -507,4 +579,6 @@ void test_ringbuf(void)
507579
ringbuf_map_key_subtest();
508580
if (test__start_subtest("ringbuf_write"))
509581
ringbuf_write_subtest();
582+
if (test__start_subtest("ringbuf_overwrite_mode"))
583+
ringbuf_overwrite_mode_subtest();
510584
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (C) 2025. Huawei Technologies Co., Ltd */
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 {
11+
__uint(type, BPF_MAP_TYPE_RINGBUF);
12+
__uint(map_flags, BPF_F_OVERWRITE);
13+
} ringbuf SEC(".maps");
14+
15+
int pid;
16+
17+
const volatile unsigned long LEN1;
18+
const volatile unsigned long LEN2;
19+
const volatile unsigned long LEN3;
20+
const volatile unsigned long LEN4;
21+
const volatile unsigned long LEN5;
22+
23+
long reserve1_fail = 0;
24+
long reserve2_fail = 0;
25+
long reserve3_fail = 0;
26+
long reserve4_fail = 0;
27+
long reserve5_fail = 0;
28+
29+
unsigned long avail_data = 0;
30+
unsigned long ring_size = 0;
31+
unsigned long cons_pos = 0;
32+
unsigned long prod_pos = 0;
33+
unsigned long over_pos = 0;
34+
35+
SEC("fentry/" SYS_PREFIX "sys_getpgid")
36+
int test_overwrite_ringbuf(void *ctx)
37+
{
38+
char *rec1, *rec2, *rec3, *rec4, *rec5;
39+
int cur_pid = bpf_get_current_pid_tgid() >> 32;
40+
41+
if (cur_pid != pid)
42+
return 0;
43+
44+
rec1 = bpf_ringbuf_reserve(&ringbuf, LEN1, 0);
45+
if (!rec1) {
46+
reserve1_fail = 1;
47+
return 0;
48+
}
49+
50+
rec2 = bpf_ringbuf_reserve(&ringbuf, LEN2, 0);
51+
if (!rec2) {
52+
bpf_ringbuf_discard(rec1, 0);
53+
reserve2_fail = 1;
54+
return 0;
55+
}
56+
57+
rec3 = bpf_ringbuf_reserve(&ringbuf, LEN3, 0);
58+
/* expect failure */
59+
if (!rec3) {
60+
reserve3_fail = 1;
61+
} else {
62+
bpf_ringbuf_discard(rec1, 0);
63+
bpf_ringbuf_discard(rec2, 0);
64+
bpf_ringbuf_discard(rec3, 0);
65+
return 0;
66+
}
67+
68+
rec4 = bpf_ringbuf_reserve(&ringbuf, LEN4, 0);
69+
if (!rec4) {
70+
reserve4_fail = 1;
71+
bpf_ringbuf_discard(rec1, 0);
72+
bpf_ringbuf_discard(rec2, 0);
73+
return 0;
74+
}
75+
76+
bpf_ringbuf_submit(rec1, 0);
77+
bpf_ringbuf_submit(rec2, 0);
78+
bpf_ringbuf_submit(rec4, 0);
79+
80+
rec5 = bpf_ringbuf_reserve(&ringbuf, LEN5, 0);
81+
if (!rec5) {
82+
reserve5_fail = 1;
83+
return 0;
84+
}
85+
86+
for (int i = 0; i < LEN3; i++)
87+
rec5[i] = 0xdd;
88+
89+
bpf_ringbuf_submit(rec5, 0);
90+
91+
ring_size = bpf_ringbuf_query(&ringbuf, BPF_RB_RING_SIZE);
92+
avail_data = bpf_ringbuf_query(&ringbuf, BPF_RB_AVAIL_DATA);
93+
cons_pos = bpf_ringbuf_query(&ringbuf, BPF_RB_CONS_POS);
94+
prod_pos = bpf_ringbuf_query(&ringbuf, BPF_RB_PROD_POS);
95+
over_pos = bpf_ringbuf_query(&ringbuf, BPF_RB_OVER_POS);
96+
97+
return 0;
98+
}

0 commit comments

Comments
 (0)