1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
8 #include <linux/kernel.h>
15 #include <sys/types.h>
21 #include "json_writer.h"
24 const char * const map_type_name
[] = {
25 [BPF_MAP_TYPE_UNSPEC
] = "unspec",
26 [BPF_MAP_TYPE_HASH
] = "hash",
27 [BPF_MAP_TYPE_ARRAY
] = "array",
28 [BPF_MAP_TYPE_PROG_ARRAY
] = "prog_array",
29 [BPF_MAP_TYPE_PERF_EVENT_ARRAY
] = "perf_event_array",
30 [BPF_MAP_TYPE_PERCPU_HASH
] = "percpu_hash",
31 [BPF_MAP_TYPE_PERCPU_ARRAY
] = "percpu_array",
32 [BPF_MAP_TYPE_STACK_TRACE
] = "stack_trace",
33 [BPF_MAP_TYPE_CGROUP_ARRAY
] = "cgroup_array",
34 [BPF_MAP_TYPE_LRU_HASH
] = "lru_hash",
35 [BPF_MAP_TYPE_LRU_PERCPU_HASH
] = "lru_percpu_hash",
36 [BPF_MAP_TYPE_LPM_TRIE
] = "lpm_trie",
37 [BPF_MAP_TYPE_ARRAY_OF_MAPS
] = "array_of_maps",
38 [BPF_MAP_TYPE_HASH_OF_MAPS
] = "hash_of_maps",
39 [BPF_MAP_TYPE_DEVMAP
] = "devmap",
40 [BPF_MAP_TYPE_DEVMAP_HASH
] = "devmap_hash",
41 [BPF_MAP_TYPE_SOCKMAP
] = "sockmap",
42 [BPF_MAP_TYPE_CPUMAP
] = "cpumap",
43 [BPF_MAP_TYPE_XSKMAP
] = "xskmap",
44 [BPF_MAP_TYPE_SOCKHASH
] = "sockhash",
45 [BPF_MAP_TYPE_CGROUP_STORAGE
] = "cgroup_storage",
46 [BPF_MAP_TYPE_REUSEPORT_SOCKARRAY
] = "reuseport_sockarray",
47 [BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE
] = "percpu_cgroup_storage",
48 [BPF_MAP_TYPE_QUEUE
] = "queue",
49 [BPF_MAP_TYPE_STACK
] = "stack",
50 [BPF_MAP_TYPE_SK_STORAGE
] = "sk_storage",
51 [BPF_MAP_TYPE_STRUCT_OPS
] = "struct_ops",
52 [BPF_MAP_TYPE_RINGBUF
] = "ringbuf",
53 [BPF_MAP_TYPE_INODE_STORAGE
] = "inode_storage",
54 [BPF_MAP_TYPE_TASK_STORAGE
] = "task_storage",
57 const size_t map_type_name_size
= ARRAY_SIZE(map_type_name
);
59 static bool map_is_per_cpu(__u32 type
)
61 return type
== BPF_MAP_TYPE_PERCPU_HASH
||
62 type
== BPF_MAP_TYPE_PERCPU_ARRAY
||
63 type
== BPF_MAP_TYPE_LRU_PERCPU_HASH
||
64 type
== BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE
;
67 static bool map_is_map_of_maps(__u32 type
)
69 return type
== BPF_MAP_TYPE_ARRAY_OF_MAPS
||
70 type
== BPF_MAP_TYPE_HASH_OF_MAPS
;
73 static bool map_is_map_of_progs(__u32 type
)
75 return type
== BPF_MAP_TYPE_PROG_ARRAY
;
78 static int map_type_from_str(const char *type
)
82 for (i
= 0; i
< ARRAY_SIZE(map_type_name
); i
++)
83 /* Don't allow prefixing in case of possible future shadowing */
84 if (map_type_name
[i
] && !strcmp(map_type_name
[i
], type
))
89 static void *alloc_value(struct bpf_map_info
*info
)
91 if (map_is_per_cpu(info
->type
))
92 return malloc(round_up(info
->value_size
, 8) *
95 return malloc(info
->value_size
);
98 static int do_dump_btf(const struct btf_dumper
*d
,
99 struct bpf_map_info
*map_info
, void *key
,
105 /* start of key-value pair */
106 jsonw_start_object(d
->jw
);
108 if (map_info
->btf_key_type_id
) {
109 jsonw_name(d
->jw
, "key");
111 ret
= btf_dumper_type(d
, map_info
->btf_key_type_id
, key
);
116 value_id
= map_info
->btf_vmlinux_value_type_id
?
117 : map_info
->btf_value_type_id
;
119 if (!map_is_per_cpu(map_info
->type
)) {
120 jsonw_name(d
->jw
, "value");
121 ret
= btf_dumper_type(d
, value_id
, value
);
123 unsigned int i
, n
, step
;
125 jsonw_name(d
->jw
, "values");
126 jsonw_start_array(d
->jw
);
127 n
= get_possible_cpus();
128 step
= round_up(map_info
->value_size
, 8);
129 for (i
= 0; i
< n
; i
++) {
130 jsonw_start_object(d
->jw
);
131 jsonw_int_field(d
->jw
, "cpu", i
);
132 jsonw_name(d
->jw
, "value");
133 ret
= btf_dumper_type(d
, value_id
, value
+ i
* step
);
134 jsonw_end_object(d
->jw
);
138 jsonw_end_array(d
->jw
);
142 /* end of key-value pair */
143 jsonw_end_object(d
->jw
);
148 static json_writer_t
*get_btf_writer(void)
150 json_writer_t
*jw
= jsonw_new(stdout
);
154 jsonw_pretty(jw
, true);
159 static void print_entry_json(struct bpf_map_info
*info
, unsigned char *key
,
160 unsigned char *value
, struct btf
*btf
)
162 jsonw_start_object(json_wtr
);
164 if (!map_is_per_cpu(info
->type
)) {
165 jsonw_name(json_wtr
, "key");
166 print_hex_data_json(key
, info
->key_size
);
167 jsonw_name(json_wtr
, "value");
168 print_hex_data_json(value
, info
->value_size
);
170 struct btf_dumper d
= {
173 .is_plain_text
= false,
176 jsonw_name(json_wtr
, "formatted");
177 do_dump_btf(&d
, info
, key
, value
);
180 unsigned int i
, n
, step
;
182 n
= get_possible_cpus();
183 step
= round_up(info
->value_size
, 8);
185 jsonw_name(json_wtr
, "key");
186 print_hex_data_json(key
, info
->key_size
);
188 jsonw_name(json_wtr
, "values");
189 jsonw_start_array(json_wtr
);
190 for (i
= 0; i
< n
; i
++) {
191 jsonw_start_object(json_wtr
);
193 jsonw_int_field(json_wtr
, "cpu", i
);
195 jsonw_name(json_wtr
, "value");
196 print_hex_data_json(value
+ i
* step
,
199 jsonw_end_object(json_wtr
);
201 jsonw_end_array(json_wtr
);
203 struct btf_dumper d
= {
206 .is_plain_text
= false,
209 jsonw_name(json_wtr
, "formatted");
210 do_dump_btf(&d
, info
, key
, value
);
214 jsonw_end_object(json_wtr
);
218 print_entry_error_msg(struct bpf_map_info
*info
, unsigned char *key
,
219 const char *error_msg
)
221 int msg_size
= strlen(error_msg
);
222 bool single_line
, break_names
;
224 break_names
= info
->key_size
> 16 || msg_size
> 16;
225 single_line
= info
->key_size
+ msg_size
<= 24 && !break_names
;
227 printf("key:%c", break_names
? '\n' : ' ');
228 fprint_hex(stdout
, key
, info
->key_size
, " ");
230 printf(single_line
? " " : "\n");
232 printf("value:%c%s", break_names
? '\n' : ' ', error_msg
);
238 print_entry_error(struct bpf_map_info
*map_info
, void *key
, int lookup_errno
)
240 /* For prog_array maps or arrays of maps, failure to lookup the value
241 * means there is no entry for that key. Do not print an error message
244 if ((map_is_map_of_maps(map_info
->type
) ||
245 map_is_map_of_progs(map_info
->type
)) && lookup_errno
== ENOENT
)
249 jsonw_start_object(json_wtr
); /* entry */
250 jsonw_name(json_wtr
, "key");
251 print_hex_data_json(key
, map_info
->key_size
);
252 jsonw_name(json_wtr
, "value");
253 jsonw_start_object(json_wtr
); /* error */
254 jsonw_string_field(json_wtr
, "error", strerror(lookup_errno
));
255 jsonw_end_object(json_wtr
); /* error */
256 jsonw_end_object(json_wtr
); /* entry */
258 const char *msg
= NULL
;
260 if (lookup_errno
== ENOENT
)
262 else if (lookup_errno
== ENOSPC
&&
263 map_info
->type
== BPF_MAP_TYPE_REUSEPORT_SOCKARRAY
)
264 msg
= "<cannot read>";
266 print_entry_error_msg(map_info
, key
,
267 msg
? : strerror(lookup_errno
));
271 static void print_entry_plain(struct bpf_map_info
*info
, unsigned char *key
,
272 unsigned char *value
)
274 if (!map_is_per_cpu(info
->type
)) {
275 bool single_line
, break_names
;
277 break_names
= info
->key_size
> 16 || info
->value_size
> 16;
278 single_line
= info
->key_size
+ info
->value_size
<= 24 &&
281 if (info
->key_size
) {
282 printf("key:%c", break_names
? '\n' : ' ');
283 fprint_hex(stdout
, key
, info
->key_size
, " ");
285 printf(single_line
? " " : "\n");
288 if (info
->value_size
) {
289 printf("value:%c", break_names
? '\n' : ' ');
290 fprint_hex(stdout
, value
, info
->value_size
, " ");
295 unsigned int i
, n
, step
;
297 n
= get_possible_cpus();
298 step
= round_up(info
->value_size
, 8);
300 if (info
->key_size
) {
302 fprint_hex(stdout
, key
, info
->key_size
, " ");
305 if (info
->value_size
) {
306 for (i
= 0; i
< n
; i
++) {
307 printf("value (CPU %02d):%c",
308 i
, info
->value_size
> 16 ? '\n' : ' ');
309 fprint_hex(stdout
, value
+ i
* step
,
310 info
->value_size
, " ");
317 static char **parse_bytes(char **argv
, const char *name
, unsigned char *val
,
320 unsigned int i
= 0, base
= 0;
323 if (is_prefix(*argv
, "hex")) {
328 while (i
< n
&& argv
[i
]) {
329 val
[i
] = strtoul(argv
[i
], &endptr
, base
);
331 p_err("error parsing byte: %s", argv
[i
]);
338 p_err("%s expected %d bytes got %d", name
, n
, i
);
345 /* on per cpu maps we must copy the provided value on all value instances */
346 static void fill_per_cpu_value(struct bpf_map_info
*info
, void *value
)
348 unsigned int i
, n
, step
;
350 if (!map_is_per_cpu(info
->type
))
353 n
= get_possible_cpus();
354 step
= round_up(info
->value_size
, 8);
355 for (i
= 1; i
< n
; i
++)
356 memcpy(value
+ i
* step
, value
, info
->value_size
);
359 static int parse_elem(char **argv
, struct bpf_map_info
*info
,
360 void *key
, void *value
, __u32 key_size
, __u32 value_size
,
361 __u32
*flags
, __u32
**value_fd
)
366 p_err("did not find %s", key
? "key" : "value");
370 if (is_prefix(*argv
, "key")) {
373 p_err("duplicate key");
375 p_err("unnecessary key");
379 argv
= parse_bytes(argv
+ 1, "key", key
, key_size
);
383 return parse_elem(argv
, info
, NULL
, value
, key_size
, value_size
,
385 } else if (is_prefix(*argv
, "value")) {
390 p_err("duplicate value");
392 p_err("unnecessary value");
398 if (map_is_map_of_maps(info
->type
)) {
401 if (value_size
!= 4) {
402 p_err("value smaller than 4B for map in map?");
405 if (!argv
[0] || !argv
[1]) {
406 p_err("not enough value arguments for map in map");
410 fd
= map_parse_fd(&argc
, &argv
);
416 } else if (map_is_map_of_progs(info
->type
)) {
419 if (value_size
!= 4) {
420 p_err("value smaller than 4B for map of progs?");
423 if (!argv
[0] || !argv
[1]) {
424 p_err("not enough value arguments for map of progs");
427 if (is_prefix(*argv
, "id"))
428 p_info("Warning: updating program array via MAP_ID, make sure this map is kept open\n"
429 " by some process or pinned otherwise update will be lost");
431 fd
= prog_parse_fd(&argc
, &argv
);
438 argv
= parse_bytes(argv
, "value", value
, value_size
);
442 fill_per_cpu_value(info
, value
);
445 return parse_elem(argv
, info
, key
, NULL
, key_size
, value_size
,
447 } else if (is_prefix(*argv
, "any") || is_prefix(*argv
, "noexist") ||
448 is_prefix(*argv
, "exist")) {
450 p_err("flags specified multiple times: %s", *argv
);
454 if (is_prefix(*argv
, "any"))
456 else if (is_prefix(*argv
, "noexist"))
457 *flags
= BPF_NOEXIST
;
458 else if (is_prefix(*argv
, "exist"))
461 return parse_elem(argv
+ 1, info
, key
, value
, key_size
,
462 value_size
, NULL
, value_fd
);
465 p_err("expected key or value, got: %s", *argv
);
469 static void show_map_header_json(struct bpf_map_info
*info
, json_writer_t
*wtr
)
471 jsonw_uint_field(wtr
, "id", info
->id
);
472 if (info
->type
< ARRAY_SIZE(map_type_name
))
473 jsonw_string_field(wtr
, "type", map_type_name
[info
->type
]);
475 jsonw_uint_field(wtr
, "type", info
->type
);
478 jsonw_string_field(wtr
, "name", info
->name
);
480 jsonw_name(wtr
, "flags");
481 jsonw_printf(wtr
, "%d", info
->map_flags
);
484 static int show_map_close_json(int fd
, struct bpf_map_info
*info
)
486 char *memlock
, *frozen_str
;
489 memlock
= get_fdinfo(fd
, "memlock");
490 frozen_str
= get_fdinfo(fd
, "frozen");
492 jsonw_start_object(json_wtr
);
494 show_map_header_json(info
, json_wtr
);
496 print_dev_json(info
->ifindex
, info
->netns_dev
, info
->netns_ino
);
498 jsonw_uint_field(json_wtr
, "bytes_key", info
->key_size
);
499 jsonw_uint_field(json_wtr
, "bytes_value", info
->value_size
);
500 jsonw_uint_field(json_wtr
, "max_entries", info
->max_entries
);
503 jsonw_int_field(json_wtr
, "bytes_memlock", atoi(memlock
));
506 if (info
->type
== BPF_MAP_TYPE_PROG_ARRAY
) {
507 char *owner_prog_type
= get_fdinfo(fd
, "owner_prog_type");
508 char *owner_jited
= get_fdinfo(fd
, "owner_jited");
510 if (owner_prog_type
) {
511 unsigned int prog_type
= atoi(owner_prog_type
);
513 if (prog_type
< prog_type_name_size
)
514 jsonw_string_field(json_wtr
, "owner_prog_type",
515 prog_type_name
[prog_type
]);
517 jsonw_uint_field(json_wtr
, "owner_prog_type",
521 jsonw_bool_field(json_wtr
, "owner_jited",
522 !!atoi(owner_jited
));
524 free(owner_prog_type
);
530 frozen
= atoi(frozen_str
);
533 jsonw_int_field(json_wtr
, "frozen", frozen
);
536 jsonw_int_field(json_wtr
, "btf_id", info
->btf_id
);
538 if (!hash_empty(map_table
.table
)) {
539 struct pinned_obj
*obj
;
541 jsonw_name(json_wtr
, "pinned");
542 jsonw_start_array(json_wtr
);
543 hash_for_each_possible(map_table
.table
, obj
, hash
, info
->id
) {
544 if (obj
->id
== info
->id
)
545 jsonw_string(json_wtr
, obj
->path
);
547 jsonw_end_array(json_wtr
);
550 emit_obj_refs_json(&refs_table
, info
->id
, json_wtr
);
552 jsonw_end_object(json_wtr
);
557 static void show_map_header_plain(struct bpf_map_info
*info
)
559 printf("%u: ", info
->id
);
560 if (info
->type
< ARRAY_SIZE(map_type_name
))
561 printf("%s ", map_type_name
[info
->type
]);
563 printf("type %u ", info
->type
);
566 printf("name %s ", info
->name
);
568 printf("flags 0x%x", info
->map_flags
);
569 print_dev_plain(info
->ifindex
, info
->netns_dev
, info
->netns_ino
);
573 static int show_map_close_plain(int fd
, struct bpf_map_info
*info
)
575 char *memlock
, *frozen_str
;
578 memlock
= get_fdinfo(fd
, "memlock");
579 frozen_str
= get_fdinfo(fd
, "frozen");
581 show_map_header_plain(info
);
582 printf("\tkey %uB value %uB max_entries %u",
583 info
->key_size
, info
->value_size
, info
->max_entries
);
586 printf(" memlock %sB", memlock
);
589 if (info
->type
== BPF_MAP_TYPE_PROG_ARRAY
) {
590 char *owner_prog_type
= get_fdinfo(fd
, "owner_prog_type");
591 char *owner_jited
= get_fdinfo(fd
, "owner_jited");
593 if (owner_prog_type
|| owner_jited
)
595 if (owner_prog_type
) {
596 unsigned int prog_type
= atoi(owner_prog_type
);
598 if (prog_type
< prog_type_name_size
)
599 printf("owner_prog_type %s ",
600 prog_type_name
[prog_type
]);
602 printf("owner_prog_type %d ", prog_type
);
605 printf("owner%s jited",
606 atoi(owner_jited
) ? "" : " not");
608 free(owner_prog_type
);
613 if (!hash_empty(map_table
.table
)) {
614 struct pinned_obj
*obj
;
616 hash_for_each_possible(map_table
.table
, obj
, hash
, info
->id
) {
617 if (obj
->id
== info
->id
)
618 printf("\n\tpinned %s", obj
->path
);
624 frozen
= atoi(frozen_str
);
628 if (!info
->btf_id
&& !frozen
)
634 printf("btf_id %d", info
->btf_id
);
637 printf("%sfrozen", info
->btf_id
? " " : "");
639 emit_obj_refs_plain(&refs_table
, info
->id
, "\n\tpids ");
645 static int do_show_subset(int argc
, char **argv
)
647 struct bpf_map_info info
= {};
648 __u32 len
= sizeof(info
);
653 fds
= malloc(sizeof(int));
655 p_err("mem alloc failed");
658 nb_fds
= map_parse_fds(&argc
, &argv
, &fds
);
662 if (json_output
&& nb_fds
> 1)
663 jsonw_start_array(json_wtr
); /* root array */
664 for (i
= 0; i
< nb_fds
; i
++) {
665 err
= bpf_obj_get_info_by_fd(fds
[i
], &info
, &len
);
667 p_err("can't get map info: %s",
669 for (; i
< nb_fds
; i
++)
675 show_map_close_json(fds
[i
], &info
);
677 show_map_close_plain(fds
[i
], &info
);
681 if (json_output
&& nb_fds
> 1)
682 jsonw_end_array(json_wtr
); /* root array */
689 static int do_show(int argc
, char **argv
)
691 struct bpf_map_info info
= {};
692 __u32 len
= sizeof(info
);
698 build_pinned_obj_table(&map_table
, BPF_OBJ_MAP
);
699 build_obj_refs_table(&refs_table
, BPF_OBJ_MAP
);
702 return do_show_subset(argc
, argv
);
708 jsonw_start_array(json_wtr
);
710 err
= bpf_map_get_next_id(id
, &id
);
714 p_err("can't get next map: %s%s", strerror(errno
),
715 errno
== EINVAL
? " -- kernel too old?" : "");
719 fd
= bpf_map_get_fd_by_id(id
);
723 p_err("can't get map by id (%u): %s",
724 id
, strerror(errno
));
728 err
= bpf_obj_get_info_by_fd(fd
, &info
, &len
);
730 p_err("can't get map info: %s", strerror(errno
));
736 show_map_close_json(fd
, &info
);
738 show_map_close_plain(fd
, &info
);
741 jsonw_end_array(json_wtr
);
743 delete_obj_refs_table(&refs_table
);
745 return errno
== ENOENT
? 0 : -1;
748 static int dump_map_elem(int fd
, void *key
, void *value
,
749 struct bpf_map_info
*map_info
, struct btf
*btf
,
750 json_writer_t
*btf_wtr
)
752 if (bpf_map_lookup_elem(fd
, key
, value
)) {
753 print_entry_error(map_info
, key
, errno
);
758 print_entry_json(map_info
, key
, value
, btf
);
760 struct btf_dumper d
= {
763 .is_plain_text
= true,
766 do_dump_btf(&d
, map_info
, key
, value
);
768 print_entry_plain(map_info
, key
, value
);
774 static int maps_have_btf(int *fds
, int nb_fds
)
776 struct bpf_map_info info
= {};
777 __u32 len
= sizeof(info
);
780 for (i
= 0; i
< nb_fds
; i
++) {
781 err
= bpf_obj_get_info_by_fd(fds
[i
], &info
, &len
);
783 p_err("can't get map info: %s", strerror(errno
));
794 static struct btf
*btf_vmlinux
;
796 static struct btf
*get_map_kv_btf(const struct bpf_map_info
*info
)
798 struct btf
*btf
= NULL
;
800 if (info
->btf_vmlinux_value_type_id
) {
802 btf_vmlinux
= libbpf_find_kernel_btf();
803 if (IS_ERR(btf_vmlinux
))
804 p_err("failed to get kernel btf");
807 } else if (info
->btf_value_type_id
) {
810 err
= btf__get_from_id(info
->btf_id
, &btf
);
812 p_err("failed to get btf");
813 btf
= err
? ERR_PTR(err
) : ERR_PTR(-ESRCH
);
820 static void free_map_kv_btf(struct btf
*btf
)
822 if (!IS_ERR(btf
) && btf
!= btf_vmlinux
)
826 static void free_btf_vmlinux(void)
828 if (!IS_ERR(btf_vmlinux
))
829 btf__free(btf_vmlinux
);
833 map_dump(int fd
, struct bpf_map_info
*info
, json_writer_t
*wtr
,
836 void *key
, *value
, *prev_key
;
837 unsigned int num_elems
= 0;
838 struct btf
*btf
= NULL
;
841 key
= malloc(info
->key_size
);
842 value
= alloc_value(info
);
843 if (!key
|| !value
) {
844 p_err("mem alloc failed");
852 btf
= get_map_kv_btf(info
);
859 jsonw_start_object(wtr
); /* map object */
860 show_map_header_json(info
, wtr
);
861 jsonw_name(wtr
, "elements");
863 jsonw_start_array(wtr
); /* elements */
864 } else if (show_header
) {
865 show_map_header_plain(info
);
868 if (info
->type
== BPF_MAP_TYPE_REUSEPORT_SOCKARRAY
&&
869 info
->value_size
!= 8)
870 p_info("Warning: cannot read values from %s map with value_size != 8",
871 map_type_name
[info
->type
]);
873 err
= bpf_map_get_next_key(fd
, prev_key
, key
);
879 if (!dump_map_elem(fd
, key
, value
, info
, btf
, wtr
))
885 jsonw_end_array(wtr
); /* elements */
887 jsonw_end_object(wtr
); /* map object */
889 printf("Found %u element%s\n", num_elems
,
890 num_elems
!= 1 ? "s" : "");
897 free_map_kv_btf(btf
);
902 static int do_dump(int argc
, char **argv
)
904 json_writer_t
*wtr
= NULL
, *btf_wtr
= NULL
;
905 struct bpf_map_info info
= {};
907 __u32 len
= sizeof(info
);
914 fds
= malloc(sizeof(int));
916 p_err("mem alloc failed");
919 nb_fds
= map_parse_fds(&argc
, &argv
, &fds
);
928 do_plain_btf
= maps_have_btf(fds
, nb_fds
);
929 if (do_plain_btf
< 0)
933 btf_wtr
= get_btf_writer();
936 p_info("failed to create json writer for btf. falling back to plain output");
940 if (wtr
&& nb_fds
> 1)
941 jsonw_start_array(wtr
); /* root array */
942 for (i
= 0; i
< nb_fds
; i
++) {
943 if (bpf_obj_get_info_by_fd(fds
[i
], &info
, &len
)) {
944 p_err("can't get map info: %s", strerror(errno
));
947 err
= map_dump(fds
[i
], &info
, wtr
, nb_fds
> 1);
948 if (!wtr
&& i
!= nb_fds
- 1)
955 if (wtr
&& nb_fds
> 1)
956 jsonw_end_array(wtr
); /* root array */
959 jsonw_destroy(&btf_wtr
);
961 for (; i
< nb_fds
; i
++)
969 static int alloc_key_value(struct bpf_map_info
*info
, void **key
, void **value
)
974 if (info
->key_size
) {
975 *key
= malloc(info
->key_size
);
977 p_err("key mem alloc failed");
982 if (info
->value_size
) {
983 *value
= alloc_value(info
);
985 p_err("value mem alloc failed");
995 static int do_update(int argc
, char **argv
)
997 struct bpf_map_info info
= {};
998 __u32 len
= sizeof(info
);
999 __u32
*value_fd
= NULL
;
1000 __u32 flags
= BPF_ANY
;
1007 fd
= map_parse_fd_and_info(&argc
, &argv
, &info
, &len
);
1011 err
= alloc_key_value(&info
, &key
, &value
);
1015 err
= parse_elem(argv
, &info
, key
, value
, info
.key_size
,
1016 info
.value_size
, &flags
, &value_fd
);
1020 err
= bpf_map_update_elem(fd
, key
, value
, flags
);
1022 p_err("update failed: %s", strerror(errno
));
1033 if (!err
&& json_output
)
1034 jsonw_null(json_wtr
);
1038 static void print_key_value(struct bpf_map_info
*info
, void *key
,
1041 json_writer_t
*btf_wtr
;
1042 struct btf
*btf
= NULL
;
1045 err
= btf__get_from_id(info
->btf_id
, &btf
);
1047 p_err("failed to get btf");
1052 print_entry_json(info
, key
, value
, btf
);
1054 /* if here json_wtr wouldn't have been initialised,
1055 * so let's create separate writer for btf
1057 btf_wtr
= get_btf_writer();
1059 p_info("failed to create json writer for btf. falling back to plain output");
1062 print_entry_plain(info
, key
, value
);
1064 struct btf_dumper d
= {
1067 .is_plain_text
= true,
1070 do_dump_btf(&d
, info
, key
, value
);
1071 jsonw_destroy(&btf_wtr
);
1074 print_entry_plain(info
, key
, value
);
1079 static int do_lookup(int argc
, char **argv
)
1081 struct bpf_map_info info
= {};
1082 __u32 len
= sizeof(info
);
1090 fd
= map_parse_fd_and_info(&argc
, &argv
, &info
, &len
);
1094 err
= alloc_key_value(&info
, &key
, &value
);
1098 err
= parse_elem(argv
, &info
, key
, NULL
, info
.key_size
, 0, NULL
, NULL
);
1102 err
= bpf_map_lookup_elem(fd
, key
, value
);
1104 if (errno
== ENOENT
) {
1106 jsonw_null(json_wtr
);
1109 fprint_hex(stdout
, key
, info
.key_size
, " ");
1110 printf("\n\nNot found\n");
1113 p_err("lookup failed: %s", strerror(errno
));
1119 /* here means bpf_map_lookup_elem() succeeded */
1120 print_key_value(&info
, key
, value
);
1130 static int do_getnext(int argc
, char **argv
)
1132 struct bpf_map_info info
= {};
1133 __u32 len
= sizeof(info
);
1134 void *key
, *nextkey
;
1141 fd
= map_parse_fd_and_info(&argc
, &argv
, &info
, &len
);
1145 key
= malloc(info
.key_size
);
1146 nextkey
= malloc(info
.key_size
);
1147 if (!key
|| !nextkey
) {
1148 p_err("mem alloc failed");
1154 err
= parse_elem(argv
, &info
, key
, NULL
, info
.key_size
, 0,
1163 err
= bpf_map_get_next_key(fd
, key
, nextkey
);
1165 p_err("can't get next key: %s", strerror(errno
));
1170 jsonw_start_object(json_wtr
);
1172 jsonw_name(json_wtr
, "key");
1173 print_hex_data_json(key
, info
.key_size
);
1175 jsonw_null_field(json_wtr
, "key");
1177 jsonw_name(json_wtr
, "next_key");
1178 print_hex_data_json(nextkey
, info
.key_size
);
1179 jsonw_end_object(json_wtr
);
1183 fprint_hex(stdout
, key
, info
.key_size
, " ");
1186 printf("key: None\n");
1188 printf("next key:\n");
1189 fprint_hex(stdout
, nextkey
, info
.key_size
, " ");
1201 static int do_delete(int argc
, char **argv
)
1203 struct bpf_map_info info
= {};
1204 __u32 len
= sizeof(info
);
1212 fd
= map_parse_fd_and_info(&argc
, &argv
, &info
, &len
);
1216 key
= malloc(info
.key_size
);
1218 p_err("mem alloc failed");
1223 err
= parse_elem(argv
, &info
, key
, NULL
, info
.key_size
, 0, NULL
, NULL
);
1227 err
= bpf_map_delete_elem(fd
, key
);
1229 p_err("delete failed: %s", strerror(errno
));
1235 if (!err
&& json_output
)
1236 jsonw_null(json_wtr
);
1240 static int do_pin(int argc
, char **argv
)
1244 err
= do_pin_any(argc
, argv
, map_parse_fd
);
1245 if (!err
&& json_output
)
1246 jsonw_null(json_wtr
);
1250 static int do_create(int argc
, char **argv
)
1252 struct bpf_create_map_attr attr
= { NULL
, };
1253 const char *pinfile
;
1258 pinfile
= GET_ARG();
1264 if (is_prefix(*argv
, "type")) {
1267 if (attr
.map_type
) {
1268 p_err("map type already specified");
1272 attr
.map_type
= map_type_from_str(*argv
);
1273 if ((int)attr
.map_type
< 0) {
1274 p_err("unrecognized map type: %s", *argv
);
1278 } else if (is_prefix(*argv
, "name")) {
1280 attr
.name
= GET_ARG();
1281 } else if (is_prefix(*argv
, "key")) {
1282 if (parse_u32_arg(&argc
, &argv
, &attr
.key_size
,
1285 } else if (is_prefix(*argv
, "value")) {
1286 if (parse_u32_arg(&argc
, &argv
, &attr
.value_size
,
1289 } else if (is_prefix(*argv
, "entries")) {
1290 if (parse_u32_arg(&argc
, &argv
, &attr
.max_entries
,
1293 } else if (is_prefix(*argv
, "flags")) {
1294 if (parse_u32_arg(&argc
, &argv
, &attr
.map_flags
,
1297 } else if (is_prefix(*argv
, "dev")) {
1300 if (attr
.map_ifindex
) {
1301 p_err("offload device already specified");
1305 attr
.map_ifindex
= if_nametoindex(*argv
);
1306 if (!attr
.map_ifindex
) {
1307 p_err("unrecognized netdevice '%s': %s",
1308 *argv
, strerror(errno
));
1312 } else if (is_prefix(*argv
, "inner_map")) {
1313 struct bpf_map_info info
= {};
1314 __u32 len
= sizeof(info
);
1320 inner_map_fd
= map_parse_fd_and_info(&argc
, &argv
,
1322 if (inner_map_fd
< 0)
1324 attr
.inner_map_fd
= inner_map_fd
;
1326 p_err("unknown arg %s", *argv
);
1332 p_err("map name not specified");
1338 fd
= bpf_create_map_xattr(&attr
);
1340 p_err("map create failed: %s", strerror(errno
));
1344 err
= do_pin_fd(fd
, pinfile
);
1350 jsonw_null(json_wtr
);
1353 if (attr
.inner_map_fd
> 0)
1354 close(attr
.inner_map_fd
);
1359 static int do_pop_dequeue(int argc
, char **argv
)
1361 struct bpf_map_info info
= {};
1362 __u32 len
= sizeof(info
);
1370 fd
= map_parse_fd_and_info(&argc
, &argv
, &info
, &len
);
1374 err
= alloc_key_value(&info
, &key
, &value
);
1378 err
= bpf_map_lookup_and_delete_elem(fd
, key
, value
);
1380 if (errno
== ENOENT
) {
1382 jsonw_null(json_wtr
);
1384 printf("Error: empty map\n");
1386 p_err("pop failed: %s", strerror(errno
));
1392 print_key_value(&info
, key
, value
);
1402 static int do_freeze(int argc
, char **argv
)
1409 fd
= map_parse_fd(&argc
, &argv
);
1418 err
= bpf_map_freeze(fd
);
1421 p_err("failed to freeze map: %s", strerror(errno
));
1426 jsonw_null(json_wtr
);
1431 static int do_help(int argc
, char **argv
)
1434 jsonw_null(json_wtr
);
1439 "Usage: %1$s %2$s { show | list } [MAP]\n"
1440 " %1$s %2$s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n"
1441 " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n"
1442 " [inner_map MAP] [dev NAME]\n"
1443 " %1$s %2$s dump MAP\n"
1444 " %1$s %2$s update MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n"
1445 " %1$s %2$s lookup MAP [key DATA]\n"
1446 " %1$s %2$s getnext MAP [key DATA]\n"
1447 " %1$s %2$s delete MAP key DATA\n"
1448 " %1$s %2$s pin MAP FILE\n"
1449 " %1$s %2$s event_pipe MAP [cpu N index M]\n"
1450 " %1$s %2$s peek MAP\n"
1451 " %1$s %2$s push MAP value VALUE\n"
1452 " %1$s %2$s pop MAP\n"
1453 " %1$s %2$s enqueue MAP value VALUE\n"
1454 " %1$s %2$s dequeue MAP\n"
1455 " %1$s %2$s freeze MAP\n"
1458 " " HELP_SPEC_MAP
"\n"
1459 " DATA := { [hex] BYTES }\n"
1460 " " HELP_SPEC_PROGRAM
"\n"
1461 " VALUE := { DATA | MAP | PROG }\n"
1462 " UPDATE_FLAGS := { any | exist | noexist }\n"
1463 " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n"
1464 " percpu_array | stack_trace | cgroup_array | lru_hash |\n"
1465 " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
1466 " devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n"
1467 " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage |\n"
1468 " queue | stack | sk_storage | struct_ops | ringbuf | inode_storage |\n"
1470 " " HELP_SPEC_OPTIONS
"\n"
1472 bin_name
, argv
[-2]);
1477 static const struct cmd cmds
[] = {
1478 { "show", do_show
},
1479 { "list", do_show
},
1480 { "help", do_help
},
1481 { "dump", do_dump
},
1482 { "update", do_update
},
1483 { "lookup", do_lookup
},
1484 { "getnext", do_getnext
},
1485 { "delete", do_delete
},
1487 { "event_pipe", do_event_pipe
},
1488 { "create", do_create
},
1489 { "peek", do_lookup
},
1490 { "push", do_update
},
1491 { "enqueue", do_update
},
1492 { "pop", do_pop_dequeue
},
1493 { "dequeue", do_pop_dequeue
},
1494 { "freeze", do_freeze
},
1498 int do_map(int argc
, char **argv
)
1500 return cmd_select(cmds
, argc
, argv
, do_help
);