1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) 2 /* Copyright (C) 2019 Netronome Systems, Inc. */ 3 /* Copyright (C) 2020 Facebook, Inc. */ 4 #include <stdlib.h> 5 #include <string.h> 6 #include <errno.h> 7 #include <bpf/bpf.h> 8 #include <bpf/libbpf.h> 9 #include "testing_helpers.h" 10 11 int parse_num_list(const char *s, bool **num_set, int *num_set_len) 12 { 13 int i, set_len = 0, new_len, num, start = 0, end = -1; 14 bool *set = NULL, *tmp, parsing_end = false; 15 char *next; 16 17 while (s[0]) { 18 errno = 0; 19 num = strtol(s, &next, 10); 20 if (errno) 21 return -errno; 22 23 if (parsing_end) 24 end = num; 25 else 26 start = num; 27 28 if (!parsing_end && *next == '-') { 29 s = next + 1; 30 parsing_end = true; 31 continue; 32 } else if (*next == ',') { 33 parsing_end = false; 34 s = next + 1; 35 end = num; 36 } else if (*next == '\0') { 37 parsing_end = false; 38 s = next; 39 end = num; 40 } else { 41 return -EINVAL; 42 } 43 44 if (start > end) 45 return -EINVAL; 46 47 if (end + 1 > set_len) { 48 new_len = end + 1; 49 tmp = realloc(set, new_len); 50 if (!tmp) { 51 free(set); 52 return -ENOMEM; 53 } 54 for (i = set_len; i < start; i++) 55 tmp[i] = false; 56 set = tmp; 57 set_len = new_len; 58 } 59 for (i = start; i <= end; i++) 60 set[i] = true; 61 } 62 63 if (!set) 64 return -EINVAL; 65 66 *num_set = set; 67 *num_set_len = set_len; 68 69 return 0; 70 } 71 72 __u32 link_info_prog_id(const struct bpf_link *link, struct bpf_link_info *info) 73 { 74 __u32 info_len = sizeof(*info); 75 int err; 76 77 memset(info, 0, sizeof(*info)); 78 err = bpf_obj_get_info_by_fd(bpf_link__fd(link), info, &info_len); 79 if (err) { 80 printf("failed to get link info: %d\n", -errno); 81 return 0; 82 } 83 return info->prog_id; 84 } 85 86 int extra_prog_load_log_flags = 0; 87 88 int bpf_prog_test_load(const char *file, enum bpf_prog_type type, 89 struct bpf_object **pobj, int *prog_fd) 90 { 91 LIBBPF_OPTS(bpf_object_open_opts, opts, 92 .kernel_log_level = extra_prog_load_log_flags, 93 ); 94 struct bpf_object *obj; 95 struct bpf_program *prog; 96 __u32 flags; 97 int err; 98 99 obj = bpf_object__open_file(file, &opts); 100 if (!obj) 101 return -errno; 102 103 prog = bpf_object__next_program(obj, NULL); 104 if (!prog) { 105 err = -ENOENT; 106 goto err_out; 107 } 108 109 if (type != BPF_PROG_TYPE_UNSPEC) 110 bpf_program__set_type(prog, type); 111 112 flags = bpf_program__flags(prog) | BPF_F_TEST_RND_HI32; 113 bpf_program__set_flags(prog, flags); 114 115 err = bpf_object__load(obj); 116 if (err) 117 goto err_out; 118 119 *pobj = obj; 120 *prog_fd = bpf_program__fd(prog); 121 122 return 0; 123 err_out: 124 bpf_object__close(obj); 125 return err; 126 } 127 128 int bpf_test_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 129 size_t insns_cnt, const char *license, 130 __u32 kern_version, char *log_buf, 131 size_t log_buf_sz) 132 { 133 LIBBPF_OPTS(bpf_prog_load_opts, opts, 134 .kern_version = kern_version, 135 .prog_flags = BPF_F_TEST_RND_HI32, 136 .log_level = extra_prog_load_log_flags, 137 .log_buf = log_buf, 138 .log_size = log_buf_sz, 139 ); 140 141 return bpf_prog_load(type, NULL, license, insns, insns_cnt, &opts); 142 } 143