diff options
author | Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp> | 2017-11-07 23:55:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-11-10 22:35:41 -0500 |
commit | 4990f1f4610b483a60397ed2768d268df228a551 (patch) | |
tree | 7a720763c6ec3710eeeb333c4d502f25139f7576 /tools | |
parent | 1852719658c0f853b5481c9eaed862f1a9355edc (diff) |
tools: bpftool: show filenames of pinned objects
Added support to show filenames of pinned objects.
For example:
root@test# ./bpftool prog
3: tracepoint name tracepoint__irq tag f677a7dd722299a3
loaded_at Oct 26/11:39 uid 0
xlated 160B not jited memlock 4096B map_ids 4
pinned /sys/fs/bpf/softirq_prog
4: tracepoint name tracepoint__irq tag ea5dc530d00b92b6
loaded_at Oct 26/11:39 uid 0
xlated 392B not jited memlock 4096B map_ids 4,6
root@test# ./bpftool --json --pretty prog
[{
"id": 3,
"type": "tracepoint",
"name": "tracepoint__irq",
"tag": "f677a7dd722299a3",
"loaded_at": "Oct 26/11:39",
"uid": 0,
"bytes_xlated": 160,
"jited": false,
"bytes_memlock": 4096,
"map_ids": [4
],
"pinned": ["/sys/fs/bpf/softirq_prog"
]
},{
"id": 4,
"type": "tracepoint",
"name": "tracepoint__irq",
"tag": "ea5dc530d00b92b6",
"loaded_at": "Oct 26/11:39",
"uid": 0,
"bytes_xlated": 392,
"jited": false,
"bytes_memlock": 4096,
"map_ids": [4,6
],
"pinned": []
}
]
root@test# ./bpftool map
4: hash name start flags 0x0
key 4B value 16B max_entries 10240 memlock 1003520B
pinned /sys/fs/bpf/softirq_map1
5: hash name iptr flags 0x0
key 4B value 8B max_entries 10240 memlock 921600B
root@test# ./bpftool --json --pretty map
[{
"id": 4,
"type": "hash",
"name": "start",
"flags": 0,
"bytes_key": 4,
"bytes_value": 16,
"max_entries": 10240,
"bytes_memlock": 1003520,
"pinned": ["/sys/fs/bpf/softirq_map1"
]
},{
"id": 5,
"type": "hash",
"name": "iptr",
"flags": 0,
"bytes_key": 4,
"bytes_value": 8,
"max_entries": 10240,
"bytes_memlock": 921600,
"pinned": []
}
]
Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/bpf/bpftool/common.c | 82 | ||||
-rw-r--r-- | tools/bpf/bpftool/main.c | 8 | ||||
-rw-r--r-- | tools/bpf/bpftool/main.h | 17 | ||||
-rw-r--r-- | tools/bpf/bpftool/map.c | 21 | ||||
-rw-r--r-- | tools/bpf/bpftool/prog.c | 24 |
5 files changed, 152 insertions, 0 deletions
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c index 6b3d25d6a782..2bd3b280e6dd 100644 --- a/tools/bpf/bpftool/common.c +++ b/tools/bpf/bpftool/common.c | |||
@@ -34,7 +34,9 @@ | |||
34 | /* Author: Jakub Kicinski <kubakici@wp.pl> */ | 34 | /* Author: Jakub Kicinski <kubakici@wp.pl> */ |
35 | 35 | ||
36 | #include <errno.h> | 36 | #include <errno.h> |
37 | #include <fts.h> | ||
37 | #include <libgen.h> | 38 | #include <libgen.h> |
39 | #include <mntent.h> | ||
38 | #include <stdbool.h> | 40 | #include <stdbool.h> |
39 | #include <stdio.h> | 41 | #include <stdio.h> |
40 | #include <stdlib.h> | 42 | #include <stdlib.h> |
@@ -321,3 +323,83 @@ void print_hex_data_json(uint8_t *data, size_t len) | |||
321 | jsonw_printf(json_wtr, "\"0x%02hhx\"", data[i]); | 323 | jsonw_printf(json_wtr, "\"0x%02hhx\"", data[i]); |
322 | jsonw_end_array(json_wtr); | 324 | jsonw_end_array(json_wtr); |
323 | } | 325 | } |
326 | |||
327 | int build_pinned_obj_table(struct pinned_obj_table *tab, | ||
328 | enum bpf_obj_type type) | ||
329 | { | ||
330 | struct bpf_prog_info pinned_info = {}; | ||
331 | struct pinned_obj *obj_node = NULL; | ||
332 | __u32 len = sizeof(pinned_info); | ||
333 | struct mntent *mntent = NULL; | ||
334 | enum bpf_obj_type objtype; | ||
335 | FILE *mntfile = NULL; | ||
336 | FTSENT *ftse = NULL; | ||
337 | FTS *fts = NULL; | ||
338 | int fd, err; | ||
339 | |||
340 | mntfile = setmntent("/proc/mounts", "r"); | ||
341 | if (!mntfile) | ||
342 | return -1; | ||
343 | |||
344 | while ((mntent = getmntent(mntfile))) { | ||
345 | char *path[] = { mntent->mnt_dir, NULL }; | ||
346 | |||
347 | if (strncmp(mntent->mnt_type, "bpf", 3) != 0) | ||
348 | continue; | ||
349 | |||
350 | fts = fts_open(path, 0, NULL); | ||
351 | if (!fts) | ||
352 | continue; | ||
353 | |||
354 | while ((ftse = fts_read(fts))) { | ||
355 | if (!(ftse->fts_info & FTS_F)) | ||
356 | continue; | ||
357 | fd = open_obj_pinned(ftse->fts_path); | ||
358 | if (fd < 0) | ||
359 | continue; | ||
360 | |||
361 | objtype = get_fd_type(fd); | ||
362 | if (objtype != type) { | ||
363 | close(fd); | ||
364 | continue; | ||
365 | } | ||
366 | memset(&pinned_info, 0, sizeof(pinned_info)); | ||
367 | err = bpf_obj_get_info_by_fd(fd, &pinned_info, &len); | ||
368 | if (err) { | ||
369 | close(fd); | ||
370 | continue; | ||
371 | } | ||
372 | |||
373 | obj_node = malloc(sizeof(*obj_node)); | ||
374 | if (!obj_node) { | ||
375 | close(fd); | ||
376 | fts_close(fts); | ||
377 | fclose(mntfile); | ||
378 | return -1; | ||
379 | } | ||
380 | |||
381 | memset(obj_node, 0, sizeof(*obj_node)); | ||
382 | obj_node->id = pinned_info.id; | ||
383 | obj_node->path = strdup(ftse->fts_path); | ||
384 | hash_add(tab->table, &obj_node->hash, obj_node->id); | ||
385 | |||
386 | close(fd); | ||
387 | } | ||
388 | fts_close(fts); | ||
389 | } | ||
390 | fclose(mntfile); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | void delete_pinned_obj_table(struct pinned_obj_table *tab) | ||
395 | { | ||
396 | struct pinned_obj *obj; | ||
397 | struct hlist_node *tmp; | ||
398 | unsigned int bkt; | ||
399 | |||
400 | hash_for_each_safe(tab->table, bkt, tmp, obj, hash) { | ||
401 | hash_del(&obj->hash); | ||
402 | free(obj->path); | ||
403 | free(obj); | ||
404 | } | ||
405 | } | ||
diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c index 78d9afb74ef4..6ad53f1797fa 100644 --- a/tools/bpf/bpftool/main.c +++ b/tools/bpf/bpftool/main.c | |||
@@ -54,6 +54,8 @@ static int (*last_do_help)(int argc, char **argv); | |||
54 | json_writer_t *json_wtr; | 54 | json_writer_t *json_wtr; |
55 | bool pretty_output; | 55 | bool pretty_output; |
56 | bool json_output; | 56 | bool json_output; |
57 | struct pinned_obj_table prog_table; | ||
58 | struct pinned_obj_table map_table; | ||
57 | 59 | ||
58 | void usage(void) | 60 | void usage(void) |
59 | { | 61 | { |
@@ -272,6 +274,9 @@ int main(int argc, char **argv) | |||
272 | json_output = false; | 274 | json_output = false; |
273 | bin_name = argv[0]; | 275 | bin_name = argv[0]; |
274 | 276 | ||
277 | hash_init(prog_table.table); | ||
278 | hash_init(map_table.table); | ||
279 | |||
275 | while ((opt = getopt_long(argc, argv, "Vhpj", | 280 | while ((opt = getopt_long(argc, argv, "Vhpj", |
276 | options, NULL)) >= 0) { | 281 | options, NULL)) >= 0) { |
277 | switch (opt) { | 282 | switch (opt) { |
@@ -311,5 +316,8 @@ int main(int argc, char **argv) | |||
311 | if (json_output) | 316 | if (json_output) |
312 | jsonw_destroy(&json_wtr); | 317 | jsonw_destroy(&json_wtr); |
313 | 318 | ||
319 | delete_pinned_obj_table(&prog_table); | ||
320 | delete_pinned_obj_table(&map_table); | ||
321 | |||
314 | return ret; | 322 | return ret; |
315 | } | 323 | } |
diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 2ff2a361af0d..13453de2e570 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <stdio.h> | 42 | #include <stdio.h> |
43 | #include <linux/bpf.h> | 43 | #include <linux/bpf.h> |
44 | #include <linux/kernel.h> | 44 | #include <linux/kernel.h> |
45 | #include <linux/hashtable.h> | ||
45 | 46 | ||
46 | #include "json_writer.h" | 47 | #include "json_writer.h" |
47 | 48 | ||
@@ -70,6 +71,8 @@ extern const char *bin_name; | |||
70 | 71 | ||
71 | extern json_writer_t *json_wtr; | 72 | extern json_writer_t *json_wtr; |
72 | extern bool json_output; | 73 | extern bool json_output; |
74 | extern struct pinned_obj_table prog_table; | ||
75 | extern struct pinned_obj_table map_table; | ||
73 | 76 | ||
74 | void p_err(const char *fmt, ...); | 77 | void p_err(const char *fmt, ...); |
75 | void p_info(const char *fmt, ...); | 78 | void p_info(const char *fmt, ...); |
@@ -78,6 +81,20 @@ bool is_prefix(const char *pfx, const char *str); | |||
78 | void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep); | 81 | void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep); |
79 | void usage(void) __attribute__((noreturn)); | 82 | void usage(void) __attribute__((noreturn)); |
80 | 83 | ||
84 | struct pinned_obj_table { | ||
85 | DECLARE_HASHTABLE(table, 16); | ||
86 | }; | ||
87 | |||
88 | struct pinned_obj { | ||
89 | __u32 id; | ||
90 | char *path; | ||
91 | struct hlist_node hash; | ||
92 | }; | ||
93 | |||
94 | int build_pinned_obj_table(struct pinned_obj_table *table, | ||
95 | enum bpf_obj_type type); | ||
96 | void delete_pinned_obj_table(struct pinned_obj_table *tab); | ||
97 | |||
81 | struct cmd { | 98 | struct cmd { |
82 | const char *cmd; | 99 | const char *cmd; |
83 | int (*func)(int argc, char **argv); | 100 | int (*func)(int argc, char **argv); |
diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c index e978ab23a77f..de0980657cef 100644 --- a/tools/bpf/bpftool/map.c +++ b/tools/bpf/bpftool/map.c | |||
@@ -436,6 +436,18 @@ static int show_map_close_json(int fd, struct bpf_map_info *info) | |||
436 | jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock)); | 436 | jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock)); |
437 | free(memlock); | 437 | free(memlock); |
438 | 438 | ||
439 | if (!hash_empty(map_table.table)) { | ||
440 | struct pinned_obj *obj; | ||
441 | |||
442 | jsonw_name(json_wtr, "pinned"); | ||
443 | jsonw_start_array(json_wtr); | ||
444 | hash_for_each_possible(map_table.table, obj, hash, info->id) { | ||
445 | if (obj->id == info->id) | ||
446 | jsonw_string(json_wtr, obj->path); | ||
447 | } | ||
448 | jsonw_end_array(json_wtr); | ||
449 | } | ||
450 | |||
439 | jsonw_end_object(json_wtr); | 451 | jsonw_end_object(json_wtr); |
440 | 452 | ||
441 | return 0; | 453 | return 0; |
@@ -466,7 +478,14 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info) | |||
466 | free(memlock); | 478 | free(memlock); |
467 | 479 | ||
468 | printf("\n"); | 480 | printf("\n"); |
481 | if (!hash_empty(map_table.table)) { | ||
482 | struct pinned_obj *obj; | ||
469 | 483 | ||
484 | hash_for_each_possible(map_table.table, obj, hash, info->id) { | ||
485 | if (obj->id == info->id) | ||
486 | printf("\tpinned %s\n", obj->path); | ||
487 | } | ||
488 | } | ||
470 | return 0; | 489 | return 0; |
471 | } | 490 | } |
472 | 491 | ||
@@ -478,6 +497,8 @@ static int do_show(int argc, char **argv) | |||
478 | int err; | 497 | int err; |
479 | int fd; | 498 | int fd; |
480 | 499 | ||
500 | build_pinned_obj_table(&map_table, BPF_OBJ_MAP); | ||
501 | |||
481 | if (argc == 2) { | 502 | if (argc == 2) { |
482 | fd = map_parse_fd_and_info(&argc, &argv, &info, &len); | 503 | fd = map_parse_fd_and_info(&argc, &argv, &info, &len); |
483 | if (fd < 0) | 504 | if (fd < 0) |
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c index d3ab808dc882..8f94b8ac2e63 100644 --- a/tools/bpf/bpftool/prog.c +++ b/tools/bpf/bpftool/prog.c | |||
@@ -272,6 +272,18 @@ static void print_prog_json(struct bpf_prog_info *info, int fd) | |||
272 | if (info->nr_map_ids) | 272 | if (info->nr_map_ids) |
273 | show_prog_maps(fd, info->nr_map_ids); | 273 | show_prog_maps(fd, info->nr_map_ids); |
274 | 274 | ||
275 | if (!hash_empty(prog_table.table)) { | ||
276 | struct pinned_obj *obj; | ||
277 | |||
278 | jsonw_name(json_wtr, "pinned"); | ||
279 | jsonw_start_array(json_wtr); | ||
280 | hash_for_each_possible(prog_table.table, obj, hash, info->id) { | ||
281 | if (obj->id == info->id) | ||
282 | jsonw_string(json_wtr, obj->path); | ||
283 | } | ||
284 | jsonw_end_array(json_wtr); | ||
285 | } | ||
286 | |||
275 | jsonw_end_object(json_wtr); | 287 | jsonw_end_object(json_wtr); |
276 | } | 288 | } |
277 | 289 | ||
@@ -331,6 +343,16 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd) | |||
331 | if (info->nr_map_ids) | 343 | if (info->nr_map_ids) |
332 | show_prog_maps(fd, info->nr_map_ids); | 344 | show_prog_maps(fd, info->nr_map_ids); |
333 | 345 | ||
346 | if (!hash_empty(prog_table.table)) { | ||
347 | struct pinned_obj *obj; | ||
348 | |||
349 | printf("\n"); | ||
350 | hash_for_each_possible(prog_table.table, obj, hash, info->id) { | ||
351 | if (obj->id == info->id) | ||
352 | printf("\tpinned %s\n", obj->path); | ||
353 | } | ||
354 | } | ||
355 | |||
334 | printf("\n"); | 356 | printf("\n"); |
335 | } | 357 | } |
336 | 358 | ||
@@ -360,6 +382,8 @@ static int do_show(int argc, char **argv) | |||
360 | int err; | 382 | int err; |
361 | int fd; | 383 | int fd; |
362 | 384 | ||
385 | build_pinned_obj_table(&prog_table, BPF_OBJ_PROG); | ||
386 | |||
363 | if (argc == 2) { | 387 | if (argc == 2) { |
364 | fd = prog_parse_fd(&argc, &argv); | 388 | fd = prog_parse_fd(&argc, &argv); |
365 | if (fd < 0) | 389 | if (fd < 0) |