Skip to content

Commit 8f7a86e

Browse files
Xu Kuohaianakryiko
authored andcommitted
selftests/bpf: Add overwrite mode test for BPF ring buffer
Add overwrite mode test for BPF ring buffer. The test creates a BPF ring buffer in overwrite mode, then repeatedly reserves and commits records to check if the ring buffer works as expected both before and after overwriting occurs. Signed-off-by: Xu Kuohai <[email protected]> Signed-off-by: Andrii Nakryiko <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent feeaf13 commit 8f7a86e

File tree

3 files changed

+165
-1
lines changed

3 files changed

+165
-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

500500
LSKELS := fexit_sleep.c 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
LSKELS_SIGNED := fentry_test.c fexit_test.c atomics.c
505506

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

Lines changed: 65 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,68 @@ 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 page_size = getpagesize();
507+
int err;
508+
509+
skel = test_ringbuf_overwrite_lskel__open();
510+
if (!ASSERT_OK_PTR(skel, "skel_open"))
511+
return;
512+
513+
size = page_size;
514+
len1 = page_size / 2;
515+
len2 = page_size / 4;
516+
len3 = size - len1 - len2 - BPF_RINGBUF_HDR_SZ * 3;
517+
len4 = len3 - 8;
518+
len5 = len3; /* retry with len3 */
519+
520+
skel->maps.ringbuf.max_entries = size;
521+
skel->rodata->LEN1 = len1;
522+
skel->rodata->LEN2 = len2;
523+
skel->rodata->LEN3 = len3;
524+
skel->rodata->LEN4 = len4;
525+
skel->rodata->LEN5 = len5;
526+
527+
skel->bss->pid = getpid();
528+
529+
err = test_ringbuf_overwrite_lskel__load(skel);
530+
if (!ASSERT_OK(err, "skel_load"))
531+
goto cleanup;
532+
533+
err = test_ringbuf_overwrite_lskel__attach(skel);
534+
if (!ASSERT_OK(err, "skel_attach"))
535+
goto cleanup;
536+
537+
syscall(__NR_getpgid);
538+
539+
ASSERT_EQ(skel->bss->reserve1_fail, 0, "reserve 1");
540+
ASSERT_EQ(skel->bss->reserve2_fail, 0, "reserve 2");
541+
ASSERT_EQ(skel->bss->reserve3_fail, 1, "reserve 3");
542+
ASSERT_EQ(skel->bss->reserve4_fail, 0, "reserve 4");
543+
ASSERT_EQ(skel->bss->reserve5_fail, 0, "reserve 5");
544+
545+
ASSERT_EQ(skel->bss->ring_size, size, "check_ring_size");
546+
547+
expect_avail_data = len2 + len4 + len5 + 3 * BPF_RINGBUF_HDR_SZ;
548+
ASSERT_EQ(skel->bss->avail_data, expect_avail_data, "check_avail_size");
549+
550+
ASSERT_EQ(skel->bss->cons_pos, 0, "check_cons_pos");
551+
552+
expect_prod_pos = len1 + len2 + len4 + len5 + 4 * BPF_RINGBUF_HDR_SZ;
553+
ASSERT_EQ(skel->bss->prod_pos, expect_prod_pos, "check_prod_pos");
554+
555+
expect_over_pos = len1 + BPF_RINGBUF_HDR_SZ;
556+
ASSERT_EQ(skel->bss->over_pos, expect_over_pos, "check_over_pos");
557+
558+
test_ringbuf_overwrite_lskel__detach(skel);
559+
cleanup:
560+
test_ringbuf_overwrite_lskel__destroy(skel);
561+
}
562+
500563
void test_ringbuf(void)
501564
{
502565
if (test__start_subtest("ringbuf"))
@@ -507,4 +570,6 @@ void test_ringbuf(void)
507570
ringbuf_map_key_subtest();
508571
if (test__start_subtest("ringbuf_write"))
509572
ringbuf_write_subtest();
573+
if (test__start_subtest("ringbuf_overwrite_mode"))
574+
ringbuf_overwrite_mode_subtest();
510575
}
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_RB_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_OVERWRITE_POS);
96+
97+
return 0;
98+
}

0 commit comments

Comments
 (0)