Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
  1// SPDX-License-Identifier: GPL-2.0
  2#include <test_progs.h>
  3#include <network_helpers.h>
  4
  5#include "test_spin_lock.skel.h"
  6#include "test_spin_lock_fail.skel.h"
  7
  8static char log_buf[1024 * 1024];
  9
 10static struct {
 11	const char *prog_name;
 12	const char *err_msg;
 13} spin_lock_fail_tests[] = {
 14	{ "lock_id_kptr_preserve",
 15	  "5: (bf) r1 = r0                       ; R0_w=ptr_foo(id=2,ref_obj_id=2,off=0,imm=0) "
 16	  "R1_w=ptr_foo(id=2,ref_obj_id=2,off=0,imm=0) refs=2\n6: (85) call bpf_this_cpu_ptr#154\n"
 17	  "R1 type=ptr_ expected=percpu_ptr_" },
 18	{ "lock_id_global_zero",
 19	  "; R1_w=map_value(off=0,ks=4,vs=4,imm=0)\n2: (85) call bpf_this_cpu_ptr#154\n"
 20	  "R1 type=map_value expected=percpu_ptr_" },
 21	{ "lock_id_mapval_preserve",
 22	  "8: (bf) r1 = r0                       ; R0_w=map_value(id=1,off=0,ks=4,vs=8,imm=0) "
 23	  "R1_w=map_value(id=1,off=0,ks=4,vs=8,imm=0)\n9: (85) call bpf_this_cpu_ptr#154\n"
 24	  "R1 type=map_value expected=percpu_ptr_" },
 25	{ "lock_id_innermapval_preserve",
 26	  "13: (bf) r1 = r0                      ; R0=map_value(id=2,off=0,ks=4,vs=8,imm=0) "
 27	  "R1_w=map_value(id=2,off=0,ks=4,vs=8,imm=0)\n14: (85) call bpf_this_cpu_ptr#154\n"
 28	  "R1 type=map_value expected=percpu_ptr_" },
 29	{ "lock_id_mismatch_kptr_kptr", "bpf_spin_unlock of different lock" },
 30	{ "lock_id_mismatch_kptr_global", "bpf_spin_unlock of different lock" },
 31	{ "lock_id_mismatch_kptr_mapval", "bpf_spin_unlock of different lock" },
 32	{ "lock_id_mismatch_kptr_innermapval", "bpf_spin_unlock of different lock" },
 33	{ "lock_id_mismatch_global_global", "bpf_spin_unlock of different lock" },
 34	{ "lock_id_mismatch_global_kptr", "bpf_spin_unlock of different lock" },
 35	{ "lock_id_mismatch_global_mapval", "bpf_spin_unlock of different lock" },
 36	{ "lock_id_mismatch_global_innermapval", "bpf_spin_unlock of different lock" },
 37	{ "lock_id_mismatch_mapval_mapval", "bpf_spin_unlock of different lock" },
 38	{ "lock_id_mismatch_mapval_kptr", "bpf_spin_unlock of different lock" },
 39	{ "lock_id_mismatch_mapval_global", "bpf_spin_unlock of different lock" },
 40	{ "lock_id_mismatch_mapval_innermapval", "bpf_spin_unlock of different lock" },
 41	{ "lock_id_mismatch_innermapval_innermapval1", "bpf_spin_unlock of different lock" },
 42	{ "lock_id_mismatch_innermapval_innermapval2", "bpf_spin_unlock of different lock" },
 43	{ "lock_id_mismatch_innermapval_kptr", "bpf_spin_unlock of different lock" },
 44	{ "lock_id_mismatch_innermapval_global", "bpf_spin_unlock of different lock" },
 45	{ "lock_id_mismatch_innermapval_mapval", "bpf_spin_unlock of different lock" },
 46};
 47
 48static void test_spin_lock_fail_prog(const char *prog_name, const char *err_msg)
 49{
 50	LIBBPF_OPTS(bpf_object_open_opts, opts, .kernel_log_buf = log_buf,
 51						.kernel_log_size = sizeof(log_buf),
 52						.kernel_log_level = 1);
 53	struct test_spin_lock_fail *skel;
 54	struct bpf_program *prog;
 55	int ret;
 56
 57	skel = test_spin_lock_fail__open_opts(&opts);
 58	if (!ASSERT_OK_PTR(skel, "test_spin_lock_fail__open_opts"))
 59		return;
 60
 61	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
 62	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
 63		goto end;
 64
 65	bpf_program__set_autoload(prog, true);
 66
 67	ret = test_spin_lock_fail__load(skel);
 68	if (!ASSERT_ERR(ret, "test_spin_lock_fail__load must fail"))
 69		goto end;
 70
 71	/* Skip check if JIT does not support kfuncs */
 72	if (strstr(log_buf, "JIT does not support calling kernel function")) {
 73		test__skip();
 74		goto end;
 75	}
 76
 77	if (!ASSERT_OK_PTR(strstr(log_buf, err_msg), "expected error message")) {
 78		fprintf(stderr, "Expected: %s\n", err_msg);
 79		fprintf(stderr, "Verifier: %s\n", log_buf);
 80	}
 81
 82end:
 83	test_spin_lock_fail__destroy(skel);
 84}
 85
 86static void *spin_lock_thread(void *arg)
 87{
 88	int err, prog_fd = *(u32 *) arg;
 89	LIBBPF_OPTS(bpf_test_run_opts, topts,
 90		.data_in = &pkt_v4,
 91		.data_size_in = sizeof(pkt_v4),
 92		.repeat = 10000,
 93	);
 94
 95	err = bpf_prog_test_run_opts(prog_fd, &topts);
 96	ASSERT_OK(err, "test_run");
 97	ASSERT_OK(topts.retval, "test_run retval");
 98	pthread_exit(arg);
 99}
100
101void test_spin_lock_success(void)
102{
103	struct test_spin_lock *skel;
104	pthread_t thread_id[4];
105	int prog_fd, i;
106	void *ret;
107
108	skel = test_spin_lock__open_and_load();
109	if (!ASSERT_OK_PTR(skel, "test_spin_lock__open_and_load"))
110		return;
111	prog_fd = bpf_program__fd(skel->progs.bpf_spin_lock_test);
112	for (i = 0; i < 4; i++) {
113		int err;
114
115		err = pthread_create(&thread_id[i], NULL, &spin_lock_thread, &prog_fd);
116		if (!ASSERT_OK(err, "pthread_create"))
117			goto end;
118	}
119
120	for (i = 0; i < 4; i++) {
121		if (!ASSERT_OK(pthread_join(thread_id[i], &ret), "pthread_join"))
122			goto end;
123		if (!ASSERT_EQ(ret, &prog_fd, "ret == prog_fd"))
124			goto end;
125	}
126end:
127	test_spin_lock__destroy(skel);
128}
129
130void test_spin_lock(void)
131{
132	int i;
133
134	test_spin_lock_success();
135
136	for (i = 0; i < ARRAY_SIZE(spin_lock_fail_tests); i++) {
137		if (!test__start_subtest(spin_lock_fail_tests[i].prog_name))
138			continue;
139		test_spin_lock_fail_prog(spin_lock_fail_tests[i].prog_name,
140					 spin_lock_fail_tests[i].err_msg);
141	}
142}