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
next prev 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®