mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-23 14:24:25 +08:00
selftests/bpf: Add selftest for multi-prog sections and bpf-to-bpf calls
Add a selftest excercising bpf-to-bpf subprogram calls, as well as multiple entry-point BPF programs per section. Also make sure that BPF CO-RE works for such set ups both for sub-programs and for multi-entry sections. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200903203542.15944-8-andriin@fb.com
This commit is contained in:
parent
7e06aad529
commit
a08c02f8d4
31
tools/testing/selftests/bpf/prog_tests/subprogs.c
Normal file
31
tools/testing/selftests/bpf/prog_tests/subprogs.c
Normal file
@ -0,0 +1,31 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2020 Facebook */
|
||||
#include <test_progs.h>
|
||||
#include <time.h>
|
||||
#include "test_subprogs.skel.h"
|
||||
|
||||
static int duration;
|
||||
|
||||
void test_subprogs(void)
|
||||
{
|
||||
struct test_subprogs *skel;
|
||||
int err;
|
||||
|
||||
skel = test_subprogs__open_and_load();
|
||||
if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
|
||||
return;
|
||||
|
||||
err = test_subprogs__attach(skel);
|
||||
if (CHECK(err, "skel_attach", "failed to attach skeleton: %d\n", err))
|
||||
goto cleanup;
|
||||
|
||||
usleep(1);
|
||||
|
||||
CHECK(skel->bss->res1 != 12, "res1", "got %d, exp %d\n", skel->bss->res1, 12);
|
||||
CHECK(skel->bss->res2 != 17, "res2", "got %d, exp %d\n", skel->bss->res2, 17);
|
||||
CHECK(skel->bss->res3 != 19, "res3", "got %d, exp %d\n", skel->bss->res3, 19);
|
||||
CHECK(skel->bss->res4 != 36, "res4", "got %d, exp %d\n", skel->bss->res4, 36);
|
||||
|
||||
cleanup:
|
||||
test_subprogs__destroy(skel);
|
||||
}
|
103
tools/testing/selftests/bpf/progs/test_subprogs.c
Normal file
103
tools/testing/selftests/bpf/progs/test_subprogs.c
Normal file
@ -0,0 +1,103 @@
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_core_read.h>
|
||||
|
||||
const char LICENSE[] SEC("license") = "GPL";
|
||||
|
||||
__noinline int sub1(int x)
|
||||
{
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
static __noinline int sub5(int v);
|
||||
|
||||
__noinline int sub2(int y)
|
||||
{
|
||||
return sub5(y + 2);
|
||||
}
|
||||
|
||||
static __noinline int sub3(int z)
|
||||
{
|
||||
return z + 3 + sub1(4);
|
||||
}
|
||||
|
||||
static __noinline int sub4(int w)
|
||||
{
|
||||
return w + sub3(5) + sub1(6);
|
||||
}
|
||||
|
||||
/* sub5() is an identitify function, just to test weirder functions layout and
|
||||
* call patterns
|
||||
*/
|
||||
static __noinline int sub5(int v)
|
||||
{
|
||||
return sub1(v) - 1; /* compensates sub1()'s + 1 */
|
||||
}
|
||||
|
||||
/* unfortunately verifier rejects `struct task_struct *t` as an unkown pointer
|
||||
* type, so we need to accept pointer as integer and then cast it inside the
|
||||
* function
|
||||
*/
|
||||
__noinline int get_task_tgid(uintptr_t t)
|
||||
{
|
||||
/* this ensures that CO-RE relocs work in multi-subprogs .text */
|
||||
return BPF_CORE_READ((struct task_struct *)(void *)t, tgid);
|
||||
}
|
||||
|
||||
int res1 = 0;
|
||||
int res2 = 0;
|
||||
int res3 = 0;
|
||||
int res4 = 0;
|
||||
|
||||
SEC("raw_tp/sys_enter")
|
||||
int prog1(void *ctx)
|
||||
{
|
||||
/* perform some CO-RE relocations to ensure they work with multi-prog
|
||||
* sections correctly
|
||||
*/
|
||||
struct task_struct *t = (void *)bpf_get_current_task();
|
||||
|
||||
if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
|
||||
return 1;
|
||||
|
||||
res1 = sub1(1) + sub3(2); /* (1 + 1) + (2 + 3 + (4 + 1)) = 12 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("raw_tp/sys_exit")
|
||||
int prog2(void *ctx)
|
||||
{
|
||||
struct task_struct *t = (void *)bpf_get_current_task();
|
||||
|
||||
if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
|
||||
return 1;
|
||||
|
||||
res2 = sub2(3) + sub3(4); /* (3 + 2) + (4 + 3 + (4 + 1)) = 17 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* prog3 has the same section name as prog1 */
|
||||
SEC("raw_tp/sys_enter")
|
||||
int prog3(void *ctx)
|
||||
{
|
||||
struct task_struct *t = (void *)bpf_get_current_task();
|
||||
|
||||
if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
|
||||
return 1;
|
||||
|
||||
res3 = sub3(5) + 6; /* (5 + 3 + (4 + 1)) + 6 = 19 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* prog4 has the same section name as prog2 */
|
||||
SEC("raw_tp/sys_exit")
|
||||
int prog4(void *ctx)
|
||||
{
|
||||
struct task_struct *t = (void *)bpf_get_current_task();
|
||||
|
||||
if (!BPF_CORE_READ(t, pid) || !get_task_tgid((uintptr_t)t))
|
||||
return 1;
|
||||
|
||||
res4 = sub4(7) + sub1(8); /* (7 + (5 + 3 + (4 + 1)) + (6 + 1)) + (8 + 1) = 36 */
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user