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_SOCKMAP] = "sockmap",
41 [BPF_MAP_TYPE_CPUMAP] = "cpumap",
42 [BPF_MAP_TYPE_XSKMAP] = "xskmap",
43 [BPF_MAP_TYPE_SOCKHASH] = "sockhash",
44 [BPF_MAP_TYPE_CGROUP_STORAGE] = "cgroup_storage",
45 [BPF_MAP_TYPE_REUSEPORT_SOCKARRAY] = "reuseport_sockarray",
46 [BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE] = "percpu_cgroup_storage",
47 [BPF_MAP_TYPE_QUEUE] = "queue",
48 [BPF_MAP_TYPE_STACK] = "stack",
49 [BPF_MAP_TYPE_SK_STORAGE] = "sk_storage",
52 const size_t map_type_name_size = ARRAY_SIZE(map_type_name);
54 static bool map_is_per_cpu(__u32 type)
56 return type == BPF_MAP_TYPE_PERCPU_HASH ||
57 type == BPF_MAP_TYPE_PERCPU_ARRAY ||
58 type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
59 type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
62 static bool map_is_map_of_maps(__u32 type)
64 return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
65 type == BPF_MAP_TYPE_HASH_OF_MAPS;
68 static bool map_is_map_of_progs(__u32 type)
70 return type == BPF_MAP_TYPE_PROG_ARRAY;
73 static int map_type_from_str(const char *type)
77 for (i = 0; i < ARRAY_SIZE(map_type_name); i++)
78 /* Don't allow prefixing in case of possible future shadowing */
79 if (map_type_name[i] && !strcmp(map_type_name[i], type))
84 static void *alloc_value(struct bpf_map_info *info)
86 if (map_is_per_cpu(info->type))
87 return malloc(round_up(info->value_size, 8) *
90 return malloc(info->value_size);
93 int map_parse_fd(int *argc, char ***argv)
97 if (is_prefix(**argv, "id")) {
103 id = strtoul(**argv, &endptr, 0);
105 p_err("can't parse %s as ID", **argv);
110 fd = bpf_map_get_fd_by_id(id);
112 p_err("get map by id (%u): %s", id, strerror(errno));
114 } else if (is_prefix(**argv, "pinned")) {
122 return open_obj_pinned_any(path, BPF_OBJ_MAP);
125 p_err("expected 'id' or 'pinned', got: '%s'?", **argv);
129 int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
134 fd = map_parse_fd(argc, argv);
138 err = bpf_obj_get_info_by_fd(fd, info, info_len);
140 p_err("can't get map info: %s", strerror(errno));
148 static int do_dump_btf(const struct btf_dumper *d,
149 struct bpf_map_info *map_info, void *key,
154 /* start of key-value pair */
155 jsonw_start_object(d->jw);
157 if (map_info->btf_key_type_id) {
158 jsonw_name(d->jw, "key");
160 ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
165 if (!map_is_per_cpu(map_info->type)) {
166 jsonw_name(d->jw, "value");
167 ret = btf_dumper_type(d, map_info->btf_value_type_id, value);
169 unsigned int i, n, step;
171 jsonw_name(d->jw, "values");
172 jsonw_start_array(d->jw);
173 n = get_possible_cpus();
174 step = round_up(map_info->value_size, 8);
175 for (i = 0; i < n; i++) {
176 jsonw_start_object(d->jw);
177 jsonw_int_field(d->jw, "cpu", i);
178 jsonw_name(d->jw, "value");
179 ret = btf_dumper_type(d, map_info->btf_value_type_id,
181 jsonw_end_object(d->jw);
185 jsonw_end_array(d->jw);
189 /* end of key-value pair */
190 jsonw_end_object(d->jw);
195 static json_writer_t *get_btf_writer(void)
197 json_writer_t *jw = jsonw_new(stdout);
201 jsonw_pretty(jw, true);
206 static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
207 unsigned char *value, struct btf *btf)
209 jsonw_start_object(json_wtr);
211 if (!map_is_per_cpu(info->type)) {
212 jsonw_name(json_wtr, "key");
213 print_hex_data_json(key, info->key_size);
214 jsonw_name(json_wtr, "value");
215 print_hex_data_json(value, info->value_size);
217 struct btf_dumper d = {
220 .is_plain_text = false,
223 jsonw_name(json_wtr, "formatted");
224 do_dump_btf(&d, info, key, value);
227 unsigned int i, n, step;
229 n = get_possible_cpus();
230 step = round_up(info->value_size, 8);
232 jsonw_name(json_wtr, "key");
233 print_hex_data_json(key, info->key_size);
235 jsonw_name(json_wtr, "values");
236 jsonw_start_array(json_wtr);
237 for (i = 0; i < n; i++) {
238 jsonw_start_object(json_wtr);
240 jsonw_int_field(json_wtr, "cpu", i);
242 jsonw_name(json_wtr, "value");
243 print_hex_data_json(value + i * step,
246 jsonw_end_object(json_wtr);
248 jsonw_end_array(json_wtr);
250 struct btf_dumper d = {
253 .is_plain_text = false,
256 jsonw_name(json_wtr, "formatted");
257 do_dump_btf(&d, info, key, value);
261 jsonw_end_object(json_wtr);
264 static void print_entry_error(struct bpf_map_info *info, unsigned char *key,
265 const char *error_msg)
267 int msg_size = strlen(error_msg);
268 bool single_line, break_names;
270 break_names = info->key_size > 16 || msg_size > 16;
271 single_line = info->key_size + msg_size <= 24 && !break_names;
273 printf("key:%c", break_names ? '\n' : ' ');
274 fprint_hex(stdout, key, info->key_size, " ");
276 printf(single_line ? " " : "\n");
278 printf("value:%c%s", break_names ? '\n' : ' ', error_msg);
283 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
284 unsigned char *value)
286 if (!map_is_per_cpu(info->type)) {
287 bool single_line, break_names;
289 break_names = info->key_size > 16 || info->value_size > 16;
290 single_line = info->key_size + info->value_size <= 24 &&
293 if (info->key_size) {
294 printf("key:%c", break_names ? '\n' : ' ');
295 fprint_hex(stdout, key, info->key_size, " ");
297 printf(single_line ? " " : "\n");
300 if (info->value_size) {
301 printf("value:%c", break_names ? '\n' : ' ');
302 fprint_hex(stdout, value, info->value_size, " ");
307 unsigned int i, n, step;
309 n = get_possible_cpus();
310 step = round_up(info->value_size, 8);
312 if (info->key_size) {
314 fprint_hex(stdout, key, info->key_size, " ");
317 if (info->value_size) {
318 for (i = 0; i < n; i++) {
319 printf("value (CPU %02d):%c",
320 i, info->value_size > 16 ? '\n' : ' ');
321 fprint_hex(stdout, value + i * step,
322 info->value_size, " ");
329 static char **parse_bytes(char **argv, const char *name, unsigned char *val,
332 unsigned int i = 0, base = 0;
335 if (is_prefix(*argv, "hex")) {
340 while (i < n && argv[i]) {
341 val[i] = strtoul(argv[i], &endptr, base);
343 p_err("error parsing byte: %s", argv[i]);
350 p_err("%s expected %d bytes got %d", name, n, i);
357 /* on per cpu maps we must copy the provided value on all value instances */
358 static void fill_per_cpu_value(struct bpf_map_info *info, void *value)
360 unsigned int i, n, step;
362 if (!map_is_per_cpu(info->type))
365 n = get_possible_cpus();
366 step = round_up(info->value_size, 8);
367 for (i = 1; i < n; i++)
368 memcpy(value + i * step, value, info->value_size);
371 static int parse_elem(char **argv, struct bpf_map_info *info,
372 void *key, void *value, __u32 key_size, __u32 value_size,
373 __u32 *flags, __u32 **value_fd)
378 p_err("did not find %s", key ? "key" : "value");
382 if (is_prefix(*argv, "key")) {
385 p_err("duplicate key");
387 p_err("unnecessary key");
391 argv = parse_bytes(argv + 1, "key", key, key_size);
395 return parse_elem(argv, info, NULL, value, key_size, value_size,
397 } else if (is_prefix(*argv, "value")) {
402 p_err("duplicate value");
404 p_err("unnecessary value");
410 if (map_is_map_of_maps(info->type)) {
413 if (value_size != 4) {
414 p_err("value smaller than 4B for map in map?");
417 if (!argv[0] || !argv[1]) {
418 p_err("not enough value arguments for map in map");
422 fd = map_parse_fd(&argc, &argv);
428 } else if (map_is_map_of_progs(info->type)) {
431 if (value_size != 4) {
432 p_err("value smaller than 4B for map of progs?");
435 if (!argv[0] || !argv[1]) {
436 p_err("not enough value arguments for map of progs");
439 if (is_prefix(*argv, "id"))
440 p_info("Warning: updating program array via MAP_ID, make sure this map is kept open\n"
441 " by some process or pinned otherwise update will be lost");
443 fd = prog_parse_fd(&argc, &argv);
450 argv = parse_bytes(argv, "value", value, value_size);
454 fill_per_cpu_value(info, value);
457 return parse_elem(argv, info, key, NULL, key_size, value_size,
459 } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
460 is_prefix(*argv, "exist")) {
462 p_err("flags specified multiple times: %s", *argv);
466 if (is_prefix(*argv, "any"))
468 else if (is_prefix(*argv, "noexist"))
469 *flags = BPF_NOEXIST;
470 else if (is_prefix(*argv, "exist"))
473 return parse_elem(argv + 1, info, key, value, key_size,
474 value_size, NULL, value_fd);
477 p_err("expected key or value, got: %s", *argv);
481 static int show_map_close_json(int fd, struct bpf_map_info *info)
485 memlock = get_fdinfo(fd, "memlock");
487 jsonw_start_object(json_wtr);
489 jsonw_uint_field(json_wtr, "id", info->id);
490 if (info->type < ARRAY_SIZE(map_type_name))
491 jsonw_string_field(json_wtr, "type",
492 map_type_name[info->type]);
494 jsonw_uint_field(json_wtr, "type", info->type);
497 jsonw_string_field(json_wtr, "name", info->name);
499 jsonw_name(json_wtr, "flags");
500 jsonw_printf(json_wtr, "%d", info->map_flags);
502 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
504 jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
505 jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
506 jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
509 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
512 if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
513 char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
514 char *owner_jited = get_fdinfo(fd, "owner_jited");
516 if (owner_prog_type) {
517 unsigned int prog_type = atoi(owner_prog_type);
519 if (prog_type < ARRAY_SIZE(prog_type_name))
520 jsonw_string_field(json_wtr, "owner_prog_type",
521 prog_type_name[prog_type]);
523 jsonw_uint_field(json_wtr, "owner_prog_type",
527 jsonw_bool_field(json_wtr, "owner_jited",
528 !!atoi(owner_jited));
530 free(owner_prog_type);
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 jsonw_end_object(json_wtr);
555 static int show_map_close_plain(int fd, struct bpf_map_info *info)
559 memlock = get_fdinfo(fd, "memlock");
561 printf("%u: ", info->id);
562 if (info->type < ARRAY_SIZE(map_type_name))
563 printf("%s ", map_type_name[info->type]);
565 printf("type %u ", info->type);
568 printf("name %s ", info->name);
570 printf("flags 0x%x", info->map_flags);
571 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
573 printf("\tkey %uB value %uB max_entries %u",
574 info->key_size, info->value_size, info->max_entries);
577 printf(" memlock %sB", memlock);
580 if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
581 char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
582 char *owner_jited = get_fdinfo(fd, "owner_jited");
584 if (owner_prog_type || owner_jited)
586 if (owner_prog_type) {
587 unsigned int prog_type = atoi(owner_prog_type);
589 if (prog_type < ARRAY_SIZE(prog_type_name))
590 printf("owner_prog_type %s ",
591 prog_type_name[prog_type]);
593 printf("owner_prog_type %d ", prog_type);
596 printf("owner%s jited",
597 atoi(owner_jited) ? "" : " not");
599 free(owner_prog_type);
604 if (!hash_empty(map_table.table)) {
605 struct pinned_obj *obj;
607 hash_for_each_possible(map_table.table, obj, hash, info->id) {
608 if (obj->id == info->id)
609 printf("\n\tpinned %s", obj->path);
614 printf("\n\tbtf_id %d", info->btf_id);
620 static int do_show(int argc, char **argv)
622 struct bpf_map_info info = {};
623 __u32 len = sizeof(info);
629 build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
632 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
637 return show_map_close_json(fd, &info);
639 return show_map_close_plain(fd, &info);
646 jsonw_start_array(json_wtr);
648 err = bpf_map_get_next_id(id, &id);
652 p_err("can't get next map: %s%s", strerror(errno),
653 errno == EINVAL ? " -- kernel too old?" : "");
657 fd = bpf_map_get_fd_by_id(id);
661 p_err("can't get map by id (%u): %s",
662 id, strerror(errno));
666 err = bpf_obj_get_info_by_fd(fd, &info, &len);
668 p_err("can't get map info: %s", strerror(errno));
674 show_map_close_json(fd, &info);
676 show_map_close_plain(fd, &info);
679 jsonw_end_array(json_wtr);
681 return errno == ENOENT ? 0 : -1;
684 static int dump_map_elem(int fd, void *key, void *value,
685 struct bpf_map_info *map_info, struct btf *btf,
686 json_writer_t *btf_wtr)
691 if (!bpf_map_lookup_elem(fd, key, value)) {
693 print_entry_json(map_info, key, value, btf);
696 struct btf_dumper d = {
699 .is_plain_text = true,
702 do_dump_btf(&d, map_info, key, value);
704 print_entry_plain(map_info, key, value);
711 /* lookup error handling */
712 lookup_errno = errno;
714 if (map_is_map_of_maps(map_info->type) ||
715 map_is_map_of_progs(map_info->type))
719 jsonw_start_object(json_wtr);
720 jsonw_name(json_wtr, "key");
721 print_hex_data_json(key, map_info->key_size);
722 jsonw_name(json_wtr, "value");
723 jsonw_start_object(json_wtr);
724 jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
725 jsonw_end_object(json_wtr);
726 jsonw_end_object(json_wtr);
728 const char *msg = NULL;
730 if (lookup_errno == ENOENT)
732 else if (lookup_errno == ENOSPC &&
733 map_info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY)
734 msg = "<cannot read>";
736 print_entry_error(map_info, key,
737 msg ? : strerror(lookup_errno));
743 static int do_dump(int argc, char **argv)
745 struct bpf_map_info info = {};
746 void *key, *value, *prev_key;
747 unsigned int num_elems = 0;
748 __u32 len = sizeof(info);
749 json_writer_t *btf_wtr;
750 struct btf *btf = NULL;
757 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
761 key = malloc(info.key_size);
762 value = alloc_value(&info);
763 if (!key || !value) {
764 p_err("mem alloc failed");
771 err = btf__get_from_id(info.btf_id, &btf);
773 p_err("failed to get btf");
778 jsonw_start_array(json_wtr);
781 btf_wtr = get_btf_writer();
783 p_info("failed to create json writer for btf. falling back to plain output");
787 jsonw_start_array(btf_wtr);
791 if (info.type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY &&
792 info.value_size != 8)
793 p_info("Warning: cannot read values from %s map with value_size != 8",
794 map_type_name[info.type]);
796 err = bpf_map_get_next_key(fd, prev_key, key);
802 num_elems += dump_map_elem(fd, key, value, &info, btf, btf_wtr);
807 jsonw_end_array(json_wtr);
809 jsonw_end_array(btf_wtr);
810 jsonw_destroy(&btf_wtr);
812 printf("Found %u element%s\n", num_elems,
813 num_elems != 1 ? "s" : "");
825 static int alloc_key_value(struct bpf_map_info *info, void **key, void **value)
830 if (info->key_size) {
831 *key = malloc(info->key_size);
833 p_err("key mem alloc failed");
838 if (info->value_size) {
839 *value = alloc_value(info);
841 p_err("value mem alloc failed");
851 static int do_update(int argc, char **argv)
853 struct bpf_map_info info = {};
854 __u32 len = sizeof(info);
855 __u32 *value_fd = NULL;
856 __u32 flags = BPF_ANY;
863 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
867 err = alloc_key_value(&info, &key, &value);
871 err = parse_elem(argv, &info, key, value, info.key_size,
872 info.value_size, &flags, &value_fd);
876 err = bpf_map_update_elem(fd, key, value, flags);
878 p_err("update failed: %s", strerror(errno));
889 if (!err && json_output)
890 jsonw_null(json_wtr);
894 static void print_key_value(struct bpf_map_info *info, void *key,
897 json_writer_t *btf_wtr;
898 struct btf *btf = NULL;
901 err = btf__get_from_id(info->btf_id, &btf);
903 p_err("failed to get btf");
908 print_entry_json(info, key, value, btf);
910 /* if here json_wtr wouldn't have been initialised,
911 * so let's create separate writer for btf
913 btf_wtr = get_btf_writer();
915 p_info("failed to create json writer for btf. falling back to plain output");
918 print_entry_plain(info, key, value);
920 struct btf_dumper d = {
923 .is_plain_text = true,
926 do_dump_btf(&d, info, key, value);
927 jsonw_destroy(&btf_wtr);
930 print_entry_plain(info, key, value);
935 static int do_lookup(int argc, char **argv)
937 struct bpf_map_info info = {};
938 __u32 len = sizeof(info);
946 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
950 err = alloc_key_value(&info, &key, &value);
954 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
958 err = bpf_map_lookup_elem(fd, key, value);
960 if (errno == ENOENT) {
962 jsonw_null(json_wtr);
965 fprint_hex(stdout, key, info.key_size, " ");
966 printf("\n\nNot found\n");
969 p_err("lookup failed: %s", strerror(errno));
975 /* here means bpf_map_lookup_elem() succeeded */
976 print_key_value(&info, key, value);
986 static int do_getnext(int argc, char **argv)
988 struct bpf_map_info info = {};
989 __u32 len = sizeof(info);
997 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1001 key = malloc(info.key_size);
1002 nextkey = malloc(info.key_size);
1003 if (!key || !nextkey) {
1004 p_err("mem alloc failed");
1010 err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
1019 err = bpf_map_get_next_key(fd, key, nextkey);
1021 p_err("can't get next key: %s", strerror(errno));
1026 jsonw_start_object(json_wtr);
1028 jsonw_name(json_wtr, "key");
1029 print_hex_data_json(key, info.key_size);
1031 jsonw_null_field(json_wtr, "key");
1033 jsonw_name(json_wtr, "next_key");
1034 print_hex_data_json(nextkey, info.key_size);
1035 jsonw_end_object(json_wtr);
1039 fprint_hex(stdout, key, info.key_size, " ");
1042 printf("key: None\n");
1044 printf("next key:\n");
1045 fprint_hex(stdout, nextkey, info.key_size, " ");
1057 static int do_delete(int argc, char **argv)
1059 struct bpf_map_info info = {};
1060 __u32 len = sizeof(info);
1068 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1072 key = malloc(info.key_size);
1074 p_err("mem alloc failed");
1079 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
1083 err = bpf_map_delete_elem(fd, key);
1085 p_err("delete failed: %s", strerror(errno));
1091 if (!err && json_output)
1092 jsonw_null(json_wtr);
1096 static int do_pin(int argc, char **argv)
1100 err = do_pin_any(argc, argv, bpf_map_get_fd_by_id);
1101 if (!err && json_output)
1102 jsonw_null(json_wtr);
1106 static int do_create(int argc, char **argv)
1108 struct bpf_create_map_attr attr = { NULL, };
1109 const char *pinfile;
1114 pinfile = GET_ARG();
1120 if (is_prefix(*argv, "type")) {
1123 if (attr.map_type) {
1124 p_err("map type already specified");
1128 attr.map_type = map_type_from_str(*argv);
1129 if ((int)attr.map_type < 0) {
1130 p_err("unrecognized map type: %s", *argv);
1134 } else if (is_prefix(*argv, "name")) {
1136 attr.name = GET_ARG();
1137 } else if (is_prefix(*argv, "key")) {
1138 if (parse_u32_arg(&argc, &argv, &attr.key_size,
1141 } else if (is_prefix(*argv, "value")) {
1142 if (parse_u32_arg(&argc, &argv, &attr.value_size,
1145 } else if (is_prefix(*argv, "entries")) {
1146 if (parse_u32_arg(&argc, &argv, &attr.max_entries,
1149 } else if (is_prefix(*argv, "flags")) {
1150 if (parse_u32_arg(&argc, &argv, &attr.map_flags,
1153 } else if (is_prefix(*argv, "dev")) {
1156 if (attr.map_ifindex) {
1157 p_err("offload device already specified");
1161 attr.map_ifindex = if_nametoindex(*argv);
1162 if (!attr.map_ifindex) {
1163 p_err("unrecognized netdevice '%s': %s",
1164 *argv, strerror(errno));
1169 p_err("unknown arg %s", *argv);
1175 p_err("map name not specified");
1181 fd = bpf_create_map_xattr(&attr);
1183 p_err("map create failed: %s", strerror(errno));
1187 err = do_pin_fd(fd, pinfile);
1193 jsonw_null(json_wtr);
1197 static int do_pop_dequeue(int argc, char **argv)
1199 struct bpf_map_info info = {};
1200 __u32 len = sizeof(info);
1208 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1212 err = alloc_key_value(&info, &key, &value);
1216 err = bpf_map_lookup_and_delete_elem(fd, key, value);
1218 if (errno == ENOENT) {
1220 jsonw_null(json_wtr);
1222 printf("Error: empty map\n");
1224 p_err("pop failed: %s", strerror(errno));
1230 print_key_value(&info, key, value);
1240 static int do_help(int argc, char **argv)
1243 jsonw_null(json_wtr);
1248 "Usage: %s %s { show | list } [MAP]\n"
1249 " %s %s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n"
1250 " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n"
1253 " %s %s update MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n"
1254 " %s %s lookup MAP [key DATA]\n"
1255 " %s %s getnext MAP [key DATA]\n"
1256 " %s %s delete MAP key DATA\n"
1257 " %s %s pin MAP FILE\n"
1258 " %s %s event_pipe MAP [cpu N index M]\n"
1260 " %s %s push MAP value VALUE\n"
1262 " %s %s enqueue MAP value VALUE\n"
1263 " %s %s dequeue MAP\n"
1266 " " HELP_SPEC_MAP "\n"
1267 " DATA := { [hex] BYTES }\n"
1268 " " HELP_SPEC_PROGRAM "\n"
1269 " VALUE := { DATA | MAP | PROG }\n"
1270 " UPDATE_FLAGS := { any | exist | noexist }\n"
1271 " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n"
1272 " percpu_array | stack_trace | cgroup_array | lru_hash |\n"
1273 " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
1274 " devmap | sockmap | cpumap | xskmap | sockhash |\n"
1275 " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n"
1276 " " HELP_SPEC_OPTIONS "\n"
1278 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1279 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1280 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1281 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1282 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]);
1287 static const struct cmd cmds[] = {
1288 { "show", do_show },
1289 { "list", do_show },
1290 { "help", do_help },
1291 { "dump", do_dump },
1292 { "update", do_update },
1293 { "lookup", do_lookup },
1294 { "getnext", do_getnext },
1295 { "delete", do_delete },
1297 { "event_pipe", do_event_pipe },
1298 { "create", do_create },
1299 { "peek", do_lookup },
1300 { "push", do_update },
1301 { "enqueue", do_update },
1302 { "pop", do_pop_dequeue },
1303 { "dequeue", do_pop_dequeue },
1307 int do_map(int argc, char **argv)
1309 return cmd_select(cmds, argc, argv, do_help);