forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
- Loading branch information
Hou Tao
authored and
Alexei Starovoitov
committed
Nov 1, 2021
1 parent
c196906
commit 31122b2
Showing
2 changed files
with
165 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (C) 2021. Huawei Technologies Co., Ltd */ | ||
#include <test_progs.h> | ||
#include "dummy_st_ops.skel.h" | ||
|
||
/* Need to keep consistent with definition in include/linux/bpf.h */ | ||
struct bpf_dummy_ops_state { | ||
int val; | ||
}; | ||
|
||
static void test_dummy_st_ops_attach(void) | ||
{ | ||
struct dummy_st_ops *skel; | ||
struct bpf_link *link; | ||
|
||
skel = dummy_st_ops__open_and_load(); | ||
if (!ASSERT_OK_PTR(skel, "dummy_st_ops_load")) | ||
return; | ||
|
||
link = bpf_map__attach_struct_ops(skel->maps.dummy_1); | ||
ASSERT_EQ(libbpf_get_error(link), -EOPNOTSUPP, "dummy_st_ops_attach"); | ||
|
||
dummy_st_ops__destroy(skel); | ||
} | ||
|
||
static void test_dummy_init_ret_value(void) | ||
{ | ||
__u64 args[1] = {0}; | ||
struct bpf_prog_test_run_attr attr = { | ||
.ctx_size_in = sizeof(args), | ||
.ctx_in = args, | ||
}; | ||
struct dummy_st_ops *skel; | ||
int fd, err; | ||
|
||
skel = dummy_st_ops__open_and_load(); | ||
if (!ASSERT_OK_PTR(skel, "dummy_st_ops_load")) | ||
return; | ||
|
||
fd = bpf_program__fd(skel->progs.test_1); | ||
attr.prog_fd = fd; | ||
err = bpf_prog_test_run_xattr(&attr); | ||
ASSERT_OK(err, "test_run"); | ||
ASSERT_EQ(attr.retval, 0xf2f3f4f5, "test_ret"); | ||
|
||
dummy_st_ops__destroy(skel); | ||
} | ||
|
||
static void test_dummy_init_ptr_arg(void) | ||
{ | ||
int exp_retval = 0xbeef; | ||
struct bpf_dummy_ops_state in_state = { | ||
.val = exp_retval, | ||
}; | ||
__u64 args[1] = {(unsigned long)&in_state}; | ||
struct bpf_prog_test_run_attr attr = { | ||
.ctx_size_in = sizeof(args), | ||
.ctx_in = args, | ||
}; | ||
struct dummy_st_ops *skel; | ||
int fd, err; | ||
|
||
skel = dummy_st_ops__open_and_load(); | ||
if (!ASSERT_OK_PTR(skel, "dummy_st_ops_load")) | ||
return; | ||
|
||
fd = bpf_program__fd(skel->progs.test_1); | ||
attr.prog_fd = fd; | ||
err = bpf_prog_test_run_xattr(&attr); | ||
ASSERT_OK(err, "test_run"); | ||
ASSERT_EQ(in_state.val, 0x5a, "test_ptr_ret"); | ||
ASSERT_EQ(attr.retval, exp_retval, "test_ret"); | ||
|
||
dummy_st_ops__destroy(skel); | ||
} | ||
|
||
static void test_dummy_multiple_args(void) | ||
{ | ||
__u64 args[5] = {0, -100, 0x8a5f, 'c', 0x1234567887654321ULL}; | ||
struct bpf_prog_test_run_attr attr = { | ||
.ctx_size_in = sizeof(args), | ||
.ctx_in = args, | ||
}; | ||
struct dummy_st_ops *skel; | ||
int fd, err; | ||
size_t i; | ||
char name[8]; | ||
|
||
skel = dummy_st_ops__open_and_load(); | ||
if (!ASSERT_OK_PTR(skel, "dummy_st_ops_load")) | ||
return; | ||
|
||
fd = bpf_program__fd(skel->progs.test_2); | ||
attr.prog_fd = fd; | ||
err = bpf_prog_test_run_xattr(&attr); | ||
ASSERT_OK(err, "test_run"); | ||
for (i = 0; i < ARRAY_SIZE(args); i++) { | ||
snprintf(name, sizeof(name), "arg %zu", i); | ||
ASSERT_EQ(skel->bss->test_2_args[i], args[i], name); | ||
} | ||
|
||
dummy_st_ops__destroy(skel); | ||
} | ||
|
||
void test_dummy_st_ops(void) | ||
{ | ||
if (test__start_subtest("dummy_st_ops_attach")) | ||
test_dummy_st_ops_attach(); | ||
if (test__start_subtest("dummy_init_ret_value")) | ||
test_dummy_init_ret_value(); | ||
if (test__start_subtest("dummy_init_ptr_arg")) | ||
test_dummy_init_ptr_arg(); | ||
if (test__start_subtest("dummy_multiple_args")) | ||
test_dummy_multiple_args(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (C) 2021. Huawei Technologies Co., Ltd */ | ||
#include <linux/bpf.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include <bpf/bpf_tracing.h> | ||
|
||
struct bpf_dummy_ops_state { | ||
int val; | ||
} __attribute__((preserve_access_index)); | ||
|
||
struct bpf_dummy_ops { | ||
int (*test_1)(struct bpf_dummy_ops_state *state); | ||
int (*test_2)(struct bpf_dummy_ops_state *state, int a1, unsigned short a2, | ||
char a3, unsigned long a4); | ||
}; | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|
||
SEC("struct_ops/test_1") | ||
int BPF_PROG(test_1, struct bpf_dummy_ops_state *state) | ||
{ | ||
int ret; | ||
|
||
if (!state) | ||
return 0xf2f3f4f5; | ||
|
||
ret = state->val; | ||
state->val = 0x5a; | ||
return ret; | ||
} | ||
|
||
__u64 test_2_args[5]; | ||
|
||
SEC("struct_ops/test_2") | ||
int BPF_PROG(test_2, struct bpf_dummy_ops_state *state, int a1, unsigned short a2, | ||
char a3, unsigned long a4) | ||
{ | ||
test_2_args[0] = (unsigned long)state; | ||
test_2_args[1] = a1; | ||
test_2_args[2] = a2; | ||
test_2_args[3] = a3; | ||
test_2_args[4] = a4; | ||
return 0; | ||
} | ||
|
||
SEC(".struct_ops") | ||
struct bpf_dummy_ops dummy_1 = { | ||
.test_1 = (void *)test_1, | ||
.test_2 = (void *)test_2, | ||
}; |