bpftool: Implement link_query for bpf iterators
authorYonghong Song <yhs@fb.com>
Fri, 21 Aug 2020 18:44:20 +0000 (11:44 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 21 Aug 2020 21:01:39 +0000 (14:01 -0700)
The link query for bpf iterators is implemented.
Besides being shown to the user what bpf iterator
the link represents, the target_name is also used
to filter out what additional information should be
printed out, e.g., whether map_id should be shown or not.
The following is an example of bpf_iter link dump,
plain output or pretty output.

  $ bpftool link show
  11: iter  prog 59  target_name task
          pids test_progs(1749)
  34: iter  prog 173  target_name bpf_map_elem  map_id 127
          pids test_progs_1(1753)
  $ bpftool -p link show
  [{
          "id": 11,
          "type": "iter",
          "prog_id": 59,
          "target_name": "task",
          "pids": [{
                  "pid": 1749,
                  "comm": "test_progs"
              }
          ]
      },{
          "id": 34,
          "type": "iter",
          "prog_id": 173,
          "target_name": "bpf_map_elem",
          "map_id": 127,
          "pids": [{
                  "pid": 1753,
                  "comm": "test_progs_1"
              }
          ]
      }
  ]

Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Link: https://lore.kernel.org/bpf/20200821184420.574430-1-yhs@fb.com
tools/bpf/bpftool/link.c

index a89f09e..e77e152 100644 (file)
@@ -77,6 +77,22 @@ static void show_link_attach_type_json(__u32 attach_type, json_writer_t *wtr)
                jsonw_uint_field(wtr, "attach_type", attach_type);
 }
 
+static bool is_iter_map_target(const char *target_name)
+{
+       return strcmp(target_name, "bpf_map_elem") == 0 ||
+              strcmp(target_name, "bpf_sk_storage_map") == 0;
+}
+
+static void show_iter_json(struct bpf_link_info *info, json_writer_t *wtr)
+{
+       const char *target_name = u64_to_ptr(info->iter.target_name);
+
+       jsonw_string_field(wtr, "target_name", target_name);
+
+       if (is_iter_map_target(target_name))
+               jsonw_uint_field(wtr, "map_id", info->iter.map.map_id);
+}
+
 static int get_prog_info(int prog_id, struct bpf_prog_info *info)
 {
        __u32 len = sizeof(*info);
@@ -128,6 +144,9 @@ static int show_link_close_json(int fd, struct bpf_link_info *info)
                                   info->cgroup.cgroup_id);
                show_link_attach_type_json(info->cgroup.attach_type, json_wtr);
                break;
+       case BPF_LINK_TYPE_ITER:
+               show_iter_json(info, json_wtr);
+               break;
        case BPF_LINK_TYPE_NETNS:
                jsonw_uint_field(json_wtr, "netns_ino",
                                 info->netns.netns_ino);
@@ -175,6 +194,16 @@ static void show_link_attach_type_plain(__u32 attach_type)
                printf("attach_type %u  ", attach_type);
 }
 
+static void show_iter_plain(struct bpf_link_info *info)
+{
+       const char *target_name = u64_to_ptr(info->iter.target_name);
+
+       printf("target_name %s  ", target_name);
+
+       if (is_iter_map_target(target_name))
+               printf("map_id %u  ", info->iter.map.map_id);
+}
+
 static int show_link_close_plain(int fd, struct bpf_link_info *info)
 {
        struct bpf_prog_info prog_info;
@@ -204,6 +233,9 @@ static int show_link_close_plain(int fd, struct bpf_link_info *info)
                printf("\n\tcgroup_id %zu  ", (size_t)info->cgroup.cgroup_id);
                show_link_attach_type_plain(info->cgroup.attach_type);
                break;
+       case BPF_LINK_TYPE_ITER:
+               show_iter_plain(info);
+               break;
        case BPF_LINK_TYPE_NETNS:
                printf("\n\tnetns_ino %u  ", info->netns.netns_ino);
                show_link_attach_type_plain(info->netns.attach_type);
@@ -231,7 +263,7 @@ static int do_show_link(int fd)
 {
        struct bpf_link_info info;
        __u32 len = sizeof(info);
-       char raw_tp_name[256];
+       char buf[256];
        int err;
 
        memset(&info, 0, sizeof(info));
@@ -245,8 +277,14 @@ again:
        }
        if (info.type == BPF_LINK_TYPE_RAW_TRACEPOINT &&
            !info.raw_tracepoint.tp_name) {
-               info.raw_tracepoint.tp_name = (unsigned long)&raw_tp_name;
-               info.raw_tracepoint.tp_name_len = sizeof(raw_tp_name);
+               info.raw_tracepoint.tp_name = (unsigned long)&buf;
+               info.raw_tracepoint.tp_name_len = sizeof(buf);
+               goto again;
+       }
+       if (info.type == BPF_LINK_TYPE_ITER &&
+           !info.iter.target_name) {
+               info.iter.target_name = (unsigned long)&buf;
+               info.iter.target_name_len = sizeof(buf);
                goto again;
        }