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 struct bpf_object_load_attr attr = {}; 92 struct bpf_object *obj; 93 struct bpf_program *prog; 94 int err; 95 96 obj = bpf_object__open(file); 97 if (!obj) 98 return -errno; 99 100 prog = bpf_object__next_program(obj, NULL); 101 if (!prog) { 102 err = -ENOENT; 103 goto err_out; 104 } 105 106 if (type != BPF_PROG_TYPE_UNSPEC) 107 bpf_program__set_type(prog, type); 108 109 bpf_program__set_extra_flags(prog, BPF_F_TEST_RND_HI32); 110 111 attr.obj = obj; 112 attr.log_level = extra_prog_load_log_flags; 113 err = bpf_object__load_xattr(&attr); 114 if (err) 115 goto err_out; 116 117 *pobj = obj; 118 *prog_fd = bpf_program__fd(prog); 119 120 return 0; 121 err_out: 122 bpf_object__close(obj); 123 return err; 124 } 125 126 int bpf_test_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, 127 size_t insns_cnt, const char *license, 128 __u32 kern_version, char *log_buf, 129 size_t log_buf_sz) 130 { 131 LIBBPF_OPTS(bpf_prog_load_opts, opts, 132 .kern_version = kern_version, 133 .prog_flags = BPF_F_TEST_RND_HI32, 134 .log_level = extra_prog_load_log_flags, 135 .log_buf = log_buf, 136 .log_size = log_buf_sz, 137 ); 138 139 return bpf_prog_load(type, NULL, license, insns, insns_cnt, &opts); 140 } 141