diff options
author | Wang Nan <wangnan0@huawei.com> | 2016-02-22 04:10:31 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2016-02-22 10:20:35 -0500 |
commit | a34f3be70cdf986850552e62b9f22d659bfbcef3 (patch) | |
tree | 0bd3d7848a84524bb5c55b4eb38466bdfda36a77 /tools/perf/util/parse-events.c | |
parent | 066dacbf2a32defb4de23ea4c1af9e77578b5ac2 (diff) |
perf tools: Enable BPF object configure syntax
This patch adds the final step for BPF map configuration. A new syntax
is appended into parser so user can config BPF objects through '/' '/'
enclosed config terms.
After this patch, following syntax is available:
# perf record -e ./test_bpf_map_1.c/map:channel.value=10/ ...
It would takes effect after appling following commits.
Test result:
# cat ./test_bpf_map_1.c
/************************ BEGIN **************************/
#include <uapi/linux/bpf.h>
#define SEC(NAME) __attribute__((section(NAME), used))
struct bpf_map_def {
unsigned int type;
unsigned int key_size;
unsigned int value_size;
unsigned int max_entries;
};
static void *(*map_lookup_elem)(struct bpf_map_def *, void *) =
(void *)BPF_FUNC_map_lookup_elem;
static int (*trace_printk)(const char *fmt, int fmt_size, ...) =
(void *)BPF_FUNC_trace_printk;
struct bpf_map_def SEC("maps") channel = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(int),
.max_entries = 1,
};
SEC("func=sys_nanosleep")
int func(void *ctx)
{
int key = 0;
char fmt[] = "%d\n";
int *pval = map_lookup_elem(&channel, &key);
if (!pval)
return 0;
trace_printk(fmt, sizeof(fmt), *pval);
return 0;
}
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
/************************* END ***************************/
- Normal case:
# ./perf record -e './test_bpf_map_1.c/map:channel.value=10/' usleep 10
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.012 MB perf.data ]
- Error case:
# ./perf record -e './test_bpf_map_1.c/map:channel.value/' usleep 10
event syntax error: '..ps:channel:value/'
\___ Config value not set (missing '=')
Hint: Valid config term:
map:[<arraymap>]:value=[value]
(add -v to see detail)
Run 'perf list' for a list of valid events
Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]
-e, --event <event> event selector. use 'perf list' to list available events
# ./perf record -e './test_bpf_map_1.c/xmap:channel.value=10/' usleep 10
event syntax error: '..pf_map_1.c/xmap:channel.value=10/'
\___ Invalid object config option
[SNIP]
# ./perf record -e './test_bpf_map_1.c/map:xchannel.value=10/' usleep 10
event syntax error: '..p_1.c/map:xchannel.value=10/'
\___ Target map not exist
[SNIP]
# ./perf record -e './test_bpf_map_1.c/map:channel.xvalue=10/' usleep 10
event syntax error: '..ps:channel.xvalue=10/'
\___ Invalid object map config option
[SNIP]
# ./perf record -e './test_bpf_map_1.c/map:channel.value=x10/' usleep 10
event syntax error: '..nnel.value=x10/'
\___ Incorrect value type for map
[SNIP]
Change BPF_MAP_TYPE_ARRAY to '1' in test_bpf_map_1.c:
# ./perf record -e './test_bpf_map_1.c/map:channel.value=10/' usleep 10
event syntax error: '..ps:channel.value=10/'
\___ Can't use this config term to this type of map
Hint: Valid config term:
map:[<arraymap>].value=[value]
(add -v to see detail)
Signed-off-by: Wang Nan <wangnan0@huawei.com>
[for parser part]
Acked-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Brendan Gregg <brendan.d.gregg@gmail.com>
Cc: Cody P Schafer <dev@codyps.com>
Cc: He Kuang <hekuang@huawei.com>
Cc: Jeremie Galarneau <jeremie.galarneau@efficios.com>
Cc: Kirill Smelkov <kirr@nexedi.com>
Cc: Li Zefan <lizefan@huawei.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1456132275-98875-5-git-send-email-wangnan0@huawei.com
Signed-off-by: He Kuang <hekuang@huawei.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/parse-events.c')
-rw-r--r-- | tools/perf/util/parse-events.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index b0b329539db5..a5dd6703a56b 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -672,17 +672,63 @@ errout: | |||
672 | return err; | 672 | return err; |
673 | } | 673 | } |
674 | 674 | ||
675 | static int | ||
676 | parse_events_config_bpf(struct parse_events_evlist *data, | ||
677 | struct bpf_object *obj, | ||
678 | struct list_head *head_config) | ||
679 | { | ||
680 | struct parse_events_term *term; | ||
681 | int error_pos; | ||
682 | |||
683 | if (!head_config || list_empty(head_config)) | ||
684 | return 0; | ||
685 | |||
686 | list_for_each_entry(term, head_config, list) { | ||
687 | char errbuf[BUFSIZ]; | ||
688 | int err; | ||
689 | |||
690 | if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) { | ||
691 | snprintf(errbuf, sizeof(errbuf), | ||
692 | "Invalid config term for BPF object"); | ||
693 | errbuf[BUFSIZ - 1] = '\0'; | ||
694 | |||
695 | data->error->idx = term->err_term; | ||
696 | data->error->str = strdup(errbuf); | ||
697 | return -EINVAL; | ||
698 | } | ||
699 | |||
700 | err = bpf__config_obj(obj, term, NULL, &error_pos); | ||
701 | if (err) { | ||
702 | bpf__strerror_config_obj(obj, term, NULL, | ||
703 | &error_pos, err, errbuf, | ||
704 | sizeof(errbuf)); | ||
705 | data->error->help = strdup( | ||
706 | "Hint:\tValid config term:\n" | ||
707 | " \tmap:[<arraymap>].value=[value]\n" | ||
708 | " \t(add -v to see detail)"); | ||
709 | data->error->str = strdup(errbuf); | ||
710 | if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE) | ||
711 | data->error->idx = term->err_val; | ||
712 | else | ||
713 | data->error->idx = term->err_term + error_pos; | ||
714 | return err; | ||
715 | } | ||
716 | } | ||
717 | return 0; | ||
718 | } | ||
719 | |||
675 | int parse_events_load_bpf(struct parse_events_evlist *data, | 720 | int parse_events_load_bpf(struct parse_events_evlist *data, |
676 | struct list_head *list, | 721 | struct list_head *list, |
677 | char *bpf_file_name, | 722 | char *bpf_file_name, |
678 | bool source) | 723 | bool source, |
724 | struct list_head *head_config) | ||
679 | { | 725 | { |
680 | struct bpf_object *obj; | 726 | struct bpf_object *obj; |
727 | int err; | ||
681 | 728 | ||
682 | obj = bpf__prepare_load(bpf_file_name, source); | 729 | obj = bpf__prepare_load(bpf_file_name, source); |
683 | if (IS_ERR(obj)) { | 730 | if (IS_ERR(obj)) { |
684 | char errbuf[BUFSIZ]; | 731 | char errbuf[BUFSIZ]; |
685 | int err; | ||
686 | 732 | ||
687 | err = PTR_ERR(obj); | 733 | err = PTR_ERR(obj); |
688 | 734 | ||
@@ -700,7 +746,10 @@ int parse_events_load_bpf(struct parse_events_evlist *data, | |||
700 | return err; | 746 | return err; |
701 | } | 747 | } |
702 | 748 | ||
703 | return parse_events_load_bpf_obj(data, list, obj); | 749 | err = parse_events_load_bpf_obj(data, list, obj); |
750 | if (err) | ||
751 | return err; | ||
752 | return parse_events_config_bpf(data, obj, head_config); | ||
704 | } | 753 | } |
705 | 754 | ||
706 | static int | 755 | static int |