diff options
Diffstat (limited to 'tools/testing/selftests/bpf/prog_tests/link_pinning.c')
| -rw-r--r-- | tools/testing/selftests/bpf/prog_tests/link_pinning.c | 105 | 
1 files changed, 105 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/prog_tests/link_pinning.c b/tools/testing/selftests/bpf/prog_tests/link_pinning.c new file mode 100644 index 000000000000..a743288cf384 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/link_pinning.c @@ -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); +}  | 
