Commit e52a8b96 authored by Andrii Nakryiko's avatar Andrii Nakryiko

Merge branch 'selftests/bpf: Add parallelism to test_progs'

Yucong Sun says:

====================

This patch series adds "-j" parelell execution to test_progs, with "--debug" to
display server/worker communications. Also, some Tests that often fails in
parallel are marked as serial test, and it will run in sequence after parallel
execution is done.

This patch series also adds a error summary after all tests execution finished.

V6 -> V5:
  * adding error summary logic for non parallel mode too.
  * changed how serial tests are implemented, use main process instead of worker 0.
  * fixed a dozen broken test when running in parallel.

V5 -> V4:
  * change to SOCK_SEQPACKET for close notification.
  * move all debug output to "--debug" mode
  * output log as test finish, and all error logs again after summary line.
  * variable naming / style changes
  * adds serial_test_name() to replace serial test lists.
====================
Signed-off-by: default avatarAndrii Nakryiko <andrii@kernel.org>
parents a1852ce0 d3f7b166
......@@ -11,6 +11,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <ftw.h>
#include <unistd.h>
#include "cgroup_helpers.h"
......@@ -33,10 +34,9 @@
#define CGROUP_MOUNT_DFLT "/sys/fs/cgroup"
#define NETCLS_MOUNT_PATH CGROUP_MOUNT_DFLT "/net_cls"
#define CGROUP_WORK_DIR "/cgroup-test-work-dir"
#define format_cgroup_path(buf, path) \
snprintf(buf, sizeof(buf), "%s%s%s", CGROUP_MOUNT_PATH, \
CGROUP_WORK_DIR, path)
snprintf(buf, sizeof(buf), "%s%s%d%s", CGROUP_MOUNT_PATH, \
CGROUP_WORK_DIR, getpid(), path)
#define format_classid_path(buf) \
snprintf(buf, sizeof(buf), "%s%s", NETCLS_MOUNT_PATH, \
......
......@@ -26,4 +26,4 @@ int join_classid(void);
int setup_classid_environment(void);
void cleanup_classid_environment(void);
#endif /* __CGROUP_HELPERS_H */
#endif /* __CGROUP_HELPERS_H */
\ No newline at end of file
......@@ -225,6 +225,7 @@ void test_atomics(void)
test__skip();
goto cleanup;
}
skel->bss->pid = getpid();
if (test__start_subtest("add"))
test_add(skel);
......
......@@ -179,7 +179,7 @@ static void do_bpf_iter_setsockopt(struct bpf_iter_setsockopt *iter_skel,
free_fds(est_fds, nr_est);
}
void test_bpf_iter_setsockopt(void)
void serial_test_bpf_iter_setsockopt(void)
{
struct bpf_iter_setsockopt *iter_skel = NULL;
struct bpf_cubic *cubic_skel = NULL;
......
......@@ -3,7 +3,7 @@
#define nr_iters 2
void test_bpf_obj_id(void)
void serial_test_bpf_obj_id(void)
{
const __u64 array_magic_value = 0xfaceb00c;
const __u32 array_key = 0;
......
......@@ -363,7 +363,7 @@ static void test_shared(int parent_cgroup_fd, int child_cgroup_fd)
cg_storage_multi_shared__destroy(obj);
}
void test_cg_storage_multi(void)
void serial_test_cg_storage_multi(void)
{
int parent_cgroup_fd = -1, child_cgroup_fd = -1;
......
......@@ -21,7 +21,7 @@ static int prog_load(void)
bpf_log_buf, BPF_LOG_BUF_SIZE);
}
void test_cgroup_attach_autodetach(void)
void serial_test_cgroup_attach_autodetach(void)
{
__u32 duration = 0, prog_cnt = 4, attach_flags;
int allow_prog[2] = {-1};
......
......@@ -74,7 +74,7 @@ static int prog_load_cnt(int verdict, int val)
return ret;
}
void test_cgroup_attach_multi(void)
void serial_test_cgroup_attach_multi(void)
{
__u32 prog_ids[4], prog_cnt = 0, attach_flags, saved_prog_id;
int cg1 = 0, cg2 = 0, cg3 = 0, cg4 = 0, cg5 = 0, key = 0;
......
......@@ -23,7 +23,7 @@ static int prog_load(int verdict)
bpf_log_buf, BPF_LOG_BUF_SIZE);
}
void test_cgroup_attach_override(void)
void serial_test_cgroup_attach_override(void)
{
int drop_prog = -1, allow_prog = -1, foo = -1, bar = -1;
__u32 duration = 0;
......
......@@ -24,7 +24,7 @@ int ping_and_check(int exp_calls, int exp_alt_calls)
return 0;
}
void test_cgroup_link(void)
void serial_test_cgroup_link(void)
{
struct {
const char *path;
......
......@@ -46,7 +46,7 @@ void test_cgroup_v1v2(void)
{
struct network_helper_opts opts = {};
int server_fd, client_fd, cgroup_fd;
static const int port = 60123;
static const int port = 60120;
/* Step 1: Check base connectivity works without any BPF. */
server_fd = start_server(AF_INET, SOCK_STREAM, NULL, port, 0);
......
......@@ -195,7 +195,7 @@ static void test_check_mtu_tc(__u32 mtu, __u32 ifindex)
test_check_mtu__destroy(skel);
}
void test_check_mtu(void)
void serial_test_check_mtu(void)
{
__u32 mtu_lo;
......
......@@ -380,7 +380,8 @@ static void test_func_map_prog_compatibility(void)
"./test_attach_probe.o");
}
void test_fexit_bpf2bpf(void)
/* NOTE: affect other tests, must run in serial mode */
void serial_test_fexit_bpf2bpf(void)
{
if (test__start_subtest("target_no_callees"))
test_target_no_callees();
......
......@@ -2,7 +2,7 @@
#include <test_progs.h>
#include <network_helpers.h>
void test_flow_dissector_load_bytes(void)
void serial_test_flow_dissector_load_bytes(void)
{
struct bpf_flow_keys flow_keys;
__u32 duration = 0, retval, size;
......
......@@ -628,7 +628,7 @@ static void run_tests(int netns)
}
}
void test_flow_dissector_reattach(void)
void serial_test_flow_dissector_reattach(void)
{
int err, new_net, saved_net;
......
......@@ -73,7 +73,7 @@ static void close_perf_events(void)
free(pfd_array);
}
void test_get_branch_snapshot(void)
void serial_test_get_branch_snapshot(void)
{
struct get_branch_snapshot *skel = NULL;
int err;
......
......@@ -48,7 +48,8 @@ static void on_sample(void *ctx, int cpu, void *data, __u32 size)
*(bool *)ctx = true;
}
void test_kfree_skb(void)
/* TODO: fix kernel panic caused by this test in parallel mode */
void serial_test_kfree_skb(void)
{
struct __sk_buff skb = {};
struct bpf_prog_test_run_attr tattr = {
......
......@@ -541,7 +541,7 @@ static void run_test(struct migrate_reuseport_test_case *test_case,
}
}
void test_migrate_reuseport(void)
void serial_test_migrate_reuseport(void)
{
struct test_migrate_reuseport *skel;
int i;
......
......@@ -53,7 +53,8 @@ static void run_test(__u32 input_retval, __u16 want_side_effect, __s16 want_ret)
modify_return__destroy(skel);
}
void test_modify_return(void)
/* TODO: conflict with get_func_ip_test */
void serial_test_modify_return(void)
{
run_test(0 /* input_retval */,
1 /* want_side_effect */,
......
......@@ -78,7 +78,8 @@ static void test_ns_current_pid_tgid_new_ns(void)
return;
}
void test_ns_current_pid_tgid(void)
/* TODO: use a different tracepoint */
void serial_test_ns_current_pid_tgid(void)
{
if (test__start_subtest("ns_current_pid_tgid_root_ns"))
test_current_pid_tgid(NULL);
......
......@@ -43,7 +43,7 @@ int trigger_on_cpu(int cpu)
return 0;
}
void test_perf_buffer(void)
void serial_test_perf_buffer(void)
{
int err, on_len, nr_on_cpus = 0, nr_cpus, i;
struct perf_buffer_opts pb_opts = {};
......
......@@ -23,7 +23,8 @@ static void burn_cpu(void)
++j;
}
void test_perf_link(void)
/* TODO: often fails in concurrent mode */
void serial_test_perf_link(void)
{
struct test_perf_link *skel = NULL;
struct perf_event_attr attr;
......
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
void test_probe_user(void)
/* TODO: corrupts other tests uses connect() */
void serial_test_probe_user(void)
{
const char *prog_name = "handle_sys_connect";
const char *obj_file = "./test_probe_user.o";
......
......@@ -3,7 +3,8 @@
#include <test_progs.h>
#include <linux/nbd.h>
void test_raw_tp_writable_test_run(void)
/* NOTE: conflict with other tests. */
void serial_test_raw_tp_writable_test_run(void)
{
__u32 duration = 0;
char error[4096];
......
......@@ -858,7 +858,7 @@ void test_map_type(enum bpf_map_type mt)
cleanup();
}
void test_select_reuseport(void)
void serial_test_select_reuseport(void)
{
saved_tcp_fo = read_int_sysctl(TCP_FO_SYSCTL);
if (saved_tcp_fo < 0)
......
......@@ -25,7 +25,8 @@ static void *worker(void *p)
return NULL;
}
void test_send_signal_sched_switch(void)
/* NOTE: cause events loss */
void serial_test_send_signal_sched_switch(void)
{
struct test_send_signal_kern *skel;
pthread_t threads[THREAD_COUNT];
......
......@@ -105,7 +105,7 @@ static void do_test(void)
close(listen_fd);
}
void test_sk_storage_tracing(void)
void serial_test_sk_storage_tracing(void)
{
struct test_sk_storage_trace_itself *skel_itself;
int err;
......
......@@ -6,7 +6,7 @@
/* Demonstrate that bpf_snprintf_btf succeeds and that various data types
* are formatted correctly.
*/
void test_snprintf_btf(void)
void serial_test_snprintf_btf(void)
{
struct netif_receive_skb *skel;
struct netif_receive_skb__bss *bss;
......
......@@ -329,7 +329,7 @@ static void test(void)
close(listen_fd);
}
void test_sock_fields(void)
void serial_test_sock_fields(void)
{
struct bpf_link *egress_link = NULL, *ingress_link = NULL;
int parent_cg_fd = -1, child_cg_fd = -1;
......
......@@ -2037,7 +2037,7 @@ static void run_tests(struct test_sockmap_listen *skel, struct bpf_map *map,
test_udp_unix_redir(skel, map, family);
}
void test_sockmap_listen(void)
void serial_test_sockmap_listen(void)
{
struct test_sockmap_listen *skel;
......
......@@ -39,7 +39,8 @@ static int timer(struct timer *timer_skel)
return 0;
}
void test_timer(void)
/* TODO: use pid filtering */
void serial_test_timer(void)
{
struct timer *timer_skel = NULL;
int err;
......
......@@ -52,7 +52,7 @@ static int timer_mim(struct timer_mim *timer_skel)
return 0;
}
void test_timer_mim(void)
void serial_test_timer_mim(void)
{
struct timer_mim_reject *timer_reject_skel = NULL;
libbpf_print_fn_t old_print_fn = NULL;
......
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
void test_tp_attach_query(void)
void serial_test_tp_attach_query(void)
{
const int num_progs = 3;
int i, j, bytes, efd, err, prog_fd[num_progs], pmu_fd[num_progs];
......
......@@ -8,7 +8,7 @@
#define TRACEBUF "/sys/kernel/debug/tracing/trace_pipe"
#define SEARCHMSG "testing,testing"
void test_trace_printk(void)
void serial_test_trace_printk(void)
{
int err = 0, iter = 0, found = 0;
struct trace_printk__bss *bss;
......
......@@ -8,7 +8,7 @@
#define TRACEBUF "/sys/kernel/debug/tracing/trace_pipe"
#define SEARCHMSG "1,2,3,4,5,6,7,8,9,10"
void test_trace_vprintk(void)
void serial_test_trace_vprintk(void)
{
int err = 0, iter = 0, found = 0;
struct trace_vprintk__bss *bss;
......
......@@ -41,7 +41,8 @@ static struct bpf_link *load(struct bpf_object *obj, const char *name)
return bpf_program__attach_trace(prog);
}
void test_trampoline_count(void)
/* TODO: use different target function to run in concurrent mode */
void serial_test_trampoline_count(void)
{
const char *fentry_name = "fentry/__set_task_comm";
const char *fexit_name = "fexit/__set_task_comm";
......
......@@ -4,7 +4,7 @@
#define IFINDEX_LO 1
#define XDP_FLAGS_REPLACE (1U << 4)
void test_xdp_attach(void)
void serial_test_xdp_attach(void)
{
__u32 duration = 0, id1, id2, id0 = 0, len;
struct bpf_object *obj1, *obj2, *obj3;
......
......@@ -519,7 +519,7 @@ static struct bond_test_case bond_test_cases[] = {
{ "xdp_bonding_xor_layer34", BOND_MODE_XOR, BOND_XMIT_POLICY_LAYER34, },
};
void test_xdp_bonding(void)
void serial_test_xdp_bonding(void)
{
libbpf_print_fn_t old_print_fn;
struct skeletons skeletons = {};
......
......@@ -7,7 +7,7 @@
#define IFINDEX_LO 1
void test_xdp_cpumap_attach(void)
void serial_test_xdp_cpumap_attach(void)
{
struct test_xdp_with_cpumap_helpers *skel;
struct bpf_prog_info info = {};
......
......@@ -72,7 +72,7 @@ void test_neg_xdp_devmap_helpers(void)
}
void test_xdp_devmap_attach(void)
void serial_test_xdp_devmap_attach(void)
{
if (test__start_subtest("DEVMAP with programs in entries"))
test_xdp_with_devmap_helpers();
......
......@@ -4,7 +4,7 @@
#define IFINDEX_LO 1
void test_xdp_info(void)
void serial_test_xdp_info(void)
{
__u32 len = sizeof(struct bpf_prog_info), duration = 0, prog_id;
const char *file = "./xdp_dummy.o";
......
......@@ -6,7 +6,7 @@
#define IFINDEX_LO 1
void test_xdp_link(void)
void serial_test_xdp_link(void)
{
__u32 duration = 0, id1, id2, id0 = 0, prog_fd1, prog_fd2, err;
DECLARE_LIBBPF_OPTS(bpf_xdp_set_link_opts, opts, .old_fd = -1);
......
......@@ -10,6 +10,8 @@ bool skip_tests __attribute((__section__(".data"))) = false;
bool skip_tests = true;
#endif
__u32 pid = 0;
__u64 add64_value = 1;
__u64 add64_result = 0;
__u32 add32_value = 1;
......@@ -21,6 +23,8 @@ __u64 add_noreturn_value = 1;
SEC("fentry/bpf_fentry_test1")
int BPF_PROG(add, int a)
{
if (pid != (bpf_get_current_pid_tgid() >> 32))
return 0;
#ifdef ENABLE_ATOMICS_TESTS
__u64 add_stack_value = 1;
......@@ -45,6 +49,8 @@ __s64 sub_noreturn_value = 1;
SEC("fentry/bpf_fentry_test1")
int BPF_PROG(sub, int a)
{
if (pid != (bpf_get_current_pid_tgid() >> 32))
return 0;
#ifdef ENABLE_ATOMICS_TESTS
__u64 sub_stack_value = 1;
......@@ -67,6 +73,8 @@ __u64 and_noreturn_value = (0x110ull << 32);
SEC("fentry/bpf_fentry_test1")
int BPF_PROG(and, int a)
{
if (pid != (bpf_get_current_pid_tgid() >> 32))
return 0;
#ifdef ENABLE_ATOMICS_TESTS
and64_result = __sync_fetch_and_and(&and64_value, 0x011ull << 32);
......@@ -86,6 +94,8 @@ __u64 or_noreturn_value = (0x110ull << 32);
SEC("fentry/bpf_fentry_test1")
int BPF_PROG(or, int a)
{
if (pid != (bpf_get_current_pid_tgid() >> 32))
return 0;
#ifdef ENABLE_ATOMICS_TESTS
or64_result = __sync_fetch_and_or(&or64_value, 0x011ull << 32);
or32_result = __sync_fetch_and_or(&or32_value, 0x011);
......@@ -104,6 +114,8 @@ __u64 xor_noreturn_value = (0x110ull << 32);
SEC("fentry/bpf_fentry_test1")
int BPF_PROG(xor, int a)
{
if (pid != (bpf_get_current_pid_tgid() >> 32))
return 0;
#ifdef ENABLE_ATOMICS_TESTS
xor64_result = __sync_fetch_and_xor(&xor64_value, 0x011ull << 32);
xor32_result = __sync_fetch_and_xor(&xor32_value, 0x011);
......@@ -123,6 +135,8 @@ __u32 cmpxchg32_result_succeed = 0;
SEC("fentry/bpf_fentry_test1")
int BPF_PROG(cmpxchg, int a)
{
if (pid != (bpf_get_current_pid_tgid() >> 32))
return 0;
#ifdef ENABLE_ATOMICS_TESTS
cmpxchg64_result_fail = __sync_val_compare_and_swap(&cmpxchg64_value, 0, 3);
cmpxchg64_result_succeed = __sync_val_compare_and_swap(&cmpxchg64_value, 1, 2);
......@@ -142,6 +156,8 @@ __u32 xchg32_result = 0;
SEC("fentry/bpf_fentry_test1")
int BPF_PROG(xchg, int a)
{
if (pid != (bpf_get_current_pid_tgid() >> 32))
return 0;
#ifdef ENABLE_ATOMICS_TESTS
__u64 val64 = 2;
__u32 val32 = 2;
......
......@@ -18,7 +18,7 @@ int connect_v4_dropper(struct bpf_sock_addr *ctx)
{
if (ctx->type != SOCK_STREAM)
return VERDICT_PROCEED;
if (ctx->user_port == bpf_htons(60123))
if (ctx->user_port == bpf_htons(60120))
return VERDICT_REJECT;
return VERDICT_PROCEED;
}
......
......@@ -13,7 +13,7 @@ int fexit_cnt = 0;
SEC("fentry/__x64_sys_nanosleep")
int BPF_PROG(nanosleep_fentry, const struct pt_regs *regs)
{
if ((int)bpf_get_current_pid_tgid() != pid)
if (bpf_get_current_pid_tgid() >> 32 != pid)
return 0;
fentry_cnt++;
......@@ -23,7 +23,7 @@ int BPF_PROG(nanosleep_fentry, const struct pt_regs *regs)
SEC("fexit/__x64_sys_nanosleep")
int BPF_PROG(nanosleep_fexit, const struct pt_regs *regs, int ret)
{
if ((int)bpf_get_current_pid_tgid() != pid)
if (bpf_get_current_pid_tgid() >> 32 != pid)
return 0;
fexit_cnt++;
......
......@@ -13,6 +13,6 @@ __u64 count = 0;
SEC("raw_tracepoint/sys_enter")
int test_enable_stats(void *ctx)
{
count += 1;
__sync_fetch_and_add(&count, 1);
return 0;
}
This diff is collapsed.
......@@ -62,6 +62,7 @@ struct test_env {
struct test_selector test_selector;
struct test_selector subtest_selector;
bool verifier_stats;
bool debug;
enum verbosity verbosity;
bool jit_enabled;
......@@ -69,7 +70,8 @@ struct test_env {
bool get_test_cnt;
bool list_test_names;
struct prog_test_def *test;
struct prog_test_def *test; /* current running tests */
FILE *stdout;
FILE *stderr;
char *log_buf;
......@@ -82,6 +84,38 @@ struct test_env {
int skip_cnt; /* skipped tests */
int saved_netns_fd;
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
enum msg_type {
MSG_DO_TEST = 0,
MSG_TEST_DONE = 1,
MSG_TEST_LOG = 2,
MSG_EXIT = 255,
};
struct msg {
enum msg_type type;
union {
struct {
int test_num;
} do_test;
struct {
int test_num;
int sub_succ_cnt;
int error_cnt;
int skip_cnt;
bool have_log;
} test_done;
struct {
char log_buf[MAX_LOG_TRUNK_SIZE + 1];
bool is_last;
} test_log;
};
};
extern struct test_env env;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment