2019-03-01 19:42:13 -08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2022-12-07 12:16:47 -08:00
|
|
|
#ifndef __TEST_PROGS_H
|
|
|
|
#define __TEST_PROGS_H
|
|
|
|
|
2019-03-01 19:42:13 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
#include <linux/types.h>
|
|
|
|
typedef __u16 __sum16;
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <linux/if_ether.h>
|
|
|
|
#include <linux/if_packet.h>
|
|
|
|
#include <linux/ip.h>
|
|
|
|
#include <linux/ipv6.h>
|
|
|
|
#include <linux/filter.h>
|
|
|
|
#include <linux/perf_event.h>
|
2019-09-04 09:25:06 -07:00
|
|
|
#include <linux/socket.h>
|
2019-03-01 19:42:13 -08:00
|
|
|
#include <linux/unistd.h>
|
|
|
|
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/time.h>
|
2022-04-09 07:58:17 +08:00
|
|
|
#include <sys/param.h>
|
2019-03-01 19:42:13 -08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
#include <linux/bpf.h>
|
|
|
|
#include <linux/err.h>
|
|
|
|
#include <bpf/bpf.h>
|
|
|
|
#include <bpf/libbpf.h>
|
|
|
|
|
|
|
|
#include "test_iptunnel_common.h"
|
|
|
|
#include "bpf_util.h"
|
2020-01-20 14:06:45 +01:00
|
|
|
#include <bpf/bpf_endian.h>
|
2019-03-01 19:42:13 -08:00
|
|
|
#include "trace_helpers.h"
|
2020-05-12 12:24:42 -07:00
|
|
|
#include "testing_helpers.h"
|
2019-03-01 19:42:13 -08:00
|
|
|
|
2019-11-19 16:35:48 -08:00
|
|
|
enum verbosity {
|
|
|
|
VERBOSE_NONE,
|
|
|
|
VERBOSE_NORMAL,
|
|
|
|
VERBOSE_VERY,
|
|
|
|
VERBOSE_SUPER,
|
|
|
|
};
|
|
|
|
|
2022-04-08 17:17:49 -07:00
|
|
|
struct test_filter {
|
|
|
|
char *name;
|
|
|
|
char **subtests;
|
|
|
|
int subtest_cnt;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct test_filter_set {
|
|
|
|
struct test_filter *tests;
|
selftests/bpf: Add whitelist/blacklist of test names to test_progs
Add ability to specify a list of test name substrings for selecting which
tests to run. So now -t is accepting a comma-separated list of strings,
similarly to how -n accepts a comma-separated list of test numbers.
Additionally, add ability to blacklist tests by name. Blacklist takes
precedence over whitelist. Blacklisting is important for cases where it's
known that some tests can't pass (e.g., due to perf hardware events that are
not available within VM). This is going to be used for libbpf testing in
Travis CI in its Github repo.
Example runs with just whitelist and whitelist + blacklist:
$ sudo ./test_progs -tattach,core/existence
#1 attach_probe:OK
#6 cgroup_attach_autodetach:OK
#7 cgroup_attach_multi:OK
#8 cgroup_attach_override:OK
#9 core_extern:OK
#10/44 existence:OK
#10/45 existence___minimal:OK
#10/46 existence__err_int_sz:OK
#10/47 existence__err_int_type:OK
#10/48 existence__err_int_kind:OK
#10/49 existence__err_arr_kind:OK
#10/50 existence__err_arr_value_type:OK
#10/51 existence__err_struct_type:OK
#10 core_reloc:OK
#19 flow_dissector_reattach:OK
#60 tp_attach_query:OK
Summary: 8/8 PASSED, 0 SKIPPED, 0 FAILED
$ sudo ./test_progs -tattach,core/existence -bcgroup,flow/arr
#1 attach_probe:OK
#9 core_extern:OK
#10/44 existence:OK
#10/45 existence___minimal:OK
#10/46 existence__err_int_sz:OK
#10/47 existence__err_int_type:OK
#10/48 existence__err_int_kind:OK
#10/51 existence__err_struct_type:OK
#10 core_reloc:OK
#60 tp_attach_query:OK
Summary: 4/6 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Cc: Julia Kartseva <hex@fb.com>
Link: https://lore.kernel.org/bpf/20200116005549.3644118-1-andriin@fb.com
2020-01-15 16:55:49 -08:00
|
|
|
int cnt;
|
|
|
|
};
|
|
|
|
|
selftests/bpf: add sub-tests support for test_progs
Allow tests to have their own set of sub-tests. Also add ability to do
test/subtest selection using `-t <test-name>/<subtest-name>` and `-n
<test-nums-set>/<subtest-nums-set>`, as an extension of existing -t/-n
selector options. For the <test-num-set> format: it's a comma-separated
list of either individual test numbers (1-based), or range of test
numbers. E.g., all of the following are valid sets of test numbers:
- 10
- 1,2,3
- 1-3
- 5-10,1,3-4
'/<subtest' part is optional, but has the same format. E.g., to select
test #3 and its sub-tests #10 through #15, use: -t 3/10-15.
Similarly, to select tests by name, use `-t verif/strobe`:
$ sudo ./test_progs -t verif/strobe
#3/12 strobemeta.o:OK
#3/13 strobemeta_nounroll1.o:OK
#3/14 strobemeta_nounroll2.o:OK
#3 bpf_verif_scale:OK
Summary: 1/3 PASSED, 0 FAILED
Example of using subtest API is in the next patch, converting
bpf_verif_scale.c tests to use sub-tests.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-07-27 20:25:29 -07:00
|
|
|
struct test_selector {
|
2022-04-08 17:17:49 -07:00
|
|
|
struct test_filter_set whitelist;
|
|
|
|
struct test_filter_set blacklist;
|
selftests/bpf: add sub-tests support for test_progs
Allow tests to have their own set of sub-tests. Also add ability to do
test/subtest selection using `-t <test-name>/<subtest-name>` and `-n
<test-nums-set>/<subtest-nums-set>`, as an extension of existing -t/-n
selector options. For the <test-num-set> format: it's a comma-separated
list of either individual test numbers (1-based), or range of test
numbers. E.g., all of the following are valid sets of test numbers:
- 10
- 1,2,3
- 1-3
- 5-10,1,3-4
'/<subtest' part is optional, but has the same format. E.g., to select
test #3 and its sub-tests #10 through #15, use: -t 3/10-15.
Similarly, to select tests by name, use `-t verif/strobe`:
$ sudo ./test_progs -t verif/strobe
#3/12 strobemeta.o:OK
#3/13 strobemeta_nounroll1.o:OK
#3/14 strobemeta_nounroll2.o:OK
#3 bpf_verif_scale:OK
Summary: 1/3 PASSED, 0 FAILED
Example of using subtest API is in the next patch, converting
bpf_verif_scale.c tests to use sub-tests.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-07-27 20:25:29 -07:00
|
|
|
bool *num_set;
|
|
|
|
int num_set_len;
|
|
|
|
};
|
|
|
|
|
2022-04-26 21:13:53 -07:00
|
|
|
struct subtest_state {
|
|
|
|
char *name;
|
|
|
|
size_t log_cnt;
|
|
|
|
char *log_buf;
|
|
|
|
int error_cnt;
|
|
|
|
bool skipped;
|
2022-05-19 23:13:03 -07:00
|
|
|
bool filtered;
|
2022-04-26 21:13:53 -07:00
|
|
|
|
|
|
|
FILE *stdout;
|
|
|
|
};
|
|
|
|
|
2022-04-18 15:25:07 -07:00
|
|
|
struct test_state {
|
|
|
|
bool tested;
|
|
|
|
bool force_log;
|
|
|
|
|
|
|
|
int error_cnt;
|
|
|
|
int skip_cnt;
|
|
|
|
int sub_succ_cnt;
|
|
|
|
|
2022-04-26 21:13:53 -07:00
|
|
|
struct subtest_state *subtest_states;
|
2022-04-18 15:25:07 -07:00
|
|
|
int subtest_num;
|
|
|
|
|
|
|
|
size_t log_cnt;
|
|
|
|
char *log_buf;
|
2022-04-26 21:13:53 -07:00
|
|
|
|
|
|
|
FILE *stdout;
|
2022-04-18 15:25:07 -07:00
|
|
|
};
|
|
|
|
|
2019-07-27 20:25:28 -07:00
|
|
|
struct test_env {
|
selftests/bpf: add sub-tests support for test_progs
Allow tests to have their own set of sub-tests. Also add ability to do
test/subtest selection using `-t <test-name>/<subtest-name>` and `-n
<test-nums-set>/<subtest-nums-set>`, as an extension of existing -t/-n
selector options. For the <test-num-set> format: it's a comma-separated
list of either individual test numbers (1-based), or range of test
numbers. E.g., all of the following are valid sets of test numbers:
- 10
- 1,2,3
- 1-3
- 5-10,1,3-4
'/<subtest' part is optional, but has the same format. E.g., to select
test #3 and its sub-tests #10 through #15, use: -t 3/10-15.
Similarly, to select tests by name, use `-t verif/strobe`:
$ sudo ./test_progs -t verif/strobe
#3/12 strobemeta.o:OK
#3/13 strobemeta_nounroll1.o:OK
#3/14 strobemeta_nounroll2.o:OK
#3 bpf_verif_scale:OK
Summary: 1/3 PASSED, 0 FAILED
Example of using subtest API is in the next patch, converting
bpf_verif_scale.c tests to use sub-tests.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-07-27 20:25:29 -07:00
|
|
|
struct test_selector test_selector;
|
|
|
|
struct test_selector subtest_selector;
|
2019-07-27 20:25:28 -07:00
|
|
|
bool verifier_stats;
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
bool debug;
|
2019-11-19 16:35:48 -08:00
|
|
|
enum verbosity verbosity;
|
2019-07-27 20:25:28 -07:00
|
|
|
|
|
|
|
bool jit_enabled;
|
2020-12-03 12:46:26 -08:00
|
|
|
bool has_testmod;
|
2020-07-01 23:44:12 +02:00
|
|
|
bool get_test_cnt;
|
2020-07-01 23:44:17 +02:00
|
|
|
bool list_test_names;
|
2019-07-27 20:25:28 -07:00
|
|
|
|
2022-04-18 15:25:07 -07:00
|
|
|
struct prog_test_def *test; /* current running test */
|
2022-04-26 21:13:53 -07:00
|
|
|
struct test_state *test_state; /* current running test state */
|
|
|
|
struct subtest_state *subtest_state; /* current running subtest state */
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
|
2019-08-06 10:45:27 -07:00
|
|
|
FILE *stdout;
|
|
|
|
FILE *stderr;
|
2020-03-13 18:39:32 -07:00
|
|
|
int nr_cpus;
|
selftests/bpf: Add --json-summary option to test_progs
Currently, test_progs outputs all stdout/stderr as it runs, and when it
is done, prints a summary.
It is non-trivial for tooling to parse that output and extract meaningful
information from it.
This change adds a new option, `--json-summary`/`-J` that let the caller
specify a file where `test_progs{,-no_alu32}` can write a summary of the
run in a json format that can later be parsed by tooling.
Currently, it creates a summary section with successes/skipped/failures
followed by a list of failed tests and subtests.
A test contains the following fields:
- name: the name of the test
- number: the number of the test
- message: the log message that was printed by the test.
- failed: A boolean indicating whether the test failed or not. Currently
we only output failed tests, but in the future, successful tests could
be added.
- subtests: A list of subtests associated with this test.
A subtest contains the following fields:
- name: same as above
- number: sanme as above
- message: the log message that was printed by the subtest.
- failed: same as above but for the subtest
An example run and json content below:
```
$ sudo ./test_progs -a $(grep -v '^#' ./DENYLIST.aarch64 | awk '{print
$1","}' | tr -d '\n') -j -J /tmp/test_progs.json
$ jq < /tmp/test_progs.json | head -n 30
{
"success": 29,
"success_subtest": 23,
"skipped": 3,
"failed": 28,
"results": [
{
"name": "bpf_cookie",
"number": 10,
"message": "test_bpf_cookie:PASS:skel_open 0 nsec\n",
"failed": true,
"subtests": [
{
"name": "multi_kprobe_link_api",
"number": 2,
"message": "kprobe_multi_link_api_subtest:PASS:load_kallsyms 0 nsec\nlibbpf: extern 'bpf_testmod_fentry_test1' (strong): not resolved\nlibbpf: failed to load object 'kprobe_multi'\nlibbpf: failed to load BPF skeleton 'kprobe_multi': -3\nkprobe_multi_link_api_subtest:FAIL:fentry_raw_skel_load unexpected error: -3\n",
"failed": true
},
{
"name": "multi_kprobe_attach_api",
"number": 3,
"message": "libbpf: extern 'bpf_testmod_fentry_test1' (strong): not resolved\nlibbpf: failed to load object 'kprobe_multi'\nlibbpf: failed to load BPF skeleton 'kprobe_multi': -3\nkprobe_multi_attach_api_subtest:FAIL:fentry_raw_skel_load unexpected error: -3\n",
"failed": true
},
{
"name": "lsm",
"number": 8,
"message": "lsm_subtest:PASS:lsm.link_create 0 nsec\nlsm_subtest:FAIL:stack_mprotect unexpected stack_mprotect: actual 0 != expected -1\n",
"failed": true
}
```
The file can then be used to print a summary of the test run and list of
failing tests/subtests:
```
$ jq -r < /tmp/test_progs.json '"Success: \(.success)/\(.success_subtest), Skipped: \(.skipped), Failed: \(.failed)"'
Success: 29/23, Skipped: 3, Failed: 28
$ jq -r < /tmp/test_progs.json '.results | map([
if .failed then "#\(.number) \(.name)" else empty end,
(
. as {name: $tname, number: $tnum} | .subtests | map(
if .failed then "#\($tnum)/\(.number) \($tname)/\(.name)" else empty end
)
)
]) | flatten | .[]' | head -n 20
#10 bpf_cookie
#10/2 bpf_cookie/multi_kprobe_link_api
#10/3 bpf_cookie/multi_kprobe_attach_api
#10/8 bpf_cookie/lsm
#15 bpf_mod_race
#15/1 bpf_mod_race/ksym (used_btfs UAF)
#15/2 bpf_mod_race/kfunc (kfunc_btf_tab UAF)
#36 cgroup_hierarchical_stats
#61 deny_namespace
#61/1 deny_namespace/unpriv_userns_create_no_bpf
#73 fexit_stress
#83 get_func_ip_test
#99 kfunc_dynptr_param
#99/1 kfunc_dynptr_param/dynptr_data_null
#99/4 kfunc_dynptr_param/dynptr_data_null
#100 kprobe_multi_bench_attach
#100/1 kprobe_multi_bench_attach/kernel
#100/2 kprobe_multi_bench_attach/modules
#101 kprobe_multi_test
#101/1 kprobe_multi_test/skel_api
```
Signed-off-by: Manu Bretelle <chantr4@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20230317163256.3809328-1-chantr4@gmail.com
2023-03-17 09:32:56 -07:00
|
|
|
FILE *json;
|
2019-07-27 20:25:28 -07:00
|
|
|
|
selftests/bpf: add sub-tests support for test_progs
Allow tests to have their own set of sub-tests. Also add ability to do
test/subtest selection using `-t <test-name>/<subtest-name>` and `-n
<test-nums-set>/<subtest-nums-set>`, as an extension of existing -t/-n
selector options. For the <test-num-set> format: it's a comma-separated
list of either individual test numbers (1-based), or range of test
numbers. E.g., all of the following are valid sets of test numbers:
- 10
- 1,2,3
- 1-3
- 5-10,1,3-4
'/<subtest' part is optional, but has the same format. E.g., to select
test #3 and its sub-tests #10 through #15, use: -t 3/10-15.
Similarly, to select tests by name, use `-t verif/strobe`:
$ sudo ./test_progs -t verif/strobe
#3/12 strobemeta.o:OK
#3/13 strobemeta_nounroll1.o:OK
#3/14 strobemeta_nounroll2.o:OK
#3 bpf_verif_scale:OK
Summary: 1/3 PASSED, 0 FAILED
Example of using subtest API is in the next patch, converting
bpf_verif_scale.c tests to use sub-tests.
Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2019-07-27 20:25:29 -07:00
|
|
|
int succ_cnt; /* successful tests */
|
|
|
|
int sub_succ_cnt; /* successful sub-tests */
|
|
|
|
int fail_cnt; /* total failed tests + sub-tests */
|
2019-08-21 16:44:24 -07:00
|
|
|
int skip_cnt; /* skipped tests */
|
2020-07-01 17:48:58 -07:00
|
|
|
|
|
|
|
int saved_netns_fd;
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
int workers; /* number of worker process */
|
|
|
|
int worker_id; /* id number of current worker, main process is -1 */
|
|
|
|
pid_t *worker_pids; /* array of worker pids */
|
|
|
|
int *worker_socks; /* array of worker socks */
|
|
|
|
int *worker_current_test; /* array of current running test for each worker */
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_LOG_TRUNK_SIZE 8192
|
2022-04-26 21:13:53 -07:00
|
|
|
#define MAX_SUBTEST_NAME 1024
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
enum msg_type {
|
|
|
|
MSG_DO_TEST = 0,
|
|
|
|
MSG_TEST_DONE = 1,
|
|
|
|
MSG_TEST_LOG = 2,
|
2022-04-26 21:13:53 -07:00
|
|
|
MSG_SUBTEST_DONE = 3,
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
MSG_EXIT = 255,
|
|
|
|
};
|
|
|
|
struct msg {
|
|
|
|
enum msg_type type;
|
|
|
|
union {
|
|
|
|
struct {
|
2022-04-26 21:13:53 -07:00
|
|
|
int num;
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
} do_test;
|
|
|
|
struct {
|
2022-04-26 21:13:53 -07:00
|
|
|
int num;
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
int sub_succ_cnt;
|
|
|
|
int error_cnt;
|
|
|
|
int skip_cnt;
|
|
|
|
bool have_log;
|
2022-04-26 21:13:53 -07:00
|
|
|
int subtest_num;
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
} test_done;
|
|
|
|
struct {
|
|
|
|
char log_buf[MAX_LOG_TRUNK_SIZE + 1];
|
|
|
|
bool is_last;
|
|
|
|
} test_log;
|
2022-04-26 21:13:53 -07:00
|
|
|
struct {
|
|
|
|
int num;
|
|
|
|
char name[MAX_SUBTEST_NAME + 1];
|
|
|
|
int error_cnt;
|
|
|
|
bool skipped;
|
2022-05-19 23:13:03 -07:00
|
|
|
bool filtered;
|
2022-04-26 21:13:53 -07:00
|
|
|
bool have_log;
|
|
|
|
} subtest_done;
|
selftests/bpf: Add parallelism to test_progs
This patch adds "-j" mode to test_progs, executing tests in multiple
process. "-j" mode is optional, and works with all existing test
selection mechanism, as well as "-v", "-l" etc.
In "-j" mode, main process use UDS/SEQPACKET to communicate to each forked
worker, commanding it to run tests and collect logs. After all tests are
finished, a summary is printed. main process use multiple competing
threads to dispatch work to worker, trying to keep them all busy.
The test status will be printed as soon as it is finished, if there are
error logs, it will be printed after the final summary line.
By specifying "--debug", additional debug information on server/worker
communication will be printed.
Example output:
> ./test_progs -n 15-20 -j
[ 12.801730] bpf_testmod: loading out-of-tree module taints kernel.
Launching 8 workers.
#20 btf_split:OK
#16 btf_endian:OK
#18 btf_module:OK
#17 btf_map_in_map:OK
#19 btf_skc_cls_ingress:OK
#15 btf_dump:OK
Summary: 6/20 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Yucong Sun <sunyucong@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/20211006185619.364369-2-fallentree@fb.com
2021-10-06 11:56:06 -07:00
|
|
|
};
|
2019-07-27 20:25:28 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
extern struct test_env env;
|
|
|
|
|
2022-04-18 15:25:07 -07:00
|
|
|
void test__force_log(void);
|
|
|
|
bool test__start_subtest(const char *name);
|
|
|
|
void test__end_subtest(void);
|
|
|
|
void test__skip(void);
|
|
|
|
void test__fail(void);
|
|
|
|
int test__join_cgroup(const char *path);
|
2019-03-01 19:42:13 -08:00
|
|
|
|
selftests/bpf: Add cls_redirect classifier
cls_redirect is a TC clsact based replacement for the glb-redirect iptables
module available at [1]. It enables what GitHub calls "second chance"
flows [2], similarly proposed by the Beamer paper [3]. In contrast to
glb-redirect, it also supports migrating UDP flows as long as connected
sockets are used. cls_redirect is in production at Cloudflare, as part of
our own L4 load balancer.
We have modified the encapsulation format slightly from glb-redirect:
glbgue_chained_routing.private_data_type has been repurposed to form a
version field and several flags. Both have been arranged in a way that
a private_data_type value of zero matches the current glb-redirect
behaviour. This means that cls_redirect will understand packets in
glb-redirect format, but not vice versa.
The test suite only covers basic features. For example, cls_redirect will
correctly forward path MTU discovery packets, but this is not exercised.
It is also possible to switch the encapsulation format to GRE on the last
hop, which is also not tested.
There are two major distinctions from glb-redirect: first, cls_redirect
relies on receiving encapsulated packets directly from a router. This is
because we don't have access to the neighbour tables from BPF, yet. See
forward_to_next_hop for details. Second, cls_redirect performs decapsulation
instead of using separate ipip and sit tunnel devices. This
avoids issues with the sit tunnel [4] and makes deploying the classifier
easier: decapsulated packets appear on the same interface, so existing
firewall rules continue to work as expected.
The code base started it's life on v4.19, so there are most likely still
hold overs from old workarounds. In no particular order:
- The function buf_off is required to defeat a clang optimization
that leads to the verifier rejecting the program due to pointer
arithmetic in the wrong order.
- The function pkt_parse_ipv6 is force inlined, because it would
otherwise be rejected due to returning a pointer to stack memory.
- The functions fill_tuple and classify_tcp contain kludges, because
we've run out of function arguments.
- The logic in general is rather nested, due to verifier restrictions.
I think this is either because the verifier loses track of constants
on the stack, or because it can't track enum like variables.
1: https://github.com/github/glb-director/tree/master/src/glb-redirect
2: https://github.com/github/glb-director/blob/master/docs/development/second-chance-design.md
3: https://www.usenix.org/conference/nsdi18/presentation/olteanu
4: https://github.com/github/glb-director/issues/64
Signed-off-by: Lorenz Bauer <lmb@cloudflare.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200424185556.7358-2-lmb@cloudflare.com
2020-04-24 19:55:55 +01:00
|
|
|
#define PRINT_FAIL(format...) \
|
|
|
|
({ \
|
|
|
|
test__fail(); \
|
|
|
|
fprintf(stdout, "%s:FAIL:%d ", __func__, __LINE__); \
|
|
|
|
fprintf(stdout, ##format); \
|
|
|
|
})
|
|
|
|
|
2019-03-01 19:42:13 -08:00
|
|
|
#define _CHECK(condition, tag, duration, format...) ({ \
|
|
|
|
int __ret = !!(condition); \
|
2019-12-19 16:05:11 -08:00
|
|
|
int __save_errno = errno; \
|
2019-03-01 19:42:13 -08:00
|
|
|
if (__ret) { \
|
2019-08-21 16:44:25 -07:00
|
|
|
test__fail(); \
|
2020-03-13 10:23:33 -07:00
|
|
|
fprintf(stdout, "%s:FAIL:%s ", __func__, tag); \
|
|
|
|
fprintf(stdout, ##format); \
|
2019-03-01 19:42:13 -08:00
|
|
|
} else { \
|
2020-03-13 10:23:33 -07:00
|
|
|
fprintf(stdout, "%s:PASS:%s %d nsec\n", \
|
2019-08-06 10:45:28 -07:00
|
|
|
__func__, tag, duration); \
|
2019-03-01 19:42:13 -08:00
|
|
|
} \
|
2019-12-19 16:05:11 -08:00
|
|
|
errno = __save_errno; \
|
2019-03-01 19:42:13 -08:00
|
|
|
__ret; \
|
|
|
|
})
|
|
|
|
|
2019-08-21 16:44:25 -07:00
|
|
|
#define CHECK_FAIL(condition) ({ \
|
|
|
|
int __ret = !!(condition); \
|
2019-12-19 16:05:11 -08:00
|
|
|
int __save_errno = errno; \
|
2019-08-21 16:44:25 -07:00
|
|
|
if (__ret) { \
|
|
|
|
test__fail(); \
|
2020-03-13 10:23:33 -07:00
|
|
|
fprintf(stdout, "%s:FAIL:%d\n", __func__, __LINE__); \
|
2019-08-21 16:44:25 -07:00
|
|
|
} \
|
2019-12-19 16:05:11 -08:00
|
|
|
errno = __save_errno; \
|
2019-08-21 16:44:25 -07:00
|
|
|
__ret; \
|
|
|
|
})
|
|
|
|
|
2019-03-01 19:42:13 -08:00
|
|
|
#define CHECK(condition, tag, format...) \
|
|
|
|
_CHECK(condition, tag, duration, format)
|
|
|
|
#define CHECK_ATTR(condition, tag, format...) \
|
|
|
|
_CHECK(condition, tag, tattr.duration, format)
|
|
|
|
|
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2022-12-07 12:16:47 -08:00
|
|
|
#define ASSERT_FAIL(fmt, args...) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
CHECK(false, "", fmt"\n", ##args); \
|
|
|
|
false; \
|
|
|
|
})
|
|
|
|
|
2021-04-26 12:29:45 -07:00
|
|
|
#define ASSERT_TRUE(actual, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
bool ___ok = (actual); \
|
|
|
|
CHECK(!___ok, (name), "unexpected %s: got FALSE\n", (name)); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define ASSERT_FALSE(actual, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
bool ___ok = !(actual); \
|
|
|
|
CHECK(!___ok, (name), "unexpected %s: got TRUE\n", (name)); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2020-09-28 21:30:44 -07:00
|
|
|
#define ASSERT_EQ(actual, expected, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
typeof(actual) ___act = (actual); \
|
|
|
|
typeof(expected) ___exp = (expected); \
|
|
|
|
bool ___ok = ___act == ___exp; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: actual %lld != expected %lld\n", \
|
|
|
|
(name), (long long)(___act), (long long)(___exp)); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2020-11-04 20:33:55 -08:00
|
|
|
#define ASSERT_NEQ(actual, expected, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
typeof(actual) ___act = (actual); \
|
|
|
|
typeof(expected) ___exp = (expected); \
|
|
|
|
bool ___ok = ___act != ___exp; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: actual %lld == expected %lld\n", \
|
|
|
|
(name), (long long)(___act), (long long)(___exp)); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2021-02-26 12:49:33 -08:00
|
|
|
#define ASSERT_LT(actual, expected, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
typeof(actual) ___act = (actual); \
|
|
|
|
typeof(expected) ___exp = (expected); \
|
|
|
|
bool ___ok = ___act < ___exp; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: actual %lld >= expected %lld\n", \
|
|
|
|
(name), (long long)(___act), (long long)(___exp)); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2021-04-26 12:29:45 -07:00
|
|
|
#define ASSERT_LE(actual, expected, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
typeof(actual) ___act = (actual); \
|
|
|
|
typeof(expected) ___exp = (expected); \
|
|
|
|
bool ___ok = ___act <= ___exp; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: actual %lld > expected %lld\n", \
|
|
|
|
(name), (long long)(___act), (long long)(___exp)); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define ASSERT_GT(actual, expected, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
typeof(actual) ___act = (actual); \
|
|
|
|
typeof(expected) ___exp = (expected); \
|
|
|
|
bool ___ok = ___act > ___exp; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: actual %lld <= expected %lld\n", \
|
|
|
|
(name), (long long)(___act), (long long)(___exp)); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define ASSERT_GE(actual, expected, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
typeof(actual) ___act = (actual); \
|
|
|
|
typeof(expected) ___exp = (expected); \
|
|
|
|
bool ___ok = ___act >= ___exp; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: actual %lld < expected %lld\n", \
|
|
|
|
(name), (long long)(___act), (long long)(___exp)); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2020-09-28 21:30:44 -07:00
|
|
|
#define ASSERT_STREQ(actual, expected, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
const char *___act = actual; \
|
|
|
|
const char *___exp = expected; \
|
|
|
|
bool ___ok = strcmp(___act, ___exp) == 0; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: actual '%s' != expected '%s'\n", \
|
|
|
|
(name), ___act, ___exp); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2021-07-15 16:15:25 +01:00
|
|
|
#define ASSERT_STRNEQ(actual, expected, len, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
const char *___act = actual; \
|
|
|
|
const char *___exp = expected; \
|
|
|
|
int ___len = len; \
|
|
|
|
bool ___ok = strncmp(___act, ___exp, ___len) == 0; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: actual '%.*s' != expected '%.*s'\n", \
|
|
|
|
(name), ___len, ___act, ___len, ___exp); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2022-04-25 17:45:11 -07:00
|
|
|
#define ASSERT_HAS_SUBSTR(str, substr, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
const char *___str = str; \
|
|
|
|
const char *___substr = substr; \
|
|
|
|
bool ___ok = strstr(___str, ___substr) != NULL; \
|
|
|
|
CHECK(!___ok, (name), \
|
|
|
|
"unexpected %s: '%s' is not a substring of '%s'\n", \
|
|
|
|
(name), ___substr, ___str); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2020-09-28 21:30:44 -07:00
|
|
|
#define ASSERT_OK(res, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
long long ___res = (res); \
|
|
|
|
bool ___ok = ___res == 0; \
|
2021-04-26 12:29:45 -07:00
|
|
|
CHECK(!___ok, (name), "unexpected error: %lld (errno %d)\n", \
|
|
|
|
___res, errno); \
|
2020-09-28 21:30:44 -07:00
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define ASSERT_ERR(res, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
long long ___res = (res); \
|
|
|
|
bool ___ok = ___res < 0; \
|
|
|
|
CHECK(!___ok, (name), "unexpected success: %lld\n", ___res); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define ASSERT_NULL(ptr, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
const void *___res = (ptr); \
|
|
|
|
bool ___ok = !___res; \
|
|
|
|
CHECK(!___ok, (name), "unexpected pointer: %p\n", ___res); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define ASSERT_OK_PTR(ptr, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
const void *___res = (ptr); \
|
2021-05-24 20:59:32 -07:00
|
|
|
int ___err = libbpf_get_error(___res); \
|
|
|
|
bool ___ok = ___err == 0; \
|
|
|
|
CHECK(!___ok, (name), "unexpected error: %d\n", ___err); \
|
2020-09-28 21:30:44 -07:00
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define ASSERT_ERR_PTR(ptr, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
const void *___res = (ptr); \
|
2021-05-24 20:59:32 -07:00
|
|
|
int ___err = libbpf_get_error(___res); \
|
|
|
|
bool ___ok = ___err != 0; \
|
2020-09-28 21:30:44 -07:00
|
|
|
CHECK(!___ok, (name), "unexpected pointer: %p\n", ___res); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2023-02-24 14:13:42 +08:00
|
|
|
#define SYS(goto_label, fmt, ...) \
|
|
|
|
({ \
|
|
|
|
char cmd[1024]; \
|
|
|
|
snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \
|
|
|
|
if (!ASSERT_OK(system(cmd), cmd)) \
|
|
|
|
goto goto_label; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define SYS_NOFAIL(fmt, ...) \
|
|
|
|
({ \
|
|
|
|
char cmd[1024]; \
|
|
|
|
snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \
|
|
|
|
system(cmd); \
|
|
|
|
})
|
|
|
|
|
2019-03-01 19:42:19 -08:00
|
|
|
static inline __u64 ptr_to_u64(const void *ptr)
|
|
|
|
{
|
|
|
|
return (__u64) (unsigned long) ptr;
|
|
|
|
}
|
|
|
|
|
2020-08-13 13:49:38 -07:00
|
|
|
static inline void *u64_to_ptr(__u64 ptr)
|
|
|
|
{
|
|
|
|
return (void *) (unsigned long) ptr;
|
|
|
|
}
|
|
|
|
|
2019-03-01 19:42:13 -08:00
|
|
|
int bpf_find_map(const char *test, struct bpf_object *obj, const char *name);
|
2019-03-01 19:42:16 -08:00
|
|
|
int compare_map_keys(int map1_fd, int map2_fd);
|
|
|
|
int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len);
|
2021-09-10 11:33:52 -07:00
|
|
|
int trigger_module_test_read(int read_sz);
|
|
|
|
int trigger_module_test_write(int write_sz);
|
2022-09-09 00:49:40 +00:00
|
|
|
int write_sysctl(const char *sysctl, const char *value);
|
2023-01-28 01:06:22 +01:00
|
|
|
int get_bpf_max_tramp_links_from(struct btf *btf);
|
|
|
|
int get_bpf_max_tramp_links(void);
|
2019-07-16 14:58:27 +02:00
|
|
|
|
|
|
|
#ifdef __x86_64__
|
|
|
|
#define SYS_NANOSLEEP_KPROBE_NAME "__x64_sys_nanosleep"
|
|
|
|
#elif defined(__s390x__)
|
|
|
|
#define SYS_NANOSLEEP_KPROBE_NAME "__s390x_sys_nanosleep"
|
2022-04-04 16:21:01 +02:00
|
|
|
#elif defined(__aarch64__)
|
|
|
|
#define SYS_NANOSLEEP_KPROBE_NAME "__arm64_sys_nanosleep"
|
2023-10-04 13:09:05 +02:00
|
|
|
#elif defined(__riscv)
|
|
|
|
#define SYS_NANOSLEEP_KPROBE_NAME "__riscv_sys_nanosleep"
|
2019-07-16 14:58:27 +02:00
|
|
|
#else
|
|
|
|
#define SYS_NANOSLEEP_KPROBE_NAME "sys_nanosleep"
|
|
|
|
#endif
|
2021-10-04 17:48:57 +08:00
|
|
|
|
|
|
|
#define BPF_TESTMOD_TEST_FILE "/sys/kernel/bpf_testmod"
|
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2022-12-07 12:16:47 -08:00
|
|
|
|
2023-04-21 02:23:16 +03:00
|
|
|
typedef int (*pre_execution_cb)(struct bpf_object *obj);
|
|
|
|
|
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2022-12-07 12:16:47 -08:00
|
|
|
struct test_loader {
|
|
|
|
char *log_buf;
|
|
|
|
size_t log_buf_sz;
|
2023-03-01 19:54:17 +02:00
|
|
|
size_t next_match_pos;
|
2023-04-21 02:23:16 +03:00
|
|
|
pre_execution_cb pre_execution_cb;
|
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2022-12-07 12:16:47 -08:00
|
|
|
|
|
|
|
struct bpf_object *obj;
|
|
|
|
};
|
|
|
|
|
2023-04-21 02:23:16 +03:00
|
|
|
static inline void test_loader__set_pre_execution_cb(struct test_loader *tester,
|
|
|
|
pre_execution_cb cb)
|
|
|
|
{
|
|
|
|
tester->pre_execution_cb = cb;
|
|
|
|
}
|
|
|
|
|
selftests/bpf: add generic BPF program tester-loader
It's become a common pattern to have a collection of small BPF programs
in one BPF object file, each representing one test case. On user-space
side of such tests we maintain a table of program names and expected
failure or success, along with optional expected verifier log message.
This works, but each set of tests reimplement this mundane code over and
over again, which is a waste of time for anyone trying to add a new set
of tests. Furthermore, it's quite error prone as it's way too easy to miss
some entries in these manually maintained test tables (as evidences by
dynptr_fail tests, in which ringbuf_release_uninit_dynptr subtest was
accidentally missed; this is fixed in next patch).
So this patch implements generic test_loader, which accepts skeleton
name and handles the rest of details: opens and loads BPF object file,
making sure each program is tested in isolation. Optionally each test
case can specify expected BPF verifier log message. In case of failure,
tester makes sure to report verifier log, but it also reports verifier
log in verbose mode unconditionally.
Now, the interesting deviation from existing custom implementations is
the use of btf_decl_tag attribute to specify expected-to-fail vs
expected-to-succeed markers and, optionally, expected log message
directly next to BPF program source code, eliminating the need to
manually create and update table of tests.
We define few macros wrapping btf_decl_tag with a convention that all
values of btf_decl_tag start with "comment:" prefix, and then utilizing
a very simple "just_some_text_tag" or "some_key_name=<value>" pattern to
define things like expected success/failure, expected verifier message,
extra verifier log level (if necessary). This approach is demonstrated
by next patch in which two existing sets of failure tests are converted.
Tester supports both expected-to-fail and expected-to-succeed programs,
though this patch set didn't convert any existing expected-to-succeed
programs yet, as existing tests couple BPF program loading with their
further execution through attach or test_prog_run. One way to allow
testing scenarios like this would be ability to specify custom callback,
executed for each successfully loaded BPF program. This is left for
follow up patches, after some more analysis of existing test cases.
This test_loader is, hopefully, a start of a test_verifier-like runner,
but integrated into test_progs infrastructure. It will allow much better
"user experience" of defining low-level verification tests that can take
advantage of all the libbpf-provided nicety features on BPF side: global
variables, declarative maps, etc. All while having a choice of defining
it in C or as BPF assembly (through __attribute__((naked)) functions and
using embedded asm), depending on what makes most sense in each
particular case. This will be explored in follow up patches as well.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/r/20221207201648.2990661-1-andrii@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2022-12-07 12:16:47 -08:00
|
|
|
typedef const void *(*skel_elf_bytes_fn)(size_t *sz);
|
|
|
|
|
|
|
|
extern void test_loader__run_subtests(struct test_loader *tester,
|
|
|
|
const char *skel_name,
|
|
|
|
skel_elf_bytes_fn elf_bytes_factory);
|
|
|
|
|
|
|
|
extern void test_loader_fini(struct test_loader *tester);
|
|
|
|
|
|
|
|
#define RUN_TESTS(skel) ({ \
|
|
|
|
struct test_loader tester = {}; \
|
|
|
|
\
|
|
|
|
test_loader__run_subtests(&tester, #skel, skel##__elf_bytes); \
|
|
|
|
test_loader_fini(&tester); \
|
|
|
|
})
|
|
|
|
|
|
|
|
#endif /* __TEST_PROGS_H */
|