mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Wang Nan <wangnan0@huawei.com>
To: <acme@kernel.org>, <ast@plumgrid.com>
Cc: <linux-kernel@vger.kernel.org>, <lizefan@huawei.com>,
	<hekuang@huawei.com>, <xiakaixu@huawei.com>, <pi3orama@163.com>,
	<brendan.d.gregg@gmail.com>, <daniel@iogearbox.net>,
	<dsahern@gmail.com>, <jolsa@kernel.org>,
	<masami.hiramatsu.pt@hitachi.com>, <namhyung@kernel.org>,
	<paulus@samba.org>, <a.p.zijlstra@chello.nl>
Subject: [PATCH 15/27] perf test: Add 'perf test BPF'
Date: Mon, 10 Aug 2015 06:15:57 +0000	[thread overview]
Message-ID: <1439187369-66492-16-git-send-email-wangnan0@huawei.com> (raw)
In-Reply-To: <1439187369-66492-1-git-send-email-wangnan0@huawei.com>

This patch adds BPF testcase for testing BPF event filtering.

By utilizing the result of 'perf test LLVM', this patch further forks
a 'perf record' to load and use it.

The BPF script in 'perf test LLVM' collect half of execution of
epoll_pwait(), 'perf test TESTTARGET_EPOLL_PWAIT_LOOP' run 111 times
of it, so the resuling 'perf.data' should contain 56 samples. This
patch checks the result using 'perf report -D'.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: David Ahern <dsahern@gmail.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kaixu Xia <xiakaixu@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
---
 tools/perf/tests/bpf.c          | 214 ++++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/builtin-test.c |   4 +
 tools/perf/tests/llvm.c         |  19 ++++
 tools/perf/tests/llvm.h         |   1 +
 tools/perf/tests/tests.h        |   1 +
 5 files changed, 239 insertions(+)

diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 1a9eec3..e911ef8 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -1,6 +1,8 @@
 #include <stdio.h>
+#include <stdarg.h>
 #include <sys/epoll.h>
 #include "tests.h"
+#include "llvm.h"
 #include "debug.h"
 #define NR_ITERS	111
 
@@ -13,3 +15,215 @@ int testtarget__epoll_pwait_loop(void)
 		epoll_pwait(-(i + 1), NULL, 0, 0, NULL);
 	return 0;
 }
