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

selftests/bpf: Add test cases for struct_ops prog

Running a BPF_PROG_TYPE_STRUCT_OPS prog for dummy_st_ops::test_N()
through bpf_prog_test_run(). Four test cases are added:
(1) attach dummy_st_ops should fail
(2) function return value of bpf_dummy_ops::test_1() is expected
(3) pointer argument of bpf_dummy_ops::test_1() works as expected
(4) multiple arguments passed to bpf_dummy_ops::test_2() are correct

Signed-off-by: Hou Tao <houtao1@huawei.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/20211025064025.2567443-5-houtao1@huawei.com

authored by

Hou Tao and committed by
Alexei Starovoitov
31122b2f c196906d

+165
+115
tools/testing/selftests/bpf/prog_tests/dummy_st_ops.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (C) 2021. Huawei Technologies Co., Ltd */ 3 + #include <test_progs.h> 4 + #include "dummy_st_ops.skel.h" 5 + 6 + /* Need to keep consistent with definition in include/linux/bpf.h */ 7 + struct bpf_dummy_ops_state { 8 + int val; 9 + }; 10 + 11 + static void test_dummy_st_ops_attach(void) 12 + { 13 + struct dummy_st_ops *skel; 14 + struct bpf_link *link; 15 + 16 + skel = dummy_st_ops__open_and_load(); 17 + if (!ASSERT_OK_PTR(skel, "dummy_st_ops_load")) 18 + return; 19 + 20 + link = bpf_map__attach_struct_ops(skel->maps.dummy_1); 21 + ASSERT_EQ(libbpf_get_error(link), -EOPNOTSUPP, "dummy_st_ops_attach"); 22 + 23 + dummy_st_ops__destroy(skel); 24 + } 25 + 26 + static void test_dummy_init_ret_value(void) 27 + { 28 + __u64 args[1] = {0}; 29 + struct bpf_prog_test_run_attr attr = { 30 + .ctx_size_in = sizeof(args), 31 + .ctx_in = args, 32 + }; 33 + struct dummy_st_ops *skel; 34 + int fd, err; 35 + 36 + skel = dummy_st_ops__open_and_load(); 37 + if (!ASSERT_OK_PTR(skel, "dummy_st_ops_load")) 38 + return; 39 + 40 + fd = bpf_program__fd(skel->progs.test_1); 41 + attr.prog_fd = fd; 42 + err = bpf_prog_test_run_xattr(&attr); 43 + ASSERT_OK(err, "test_run"); 44 + ASSERT_EQ(attr.retval, 0xf2f3f4f5, "test_ret"); 45 + 46 + dummy_st_ops__destroy(skel); 47 + } 48 + 49 + static void test_dummy_init_ptr_arg(void) 50 + { 51 + int exp_retval = 0xbeef; 52 + struct bpf_dummy_ops_state in_state = { 53 + .val = exp_retval, 54 + }; 55 + __u64 args[1] = {(unsigned long)&in_state}; 56 + struct bpf_prog_test_run_attr attr = { 57 + .ctx_size_in = sizeof(args), 58 + .ctx_in = args, 59 + }; 60 + struct dummy_st_ops *skel; 61 + int fd, err; 62 + 63 + skel = dummy_st_ops__open_and_load(); 64 + if (!ASSERT_OK_PTR(skel, "dummy_st_ops_load")) 65 + return; 66 + 67 + fd = bpf_program__fd(skel->progs.test_1); 68 + attr.prog_fd = fd; 69 + err = bpf_prog_test_run_xattr(&attr); 70 + ASSERT_OK(err, "test_run"); 71 + ASSERT_EQ(in_state.val, 0x5a, "test_ptr_ret"); 72 + ASSERT_EQ(attr.retval, exp_retval, "test_ret"); 73 + 74 + dummy_st_ops__destroy(skel); 75 + } 76 + 77 + static void test_dummy_multiple_args(void) 78 + { 79 + __u64 args[5] = {0, -100, 0x8a5f, 'c', 0x1234567887654321ULL}; 80 + struct bpf_prog_test_run_attr attr = { 81 + .ctx_size_in = sizeof(args), 82 + .ctx_in = args, 83 + }; 84 + struct dummy_st_ops *skel; 85 + int fd, err; 86 + size_t i; 87 + char name[8]; 88 + 89 + skel = dummy_st_ops__open_and_load(); 90 + if (!ASSERT_OK_PTR(skel, "dummy_st_ops_load")) 91 + return; 92 + 93 + fd = bpf_program__fd(skel->progs.test_2); 94 + attr.prog_fd = fd; 95 + err = bpf_prog_test_run_xattr(&attr); 96 + ASSERT_OK(err, "test_run"); 97 + for (i = 0; i < ARRAY_SIZE(args); i++) { 98 + snprintf(name, sizeof(name), "arg %zu", i); 99 + ASSERT_EQ(skel->bss->test_2_args[i], args[i], name); 100 + } 101 + 102 + dummy_st_ops__destroy(skel); 103 + } 104 + 105 + void test_dummy_st_ops(void) 106 + { 107 + if (test__start_subtest("dummy_st_ops_attach")) 108 + test_dummy_st_ops_attach(); 109 + if (test__start_subtest("dummy_init_ret_value")) 110 + test_dummy_init_ret_value(); 111 + if (test__start_subtest("dummy_init_ptr_arg")) 112 + test_dummy_init_ptr_arg(); 113 + if (test__start_subtest("dummy_multiple_args")) 114 + test_dummy_multiple_args(); 115 + }
+50
tools/testing/selftests/bpf/progs/dummy_st_ops.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (C) 2021. Huawei Technologies Co., Ltd */ 3 + #include <linux/bpf.h> 4 + #include <bpf/bpf_helpers.h> 5 + #include <bpf/bpf_tracing.h> 6 + 7 + struct bpf_dummy_ops_state { 8 + int val; 9 + } __attribute__((preserve_access_index)); 10 + 11 + struct bpf_dummy_ops { 12 + int (*test_1)(struct bpf_dummy_ops_state *state); 13 + int (*test_2)(struct bpf_dummy_ops_state *state, int a1, unsigned short a2, 14 + char a3, unsigned long a4); 15 + }; 16 + 17 + char _license[] SEC("license") = "GPL"; 18 + 19 + SEC("struct_ops/test_1") 20 + int BPF_PROG(test_1, struct bpf_dummy_ops_state *state) 21 + { 22 + int ret; 23 + 24 + if (!state) 25 + return 0xf2f3f4f5; 26 + 27 + ret = state->val; 28 + state->val = 0x5a; 29 + return ret; 30 + } 31 + 32 + __u64 test_2_args[5]; 33 + 34 + SEC("struct_ops/test_2") 35 + int BPF_PROG(test_2, struct bpf_dummy_ops_state *state, int a1, unsigned short a2, 36 + char a3, unsigned long a4) 37 + { 38 + test_2_args[0] = (unsigned long)state; 39 + test_2_args[1] = a1; 40 + test_2_args[2] = a2; 41 + test_2_args[3] = a3; 42 + test_2_args[4] = a4; 43 + return 0; 44 + } 45 + 46 + SEC(".struct_ops") 47 + struct bpf_dummy_ops dummy_1 = { 48 + .test_1 = (void *)test_1, 49 + .test_2 = (void *)test_2, 50 + };