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