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