Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  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
 12int 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
 73int 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
149err:
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
175int extra_prog_load_log_flags = 0;
176
177int 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;
212err_out:
213	bpf_object__close(obj);
214	return err;
215}
216
217int 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}