+
+#ifdef HAVE_LIBBPF_SUPPORT
+
+static int
+vsystem_exec_cmd(int *pres, const char *format, va_list args)
+{
+	char *cmd;
+	int err, res;
+
+	err = vasprintf(&cmd, format, args);
+	if (err < 0) {
+		pr_err("No enough memory for vasprintf\n");
+		return TEST_FAIL;
+	}
+	res = system(cmd);
+	free(cmd);
+	*pres = res;
+	return 0;
+}
+
+#define __printf(a, b)	__attribute__((format(printf, a, b)))
+__printf(2, 3) static int
+system_exec_cmd(int *pres, const char *format, ...)
+{
+	va_list args;
+	int err;
+
+	va_start(args, format);
+	err = vsystem_exec_cmd(pres, format, args);
+	va_end(args);
+	return err;
+}
+
+static const char *get_tmpdir(void)
+{
+	const char *tmp;
+
+	tmp = getenv("TMPDIR");
+	if (tmp)
+		return tmp;
+#ifdef P_tmpdir
+	return P_tmpdir;
+#else
+	return "/tmp";
+#endif
+}
+
+#define TMPDIR_TEMPLATE "perf-bpf-test-XXXXXX"
+static int
+prepare_tmpdir(char **p_tmpdir, char **p_cmd_rmdir)
+{
+	int err;
+
+	err = asprintf(p_tmpdir, "%s/%s", get_tmpdir(), TMPDIR_TEMPLATE);
+	if (err < 0) {
+		pr_err("No enough memory for tmpdir\n");
+		return TEST_FAIL;
+	}
+
+	if (mkdtemp(*p_tmpdir) != *p_tmpdir) {
+		pr_err("mkdtemp() failed\n");
+		free(*p_tmpdir);
+		*p_tmpdir = NULL;
+		return TEST_FAIL;
+	}
+
+	err = asprintf(p_cmd_rmdir, "rm -rf %s", *p_tmpdir);
+	if (err < 0) {
+		pr_err("No enough memory for rm command\n");
+		free(*p_tmpdir);
+		*p_tmpdir = NULL;
+		return TEST_FAIL;
+	}
+
+	return 0;
+}
+
+static int
+dump_obj(void *obj_buf, size_t obj_buf_sz, const char *tmpdir)
+{
+	char *obj_name;
+	FILE *fp;
+	int err;
+
+	err = asprintf(&obj_name, "%s/test.o", tmpdir);
+	if (err < 0) {
+		pr_err("No enough memory for string '%s/test.o'\n", tmpdir);
+		return TEST_FAIL;
+	}
+
+	fp = fopen(obj_name, "wb");
+	if (!fp) {
+		pr_err("Create '%s' failed", obj_name);
+		free(obj_name);
+		return TEST_FAIL;
+	}
+
+	err = fwrite(obj_buf, 1, obj_buf_sz, fp);
+	if (err != (int)obj_buf_sz) {
+		pr_err("Dump to '%s' failed", obj_name);
+		free(obj_name);
+		fclose(fp);
+		return TEST_FAIL;
+	}
+
+	fclose(fp);
+	return 0;
+}
+
+#define exec_cmd(errstr, fmt...)		\
+do {						\
+	err = system_exec_cmd(&res, fmt);	\
+	if (!err && !res)			\
+		break;				\
+	if (verbose == 0)			\
+		fprintf(stderr, errstr);	\
+	return TEST_FAIL;			\
+} while(0)
+
+static int
+do_test(const char *tmpdir)
+{
+	char *arg0, *result_path;
+	FILE *result_file;
+	int err, res;
+
+	err = asprintf(&arg0, "/proc/%d/exe", getpid());
+	if (err < 0) {
+		pr_err("No enough memory for '/proc/%d/exe'\n", getpid());
+		return TEST_FAIL;
+	}
+
+	exec_cmd(" (failed to collect samples)",
+		"%s record -e %s/test.o -o %s/perf.data %s test '%s' %s",
+		 arg0, tmpdir, tmpdir, arg0, TESTTARGET_EPOLL_PWAIT_LOOP,
+		 verbose == 0 ? " > /dev/null 2>&1" : "");
+
+	exec_cmd(" (failed to read perf.data)",
+"%s report -i %s/perf.data -D | grep PERF_RECORD_SAMPLE | wc -l > %s/result",
+		 arg0, tmpdir, tmpdir);
+
+	free(arg0);
+	arg0 = NULL;
+
+	err = asprintf(&result_path, "%s/result", tmpdir);
+	if (err < 0) {
+		pr_err("No enough memory for result file name\n");
+		return TEST_FAIL;
+	}
+	result_file = fopen(result_path, "r");
+	if (!result_file) {
+		pr_err("Failed to open '%s'\n", result_path);
+		free(result_path);
+		return TEST_FAIL;
+	}
+	free(result_path);
+
+	err = fscanf(result_file, "%d", &res);
+	fclose(result_file);
+
+	if (err != 1) {
+		pr_err("Failed to read result file\n");
+		return TEST_FAIL;
+	}
+
+	if (res != (NR_ITERS + 1) / 2)
+		fprintf(stderr, " (filter result incorrect)");
+	return 0;
+}
+
+int test__bpf(void)
+{
+	int err;
+	char *tmpdir, *cmd_rmdir;
+	void *obj_buf;
+	size_t obj_buf_sz;
+
+	test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz);
+	if (!obj_buf || !obj_buf_sz) {
+		if (verbose == 0)
+			fprintf(stderr, " (fix 'perf test LLVM' first)");
+		return TEST_SKIP;
+	}
+
+	err = prepare_tmpdir(&tmpdir, &cmd_rmdir);
+	if (err)
+		return err;
+
+	err = dump_obj(obj_buf, obj_buf_sz, tmpdir);
+	if (err)
+		goto out;
+
+	err = do_test(tmpdir);
+out:
+	if (system(cmd_rmdir)) {
+		pr_err("'%s' failed\n", cmd_rmdir);
+		return TEST_FAIL;
+	}
+	if (err != TEST_OK)
+		fprintf(stderr, " (use 'perf test -v BPF' to see detail)");
+	return err;
+}
+
+#else
+
+int test__bpf(void)
+{
+	fprintf(stderr, " (disabled)");
+	return TEST_SKIP;
+}
+
+#endif
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 0d0c963..6d59e84 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -183,6 +183,10 @@ static struct test {
 		.prepare = test__llvm_prepare,
 		.cleanup = test__llvm_cleanup,
 	},
