]> Git Repo - linux.git/blob - tools/testing/selftests/bpf/testing_helpers.c
scsi: zfcp: Trace when request remove fails after qdio send fails
[linux.git] / tools / testing / selftests / bpf / testing_helpers.c
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 "test_progs.h"
10 #include "testing_helpers.h"
11
12 int parse_num_list(const char *s, bool **num_set, int *num_set_len)
13 {
14         int i, set_len = 0, new_len, num, start = 0, end = -1;
15         bool *set = NULL, *tmp, parsing_end = false;
16         char *next;
17
18         while (s[0]) {
19                 errno = 0;
20                 num = strtol(s, &next, 10);
21                 if (errno)
22                         return -errno;
23
24                 if (parsing_end)
25                         end = num;
26                 else
27                         start = num;
28
29                 if (!parsing_end && *next == '-') {
30                         s = next + 1;
31                         parsing_end = true;
32                         continue;
33                 } else if (*next == ',') {
34                         parsing_end = false;
35                         s = next + 1;
36                         end = num;
37                 } else if (*next == '\0') {
38                         parsing_end = false;
39                         s = next;
40                         end = num;
41                 } else {
42                         return -EINVAL;
43                 }
44
45                 if (start > end)
46                         return -EINVAL;
47
48                 if (end + 1 > set_len) {
49                         new_len = end + 1;
50                         tmp = realloc(set, new_len);
51                         if (!tmp) {
52                                 free(set);
53                                 return -ENOMEM;
54                         }
55                         for (i = set_len; i < start; i++)
56                                 tmp[i] = false;
57                         set = tmp;
58                         set_len = new_len;
59                 }
60                 for (i = start; i <= end; i++)
61                         set[i] = true;
62         }
63
64         if (!set || parsing_end)
65                 return -EINVAL;
66
67         *num_set = set;
68         *num_set_len = set_len;
69
70         return 0;
71 }
72
73 int parse_test_list(const char *s,
74                     struct test_filter_set *set,
75                     bool is_glob_pattern)
76 {
77         char *input, *state = NULL, *next;
78         struct test_filter *tmp, *tests = NULL;
79         int i, j, cnt = 0;
80
81         input = strdup(s);
82         if (!input)
83                 return -ENOMEM;
84
85         while ((next = strtok_r(state ? NULL : input, ",", &state))) {
86                 char *subtest_str = strchr(next, '/');
87                 char *pattern = NULL;
88                 int glob_chars = 0;
89
90                 tmp = realloc(tests, sizeof(*tests) * (cnt + 1));
91                 if (!tmp)
92                         goto err;
93                 tests = tmp;
94
95                 tests[cnt].subtest_cnt = 0;
96                 tests[cnt].subtests = NULL;
97
98                 if (is_glob_pattern) {
99                         pattern = "%s";
100                 } else {
101                         pattern = "*%s*";
102                         glob_chars = 2;
103                 }
104
105                 if (subtest_str) {
106                         char **tmp_subtests = NULL;
107                         int subtest_cnt = tests[cnt].subtest_cnt;
108
109                         *subtest_str = '\0';
110                         subtest_str += 1;
111                         tmp_subtests = realloc(tests[cnt].subtests,
112                                                sizeof(*tmp_subtests) *
113                                                (subtest_cnt + 1));
114                         if (!tmp_subtests)
115                                 goto err;
116                         tests[cnt].subtests = tmp_subtests;
117
118                         tests[cnt].subtests[subtest_cnt] =
119                                 malloc(strlen(subtest_str) + glob_chars + 1);
120                         if (!tests[cnt].subtests[subtest_cnt])
121                                 goto err;
122                         sprintf(tests[cnt].subtests[subtest_cnt],
123                                 pattern,
124                                 subtest_str);
125
126                         tests[cnt].subtest_cnt++;
127                 }
128
129                 tests[cnt].name = malloc(strlen(next) + glob_chars + 1);
130                 if (!tests[cnt].name)
131                         goto err;
132                 sprintf(tests[cnt].name, pattern, next);
133
134                 cnt++;
135         }
136
137         tmp = realloc(set->tests, sizeof(*tests) * (cnt + set->cnt));
138         if (!tmp)
139                 goto err;
140
141         memcpy(tmp +  set->cnt, tests, sizeof(*tests) * cnt);
142         set->tests = tmp;
143         set->cnt += cnt;
144
145         free(tests);
146         free(input);
147         return 0;
148
149 err:
150         for (i = 0; i < cnt; i++) {
151                 for (j = 0; j < tests[i].subtest_cnt; j++)
152                         free(tests[i].subtests[j]);
153
154                 free(tests[i].name);
155         }
156         free(tests);
157         free(input);
158         return -ENOMEM;
159 }
160
161 __u32 link_info_prog_id(const struct bpf_link *link, struct bpf_link_info *info)
162 {
163         __u32 info_len = sizeof(*info);
164         int err;
165
166         memset(info, 0, sizeof(*info));
167         err = bpf_obj_get_info_by_fd(bpf_link__fd(link), info, &info_len);
168         if (err) {
169                 printf("failed to get link info: %d\n", -errno);
170                 return 0;
171         }
172         return info->prog_id;
173 }
174
175 int extra_prog_load_log_flags = 0;
176
177 int bpf_prog_test_load(const char *file, enum bpf_prog_type type,
178                        struct bpf_object **pobj, int *prog_fd)
179 {
180         LIBBPF_OPTS(bpf_object_open_opts, opts,
181                 .kernel_log_level = extra_prog_load_log_flags,
182         );
183         struct bpf_object *obj;
184         struct bpf_program *prog;
185         __u32 flags;
186         int err;
187
188         obj = bpf_object__open_file(file, &opts);
189         if (!obj)
190                 return -errno;
191
192         prog = bpf_object__next_program(obj, NULL);
193         if (!prog) {
194                 err = -ENOENT;
195                 goto err_out;
196         }
197
198         if (type != BPF_PROG_TYPE_UNSPEC)
199                 bpf_program__set_type(prog, type);
200
201         flags = bpf_program__flags(prog) | BPF_F_TEST_RND_HI32;
202         bpf_program__set_flags(prog, flags);
203
204         err = bpf_object__load(obj);
205         if (err)
206                 goto err_out;
207
208         *pobj = obj;
209         *prog_fd = bpf_program__fd(prog);
210
211         return 0;
212 err_out:
213         bpf_object__close(obj);
214         return err;
215 }
216
217 int bpf_test_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
218                           size_t insns_cnt, const char *license,
219                           __u32 kern_version, char *log_buf,
220                           size_t log_buf_sz)
221 {
222         LIBBPF_OPTS(bpf_prog_load_opts, opts,
223                 .kern_version = kern_version,
224                 .prog_flags = BPF_F_TEST_RND_HI32,
225                 .log_level = extra_prog_load_log_flags,
226                 .log_buf = log_buf,
227                 .log_size = log_buf_sz,
228         );
229
230         return bpf_prog_load(type, NULL, license, insns, insns_cnt, &opts);
231 }
This page took 0.052022 seconds and 4 git commands to generate.