bpf.c 8.1 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
2
#include <errno.h>
3 4
#include <stdio.h>
#include <sys/epoll.h>
5 6
#include <sys/types.h>
#include <sys/stat.h>
7
#include <fcntl.h>
8
#include <util/record.h>
9
#include <util/util.h>
10 11
#include <util/bpf-loader.h>
#include <util/evlist.h>
12 13
#include <linux/bpf.h>
#include <linux/filter.h>
14
#include <linux/kernel.h>
15
#include <linux/string.h>
16
#include <api/fs/fs.h>
17
#include <bpf/bpf.h>
18
#include <perf/mmap.h>
19 20 21
#include "tests.h"
#include "llvm.h"
#include "debug.h"
22
#include "parse-events.h"
23
#include "util/mmap.h"
24
#define NR_ITERS       111
25
#define PERF_TEST_BPF_PATH "/sys/fs/bpf/perf_test"
26 27 28

#ifdef HAVE_LIBBPF_SUPPORT

29
static int epoll_pwait_loop(void)
30 31 32 33 34
{
	int i;

	/* Should fail NR_ITERS times */
	for (i = 0; i < NR_ITERS; i++)
35
		epoll_pwait(-(i + 1), NULL, 0, 0, NULL);
36 37 38
	return 0;
}

39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
#ifdef HAVE_BPF_PROLOGUE

static int llseek_loop(void)
{
	int fds[2], i;

	fds[0] = open("/dev/null", O_RDONLY);
	fds[1] = open("/dev/null", O_RDWR);

	if (fds[0] < 0 || fds[1] < 0)
		return -1;

	for (i = 0; i < NR_ITERS; i++) {
		lseek(fds[i % 2], i, (i / 2) % 2 ? SEEK_CUR : SEEK_SET);
		lseek(fds[(i + 1) % 2], i, (i / 2) % 2 ? SEEK_CUR : SEEK_SET);
	}
	close(fds[0]);
	close(fds[1]);
	return 0;
}

#endif

62 63 64 65 66 67 68 69
static struct {
	enum test_llvm__testcase prog_id;
	const char *desc;
	const char *name;
	const char *msg_compile_fail;
	const char *msg_load_fail;
	int (*target_func)(void);
	int expect_result;
70
	bool	pin;
71 72
} bpf_testcase_table[] = {
	{
73 74 75 76 77
		.prog_id	  = LLVM_TESTCASE_BASE,
		.desc		  = "Basic BPF filtering",
		.name		  = "[basic_bpf_test]",
		.msg_compile_fail = "fix 'perf test LLVM' first",
		.msg_load_fail	  = "load bpf object failed",
78
		.target_func	  = &epoll_pwait_loop,
79
		.expect_result	  = (NR_ITERS + 1) / 2,
80 81
	},
	{
82 83 84 85 86
		.prog_id	  = LLVM_TESTCASE_BASE,
		.desc		  = "BPF pinning",
		.name		  = "[bpf_pinning]",
		.msg_compile_fail = "fix kbuild first",
		.msg_load_fail	  = "check your vmlinux setting?",
87
		.target_func	  = &epoll_pwait_loop,
88 89
		.expect_result	  = (NR_ITERS + 1) / 2,
		.pin 		  = true,
90
	},
91 92
#ifdef HAVE_BPF_PROLOGUE
	{
93 94 95 96 97 98 99
		.prog_id	  = LLVM_TESTCASE_BPF_PROLOGUE,
		.desc		  = "BPF prologue generation",
		.name		  = "[bpf_prologue_test]",
		.msg_compile_fail = "fix kbuild first",
		.msg_load_fail	  = "check your vmlinux setting?",
		.target_func	  = &llseek_loop,
		.expect_result	  = (NR_ITERS + 1) / 4,
100 101
	},
#endif
102
	{
103 104 105 106 107
		.prog_id	  = LLVM_TESTCASE_BPF_RELOCATION,
		.desc		  = "BPF relocation checker",
		.name		  = "[bpf_relocation_test]",
		.msg_compile_fail = "fix 'perf test LLVM' first",
		.msg_load_fail	  = "libbpf error when dealing with relocation",
108
	},
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
};