+	{
+		.desc = "Test BPF filter",
+		.func = test__bpf,
+	},
 	/*
 	 * Put test targets after all test cases so sequence number will be
 	 * less confusing.
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index e48eb64..94ed5f2 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -174,3 +174,22 @@ void test__llvm_cleanup(void)
 			(~((unsigned long)page_size - 1));
 	munmap((void *)boundary, buf_end - boundary);
 }
+
+void
+test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz)
+{
+	*p_obj_buf = NULL;
+	*p_obj_buf_sz = 0;
+
+	if (!p_test_llvm__bpf_result) {
+		test__llvm_prepare();
+		test__llvm();
+		test__llvm_cleanup();
+	}
+
+	if (!p_test_llvm__bpf_result)
+		return;
+
+	*p_obj_buf = p_test_llvm__bpf_result->object;
+	*p_obj_buf_sz = p_test_llvm__bpf_result->size;
+}
diff --git a/tools/perf/tests/llvm.h b/tools/perf/tests/llvm.h
index 1e89e46..2fd7ed6 100644
--- a/tools/perf/tests/llvm.h
+++ b/tools/perf/tests/llvm.h
@@ -10,5 +10,6 @@ struct test_llvm__bpf_result {
 
 extern struct test_llvm__bpf_result *p_test_llvm__bpf_result;
 extern const char test_llvm__bpf_prog[];
+void test_llvm__fetch_bpf_obj(void **p_obj_buf, size_t *p_obj_buf_sz);
 
 #endif
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 0138a3d..7704bfd 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -65,6 +65,7 @@ int test__thread_map(void);
 int test__llvm(void);
 void test__llvm_prepare(void);
 void test__llvm_cleanup(void);
+int test__bpf(void);
 #define TESTTARGET_EPOLL_PWAIT_LOOP "TESTTARGET: epoll_pwait loop"
 int testtarget__epoll_pwait_loop(void);
 
-- 
1.8.3.4


  parent reply	other threads:[~2015-08-10  6:19 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-08-10  6:15 [GIT PULL 00/27] perf tools: filtering events using eBPF programs Wang Nan
2015-08-10  6:15 ` [PATCH 01/27] perf tools: Make perf depend on libbpf Wang Nan
2015-08-10  6:15 ` [PATCH 02/27] perf ebpf: Add the libbpf glue Wang Nan
2015-08-10  6:15 ` [PATCH 03/27] perf tools: Enable passing bpf object file to --event Wang Nan
2015-08-10  6:15 ` [PATCH 04/27] perf probe: Attach trace_probe_event with perf_probe_event Wang Nan
2015-08-10  6:15 ` [PATCH 05/27] perf record, bpf: Parse and probe eBPF programs probe points Wang Nan
2015-08-10  6:15 ` [PATCH 06/27] perf bpf: Collect 'struct perf_probe_event' for bpf_program Wang Nan
2015-08-10  6:15 ` [PATCH 07/27] perf record: Load all eBPF object into kernel Wang Nan
2015-08-10  6:15 ` [PATCH 08/27] perf tools: Add bpf_fd field to evsel and config it Wang Nan
2015-08-10  6:15 ` [PATCH 09/27] perf tools: Attach eBPF program to perf event Wang Nan
2015-08-10  6:15 ` [PATCH 10/27] perf tools: Suppress probing messages when probing by BPF loading Wang Nan
2015-08-10  6:15 ` [PATCH 11/27] perf record: Add clang options for compiling BPF scripts Wang Nan
2015-08-10  6:15 ` [PATCH 12/27] perf tools: Infrastructure for compiling scriptlets when passing '.c' to --event Wang Nan
2015-08-10  6:15 ` [PATCH 13/27] perf tests: Enforce LLVM test for BPF test Wang Nan
2015-08-10  6:15 ` [PATCH 14/27] perf test: Enable 'perf test' run as test targets Wang Nan
2015-08-10  6:15 ` Wang Nan [this message]
2015-08-10  6:15 ` [PATCH 16/27] bpf tools: Load a program with different instances using preprocessor Wang Nan
2015-08-10  6:15 ` [PATCH 17/27] perf tools: Fix probe-event.h include Wang Nan
2015-08-10  6:16 ` [PATCH 18/27] perf probe: Reset args and nargs for probe_trace_event when failure Wang Nan
2015-08-10  6:16 ` [PATCH 19/27] perf tools: Move linux/filter.h to tools/include Wang Nan
2015-08-10  6:16 ` [PATCH 20/27] perf tools: Add BPF_PROLOGUE config options for further patches Wang Nan
2015-08-10  6:16 ` [PATCH 21/27] perf tools: Introduce arch_get_reg_info() for x86 Wang Nan
2015-08-10  6:16 ` [PATCH 22/27] perf tools: Add prologue for BPF programs for fetching arguments Wang Nan
2015-08-10  6:16 ` [PATCH 23/27] perf tools: Generate prologue for BPF programs Wang Nan
2015-08-10  6:16 ` [PATCH 24/27] perf tools: Use same BPF program if arguments are identical Wang Nan
2015-08-10  6:16 ` [PATCH 25/27] perf record: Support custom vmlinux path Wang Nan
2015-08-10  6:16 ` [PATCH 26/27] perf probe: Init symbol as kprobe Wang Nan
2015-08-10  6:16 ` [PATCH 27/27] perf tools: Support attach BPF program on uprobe events Wang Nan
2015-09-06  7:13 [GIT PULL 00/27] perf tools: filtering events using eBPF programs Wang Nan
2015-09-06  7:13 ` [PATCH 15/27] perf test: Add 'perf test BPF' Wang Nan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1439187369-66492-16-git-send-email-wangnan0@huawei.com \
    --to=wangnan0@huawei.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@kernel.org \
    --cc=ast@plumgrid.com \
    --cc=brendan.d.gregg@gmail.com \
    --cc=daniel@iogearbox.net \
    --cc=dsahern@gmail.com \
    --cc=hekuang@huawei.com \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizefan@huawei.com \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=namhyung@kernel.org \
    --cc=paulus@samba.org \
    --cc=pi3orama@163.com \
    --cc=xiakaixu@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®