1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright (c) 2019 Facebook */ |
3 | #include <test_progs.h> |
4 | #include <network_helpers.h> |
5 | #include <bpf/btf.h> |
6 | #include "bind4_prog.skel.h" |
7 | #include "freplace_progmap.skel.h" |
8 | #include "xdp_dummy.skel.h" |
9 | |
10 | typedef int (*test_cb)(struct bpf_object *obj); |
11 | |
12 | static int check_data_map(struct bpf_object *obj, int prog_cnt, bool reset) |
13 | { |
14 | struct bpf_map *data_map = NULL, *map; |
15 | __u64 *result = NULL; |
16 | const int zero = 0; |
17 | __u32 duration = 0; |
18 | int ret = -1, i; |
19 | |
20 | result = malloc((prog_cnt + 32 /* spare */) * sizeof(__u64)); |
21 | if (CHECK(!result, "alloc_memory" , "failed to alloc memory" )) |
22 | return -ENOMEM; |
23 | |
24 | bpf_object__for_each_map(map, obj) |
25 | if (bpf_map__is_internal(map)) { |
26 | data_map = map; |
27 | break; |
28 | } |
29 | if (CHECK(!data_map, "find_data_map" , "data map not found\n" )) |
30 | goto out; |
31 | |
32 | ret = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, result); |
33 | if (CHECK(ret, "get_result" , |
34 | "failed to get output data: %d\n" , ret)) |
35 | goto out; |
36 | |
37 | for (i = 0; i < prog_cnt; i++) { |
38 | if (CHECK(result[i] != 1, "result" , |
39 | "fexit_bpf2bpf result[%d] failed err %llu\n" , |
40 | i, result[i])) |
41 | goto out; |
42 | result[i] = 0; |
43 | } |
44 | if (reset) { |
45 | ret = bpf_map_update_elem(bpf_map__fd(data_map), &zero, result, 0); |
46 | if (CHECK(ret, "reset_result" , "failed to reset result\n" )) |
47 | goto out; |
48 | } |
49 | |
50 | ret = 0; |
51 | out: |
52 | free(result); |
53 | return ret; |
54 | } |
55 | |
56 | static void test_fexit_bpf2bpf_common(const char *obj_file, |
57 | const char *target_obj_file, |
58 | int prog_cnt, |
59 | const char **prog_name, |
60 | bool run_prog, |
61 | test_cb cb) |
62 | { |
63 | struct bpf_object *obj = NULL, *tgt_obj; |
64 | __u32 tgt_prog_id, info_len; |
65 | struct bpf_prog_info prog_info = {}; |
66 | struct bpf_program **prog = NULL, *p; |
67 | struct bpf_link **link = NULL; |
68 | int err, tgt_fd, i; |
69 | struct btf *btf; |
70 | LIBBPF_OPTS(bpf_test_run_opts, topts, |
71 | .data_in = &pkt_v6, |
72 | .data_size_in = sizeof(pkt_v6), |
73 | .repeat = 1, |
74 | ); |
75 | |
76 | err = bpf_prog_test_load(target_obj_file, BPF_PROG_TYPE_UNSPEC, |
77 | &tgt_obj, &tgt_fd); |
78 | if (!ASSERT_OK(err, "tgt_prog_load" )) |
79 | return; |
80 | |
81 | info_len = sizeof(prog_info); |
82 | err = bpf_prog_get_info_by_fd(tgt_fd, &prog_info, &info_len); |
83 | if (!ASSERT_OK(err, "tgt_fd_get_info" )) |
84 | goto close_prog; |
85 | |
86 | tgt_prog_id = prog_info.id; |
87 | btf = bpf_object__btf(tgt_obj); |
88 | |
89 | link = calloc(sizeof(struct bpf_link *), prog_cnt); |
90 | if (!ASSERT_OK_PTR(link, "link_ptr" )) |
91 | goto close_prog; |
92 | |
93 | prog = calloc(sizeof(struct bpf_program *), prog_cnt); |
94 | if (!ASSERT_OK_PTR(prog, "prog_ptr" )) |
95 | goto close_prog; |
96 | |
97 | obj = bpf_object__open_file(obj_file, NULL); |
98 | if (!ASSERT_OK_PTR(obj, "obj_open" )) |
99 | goto close_prog; |
100 | |
101 | bpf_object__for_each_program(p, obj) { |
102 | err = bpf_program__set_attach_target(p, tgt_fd, NULL); |
103 | ASSERT_OK(err, "set_attach_target" ); |
104 | } |
105 | |
106 | err = bpf_object__load(obj); |
107 | if (!ASSERT_OK(err, "obj_load" )) |
108 | goto close_prog; |
109 | |
110 | for (i = 0; i < prog_cnt; i++) { |
111 | struct bpf_link_info link_info; |
112 | struct bpf_program *pos; |
113 | const char *pos_sec_name; |
114 | char *tgt_name; |
115 | __s32 btf_id; |
116 | |
117 | tgt_name = strstr(prog_name[i], "/" ); |
118 | if (!ASSERT_OK_PTR(tgt_name, "tgt_name" )) |
119 | goto close_prog; |
120 | btf_id = btf__find_by_name_kind(btf, tgt_name + 1, BTF_KIND_FUNC); |
121 | |
122 | prog[i] = NULL; |
123 | bpf_object__for_each_program(pos, obj) { |
124 | pos_sec_name = bpf_program__section_name(pos); |
125 | if (pos_sec_name && !strcmp(pos_sec_name, prog_name[i])) { |
126 | prog[i] = pos; |
127 | break; |
128 | } |
129 | } |
130 | if (!ASSERT_OK_PTR(prog[i], prog_name[i])) |
131 | goto close_prog; |
132 | |
133 | link[i] = bpf_program__attach_trace(prog[i]); |
134 | if (!ASSERT_OK_PTR(link[i], "attach_trace" )) |
135 | goto close_prog; |
136 | |
137 | info_len = sizeof(link_info); |
138 | memset(&link_info, 0, sizeof(link_info)); |
139 | err = bpf_link_get_info_by_fd(bpf_link__fd(link[i]), |
140 | &link_info, &info_len); |
141 | ASSERT_OK(err, "link_fd_get_info" ); |
142 | ASSERT_EQ(link_info.tracing.attach_type, |
143 | bpf_program__expected_attach_type(prog[i]), |
144 | "link_attach_type" ); |
145 | ASSERT_EQ(link_info.tracing.target_obj_id, tgt_prog_id, "link_tgt_obj_id" ); |
146 | ASSERT_EQ(link_info.tracing.target_btf_id, btf_id, "link_tgt_btf_id" ); |
147 | } |
148 | |
149 | if (cb) { |
150 | err = cb(obj); |
151 | if (err) |
152 | goto close_prog; |
153 | } |
154 | |
155 | if (!run_prog) |
156 | goto close_prog; |
157 | |
158 | err = bpf_prog_test_run_opts(tgt_fd, &topts); |
159 | ASSERT_OK(err, "prog_run" ); |
160 | ASSERT_EQ(topts.retval, 0, "prog_run_ret" ); |
161 | |
162 | if (check_data_map(obj, prog_cnt, false)) |
163 | goto close_prog; |
164 | |
165 | close_prog: |
166 | for (i = 0; i < prog_cnt; i++) |
167 | bpf_link__destroy(link[i]); |
168 | bpf_object__close(obj); |
169 | bpf_object__close(tgt_obj); |
170 | free(link); |
171 | free(prog); |
172 | } |
173 | |
174 | static void test_target_no_callees(void) |
175 | { |
176 | const char *prog_name[] = { |
177 | "fexit/test_pkt_md_access" , |
178 | }; |
179 | test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.bpf.o" , |
180 | "./test_pkt_md_access.bpf.o" , |
181 | ARRAY_SIZE(prog_name), |
182 | prog_name, true, NULL); |
183 | } |
184 | |
185 | static void test_target_yes_callees(void) |
186 | { |
187 | const char *prog_name[] = { |
188 | "fexit/test_pkt_access" , |
189 | "fexit/test_pkt_access_subprog1" , |
190 | "fexit/test_pkt_access_subprog2" , |
191 | "fexit/test_pkt_access_subprog3" , |
192 | }; |
193 | test_fexit_bpf2bpf_common("./fexit_bpf2bpf.bpf.o" , |
194 | "./test_pkt_access.bpf.o" , |
195 | ARRAY_SIZE(prog_name), |
196 | prog_name, true, NULL); |
197 | } |
198 | |
199 | static void test_func_replace(void) |
200 | { |
201 | const char *prog_name[] = { |
202 | "fexit/test_pkt_access" , |
203 | "fexit/test_pkt_access_subprog1" , |
204 | "fexit/test_pkt_access_subprog2" , |
205 | "fexit/test_pkt_access_subprog3" , |
206 | "freplace/get_skb_len" , |
207 | "freplace/get_skb_ifindex" , |
208 | "freplace/get_constant" , |
209 | "freplace/test_pkt_write_access_subprog" , |
210 | }; |
211 | test_fexit_bpf2bpf_common("./fexit_bpf2bpf.bpf.o" , |
212 | "./test_pkt_access.bpf.o" , |
213 | ARRAY_SIZE(prog_name), |
214 | prog_name, true, NULL); |
215 | } |
216 | |
217 | static void test_func_replace_verify(void) |
218 | { |
219 | const char *prog_name[] = { |
220 | "freplace/do_bind" , |
221 | }; |
222 | test_fexit_bpf2bpf_common("./freplace_connect4.bpf.o" , |
223 | "./connect4_prog.bpf.o" , |
224 | ARRAY_SIZE(prog_name), |
225 | prog_name, false, NULL); |
226 | } |
227 | |
228 | static int test_second_attach(struct bpf_object *obj) |
229 | { |
230 | const char *prog_name = "security_new_get_constant" ; |
231 | const char *tgt_name = "get_constant" ; |
232 | const char *tgt_obj_file = "./test_pkt_access.bpf.o" ; |
233 | struct bpf_program *prog = NULL; |
234 | struct bpf_object *tgt_obj; |
235 | struct bpf_link *link; |
236 | int err = 0, tgt_fd; |
237 | LIBBPF_OPTS(bpf_test_run_opts, topts, |
238 | .data_in = &pkt_v6, |
239 | .data_size_in = sizeof(pkt_v6), |
240 | .repeat = 1, |
241 | ); |
242 | |
243 | prog = bpf_object__find_program_by_name(obj, prog_name); |
244 | if (!ASSERT_OK_PTR(prog, "find_prog" )) |
245 | return -ENOENT; |
246 | |
247 | err = bpf_prog_test_load(tgt_obj_file, BPF_PROG_TYPE_UNSPEC, |
248 | &tgt_obj, &tgt_fd); |
249 | if (!ASSERT_OK(err, "second_prog_load" )) |
250 | return err; |
251 | |
252 | link = bpf_program__attach_freplace(prog, tgt_fd, tgt_name); |
253 | if (!ASSERT_OK_PTR(link, "second_link" )) |
254 | goto out; |
255 | |
256 | err = bpf_prog_test_run_opts(tgt_fd, &topts); |
257 | if (!ASSERT_OK(err, "ipv6 test_run" )) |
258 | goto out; |
259 | if (!ASSERT_OK(topts.retval, "ipv6 retval" )) |
260 | goto out; |
261 | |
262 | err = check_data_map(obj, 1, true); |
263 | if (err) |
264 | goto out; |
265 | |
266 | out: |
267 | bpf_link__destroy(link); |
268 | bpf_object__close(tgt_obj); |
269 | return err; |
270 | } |
271 | |
272 | static void test_func_replace_multi(void) |
273 | { |
274 | const char *prog_name[] = { |
275 | "freplace/get_constant" , |
276 | }; |
277 | test_fexit_bpf2bpf_common("./freplace_get_constant.bpf.o" , |
278 | "./test_pkt_access.bpf.o" , |
279 | ARRAY_SIZE(prog_name), |
280 | prog_name, true, test_second_attach); |
281 | } |
282 | |
283 | static void test_fmod_ret_freplace(void) |
284 | { |
285 | struct bpf_object *freplace_obj = NULL, *pkt_obj, *fmod_obj = NULL; |
286 | const char *freplace_name = "./freplace_get_constant.bpf.o" ; |
287 | const char *fmod_ret_name = "./fmod_ret_freplace.bpf.o" ; |
288 | DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts); |
289 | const char *tgt_name = "./test_pkt_access.bpf.o" ; |
290 | struct bpf_link *freplace_link = NULL; |
291 | struct bpf_program *prog; |
292 | __u32 duration = 0; |
293 | int err, pkt_fd, attach_prog_fd; |
294 | |
295 | err = bpf_prog_test_load(tgt_name, BPF_PROG_TYPE_UNSPEC, |
296 | &pkt_obj, &pkt_fd); |
297 | /* the target prog should load fine */ |
298 | if (CHECK(err, "tgt_prog_load" , "file %s err %d errno %d\n" , |
299 | tgt_name, err, errno)) |
300 | return; |
301 | |
302 | freplace_obj = bpf_object__open_file(freplace_name, NULL); |
303 | if (!ASSERT_OK_PTR(freplace_obj, "freplace_obj_open" )) |
304 | goto out; |
305 | |
306 | prog = bpf_object__next_program(freplace_obj, NULL); |
307 | err = bpf_program__set_attach_target(prog, pkt_fd, NULL); |
308 | ASSERT_OK(err, "freplace__set_attach_target" ); |
309 | |
310 | err = bpf_object__load(freplace_obj); |
311 | if (CHECK(err, "freplace_obj_load" , "err %d\n" , err)) |
312 | goto out; |
313 | |
314 | freplace_link = bpf_program__attach_trace(prog); |
315 | if (!ASSERT_OK_PTR(freplace_link, "freplace_attach_trace" )) |
316 | goto out; |
317 | |
318 | fmod_obj = bpf_object__open_file(fmod_ret_name, NULL); |
319 | if (!ASSERT_OK_PTR(fmod_obj, "fmod_obj_open" )) |
320 | goto out; |
321 | |
322 | attach_prog_fd = bpf_program__fd(prog); |
323 | prog = bpf_object__next_program(fmod_obj, NULL); |
324 | err = bpf_program__set_attach_target(prog, attach_prog_fd, NULL); |
325 | ASSERT_OK(err, "fmod_ret_set_attach_target" ); |
326 | |
327 | err = bpf_object__load(fmod_obj); |
328 | if (CHECK(!err, "fmod_obj_load" , "loading fmod_ret should fail\n" )) |
329 | goto out; |
330 | |
331 | out: |
332 | bpf_link__destroy(freplace_link); |
333 | bpf_object__close(freplace_obj); |
334 | bpf_object__close(fmod_obj); |
335 | bpf_object__close(pkt_obj); |
336 | } |
337 | |
338 | |
339 | static void test_func_sockmap_update(void) |
340 | { |
341 | const char *prog_name[] = { |
342 | "freplace/cls_redirect" , |
343 | }; |
344 | test_fexit_bpf2bpf_common("./freplace_cls_redirect.bpf.o" , |
345 | "./test_cls_redirect.bpf.o" , |
346 | ARRAY_SIZE(prog_name), |
347 | prog_name, false, NULL); |
348 | } |
349 | |
350 | static void test_obj_load_failure_common(const char *obj_file, |
351 | const char *target_obj_file, |
352 | const char *exp_msg) |
353 | { |
354 | /* |
355 | * standalone test that asserts failure to load freplace prog |
356 | * because of invalid return code. |
357 | */ |
358 | struct bpf_object *obj = NULL, *pkt_obj; |
359 | struct bpf_program *prog; |
360 | char log_buf[64 * 1024]; |
361 | int err, pkt_fd; |
362 | __u32 duration = 0; |
363 | |
364 | err = bpf_prog_test_load(target_obj_file, BPF_PROG_TYPE_UNSPEC, |
365 | &pkt_obj, &pkt_fd); |
366 | /* the target prog should load fine */ |
367 | if (CHECK(err, "tgt_prog_load" , "file %s err %d errno %d\n" , |
368 | target_obj_file, err, errno)) |
369 | return; |
370 | |
371 | obj = bpf_object__open_file(obj_file, NULL); |
372 | if (!ASSERT_OK_PTR(obj, "obj_open" )) |
373 | goto close_prog; |
374 | |
375 | prog = bpf_object__next_program(obj, NULL); |
376 | err = bpf_program__set_attach_target(prog, pkt_fd, NULL); |
377 | ASSERT_OK(err, "set_attach_target" ); |
378 | |
379 | log_buf[0] = '\0'; |
380 | if (exp_msg) |
381 | bpf_program__set_log_buf(prog, log_buf, sizeof(log_buf)); |
382 | if (env.verbosity > VERBOSE_NONE) |
383 | bpf_program__set_log_level(prog, 2); |
384 | |
385 | /* It should fail to load the program */ |
386 | err = bpf_object__load(obj); |
387 | if (env.verbosity > VERBOSE_NONE && exp_msg) /* we overtook log */ |
388 | printf("VERIFIER LOG:\n================\n%s\n================\n" , log_buf); |
389 | if (CHECK(!err, "bpf_obj_load should fail" , "err %d\n" , err)) |
390 | goto close_prog; |
391 | |
392 | if (exp_msg) |
393 | ASSERT_HAS_SUBSTR(log_buf, exp_msg, "fail_msg" ); |
394 | close_prog: |
395 | bpf_object__close(obj); |
396 | bpf_object__close(pkt_obj); |
397 | } |
398 | |
399 | static void test_func_replace_return_code(void) |
400 | { |
401 | /* test invalid return code in the replaced program */ |
402 | test_obj_load_failure_common("./freplace_connect_v4_prog.bpf.o" , |
403 | "./connect4_prog.bpf.o" , NULL); |
404 | } |
405 | |
406 | static void test_func_map_prog_compatibility(void) |
407 | { |
408 | /* test with spin lock map value in the replaced program */ |
409 | test_obj_load_failure_common("./freplace_attach_probe.bpf.o" , |
410 | "./test_attach_probe.bpf.o" , NULL); |
411 | } |
412 | |
413 | static void test_func_replace_unreliable(void) |
414 | { |
415 | /* freplace'ing unreliable main prog should fail with error |
416 | * "Cannot replace static functions" |
417 | */ |
418 | test_obj_load_failure_common(obj_file: "freplace_unreliable_prog.bpf.o" , |
419 | target_obj_file: "./verifier_btf_unreliable_prog.bpf.o" , |
420 | exp_msg: "Cannot replace static functions" ); |
421 | } |
422 | |
423 | static void test_func_replace_global_func(void) |
424 | { |
425 | const char *prog_name[] = { |
426 | "freplace/test_pkt_access" , |
427 | }; |
428 | |
429 | test_fexit_bpf2bpf_common("./freplace_global_func.bpf.o" , |
430 | "./test_pkt_access.bpf.o" , |
431 | ARRAY_SIZE(prog_name), |
432 | prog_name, false, NULL); |
433 | } |
434 | |
435 | static int find_prog_btf_id(const char *name, __u32 attach_prog_fd) |
436 | { |
437 | struct bpf_prog_info info = {}; |
438 | __u32 info_len = sizeof(info); |
439 | struct btf *btf; |
440 | int ret; |
441 | |
442 | ret = bpf_prog_get_info_by_fd(attach_prog_fd, &info, &info_len); |
443 | if (ret) |
444 | return ret; |
445 | |
446 | if (!info.btf_id) |
447 | return -EINVAL; |
448 | |
449 | btf = btf__load_from_kernel_by_id(info.btf_id); |
450 | ret = libbpf_get_error(btf); |
451 | if (ret) |
452 | return ret; |
453 | |
454 | ret = btf__find_by_name_kind(btf, name, BTF_KIND_FUNC); |
455 | btf__free(btf); |
456 | return ret; |
457 | } |
458 | |
459 | static int load_fentry(int attach_prog_fd, int attach_btf_id) |
460 | { |
461 | LIBBPF_OPTS(bpf_prog_load_opts, opts, |
462 | .expected_attach_type = BPF_TRACE_FENTRY, |
463 | .attach_prog_fd = attach_prog_fd, |
464 | .attach_btf_id = attach_btf_id, |
465 | ); |
466 | struct bpf_insn insns[] = { |
467 | BPF_MOV64_IMM(BPF_REG_0, 0), |
468 | BPF_EXIT_INSN(), |
469 | }; |
470 | |
471 | return bpf_prog_load(BPF_PROG_TYPE_TRACING, |
472 | "bind4_fentry" , |
473 | "GPL" , |
474 | insns, |
475 | ARRAY_SIZE(insns), |
476 | &opts); |
477 | } |
478 | |
479 | static void test_fentry_to_cgroup_bpf(void) |
480 | { |
481 | struct bind4_prog *skel = NULL; |
482 | struct bpf_prog_info info = {}; |
483 | __u32 info_len = sizeof(info); |
484 | int cgroup_fd = -1; |
485 | int fentry_fd = -1; |
486 | int btf_id; |
487 | |
488 | cgroup_fd = test__join_cgroup("/fentry_to_cgroup_bpf" ); |
489 | if (!ASSERT_GE(cgroup_fd, 0, "cgroup_fd" )) |
490 | return; |
491 | |
492 | skel = bind4_prog__open_and_load(); |
493 | if (!ASSERT_OK_PTR(skel, "skel" )) |
494 | goto cleanup; |
495 | |
496 | skel->links.bind_v4_prog = bpf_program__attach_cgroup(skel->progs.bind_v4_prog, cgroup_fd); |
497 | if (!ASSERT_OK_PTR(skel->links.bind_v4_prog, "bpf_program__attach_cgroup" )) |
498 | goto cleanup; |
499 | |
500 | btf_id = find_prog_btf_id("bind_v4_prog" , bpf_program__fd(skel->progs.bind_v4_prog)); |
501 | if (!ASSERT_GE(btf_id, 0, "find_prog_btf_id" )) |
502 | goto cleanup; |
503 | |
504 | fentry_fd = load_fentry(attach_prog_fd: bpf_program__fd(skel->progs.bind_v4_prog), attach_btf_id: btf_id); |
505 | if (!ASSERT_GE(fentry_fd, 0, "load_fentry" )) |
506 | goto cleanup; |
507 | |
508 | /* Make sure bpf_prog_get_info_by_fd works correctly when attaching |
509 | * to another BPF program. |
510 | */ |
511 | |
512 | ASSERT_OK(bpf_prog_get_info_by_fd(fentry_fd, &info, &info_len), |
513 | "bpf_prog_get_info_by_fd" ); |
514 | |
515 | ASSERT_EQ(info.btf_id, 0, "info.btf_id" ); |
516 | ASSERT_EQ(info.attach_btf_id, btf_id, "info.attach_btf_id" ); |
517 | ASSERT_GT(info.attach_btf_obj_id, 0, "info.attach_btf_obj_id" ); |
518 | |
519 | cleanup: |
520 | if (cgroup_fd >= 0) |
521 | close(cgroup_fd); |
522 | if (fentry_fd >= 0) |
523 | close(fentry_fd); |
524 | bind4_prog__destroy(skel); |
525 | } |
526 | |
527 | static void test_func_replace_progmap(void) |
528 | { |
529 | struct bpf_cpumap_val value = { .qsize = 1 }; |
530 | struct freplace_progmap *skel = NULL; |
531 | struct xdp_dummy *tgt_skel = NULL; |
532 | __u32 key = 0; |
533 | int err; |
534 | |
535 | skel = freplace_progmap__open(); |
536 | if (!ASSERT_OK_PTR(skel, "prog_open" )) |
537 | return; |
538 | |
539 | tgt_skel = xdp_dummy__open_and_load(); |
540 | if (!ASSERT_OK_PTR(tgt_skel, "tgt_prog_load" )) |
541 | goto out; |
542 | |
543 | err = bpf_program__set_attach_target(skel->progs.xdp_cpumap_prog, |
544 | bpf_program__fd(tgt_skel->progs.xdp_dummy_prog), |
545 | "xdp_dummy_prog" ); |
546 | if (!ASSERT_OK(err, "set_attach_target" )) |
547 | goto out; |
548 | |
549 | err = freplace_progmap__load(skel); |
550 | if (!ASSERT_OK(err, "obj_load" )) |
551 | goto out; |
552 | |
553 | /* Prior to fixing the kernel, loading the PROG_TYPE_EXT 'redirect' |
554 | * program above will cause the map owner type of 'cpumap' to be set to |
555 | * PROG_TYPE_EXT. This in turn will cause the bpf_map_update_elem() |
556 | * below to fail, because the program we are inserting into the map is |
557 | * of PROG_TYPE_XDP. After fixing the kernel, the initial ownership will |
558 | * be correctly resolved to the *target* of the PROG_TYPE_EXT program |
559 | * (i.e., PROG_TYPE_XDP) and the map update will succeed. |
560 | */ |
561 | value.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_drop_prog); |
562 | err = bpf_map_update_elem(bpf_map__fd(skel->maps.cpu_map), |
563 | &key, &value, 0); |
564 | ASSERT_OK(err, "map_update" ); |
565 | |
566 | out: |
567 | xdp_dummy__destroy(tgt_skel); |
568 | freplace_progmap__destroy(skel); |
569 | } |
570 | |
571 | /* NOTE: affect other tests, must run in serial mode */ |
572 | void serial_test_fexit_bpf2bpf(void) |
573 | { |
574 | if (test__start_subtest("target_no_callees" )) |
575 | test_target_no_callees(); |
576 | if (test__start_subtest("target_yes_callees" )) |
577 | test_target_yes_callees(); |
578 | if (test__start_subtest("func_replace" )) |
579 | test_func_replace(); |
580 | if (test__start_subtest("func_replace_verify" )) |
581 | test_func_replace_verify(); |
582 | if (test__start_subtest("func_sockmap_update" )) |
583 | test_func_sockmap_update(); |
584 | if (test__start_subtest("func_replace_return_code" )) |
585 | test_func_replace_return_code(); |
586 | if (test__start_subtest("func_map_prog_compatibility" )) |
587 | test_func_map_prog_compatibility(); |
588 | if (test__start_subtest("func_replace_unreliable" )) |
589 | test_func_replace_unreliable(); |
590 | if (test__start_subtest("func_replace_multi" )) |
591 | test_func_replace_multi(); |
592 | if (test__start_subtest("fmod_ret_freplace" )) |
593 | test_fmod_ret_freplace(); |
594 | if (test__start_subtest("func_replace_global_func" )) |
595 | test_func_replace_global_func(); |
596 | if (test__start_subtest("fentry_to_cgroup_bpf" )) |
597 | test_fentry_to_cgroup_bpf(); |
598 | if (test__start_subtest("func_replace_progmap" )) |
599 | test_func_replace_progmap(); |
600 | } |
601 | |