static int do_test(struct bpf_object *obj, int (*func)(void),
		   int expect)
{
	struct record_opts opts = {
		.target = {
			.uid = UINT_MAX,
			.uses_mmap = true,
		},
		.freq	      = 0,
		.mmap_pages   = 256,
		.default_interval = 1,
	};

	char pid[16];
	char sbuf[STRERR_BUFSIZE];
126
	struct evlist *evlist;
127 128
	int i, ret = TEST_FAIL, err = 0, count = 0;

129
	struct parse_events_state parse_state;
130 131 132
	struct parse_events_error parse_error;

	bzero(&parse_error, sizeof(parse_error));
133 134 135
	bzero(&parse_state, sizeof(parse_state));
	parse_state.error = &parse_error;
	INIT_LIST_HEAD(&parse_state.list);
136

137 138
	err = parse_events_load_bpf_obj(&parse_state, &parse_state.list, obj, NULL);
	if (err || list_empty(&parse_state.list)) {
139
		pr_debug("Failed to add events selected by BPF\n");
140
		return TEST_FAIL;
141 142 143 144 145 146 147
	}

	snprintf(pid, sizeof(pid), "%d", getpid());
	pid[sizeof(pid) - 1] = '\0';
	opts.target.tid = opts.target.pid = pid;

	/* Instead of perf_evlist__new_default, don't add default events */
148
	evlist = evlist__new();
149
	if (!evlist) {
150
		pr_debug("Not enough memory to create evlist\n");
151 152 153 154 155 156 157 158 159
		return TEST_FAIL;
	}

	err = perf_evlist__create_maps(evlist, &opts.target);
	if (err < 0) {
		pr_debug("Not enough memory to create thread/cpu maps\n");
		goto out_delete_evlist;
	}

160 161
	perf_evlist__splice_list_tail(evlist, &parse_state.list);
	evlist->nr_groups = parse_state.nr_groups;
162

163
	perf_evlist__config(evlist, &opts, NULL);
164

165
	err = evlist__open(evlist);
166 167
	if (err < 0) {
		pr_debug("perf_evlist__open: %s\n",
168
			 str_error_r(errno, sbuf, sizeof(sbuf)));
169 170 171
		goto out_delete_evlist;
	}

172
	err = evlist__mmap(evlist, opts.mmap_pages);
173
	if (err < 0) {
174
		pr_debug("evlist__mmap: %s\n",
175
			 str_error_r(errno, sbuf, sizeof(sbuf)));
176 177 178
		goto out_delete_evlist;
	}

179
	evlist__enable(evlist);
180
	(*func)();
181
	evlist__disable(evlist);
182

183
	for (i = 0; i < evlist->core.nr_mmaps; i++) {
184
		union perf_event *event;
185
		struct mmap *md;
186

187
		md = &evlist->mmap[i];
188
		if (perf_mmap__read_init(&md->core) < 0)
189 190
			continue;

191
		while ((event = perf_mmap__read_event(&md->core)) != NULL) {
192 193 194 195 196
			const u32 type = event->header.type;

			if (type == PERF_RECORD_SAMPLE)
				count ++;
		}
197
		perf_mmap__read_done(&md->core);
198 199
	}

200
	if (count != expect * evlist->core.nr_entries) {
201
		pr_debug("BPF filter result incorrect, expected %d, got %d samples\n", expect, count);
202 203
		goto out_delete_evlist;
	}
204 205 206 207

	ret = TEST_OK;

out_delete_evlist:
208
	evlist__delete(evlist);
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
	return ret;
}

static struct bpf_object *
prepare_bpf(void *obj_buf, size_t obj_buf_sz, const char *name)
{
	struct bpf_object *obj;

	obj = bpf__prepare_load_buffer(obj_buf, obj_buf_sz, name);
	if (IS_ERR(obj)) {
		pr_debug("Compile BPF program failed.\n");
		return NULL;
	}
	return obj;
}

225
static int __test__bpf(int idx)
226 227 228 229 230 231 232
{
	int ret;
	void *obj_buf;
	size_t obj_buf_sz;
	struct bpf_object *obj;

	ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
233
				       bpf_testcase_table[idx].prog_id,
234
				       true, NULL);
