1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2019 Facebook */ 3 #include <test_progs.h> 4 5 static void test_fexit_bpf2bpf_common(const char *obj_file, 6 const char *target_obj_file, 7 int prog_cnt, 8 const char **prog_name) 9 { 10 struct bpf_object *obj = NULL, *pkt_obj; 11 int err, pkt_fd, i; 12 struct bpf_link **link = NULL; 13 struct bpf_program **prog = NULL; 14 __u32 duration = 0, retval; 15 struct bpf_map *data_map; 16 const int zero = 0; 17 u64 *result = NULL; 18 19 err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC, 20 &pkt_obj, &pkt_fd); 21 if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno)) 22 return; 23 DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts, 24 .attach_prog_fd = pkt_fd, 25 ); 26 27 link = calloc(sizeof(struct bpf_link *), prog_cnt); 28 prog = calloc(sizeof(struct bpf_program *), prog_cnt); 29 result = malloc((prog_cnt + 32 /* spare */) * sizeof(u64)); 30 if (CHECK(!link || !prog || !result, "alloc_memory", 31 "failed to alloc memory")) 32 goto close_prog; 33 34 obj = bpf_object__open_file(obj_file, &opts); 35 if (CHECK(IS_ERR_OR_NULL(obj), "obj_open", 36 "failed to open fexit_bpf2bpf: %ld\n", 37 PTR_ERR(obj))) 38 goto close_prog; 39 40 err = bpf_object__load(obj); 41 if (CHECK(err, "obj_load", "err %d\n", err)) 42 goto close_prog; 43 44 for (i = 0; i < prog_cnt; i++) { 45 prog[i] = bpf_object__find_program_by_title(obj, prog_name[i]); 46 if (CHECK(!prog[i], "find_prog", "prog %s not found\n", prog_name[i])) 47 goto close_prog; 48 link[i] = bpf_program__attach_trace(prog[i]); 49 if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n")) 50 goto close_prog; 51 } 52 data_map = bpf_object__find_map_by_name(obj, "fexit_bp.bss"); 53 if (CHECK(!data_map, "find_data_map", "data map not found\n")) 54 goto close_prog; 55 56 err = bpf_prog_test_run(pkt_fd, 1, &pkt_v6, sizeof(pkt_v6), 57 NULL, NULL, &retval, &duration); 58 CHECK(err || retval, "ipv6", 59 "err %d errno %d retval %d duration %d\n", 60 err, errno, retval, duration); 61 62 err = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, result); 63 if (CHECK(err, "get_result", 64 "failed to get output data: %d\n", err)) 65 goto close_prog; 66 67 for (i = 0; i < prog_cnt; i++) 68 if (CHECK(result[i] != 1, "result", "fexit_bpf2bpf failed err %ld\n", 69 result[i])) 70 goto close_prog; 71 72 close_prog: 73 for (i = 0; i < prog_cnt; i++) 74 if (!IS_ERR_OR_NULL(link[i])) 75 bpf_link__destroy(link[i]); 76 if (!IS_ERR_OR_NULL(obj)) 77 bpf_object__close(obj); 78 bpf_object__close(pkt_obj); 79 free(link); 80 free(prog); 81 free(result); 82 } 83 84 static void test_target_no_callees(void) 85 { 86 const char *prog_name[] = { 87 "fexit/test_pkt_md_access", 88 }; 89 test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.o", 90 "./test_pkt_md_access.o", 91 ARRAY_SIZE(prog_name), 92 prog_name); 93 } 94 95 static void test_target_yes_callees(void) 96 { 97 const char *prog_name[] = { 98 "fexit/test_pkt_access", 99 "fexit/test_pkt_access_subprog1", 100 "fexit/test_pkt_access_subprog2", 101 "fexit/test_pkt_access_subprog3", 102 }; 103 test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o", 104 "./test_pkt_access.o", 105 ARRAY_SIZE(prog_name), 106 prog_name); 107 } 108 109 static void test_func_replace(void) 110 { 111 const char *prog_name[] = { 112 "fexit/test_pkt_access", 113 "fexit/test_pkt_access_subprog1", 114 "fexit/test_pkt_access_subprog2", 115 "fexit/test_pkt_access_subprog3", 116 "freplace/get_skb_len", 117 "freplace/get_skb_ifindex", 118 "freplace/get_constant", 119 }; 120 test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o", 121 "./test_pkt_access.o", 122 ARRAY_SIZE(prog_name), 123 prog_name); 124 } 125 126 void test_fexit_bpf2bpf(void) 127 { 128 test_target_no_callees(); 129 test_target_yes_callees(); 130 test_func_replace(); 131 } 132