|  | 
| 3 | 3 | #include <test_progs.h> | 
| 4 | 4 | #include "struct_ops_assoc.skel.h" | 
| 5 | 5 | #include "struct_ops_assoc_reuse.skel.h" | 
|  | 6 | +#include "struct_ops_assoc_in_timer.skel.h" | 
| 6 | 7 | 
 | 
| 7 | 8 | static void test_st_ops_assoc(void) | 
| 8 | 9 | { | 
| @@ -101,10 +102,89 @@ static void test_st_ops_assoc_reuse(void) | 
| 101 | 102 | 	struct_ops_assoc_reuse__destroy(skel); | 
| 102 | 103 | } | 
| 103 | 104 | 
 | 
|  | 105 | +static void test_st_ops_assoc_in_timer(void) | 
|  | 106 | +{ | 
|  | 107 | +	struct struct_ops_assoc_in_timer *skel = NULL; | 
|  | 108 | +	int err; | 
|  | 109 | + | 
|  | 110 | +	skel = struct_ops_assoc_in_timer__open_and_load(); | 
|  | 111 | +	if (!ASSERT_OK_PTR(skel, "struct_ops_assoc_reuse__open")) | 
|  | 112 | +		goto out; | 
|  | 113 | + | 
|  | 114 | +	err = bpf_program__assoc_struct_ops(skel->progs.syscall_prog, | 
|  | 115 | +					    skel->maps.st_ops_map, NULL); | 
|  | 116 | +	ASSERT_OK(err, "bpf_program__assoc_struct_ops"); | 
|  | 117 | + | 
|  | 118 | +	err = struct_ops_assoc_in_timer__attach(skel); | 
|  | 119 | +	if (!ASSERT_OK(err, "struct_ops_assoc__attach")) | 
|  | 120 | +		goto out; | 
|  | 121 | + | 
|  | 122 | +	/* run syscall_prog that calls .test_1 and checks return */ | 
|  | 123 | +	err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.syscall_prog), NULL); | 
|  | 124 | +	ASSERT_OK(err, "bpf_prog_test_run_opts"); | 
|  | 125 | + | 
|  | 126 | +	/* | 
|  | 127 | +	 * .test_1 has scheduled timer_cb that calls bpf_kfunc_multi_st_ops_test_1_prog_arg() | 
|  | 128 | +	 * again. Check the return of the kfunc after timer_cb run. | 
|  | 129 | +	 */ | 
|  | 130 | +	while (!READ_ONCE(skel->bss->timer_cb_run)) | 
|  | 131 | +		sched_yield(); | 
|  | 132 | +	ASSERT_EQ(skel->bss->timer_test_1_ret, 1234, "skel->bss->timer_test_1_ret"); | 
|  | 133 | +	ASSERT_EQ(skel->bss->test_err, 0, "skel->bss->test_err_a"); | 
|  | 134 | +out: | 
|  | 135 | +	struct_ops_assoc_in_timer__destroy(skel); | 
|  | 136 | +} | 
|  | 137 | + | 
|  | 138 | +static void test_st_ops_assoc_in_timer_after_detach(void) | 
|  | 139 | +{ | 
|  | 140 | +	struct struct_ops_assoc_in_timer *skel = NULL; | 
|  | 141 | +	struct bpf_link *link; | 
|  | 142 | +	int err; | 
|  | 143 | + | 
|  | 144 | +	skel = struct_ops_assoc_in_timer__open_and_load(); | 
|  | 145 | +	if (!ASSERT_OK_PTR(skel, "struct_ops_assoc_reuse__open")) | 
|  | 146 | +		goto out; | 
|  | 147 | + | 
|  | 148 | +	err = bpf_program__assoc_struct_ops(skel->progs.syscall_prog, | 
|  | 149 | +					    skel->maps.st_ops_map, NULL); | 
|  | 150 | +	ASSERT_OK(err, "bpf_program__assoc_struct_ops"); | 
|  | 151 | + | 
|  | 152 | +	link = bpf_map__attach_struct_ops(skel->maps.st_ops_map); | 
|  | 153 | +	if (!ASSERT_OK_PTR(link, "bpf_map__attach_struct_ops")) | 
|  | 154 | +		goto out; | 
|  | 155 | + | 
|  | 156 | +	/* timer_cb will run 500ms after syscall_prog_run when st_ops_map is gone */ | 
|  | 157 | +	skel->bss->timer_ns = 500000000; | 
|  | 158 | + | 
|  | 159 | +	/* run syscall_prog that calls .test_1 and checks return */ | 
|  | 160 | +	err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.syscall_prog), NULL); | 
|  | 161 | +	ASSERT_OK(err, "bpf_prog_test_run_opts"); | 
|  | 162 | + | 
|  | 163 | +	/* detach and free struct_ops map */ | 
|  | 164 | +	bpf_link__destroy(link); | 
|  | 165 | +	close(bpf_program__fd(skel->progs.syscall_prog)); | 
|  | 166 | +	close(bpf_map__fd(skel->maps.st_ops_map)); | 
|  | 167 | + | 
|  | 168 | +	/* | 
|  | 169 | +	 * .test_1 has scheduled timer_cb that calls bpf_kfunc_multi_st_ops_test_1_prog_arg() | 
|  | 170 | +	 * again. Check the return of the kfunc after timer_cb run. | 
|  | 171 | +	 */ | 
|  | 172 | +	while (!READ_ONCE(skel->bss->timer_cb_run)) | 
|  | 173 | +		sched_yield(); | 
|  | 174 | +	ASSERT_EQ(skel->bss->timer_test_1_ret, -1, "skel->bss->timer_test_1_ret"); | 
|  | 175 | +	ASSERT_EQ(skel->bss->test_err, 0, "skel->bss->test_err_a"); | 
|  | 176 | +out: | 
|  | 177 | +	struct_ops_assoc_in_timer__destroy(skel); | 
|  | 178 | +} | 
|  | 179 | + | 
| 104 | 180 | void test_struct_ops_assoc(void) | 
| 105 | 181 | { | 
| 106 | 182 | 	if (test__start_subtest("st_ops_assoc")) | 
| 107 | 183 | 		test_st_ops_assoc(); | 
| 108 | 184 | 	if (test__start_subtest("st_ops_assoc_reuse")) | 
| 109 | 185 | 		test_st_ops_assoc_reuse(); | 
|  | 186 | +	if (test__start_subtest("st_ops_assoc_in_timer")) | 
|  | 187 | +		test_st_ops_assoc_in_timer(); | 
|  | 188 | +	if (test__start_subtest("st_ops_assoc_in_timer_after_detach")) | 
|  | 189 | +		test_st_ops_assoc_in_timer_after_detach(); | 
| 110 | 190 | } | 
0 commit comments