235 236
	if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
		pr_debug("Unable to get BPF object, %s\n",
237 238
			 bpf_testcase_table[idx].msg_compile_fail);
		if (idx == 0)
239 240 241 242 243 244
			return TEST_SKIP;
		else
			return TEST_FAIL;
	}

	obj = prepare_bpf(obj_buf, obj_buf_sz,
245
			  bpf_testcase_table[idx].name);
246 247 248 249 250 251 252
	if ((!!bpf_testcase_table[idx].target_func) != (!!obj)) {
		if (!obj)
			pr_debug("Fail to load BPF object: %s\n",
				 bpf_testcase_table[idx].msg_load_fail);
		else
			pr_debug("Success unexpectedly: %s\n",
				 bpf_testcase_table[idx].msg_load_fail);
253 254 255 256
		ret = TEST_FAIL;
		goto out;
	}

257
	if (obj) {
258 259 260
		ret = do_test(obj,
			      bpf_testcase_table[idx].target_func,
			      bpf_testcase_table[idx].expect_result);
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
		if (ret != TEST_OK)
			goto out;
		if (bpf_testcase_table[idx].pin) {
			int err;

			if (!bpf_fs__mount()) {
				pr_debug("BPF filesystem not mounted\n");
				ret = TEST_FAIL;
				goto out;
			}
			err = mkdir(PERF_TEST_BPF_PATH, 0777);
			if (err && errno != EEXIST) {
				pr_debug("Failed to make perf_test dir: %s\n",
					 strerror(errno));
				ret = TEST_FAIL;
				goto out;
			}
			if (bpf_object__pin(obj, PERF_TEST_BPF_PATH))
				ret = TEST_FAIL;
			if (rm_rf(PERF_TEST_BPF_PATH))
				ret = TEST_FAIL;
		}
	}

285 286 287 288 289
out:
	bpf__clear();
	return ret;
}

290 291 292 293 294 295 296 297 298 299 300 301
int test__bpf_subtest_get_nr(void)
{
	return (int)ARRAY_SIZE(bpf_testcase_table);
}

const char *test__bpf_subtest_get_desc(int i)
{
	if (i < 0 || i >= (int)ARRAY_SIZE(bpf_testcase_table))
		return NULL;
	return bpf_testcase_table[i].desc;
}

302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
static int check_env(void)
{
	int err;
	unsigned int kver_int;
	char license[] = "GPL";

	struct bpf_insn insns[] = {
		BPF_MOV64_IMM(BPF_REG_0, 1),
		BPF_EXIT_INSN(),
	};

	err = fetch_kernel_version(&kver_int, NULL, 0);
	if (err) {
		pr_debug("Unable to get kernel version\n");
		return err;
	}

	err = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
			       sizeof(insns) / sizeof(insns[0]),
			       license, kver_int, NULL, 0);
	if (err < 0) {
		pr_err("Missing basic BPF support, skip this test: %s\n",
		       strerror(errno));
		return err;
	}
	close(err);

	return 0;
}

332
int test__bpf(struct test *test __maybe_unused, int i)
333 334 335
{
	int err;

336 337 338
	if (i < 0 || i >= (int)ARRAY_SIZE(bpf_testcase_table))
		return TEST_FAIL;

339 340 341 342 343
	if (geteuid() != 0) {
		pr_debug("Only root can run BPF test\n");
		return TEST_SKIP;
	}

344 345 346
	if (check_env())
		return TEST_SKIP;

347 348 349
	err = __test__bpf(i);
	return err;
}
350

351 352 353 354 355
#else
int test__bpf_subtest_get_nr(void)
{
	return 0;
}
356

357 358 359
const char *test__bpf_subtest_get_desc(int i __maybe_unused)
{
	return NULL;
360 361
}

362
int test__bpf(struct test *test __maybe_unused, int i __maybe_unused)
363 364 365 366 367
{
	pr_debug("Skip BPF test because BPF support is not compiled\n");
	return TEST_SKIP;
}
#endif
新手
引导
客服 返回
顶部