Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
0002 /* Copyright (C) 2019 Netronome Systems, Inc. */
0003 /* Copyright (C) 2020 Facebook, Inc. */
0004 #include <stdlib.h>
0005 #include <string.h>
0006 #include <errno.h>
0007 #include <bpf/bpf.h>
0008 #include <bpf/libbpf.h>
0009 #include "test_progs.h"
0010 #include "testing_helpers.h"
0011 
0012 int parse_num_list(const char *s, bool **num_set, int *num_set_len)
0013 {
0014     int i, set_len = 0, new_len, num, start = 0, end = -1;
0015     bool *set = NULL, *tmp, parsing_end = false;
0016     char *next;
0017 
0018     while (s[0]) {
0019         errno = 0;
0020         num = strtol(s, &next, 10);
0021         if (errno)
0022             return -errno;
0023 
0024         if (parsing_end)
0025             end = num;
0026         else
0027             start = num;
0028 
0029         if (!parsing_end && *next == '-') {
0030             s = next + 1;
0031             parsing_end = true;
0032             continue;
0033         } else if (*next == ',') {
0034             parsing_end = false;
0035             s = next + 1;
0036             end = num;
0037         } else if (*next == '\0') {
0038             parsing_end = false;
0039             s = next;
0040             end = num;
0041         } else {
0042             return -EINVAL;
0043         }
0044 
0045         if (start > end)
0046             return -EINVAL;
0047 
0048         if (end + 1 > set_len) {
0049             new_len = end + 1;
0050             tmp = realloc(set, new_len);
0051             if (!tmp) {
0052                 free(set);
0053                 return -ENOMEM;
0054             }
0055             for (i = set_len; i < start; i++)
0056                 tmp[i] = false;
0057             set = tmp;
0058             set_len = new_len;
0059         }
0060         for (i = start; i <= end; i++)
0061             set[i] = true;
0062     }
0063 
0064     if (!set || parsing_end)
0065         return -EINVAL;
0066 
0067     *num_set = set;
0068     *num_set_len = set_len;
0069 
0070     return 0;
0071 }
0072 
0073 int parse_test_list(const char *s,
0074             struct test_filter_set *set,
0075             bool is_glob_pattern)
0076 {
0077     char *input, *state = NULL, *next;
0078     struct test_filter *tmp, *tests = NULL;
0079     int i, j, cnt = 0;
0080 
0081     input = strdup(s);
0082     if (!input)
0083         return -ENOMEM;
0084 
0085     while ((next = strtok_r(state ? NULL : input, ",", &state))) {
0086         char *subtest_str = strchr(next, '/');
0087         char *pattern = NULL;
0088         int glob_chars = 0;
0089 
0090         tmp = realloc(tests, sizeof(*tests) * (cnt + 1));
0091         if (!tmp)
0092             goto err;
0093         tests = tmp;
0094 
0095         tests[cnt].subtest_cnt = 0;
0096         tests[cnt].subtests = NULL;
0097 
0098         if (is_glob_pattern) {
0099             pattern = "%s";
0100         } else {
0101             pattern = "*%s*";
0102             glob_chars = 2;
0103         }
0104 
0105         if (subtest_str) {
0106             char **tmp_subtests = NULL;
0107             int subtest_cnt = tests[cnt].subtest_cnt;
0108 
0109             *subtest_str = '\0';
0110             subtest_str += 1;
0111             tmp_subtests = realloc(tests[cnt].subtests,
0112                            sizeof(*tmp_subtests) *
0113                            (subtest_cnt + 1));
0114             if (!tmp_subtests)
0115                 goto err;
0116             tests[cnt].subtests = tmp_subtests;
0117 
0118             tests[cnt].subtests[subtest_cnt] =
0119                 malloc(strlen(subtest_str) + glob_chars + 1);
0120             if (!tests[cnt].subtests[subtest_cnt])
0121                 goto err;
0122             sprintf(tests[cnt].subtests[subtest_cnt],
0123                 pattern,
0124                 subtest_str);
0125 
0126             tests[cnt].subtest_cnt++;
0127         }
0128 
0129         tests[cnt].name = malloc(strlen(next) + glob_chars + 1);
0130         if (!tests[cnt].name)
0131             goto err;
0132         sprintf(tests[cnt].name, pattern, next);
0133 
0134         cnt++;
0135     }
0136 
0137     tmp = realloc(set->tests, sizeof(*tests) * (cnt + set->cnt));
0138     if (!tmp)
0139         goto err;
0140 
0141     memcpy(tmp +  set->cnt, tests, sizeof(*tests) * cnt);
0142     set->tests = tmp;
0143     set->cnt += cnt;
0144 
0145     free(tests);
0146     free(input);
0147     return 0;
0148 
0149 err:
0150     for (i = 0; i < cnt; i++) {
0151         for (j = 0; j < tests[i].subtest_cnt; j++)
0152             free(tests[i].subtests[j]);
0153 
0154         free(tests[i].name);
0155     }
0156     free(tests);
0157     free(input);
0158     return -ENOMEM;
0159 }
0160 
0161 __u32 link_info_prog_id(const struct bpf_link *link, struct bpf_link_info *info)
0162 {
0163     __u32 info_len = sizeof(*info);
0164     int err;
0165 
0166     memset(info, 0, sizeof(*info));
0167     err = bpf_obj_get_info_by_fd(bpf_link__fd(link), info, &info_len);
0168     if (err) {
0169         printf("failed to get link info: %d\n", -errno);
0170         return 0;
0171     }
0172     return info->prog_id;
0173 }
0174 
0175 int extra_prog_load_log_flags = 0;
0176 
0177 int bpf_prog_test_load(const char *file, enum bpf_prog_type type,
0178                struct bpf_object **pobj, int *prog_fd)
0179 {
0180     LIBBPF_OPTS(bpf_object_open_opts, opts,
0181         .kernel_log_level = extra_prog_load_log_flags,
0182     );
0183     struct bpf_object *obj;
0184     struct bpf_program *prog;
0185     __u32 flags;
0186     int err;
0187 
0188     obj = bpf_object__open_file(file, &opts);
0189     if (!obj)
0190         return -errno;
0191 
0192     prog = bpf_object__next_program(obj, NULL);
0193     if (!prog) {
0194         err = -ENOENT;
0195         goto err_out;
0196     }
0197 
0198     if (type != BPF_PROG_TYPE_UNSPEC)
0199         bpf_program__set_type(prog, type);
0200 
0201     flags = bpf_program__flags(prog) | BPF_F_TEST_RND_HI32;
0202     bpf_program__set_flags(prog, flags);
0203 
0204     err = bpf_object__load(obj);
0205     if (err)
0206         goto err_out;
0207 
0208     *pobj = obj;
0209     *prog_fd = bpf_program__fd(prog);
0210 
0211     return 0;
0212 err_out:
0213     bpf_object__close(obj);
0214     return err;
0215 }
0216 
0217 int bpf_test_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
0218               size_t insns_cnt, const char *license,
0219               __u32 kern_version, char *log_buf,
0220               size_t log_buf_sz)
0221 {
0222     LIBBPF_OPTS(bpf_prog_load_opts, opts,
0223         .kern_version = kern_version,
0224         .prog_flags = BPF_F_TEST_RND_HI32,
0225         .log_level = extra_prog_load_log_flags,
0226         .log_buf = log_buf,
0227         .log_size = log_buf_sz,
0228     );
0229 
0230     return bpf_prog_load(type, NULL, license, insns, insns_cnt, &opts);
0231 }