Commit a34f3be7 authored by Wang Nan's avatar Wang Nan Committed by Arnaldo Carvalho de Melo

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: default avatarWang Nan <wangnan0@huawei.com>
[for parser part]
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Tested-by: default avatarArnaldo 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.comSigned-off-by: default avatarHe Kuang <hekuang@huawei.com>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 066dacbf
...@@ -672,17 +672,63 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data, ...@@ -672,17 +672,63 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
return err; return err;
} }
static int
parse_events_config_bpf(struct parse_events_evlist *data,
struct bpf_object *obj,
struct list_head *head_config)
{
struct parse_events_term *term;
int error_pos;
if (!head_config || list_empty(head_config))
return 0;
list_for_each_entry(term, head_config, list) {
char errbuf[BUFSIZ];
int err;
if (term->type_term != PARSE_EVENTS__TERM_TYPE_USER) {
snprintf(errbuf, sizeof(errbuf),
"Invalid config term for BPF object");
errbuf[BUFSIZ - 1] = '\0';
data->error->idx = term->err_term;
data->error->str = strdup(errbuf);
return -EINVAL;
}
err = bpf__config_obj(obj, term, NULL, &error_pos);
if (err) {
bpf__strerror_config_obj(obj, term, NULL,
&error_pos, err, errbuf,
sizeof(errbuf));
data->error->help = strdup(
"Hint:\tValid config term:\n"
" \tmap:[<arraymap>].value=[value]\n"
" \t(add -v to see detail)");
data->error->str = strdup(errbuf);
if (err == -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE)
data->error->idx = term->err_val;
else
data->error->idx = term->err_term + error_pos;
return err;
}
}
return 0;
}
int parse_events_load_bpf(struct parse_events_evlist *data, int parse_events_load_bpf(struct parse_events_evlist *data,
struct list_head *list, struct list_head *list,
char *bpf_file_name, char *bpf_file_name,
bool source) bool source,
struct list_head *head_config)
{ {
struct bpf_object *obj; struct bpf_object *obj;
int err;
obj = bpf__prepare_load(bpf_file_name, source); obj = bpf__prepare_load(bpf_file_name, source);
if (IS_ERR(obj)) { if (IS_ERR(obj)) {
char errbuf[BUFSIZ]; char errbuf[BUFSIZ];
int err;
err = PTR_ERR(obj); err = PTR_ERR(obj);
...@@ -700,7 +746,10 @@ int parse_events_load_bpf(struct parse_events_evlist *data, ...@@ -700,7 +746,10 @@ int parse_events_load_bpf(struct parse_events_evlist *data,
return err; return err;
} }
return parse_events_load_bpf_obj(data, list, obj); err = parse_events_load_bpf_obj(data, list, obj);
if (err)
return err;
return parse_events_config_bpf(data, obj, head_config);
} }
static int static int
......
...@@ -129,7 +129,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx, ...@@ -129,7 +129,8 @@ int parse_events_add_tracepoint(struct list_head *list, int *idx,
int parse_events_load_bpf(struct parse_events_evlist *data, int parse_events_load_bpf(struct parse_events_evlist *data,
struct list_head *list, struct list_head *list,
char *bpf_file_name, char *bpf_file_name,
bool source); bool source,
struct list_head *head_config);
/* Provide this function for perf test */ /* Provide this function for perf test */
struct bpf_object; struct bpf_object;
int parse_events_load_bpf_obj(struct parse_events_evlist *data, int parse_events_load_bpf_obj(struct parse_events_evlist *data,
......
...@@ -122,7 +122,7 @@ num_dec [0-9]+ ...@@ -122,7 +122,7 @@ num_dec [0-9]+
num_hex 0x[a-fA-F0-9]+ num_hex 0x[a-fA-F0-9]+
num_raw_hex [a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+
name [a-zA-Z_*?][a-zA-Z0-9_*?.]* name [a-zA-Z_*?][a-zA-Z0-9_*?.]*
name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]* name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
/* If you add a modifier you need to update check_modifier() */ /* If you add a modifier you need to update check_modifier() */
modifier_event [ukhpPGHSDI]+ modifier_event [ukhpPGHSDI]+
modifier_bp [rwx]{1,3} modifier_bp [rwx]{1,3}
......
...@@ -437,24 +437,26 @@ PE_RAW opt_event_config ...@@ -437,24 +437,26 @@ PE_RAW opt_event_config
} }
event_bpf_file: event_bpf_file:
PE_BPF_OBJECT PE_BPF_OBJECT opt_event_config
{ {
struct parse_events_evlist *data = _data; struct parse_events_evlist *data = _data;
struct parse_events_error *error = data->error; struct parse_events_error *error = data->error;
struct list_head *list; struct list_head *list;
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_load_bpf(data, list, $1, false)); ABORT_ON(parse_events_load_bpf(data, list, $1, false, $2));
parse_events_terms__delete($2);
$$ = list; $$ = list;
} }
| |
PE_BPF_SOURCE PE_BPF_SOURCE opt_event_config
{ {
struct parse_events_evlist *data = _data; struct parse_events_evlist *data = _data;
struct list_head *list; struct list_head *list;
ALLOC_LIST(list); ALLOC_LIST(list);
ABORT_ON(parse_events_load_bpf(data, list, $1, true)); ABORT_ON(parse_events_load_bpf(data, list, $1, true, $2));
parse_events_terms__delete($2);
$$ = list; $$ = list;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment