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;
|
2024-08-14 22:32:50 -07:00
|
|
|
bool should_tmon;
|
2022-04-26 21:13:53 -07:00
|
|
|
|
selftests/bpf: Fix using stdout, stderr as struct field names
Typically stdin, stdout, stderr are treated as reserved identifiers under
ISO/ANSI C and libc implementations further define these as macros, both in
glibc and musl <stdio.h>.
However, while glibc defines:
...
/* Standard streams. */
extern FILE *stdin; /* Standard input stream. */
extern FILE *stdout; /* Standard output stream. */
extern FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdout
#define stderr stderr
...
musl instead uses (legally):
...
extern FILE *const stdin;
extern FILE *const stdout;
extern FILE *const stderr;
#define stdin (stdin)
#define stdout (stdout)
#define stderr (stderr)
...
The latter results in compile errors when the names are reused as fields of
'struct test_env' and elsewhere in test_progs.[ch] and reg_bounds.c.
Rename the fields to stdout_saved and stderr_saved to avoid many errors
seen building against musl, e.g.:
In file included from test_progs.h:6,
from test_progs.c:5:
test_progs.c: In function 'print_test_result':
test_progs.c:237:21: error: expected identifier before '(' token
237 | fprintf(env.stdout, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
| ^~~~~~
test_progs.c:237:9: error: too few arguments to function 'fprintf'
237 | fprintf(env.stdout, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
| ^~~~~~~
Signed-off-by: Tony Ambardar <tony.ambardar@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/ZqR2DuHdBXPX%2Fyx8@kodidev-ubuntu/
Link: https://lore.kernel.org/bpf/684ea17548e237f39dfb3f7a3d33450069015b21.1722244708.git.tony.ambardar@gmail.com
2024-07-29 02:24:23 -07:00
|
|
|
FILE *stdout_saved;
|
2022-04-26 21:13:53 -07:00
|
|
|
};
|
|
|
|
|
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
|
|
|
|
selftests/bpf: Fix using stdout, stderr as struct field names
Typically stdin, stdout, stderr are treated as reserved identifiers under
ISO/ANSI C and libc implementations further define these as macros, both in
glibc and musl <stdio.h>.
However, while glibc defines:
...
/* Standard streams. */
extern FILE *stdin; /* Standard input stream. */
extern FILE *stdout; /* Standard output stream. */
extern FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdout
#define stderr stderr
...
musl instead uses (legally):
...
extern FILE *const stdin;
extern FILE *const stdout;
extern FILE *const stderr;
#define stdin (stdin)
#define stdout (stdout)
#define stderr (stderr)
...
The latter results in compile errors when the names are reused as fields of
'struct test_env' and elsewhere in test_progs.[ch] and reg_bounds.c.
Rename the fields to stdout_saved and stderr_saved to avoid many errors
seen building against musl, e.g.:
In file included from test_progs.h:6,
from test_progs.c:5:
test_progs.c: In function 'print_test_result':
test_progs.c:237:21: error: expected identifier before '(' token
237 | fprintf(env.stdout, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
| ^~~~~~
test_progs.c:237:9: error: too few arguments to function 'fprintf'
237 | fprintf(env.stdout, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
| ^~~~~~~
Signed-off-by: Tony Ambardar <tony.ambardar@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/ZqR2DuHdBXPX%2Fyx8@kodidev-ubuntu/
Link: https://lore.kernel.org/bpf/684ea17548e237f39dfb3f7a3d33450069015b21.1722244708.git.tony.ambardar@gmail.com
2024-07-29 02:24:23 -07:00
|
|
|
FILE *stdout_saved;
|
2022-04-18 15:25:07 -07:00
|
|
|
};
|
|
|
|
|
2024-08-06 16:03:19 -07:00
|
|
|
extern int env_verbosity;
|
|
|
|
|
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;
|
2024-08-14 22:32:50 -07:00
|
|
|
struct test_selector tmon_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
|
|
|
|
selftests/bpf: Fix using stdout, stderr as struct field names
Typically stdin, stdout, stderr are treated as reserved identifiers under
ISO/ANSI C and libc implementations further define these as macros, both in
glibc and musl <stdio.h>.
However, while glibc defines:
...
/* Standard streams. */
extern FILE *stdin; /* Standard input stream. */
extern FILE *stdout; /* Standard output stream. */
extern FILE *stderr; /* Standard error output stream. */
/* C89/C99 say they're macros. Make them happy. */
#define stdin stdin
#define stdout stdout
#define stderr stderr
...
musl instead uses (legally):
...
extern FILE *const stdin;
extern FILE *const stdout;
extern FILE *const stderr;
#define stdin (stdin)
#define stdout (stdout)
#define stderr (stderr)
...
The latter results in compile errors when the names are reused as fields of
'struct test_env' and elsewhere in test_progs.[ch] and reg_bounds.c.
Rename the fields to stdout_saved and stderr_saved to avoid many errors
seen building against musl, e.g.:
In file included from test_progs.h:6,
from test_progs.c:5:
test_progs.c: In function 'print_test_result':
test_progs.c:237:21: error: expected identifier before '(' token
237 | fprintf(env.stdout, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
| ^~~~~~
test_progs.c:237:9: error: too few arguments to function 'fprintf'
237 | fprintf(env.stdout, "#%-*d %s:", TEST_NUM_WIDTH, test->test_num, test->test_name);
| ^~~~~~~
Signed-off-by: Tony Ambardar <tony.ambardar@gmail.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Link: https://lore.kernel.org/bpf/ZqR2DuHdBXPX%2Fyx8@kodidev-ubuntu/
Link: https://lore.kernel.org/bpf/684ea17548e237f39dfb3f7a3d33450069015b21.1722244708.git.tony.ambardar@gmail.com
2024-07-29 02:24:23 -07:00
|
|
|
FILE *stdout_saved;
|
|
|
|
FILE *stderr_saved;
|
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 */
|
selftests/bpf: watchdog timer for test_progs
This commit provides a watchdog timer that sets a limit of how long a
single sub-test could run:
- if sub-test runs for 10 seconds, the name of the test is printed
(currently the name of the test is printed only after it finishes);
- if sub-test runs for 120 seconds, the running thread is terminated
with SIGSEGV (to trigger crash_handler() and get a stack trace).
Specifically:
- the timer is armed on each call to run_one_test();
- re-armed at each call to test__start_subtest();
- is stopped when exiting run_one_test().
Default timeout could be overridden using '-w' or '--watchdog-timeout'
options. Value 0 can be used to turn the timer off.
Here is an example execution:
$ ./ssh-exec.sh ./test_progs -w 5 -t \
send_signal/send_signal_perf_thread_remote,send_signal/send_signal_nmi_thread_remote
WATCHDOG: test case send_signal/send_signal_nmi_thread_remote executes for 5 seconds, terminating with SIGSEGV
Caught signal #11!
Stack trace:
./test_progs(crash_handler+0x1f)[0x9049ef]
/lib64/libc.so.6(+0x40d00)[0x7f1f1184fd00]
/lib64/libc.so.6(read+0x4a)[0x7f1f1191cc4a]
./test_progs[0x720dd3]
./test_progs[0x71ef7a]
./test_progs(test_send_signal+0x1db)[0x71edeb]
./test_progs[0x9066c5]
./test_progs(main+0x5ed)[0x9054ad]
/lib64/libc.so.6(+0x2a088)[0x7f1f11839088]
/lib64/libc.so.6(__libc_start_main+0x8b)[0x7f1f1183914b]
./test_progs(_start+0x25)[0x527385]
#292 send_signal:FAIL
test_send_signal_common:PASS:reading pipe 0 nsec
test_send_signal_common:PASS:reading pipe error: size 0 0 nsec
test_send_signal_common:PASS:incorrect result 0 nsec
test_send_signal_common:PASS:pipe_write 0 nsec
test_send_signal_common:PASS:setpriority 0 nsec
Timer is implemented using timer_{create,start} librt API.
Internally librt uses pthreads for SIGEV_THREAD timers,
so this change adds a background timer thread to the test process.
Because of this a few checks in tests 'bpf_iter' and 'iters'
need an update to account for an extra thread.
For parallelized scenario the watchdog is also created for each worker
fork. If one of the workers gets stuck, it would be terminated by a
watchdog. In theory, this might lead to a scenario when all worker
threads are exhausted, however this should not be a problem for
server_main(), as it would exit with some of the tests not run.
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20241112110906.3045278-2-eddyz87@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2024-11-12 03:09:03 -08:00
|
|
|
|
|
|
|
pthread_t main_thread;
|
|
|
|
int secs_till_notify;
|
|
|
|
int secs_till_kill;
|
|
|
|
timer_t watchdog; /* watch for stalled tests/subtests */
|
|
|
|
enum { WD_NOTIFY, WD_KILL } watchdog_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
|
|
|
};
|
|
|
|
|
|
|
|
#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);
|
2024-11-20 08:43:11 +01:00
|
|
|
void hexdump(const char *prefix, const void *buf, size_t len);
|
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; \
|
|
|
|
})
|
|
|
|
|
2024-11-20 08:43:11 +01:00
|
|
|
#define ASSERT_MEMEQ(actual, expected, len, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
const void *__act = actual; \
|
|
|
|
const void *__exp = expected; \
|
|
|
|
int __len = len; \
|
|
|
|
bool ___ok = memcmp(__act, __exp, __len) == 0; \
|
|
|
|
CHECK(!___ok, (name), "unexpected memory mismatch\n"); \
|
|
|
|
fprintf(stdout, "actual:\n"); \
|
|
|
|
hexdump("\t", __act, __len); \
|
|
|
|
fprintf(stdout, "expected:\n"); \
|
|
|
|
hexdump("\t", __exp, __len); \
|
|
|
|
___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; \
|
|
|
|
})
|
|
|
|
|
2024-07-09 17:16:18 +08:00
|
|
|
#define ASSERT_OK_FD(fd, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
int ___fd = (fd); \
|
|
|
|
bool ___ok = ___fd >= 0; \
|
|
|
|
CHECK(!___ok, (name), "unexpected fd: %d (errno %d)\n", \
|
|
|
|
___fd, errno); \
|
|
|
|
___ok; \
|
|
|
|
})
|
|
|
|
|
2024-10-23 16:47:59 -07:00
|
|
|
#define ASSERT_ERR_FD(fd, name) ({ \
|
|
|
|
static int duration = 0; \
|
|
|
|
int ___fd = (fd); \
|
|
|
|
bool ___ok = ___fd < 0; \
|
|
|
|
CHECK(!___ok, (name), "unexpected fd: %d\n", ___fd); \
|
|
|
|
___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; \
|
|
|
|
})
|
|
|
|
|
2025-02-25 16:31:01 +00:00
|
|
|
#define SYS_FAIL(goto_label, fmt, ...) \
|
|
|
|
({ \
|
|
|
|
char cmd[1024]; \
|
|
|
|
snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \
|
|
|
|
if (!ASSERT_NEQ(0, system(cmd), cmd)) \
|
|
|
|
goto goto_label; \
|
|
|
|
})
|
|
|
|
|
2024-01-26 18:50:17 -08:00
|
|
|
#define ALL_TO_DEV_NULL " >/dev/null 2>&1"
|
|
|
|
|
2023-02-24 14:13:42 +08:00
|
|
|
#define SYS_NOFAIL(fmt, ...) \
|
|
|
|
({ \
|
|
|
|
char cmd[1024]; \
|
2024-01-26 18:50:17 -08:00
|
|
|
int n; \
|
|
|
|
n = snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \
|
|
|
|
if (n < sizeof(cmd) && sizeof(cmd) - n >= sizeof(ALL_TO_DEV_NULL)) \
|
|
|
|
strcat(cmd, ALL_TO_DEV_NULL); \
|
2023-02-24 14:13:42 +08:00
|
|
|
system(cmd); \
|
|
|
|
})
|
|
|
|
|
2024-03-06 12:45:19 +02:00
|
|
|
int start_libbpf_log_capture(void);
|
|
|
|
char *stop_libbpf_log_capture(void);
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2025-06-06 09:31:51 -07:00
|
|
|
static inline __u32 id_from_prog_fd(int fd)
|
|
|
|
{
|
|
|
|
struct bpf_prog_info prog_info = {};
|
|
|
|
__u32 prog_info_len = sizeof(prog_info);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bpf_obj_get_info_by_fd(fd, &prog_info, &prog_info_len);
|
|
|
|
if (!ASSERT_OK(err, "id_from_prog_fd"))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ASSERT_NEQ(prog_info.id, 0, "prog_info.id");
|
|
|
|
return prog_info.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline __u32 id_from_link_fd(int fd)
|
|
|
|
{
|
|
|
|
struct bpf_link_info link_info = {};
|
|
|
|
__u32 link_info_len = sizeof(link_info);
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = bpf_link_get_info_by_fd(fd, &link_info, &link_info_len);
|
|
|
|
if (!ASSERT_OK(err, "id_from_link_fd"))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ASSERT_NEQ(link_info.id, 0, "link_info.id");
|
|
|
|
return link_info.id;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2024-08-14 22:32:51 -07:00
|
|
|
struct netns_obj;
|
|
|
|
struct netns_obj *netns_new(const char *name, bool open);
|
|
|
|
void netns_free(struct netns_obj *netns);
|
|
|
|
|
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-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 */
|