Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <xukuohai@huawei.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20251018035738.4039621-3-xukuohai@huaweicloud.com

authored by

Xu Kuohai and committed by
Andrii Nakryiko
8f7a86ec feeaf134

+165 -1
+2 -1
tools/testing/selftests/bpf/Makefile
··· 499 499 500 500 LSKELS := fexit_sleep.c trace_printk.c trace_vprintk.c map_ptr_kern.c \ 501 501 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 503 504 504 505 LSKELS_SIGNED := fentry_test.c fexit_test.c atomics.c 505 506
+65
tools/testing/selftests/bpf/prog_tests/ringbuf.c
··· 17 17 #include "test_ringbuf_n.lskel.h" 18 18 #include "test_ringbuf_map_key.lskel.h" 19 19 #include "test_ringbuf_write.lskel.h" 20 + #include "test_ringbuf_overwrite.lskel.h" 20 21 21 22 #define EDONE 7777 22 23 ··· 498 497 test_ringbuf_map_key_lskel__destroy(skel_map_key); 499 498 } 500 499 500 + static void ringbuf_overwrite_mode_subtest(void) 501 + { 502 + unsigned long size, len1, len2, len3, len4, len5; 503 + unsigned long expect_avail_data, expect_prod_pos, expect_over_pos; 504 + struct test_ringbuf_overwrite_lskel *skel; 505 + int page_size = getpagesize(); 506 + int err; 507 + 508 + skel = test_ringbuf_overwrite_lskel__open(); 509 + if (!ASSERT_OK_PTR(skel, "skel_open")) 510 + return; 511 + 512 + size = page_size; 513 + len1 = page_size / 2; 514 + len2 = page_size / 4; 515 + len3 = size - len1 - len2 - BPF_RINGBUF_HDR_SZ * 3; 516 + len4 = len3 - 8; 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 + ASSERT_EQ(skel->bss->ring_size, size, "check_ring_size"); 545 + 546 + expect_avail_data = len2 + len4 + len5 + 3 * BPF_RINGBUF_HDR_SZ; 547 + ASSERT_EQ(skel->bss->avail_data, expect_avail_data, "check_avail_size"); 548 + 549 + ASSERT_EQ(skel->bss->cons_pos, 0, "check_cons_pos"); 550 + 551 + expect_prod_pos = len1 + len2 + len4 + len5 + 4 * BPF_RINGBUF_HDR_SZ; 552 + ASSERT_EQ(skel->bss->prod_pos, expect_prod_pos, "check_prod_pos"); 553 + 554 + expect_over_pos = len1 + BPF_RINGBUF_HDR_SZ; 555 + ASSERT_EQ(skel->bss->over_pos, expect_over_pos, "check_over_pos"); 556 + 557 + test_ringbuf_overwrite_lskel__detach(skel); 558 + cleanup: 559 + test_ringbuf_overwrite_lskel__destroy(skel); 560 + } 561 + 501 562 void test_ringbuf(void) 502 563 { 503 564 if (test__start_subtest("ringbuf")) ··· 570 507 ringbuf_map_key_subtest(); 571 508 if (test__start_subtest("ringbuf_write")) 572 509 ringbuf_write_subtest(); 510 + if (test__start_subtest("ringbuf_overwrite_mode")) 511 + ringbuf_overwrite_mode_subtest(); 573 512 }
+98
tools/testing/selftests/bpf/progs/test_ringbuf_overwrite.c
··· 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 + }