selftests/bpf: Add link pinning selftests
Add selftests validating link pinning/unpinning and associated BPF link (attachment) lifetime. Signed-off-by: Andrii Nakryiko <andriin@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/20200303043159.323675-4-andriin@fb.com
This commit is contained in:
parent
c016b68edc
commit
6489b8e1e3
|
@ -0,0 +1,105 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright (c) 2020 Facebook */
|
||||||
|
|
||||||
|
#include <test_progs.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "test_link_pinning.skel.h"
|
||||||
|
|
||||||
|
static int duration = 0;
|
||||||
|
|
||||||
|
void test_link_pinning_subtest(struct bpf_program *prog,
|
||||||
|
struct test_link_pinning__bss *bss)
|
||||||
|
{
|
||||||
|
const char *link_pin_path = "/sys/fs/bpf/pinned_link_test";
|
||||||
|
struct stat statbuf = {};
|
||||||
|
struct bpf_link *link;
|
||||||
|
int err, i;
|
||||||
|
|
||||||
|
link = bpf_program__attach(prog);
|
||||||
|
if (CHECK(IS_ERR(link), "link_attach", "err: %ld\n", PTR_ERR(link)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
bss->in = 1;
|
||||||
|
usleep(1);
|
||||||
|
CHECK(bss->out != 1, "res_check1", "exp %d, got %d\n", 1, bss->out);
|
||||||
|
|
||||||
|
/* pin link */
|
||||||
|
err = bpf_link__pin(link, link_pin_path);
|
||||||
|
if (CHECK(err, "link_pin", "err: %d\n", err))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
CHECK(strcmp(link_pin_path, bpf_link__pin_path(link)), "pin_path1",
|
||||||
|
"exp %s, got %s\n", link_pin_path, bpf_link__pin_path(link));
|
||||||
|
|
||||||
|
/* check that link was pinned */
|
||||||
|
err = stat(link_pin_path, &statbuf);
|
||||||
|
if (CHECK(err, "stat_link", "err %d errno %d\n", err, errno))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
bss->in = 2;
|
||||||
|
usleep(1);
|
||||||
|
CHECK(bss->out != 2, "res_check2", "exp %d, got %d\n", 2, bss->out);
|
||||||
|
|
||||||
|
/* destroy link, pinned link should keep program attached */
|
||||||
|
bpf_link__destroy(link);
|
||||||
|
link = NULL;
|
||||||
|
|
||||||
|
bss->in = 3;
|
||||||
|
usleep(1);
|
||||||
|
CHECK(bss->out != 3, "res_check3", "exp %d, got %d\n", 3, bss->out);
|
||||||
|
|
||||||
|
/* re-open link from BPFFS */
|
||||||
|
link = bpf_link__open(link_pin_path);
|
||||||
|
if (CHECK(IS_ERR(link), "link_open", "err: %ld\n", PTR_ERR(link)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
CHECK(strcmp(link_pin_path, bpf_link__pin_path(link)), "pin_path2",
|
||||||
|
"exp %s, got %s\n", link_pin_path, bpf_link__pin_path(link));
|
||||||
|
|
||||||
|
/* unpin link from BPFFS, program still attached */
|
||||||
|
err = bpf_link__unpin(link);
|
||||||
|
if (CHECK(err, "link_unpin", "err: %d\n", err))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* still active, as we have FD open now */
|
||||||
|
bss->in = 4;
|
||||||
|
usleep(1);
|
||||||
|
CHECK(bss->out != 4, "res_check4", "exp %d, got %d\n", 4, bss->out);
|
||||||
|
|
||||||
|
bpf_link__destroy(link);
|
||||||
|
link = NULL;
|
||||||
|
|
||||||
|
/* Validate it's finally detached.
|
||||||
|
* Actual detachment might get delayed a bit, so there is no reliable
|
||||||
|
* way to validate it immediately here, let's count up for long enough
|
||||||
|
* and see if eventually output stops being updated
|
||||||
|
*/
|
||||||
|
for (i = 5; i < 10000; i++) {
|
||||||
|
bss->in = i;
|
||||||
|
usleep(1);
|
||||||
|
if (bss->out == i - 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CHECK(i == 10000, "link_attached", "got to iteration #%d\n", i);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (!IS_ERR(link))
|
||||||
|
bpf_link__destroy(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_link_pinning(void)
|
||||||
|
{
|
||||||
|
struct test_link_pinning* skel;
|
||||||
|
|
||||||
|
skel = test_link_pinning__open_and_load();
|
||||||
|
if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (test__start_subtest("pin_raw_tp"))
|
||||||
|
test_link_pinning_subtest(skel->progs.raw_tp_prog, skel->bss);
|
||||||
|
if (test__start_subtest("pin_tp_btf"))
|
||||||
|
test_link_pinning_subtest(skel->progs.tp_btf_prog, skel->bss);
|
||||||
|
|
||||||
|
test_link_pinning__destroy(skel);
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright (c) 2020 Facebook */
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <linux/bpf.h>
|
||||||
|
#include <bpf/bpf_helpers.h>
|
||||||
|
|
||||||
|
int in = 0;
|
||||||
|
int out = 0;
|
||||||
|
|
||||||
|
SEC("raw_tp/sys_enter")
|
||||||
|
int raw_tp_prog(const void *ctx)
|
||||||
|
{
|
||||||
|
out = in;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SEC("tp_btf/sys_enter")
|
||||||
|
int tp_btf_prog(const void *ctx)
|
||||||
|
{
|
||||||
|
out = in;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char _license[] SEC("license") = "GPL";
|
Loading…
Reference in New Issue