xref: /linux/tools/bpf/bpftool/map.c (revision 70ac4de43ad1d24ae0c845f35eed307442a0aabc)
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */
3 
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <linux/err.h>
7 #include <linux/kernel.h>
8 #include <net/if.h>
9 #include <stdbool.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 
17 #include <bpf/bpf.h>
18 #include <bpf/btf.h>
19 #include <bpf/hashmap.h>
20 
21 #include "json_writer.h"
22 #include "main.h"
23 
24 static struct hashmap *map_table;
25 
26 static bool map_is_per_cpu(__u32 type)
27 {
28 	return type == BPF_MAP_TYPE_PERCPU_HASH ||
29 	       type == BPF_MAP_TYPE_PERCPU_ARRAY ||
30 	       type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
31 	       type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
32 }
33 
34 static bool map_is_map_of_maps(__u32 type)
35 {
36 	return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
37 	       type == BPF_MAP_TYPE_HASH_OF_MAPS;
38 }
39 
40 static bool map_is_map_of_progs(__u32 type)
41 {
42 	return type == BPF_MAP_TYPE_PROG_ARRAY;
43 }
44 
45 static int map_type_from_str(const char *type)
46 {
47 	const char *map_type_str;
48 	unsigned int i;
49 
50 	for (i = 0; ; i++) {
51 		map_type_str = libbpf_bpf_map_type_str(i);
52 		if (!map_type_str)
53 			break;
54 
55 		/* Don't allow prefixing in case of possible future shadowing */
56 		if (!strcmp(map_type_str, type))
57 			return i;
58 	}
59 	return -1;
60 }
61 
62 static void *alloc_value(struct bpf_map_info *info)
63 {
64 	if (map_is_per_cpu(info->type))
65 		return malloc(round_up(info->value_size, 8) *
66 			      get_possible_cpus());
67 	else
68 		return malloc(info->value_size);
69 }
70 
71 static int do_dump_btf(const struct btf_dumper *d,
72 		       struct bpf_map_info *map_info, void *key,
73 		       void *value, const int *cpu_ids, int cpu_cnt)
74 {
75 	__u32 value_id;
76 	int ret = 0;
77 
78 	/* start of key-value pair */
79 	jsonw_start_object(d->jw);
80 
81 	if (map_info->btf_key_type_id) {
82 		jsonw_name(d->jw, "key");
83 
84 		ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
85 		if (ret)
86 			goto err_end_obj;
87 	}
88 
89 	value_id = map_info->btf_vmlinux_value_type_id ?
90 		: map_info->btf_value_type_id;
91 
92 	if (!map_is_per_cpu(map_info->type)) {
93 		jsonw_name(d->jw, "value");
94 		ret = btf_dumper_type(d, value_id, value);
95 	} else {
96 		unsigned int step;
97 		int i;
98 
99 		jsonw_name(d->jw, "values");
100 		jsonw_start_array(d->jw);
101 		step = round_up(map_info->value_size, 8);
102 		for (i = 0; i < cpu_cnt; i++) {
103 			jsonw_start_object(d->jw);
104 			jsonw_int_field(d->jw, "cpu", cpu_ids[i]);
105 			jsonw_name(d->jw, "value");
106 			ret = btf_dumper_type(d, value_id, value + i * step);
107 			jsonw_end_object(d->jw);
108 			if (ret)
109 				break;
110 		}
111 		jsonw_end_array(d->jw);
112 	}
113 
114 err_end_obj:
115 	/* end of key-value pair */
116 	jsonw_end_object(d->jw);
117 
118 	return ret;
119 }
120 
121 static json_writer_t *get_btf_writer(void)
122 {
123 	json_writer_t *jw = jsonw_new(stdout);
124 
125 	if (!jw)
126 		return NULL;
127 	jsonw_pretty(jw, true);
128 
129 	return jw;
130 }
131 
132 static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
133 			     unsigned char *value, struct btf *btf,
134 			     const int *cpu_ids, int cpu_cnt)
135 {
136 	jsonw_start_object(json_wtr);
137 
138 	if (!map_is_per_cpu(info->type)) {
139 		jsonw_name(json_wtr, "key");
140 		print_hex_data_json(key, info->key_size);
141 		jsonw_name(json_wtr, "value");
142 		print_hex_data_json(value, info->value_size);
143 		if (map_is_map_of_maps(info->type))
144 			jsonw_uint_field(json_wtr, "inner_map_id",
145 					 *(unsigned int *)value);
146 		if (btf) {
147 			struct btf_dumper d = {
148 				.btf = btf,
149 				.jw = json_wtr,
150 				.is_plain_text = false,
151 			};
152 
153 			jsonw_name(json_wtr, "formatted");
154 			do_dump_btf(&d, info, key, value, cpu_ids, cpu_cnt);
155 		}
156 	} else {
157 		unsigned int step;
158 		int i;
159 
160 		step = round_up(info->value_size, 8);
161 
162 		jsonw_name(json_wtr, "key");
163 		print_hex_data_json(key, info->key_size);
164 
165 		jsonw_name(json_wtr, "values");
166 		jsonw_start_array(json_wtr);
167 		for (i = 0; i < cpu_cnt; i++) {
168 			jsonw_start_object(json_wtr);
169 
170 			jsonw_int_field(json_wtr, "cpu", cpu_ids[i]);
171 
172 			jsonw_name(json_wtr, "value");
173 			print_hex_data_json(value + i * step,
174 					    info->value_size);
175 
176 			jsonw_end_object(json_wtr);
177 		}
178 		jsonw_end_array(json_wtr);
179 		if (btf) {
180 			struct btf_dumper d = {
181 				.btf = btf,
182 				.jw = json_wtr,
183 				.is_plain_text = false,
184 			};
185 
186 			jsonw_name(json_wtr, "formatted");
187 			do_dump_btf(&d, info, key, value, cpu_ids, cpu_cnt);
188 		}
189 	}
190 
191 	jsonw_end_object(json_wtr);
192 }
193 
194 static void
195 print_entry_error_msg(struct bpf_map_info *info, unsigned char *key,
196 		      const char *error_msg)
197 {
198 	int msg_size = strlen(error_msg);
199 	bool single_line, break_names;
200 
201 	break_names = info->key_size > 16 || msg_size > 16;
202 	single_line = info->key_size + msg_size <= 24 && !break_names;
203 
204 	printf("key:%c", break_names ? '\n' : ' ');
205 	fprint_hex(stdout, key, info->key_size, " ");
206 
207 	printf(single_line ? "  " : "\n");
208 
209 	printf("value:%c%s", break_names ? '\n' : ' ', error_msg);
210 
211 	printf("\n");
212 }
213 
214 static void
215 print_entry_error(struct bpf_map_info *map_info, void *key, int lookup_errno)
216 {
217 	/* For prog_array maps or arrays of maps, failure to lookup the value
218 	 * means there is no entry for that key. Do not print an error message
219 	 * in that case.
220 	 */
221 	if ((map_is_map_of_maps(map_info->type) ||
222 	     map_is_map_of_progs(map_info->type)) && lookup_errno == ENOENT)
223 		return;
224 
225 	if (json_output) {
226 		jsonw_start_object(json_wtr);	/* entry */
227 		jsonw_name(json_wtr, "key");
228 		print_hex_data_json(key, map_info->key_size);
229 		jsonw_name(json_wtr, "value");
230 		jsonw_start_object(json_wtr);	/* error */
231 		jsonw_string_field(json_wtr, "error", bpf_strerror(lookup_errno));
232 		jsonw_end_object(json_wtr);	/* error */
233 		jsonw_end_object(json_wtr);	/* entry */
234 	} else {
235 		const char *msg = NULL;
236 
237 		if (lookup_errno == ENOENT)
238 			msg = "<no entry>";
239 		else if (lookup_errno == ENOSPC &&
240 			 map_info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY)
241 			msg = "<cannot read>";
242 
243 		print_entry_error_msg(map_info, key,
244 				      msg ? : bpf_strerror(lookup_errno));
245 	}
246 }
247 
248 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
249 			      unsigned char *value, const int *cpu_ids, int cpu_cnt)
250 {
251 	if (!map_is_per_cpu(info->type)) {
252 		bool single_line, break_names;
253 
254 		break_names = info->key_size > 16 || info->value_size > 16;
255 		single_line = info->key_size + info->value_size <= 24 &&
256 			!break_names;
257 
258 		if (info->key_size) {
259 			printf("key:%c", break_names ? '\n' : ' ');
260 			fprint_hex(stdout, key, info->key_size, " ");
261 
262 			printf(single_line ? "  " : "\n");
263 		}
264 
265 		if (info->value_size) {
266 			if (map_is_map_of_maps(info->type)) {
267 				printf("inner_map_id:%c", break_names ? '\n' : ' ');
268 				printf("%u ", *(unsigned int *)value);
269 			} else {
270 				printf("value:%c", break_names ? '\n' : ' ');
271 				fprint_hex(stdout, value, info->value_size, " ");
272 			}
273 		}
274 
275 		printf("\n");
276 	} else {
277 		unsigned int step;
278 		int i;
279 
280 		step = round_up(info->value_size, 8);
281 
282 		if (info->key_size) {
283 			printf("key:\n");
284 			fprint_hex(stdout, key, info->key_size, " ");
285 			printf("\n");
286 		}
287 		if (info->value_size) {
288 			for (i = 0; i < cpu_cnt; i++) {
289 				printf("value (CPU %02d):%c",
290 				       cpu_ids[i], info->value_size > 16 ? '\n' : ' ');
291 				fprint_hex(stdout, value + i * step,
292 					   info->value_size, " ");
293 				printf("\n");
294 			}
295 		}
296 	}
297 }
298 
299 static char **parse_bytes(char **argv, const char *name, unsigned char *val,
300 			  unsigned int n)
301 {
302 	unsigned int i = 0, base = 0;
303 	char *endptr;
304 
305 	if (is_prefix(*argv, "hex")) {
306 		base = 16;
307 		argv++;
308 	}
309 
310 	while (i < n && argv[i]) {
311 		val[i] = strtoul(argv[i], &endptr, base);
312 		if (*endptr) {
313 			p_err("error parsing byte: %s", argv[i]);
314 			return NULL;
315 		}
316 		i++;
317 	}
318 
319 	if (i != n) {
320 		p_err("%s expected %u bytes got %u", name, n, i);
321 		return NULL;
322 	}
323 
324 	return argv + i;
325 }
326 
327 /* on per cpu maps we must copy the provided value on all value instances */
328 static void fill_per_cpu_value(struct bpf_map_info *info, void *value)
329 {
330 	unsigned int i, n, step;
331 
332 	if (!map_is_per_cpu(info->type))
333 		return;
334 
335 	n = get_possible_cpus();
336 	step = round_up(info->value_size, 8);
337 	for (i = 1; i < n; i++)
338 		memcpy(value + i * step, value, info->value_size);
339 }
340 
341 static int parse_elem(char **argv, struct bpf_map_info *info, void *key,
342 		      void *value, __u32 key_size, __u32 value_size,
343 		      __u32 *flags, __u32 **value_fd, __u32 open_flags)
344 {
345 	if (!*argv) {
346 		if (!key && !value)
347 			return 0;
348 		p_err("did not find %s", key ? "key" : "value");
349 		return -1;
350 	}
351 
352 	if (is_prefix(*argv, "key")) {
353 		if (!key) {
354 			if (key_size)
355 				p_err("duplicate key");
356 			else
357 				p_err("unnecessary key");
358 			return -1;
359 		}
360 
361 		argv = parse_bytes(argv + 1, "key", key, key_size);
362 		if (!argv)
363 			return -1;
364 
365 		return parse_elem(argv, info, NULL, value, key_size, value_size,
366 				  flags, value_fd, open_flags);
367 	} else if (is_prefix(*argv, "value")) {
368 		int fd;
369 
370 		if (!value) {
371 			if (value_size)
372 				p_err("duplicate value");
373 			else
374 				p_err("unnecessary value");
375 			return -1;
376 		}
377 
378 		argv++;
379 
380 		if (map_is_map_of_maps(info->type)) {
381 			int argc = 2;
382 
383 			if (value_size != 4) {
384 				p_err("value smaller than 4B for map in map?");
385 				return -1;
386 			}
387 			if (!argv[0] || !argv[1]) {
388 				p_err("not enough value arguments for map in map");
389 				return -1;
390 			}
391 
392 			fd = map_parse_fd(&argc, &argv, open_flags);
393 			if (fd < 0)
394 				return -1;
395 
396 			*value_fd = value;
397 			**value_fd = fd;
398 		} else if (map_is_map_of_progs(info->type)) {
399 			int argc = 2;
400 
401 			if (value_size != 4) {
402 				p_err("value smaller than 4B for map of progs?");
403 				return -1;
404 			}
405 			if (!argv[0] || !argv[1]) {
406 				p_err("not enough value arguments for map of progs");
407 				return -1;
408 			}
409 			if (is_prefix(*argv, "id"))
410 				p_info("Warning: updating program array via MAP_ID, make sure this map is kept open\n"
411 				       "         by some process or pinned otherwise update will be lost");
412 
413 			fd = prog_parse_fd(&argc, &argv);
414 			if (fd < 0)
415 				return -1;
416 
417 			*value_fd = value;
418 			**value_fd = fd;
419 		} else {
420 			argv = parse_bytes(argv, "value", value, value_size);
421 			if (!argv)
422 				return -1;
423 
424 			fill_per_cpu_value(info, value);
425 		}
426 
427 		return parse_elem(argv, info, key, NULL, key_size, value_size,
428 				  flags, NULL, open_flags);
429 	} else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
430 		   is_prefix(*argv, "exist")) {
431 		if (!flags) {
432 			p_err("flags specified multiple times: %s", *argv);
433 			return -1;
434 		}
435 
436 		if (is_prefix(*argv, "any"))
437 			*flags = BPF_ANY;
438 		else if (is_prefix(*argv, "noexist"))
439 			*flags = BPF_NOEXIST;
440 		else if (is_prefix(*argv, "exist"))
441 			*flags = BPF_EXIST;
442 
443 		return parse_elem(argv + 1, info, key, value, key_size,
444 				  value_size, NULL, value_fd, open_flags);
445 	}
446 
447 	p_err("expected key or value, got: %s", *argv);
448 	return -1;
449 }
450 
451 static void show_map_header_json(struct bpf_map_info *info, json_writer_t *wtr)
452 {
453 	const char *map_type_str;
454 
455 	jsonw_uint_field(wtr, "id", info->id);
456 	map_type_str = libbpf_bpf_map_type_str(info->type);
457 	if (map_type_str)
458 		jsonw_string_field(wtr, "type", map_type_str);
459 	else
460 		jsonw_uint_field(wtr, "type", info->type);
461 
462 	if (*info->name)
463 		jsonw_string_field(wtr, "name", info->name);
464 
465 	jsonw_name(wtr, "flags");
466 	jsonw_printf(wtr, "%u", info->map_flags);
467 }
468 
469 static int show_map_close_json(int fd, struct bpf_map_info *info)
470 {
471 	char *memlock, *frozen_str;
472 	int frozen = 0;
473 
474 	memlock = get_fdinfo(fd, "memlock");
475 	frozen_str = get_fdinfo(fd, "frozen");
476 
477 	jsonw_start_object(json_wtr);
478 
479 	show_map_header_json(info, json_wtr);
480 
481 	print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
482 
483 	jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
484 	jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
485 	jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
486 
487 	if (memlock)
488 		jsonw_int_field(json_wtr, "bytes_memlock", atoll(memlock));
489 	free(memlock);
490 
491 	if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
492 		char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
493 		char *owner_jited = get_fdinfo(fd, "owner_jited");
494 
495 		if (owner_prog_type) {
496 			unsigned int prog_type = atoi(owner_prog_type);
497 			const char *prog_type_str;
498 
499 			prog_type_str = libbpf_bpf_prog_type_str(prog_type);
500 			if (prog_type_str)
501 				jsonw_string_field(json_wtr, "owner_prog_type",
502 						   prog_type_str);
503 			else
504 				jsonw_uint_field(json_wtr, "owner_prog_type",
505 						 prog_type);
506 		}
507 		if (owner_jited)
508 			jsonw_bool_field(json_wtr, "owner_jited",
509 					 !!atoi(owner_jited));
510 
511 		free(owner_prog_type);
512 		free(owner_jited);
513 	}
514 	close(fd);
515 
516 	if (frozen_str) {
517 		frozen = atoi(frozen_str);
518 		free(frozen_str);
519 	}
520 	jsonw_int_field(json_wtr, "frozen", frozen);
521 
522 	if (info->btf_id)
523 		jsonw_int_field(json_wtr, "btf_id", info->btf_id);
524 
525 	if (!hashmap__empty(map_table)) {
526 		struct hashmap_entry *entry;
527 
528 		jsonw_name(json_wtr, "pinned");
529 		jsonw_start_array(json_wtr);
530 		hashmap__for_each_key_entry(map_table, entry, info->id)
531 			jsonw_string(json_wtr, entry->pvalue);
532 		jsonw_end_array(json_wtr);
533 	}
534 
535 	emit_obj_refs_json(refs_table, info->id, json_wtr);
536 
537 	jsonw_end_object(json_wtr);
538 
539 	return 0;
540 }
541 
542 static void show_map_header_plain(struct bpf_map_info *info)
543 {
544 	const char *map_type_str;
545 
546 	printf("%u: ", info->id);
547 
548 	map_type_str = libbpf_bpf_map_type_str(info->type);
549 	if (map_type_str)
550 		printf("%s  ", map_type_str);
551 	else
552 		printf("type %u  ", info->type);
553 
554 	if (*info->name)
555 		printf("name %s  ", info->name);
556 
557 	printf("flags 0x%x", info->map_flags);
558 	print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
559 	printf("\n");
560 }
561 
562 static int show_map_close_plain(int fd, struct bpf_map_info *info)
563 {
564 	char *memlock, *frozen_str;
565 	int frozen = 0;
566 
567 	memlock = get_fdinfo(fd, "memlock");
568 	frozen_str = get_fdinfo(fd, "frozen");
569 
570 	show_map_header_plain(info);
571 	printf("\tkey %uB  value %uB  max_entries %u",
572 	       info->key_size, info->value_size, info->max_entries);
573 
574 	if (memlock)
575 		printf("  memlock %sB", memlock);
576 	free(memlock);
577 
578 	if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
579 		char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
580 		char *owner_jited = get_fdinfo(fd, "owner_jited");
581 
582 		if (owner_prog_type || owner_jited)
583 			printf("\n\t");
584 		if (owner_prog_type) {
585 			unsigned int prog_type = atoi(owner_prog_type);
586 			const char *prog_type_str;
587 
588 			prog_type_str = libbpf_bpf_prog_type_str(prog_type);
589 			if (prog_type_str)
590 				printf("owner_prog_type %s  ", prog_type_str);
591 			else
592 				printf("owner_prog_type %u  ", prog_type);
593 		}
594 		if (owner_jited)
595 			printf("owner%s jited",
596 			       atoi(owner_jited) ? "" : " not");
597 
598 		free(owner_prog_type);
599 		free(owner_jited);
600 	}
601 	close(fd);
602 
603 	if (!hashmap__empty(map_table)) {
604 		struct hashmap_entry *entry;
605 
606 		hashmap__for_each_key_entry(map_table, entry, info->id)
607 			printf("\n\tpinned %s", (char *)entry->pvalue);
608 	}
609 
610 	if (frozen_str) {
611 		frozen = atoi(frozen_str);
612 		free(frozen_str);
613 	}
614 
615 	if (info->btf_id || frozen)
616 		printf("\n\t");
617 
618 	if (info->btf_id)
619 		printf("btf_id %u", info->btf_id);
620 
621 	if (frozen)
622 		printf("%sfrozen", info->btf_id ? "  " : "");
623 
624 	emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
625 
626 	printf("\n");
627 	return 0;
628 }
629 
630 static int do_show_subset(int argc, char **argv)
631 {
632 	struct bpf_map_info info = {};
633 	__u32 len = sizeof(info);
634 	int *fds = NULL;
635 	int nb_fds, i;
636 	int err = -1;
637 
638 	fds = malloc(sizeof(int));
639 	if (!fds) {
640 		p_err("mem alloc failed");
641 		return -1;
642 	}
643 	nb_fds = map_parse_fds(&argc, &argv, &fds, BPF_F_RDONLY);
644 	if (nb_fds < 1)
645 		goto exit_free;
646 
647 	if (json_output && nb_fds > 1)
648 		jsonw_start_array(json_wtr);	/* root array */
649 	for (i = 0; i < nb_fds; i++) {
650 		err = bpf_map_get_info_by_fd(fds[i], &info, &len);
651 		if (err) {
652 			p_err("can't get map info: %s",
653 			      strerror(errno));
654 			for (; i < nb_fds; i++)
655 				close(fds[i]);
656 			break;
657 		}
658 
659 		if (json_output)
660 			show_map_close_json(fds[i], &info);
661 		else
662 			show_map_close_plain(fds[i], &info);
663 	}
664 	if (json_output && nb_fds > 1)
665 		jsonw_end_array(json_wtr);	/* root array */
666 
667 exit_free:
668 	free(fds);
669 	return err;
670 }
671 
672 static int do_show(int argc, char **argv)
673 {
674 	LIBBPF_OPTS(bpf_get_fd_by_id_opts, opts);
675 	struct bpf_map_info info = {};
676 	__u32 len = sizeof(info);
677 	__u32 id = 0;
678 	int err;
679 	int fd;
680 
681 	opts.open_flags = BPF_F_RDONLY;
682 
683 	if (show_pinned) {
684 		map_table = hashmap__new(hash_fn_for_key_as_id,
685 					 equal_fn_for_key_as_id, NULL);
686 		if (IS_ERR(map_table)) {
687 			p_err("failed to create hashmap for pinned paths");
688 			return -1;
689 		}
690 		build_pinned_obj_table(map_table, BPF_OBJ_MAP);
691 	}
692 	build_obj_refs_table(&refs_table, BPF_OBJ_MAP);
693 
694 	if (argc == 2)
695 		return do_show_subset(argc, argv);
696 
697 	if (argc)
698 		return BAD_ARG();
699 
700 	if (json_output)
701 		jsonw_start_array(json_wtr);
702 	while (true) {
703 		err = bpf_map_get_next_id(id, &id);
704 		if (err) {
705 			if (errno == ENOENT)
706 				break;
707 			p_err("can't get next map: %s%s", strerror(errno),
708 			      errno == EINVAL ? " -- kernel too old?" : "");
709 			break;
710 		}
711 
712 		fd = bpf_map_get_fd_by_id_opts(id, &opts);
713 		if (fd < 0) {
714 			if (errno == ENOENT)
715 				continue;
716 			p_err("can't get map by id (%u): %s",
717 			      id, strerror(errno));
718 			break;
719 		}
720 
721 		err = bpf_map_get_info_by_fd(fd, &info, &len);
722 		if (err) {
723 			p_err("can't get map info: %s", strerror(errno));
724 			close(fd);
725 			break;
726 		}
727 
728 		if (json_output)
729 			show_map_close_json(fd, &info);
730 		else
731 			show_map_close_plain(fd, &info);
732 	}
733 	if (json_output)
734 		jsonw_end_array(json_wtr);
735 
736 	delete_obj_refs_table(refs_table);
737 
738 	if (show_pinned)
739 		delete_pinned_obj_table(map_table);
740 
741 	return errno == ENOENT ? 0 : -1;
742 }
743 
744 static int dump_map_elem(int fd, void *key, void *value,
745 			 struct bpf_map_info *map_info, struct btf *btf,
746 			 json_writer_t *btf_wtr, const int *cpu_ids, int cpu_cnt)
747 {
748 	if (bpf_map_lookup_elem(fd, key, value)) {
749 		print_entry_error(map_info, key, errno);
750 		return -1;
751 	}
752 
753 	if (json_output) {
754 		print_entry_json(map_info, key, value, btf, cpu_ids, cpu_cnt);
755 	} else if (btf) {
756 		struct btf_dumper d = {
757 			.btf = btf,
758 			.jw = btf_wtr,
759 			.is_plain_text = true,
760 		};
761 
762 		do_dump_btf(&d, map_info, key, value, cpu_ids, cpu_cnt);
763 	} else {
764 		print_entry_plain(map_info, key, value, cpu_ids, cpu_cnt);
765 	}
766 
767 	return 0;
768 }
769 
770 static int maps_have_btf(int *fds, int nb_fds)
771 {
772 	struct bpf_map_info info = {};
773 	__u32 len = sizeof(info);
774 	int err, i;
775 
776 	for (i = 0; i < nb_fds; i++) {
777 		err = bpf_map_get_info_by_fd(fds[i], &info, &len);
778 		if (err) {
779 			p_err("can't get map info: %s", strerror(errno));
780 			return -1;
781 		}
782 
783 		if (!info.btf_id)
784 			return 0;
785 	}
786 
787 	return 1;
788 }
789 
790 static struct btf *btf_vmlinux;
791 
792 static void free_btf_vmlinux(void)
793 {
794 	btf__free(btf_vmlinux);
795 	btf_vmlinux = NULL;
796 }
797 
798 static int get_map_kv_btf(const struct bpf_map_info *info, struct btf **btf)
799 {
800 	int err = 0;
801 
802 	if (info->btf_vmlinux_value_type_id) {
803 		if (!btf_vmlinux) {
804 			btf_vmlinux = libbpf_find_kernel_btf();
805 			if (!btf_vmlinux) {
806 				p_err("failed to get kernel btf");
807 				return -errno;
808 			}
809 		}
810 		*btf = btf_vmlinux;
811 	} else if (info->btf_value_type_id) {
812 		*btf = btf__load_from_kernel_by_id(info->btf_id);
813 		if (!*btf) {
814 			err = -errno;
815 			p_err("failed to get btf");
816 		}
817 	} else {
818 		*btf = NULL;
819 	}
820 
821 	return err;
822 }
823 
824 static void free_map_kv_btf(struct btf *btf)
825 {
826 	if (btf != btf_vmlinux)
827 		btf__free(btf);
828 }
829 
830 static int
831 map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr,
832 	 bool show_header)
833 {
834 	void *key, *value, *prev_key;
835 	unsigned int num_elems = 0;
836 	struct btf *btf = NULL;
837 	int *cpu_ids = NULL;
838 	int cpu_cnt = 0;
839 	int err;
840 
841 	key = malloc(info->key_size);
842 	value = alloc_value(info);
843 	if (!key || !value) {
844 		p_err("mem alloc failed");
845 		err = -1;
846 		goto exit_free;
847 	}
848 
849 	prev_key = NULL;
850 
851 	if (map_is_per_cpu(info->type)) {
852 		cpu_cnt = get_possible_cpu_ids(&cpu_ids);
853 		if (cpu_cnt < 0) {
854 			err = cpu_cnt;
855 			goto exit_free;
856 		}
857 	}
858 
859 	/* Fail early to avoid an empty dump if map type cannot be iterated */
860 	if (bpf_map_get_next_key(fd, NULL, key) && errno != ENOENT) {
861 		const char *map_type_str, *err_str;
862 
863 		err_str = bpf_strerror(errno);
864 		map_type_str = libbpf_bpf_map_type_str(info->type);
865 		if (map_type_str)
866 			p_err("can't dump %s map: %s", map_type_str, err_str);
867 		else
868 			p_err("can't dump map of type %u: %s", info->type,
869 			      err_str);
870 		err = -1;
871 		goto exit_free;
872 	}
873 
874 	if (wtr) {
875 		err = get_map_kv_btf(info, &btf);
876 		if (err) {
877 			goto exit_free;
878 		}
879 
880 		if (show_header) {
881 			jsonw_start_object(wtr);	/* map object */
882 			show_map_header_json(info, wtr);
883 			jsonw_name(wtr, "elements");
884 		}
885 		jsonw_start_array(wtr);		/* elements */
886 	} else if (show_header) {
887 		show_map_header_plain(info);
888 	}
889 
890 	if (info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY &&
891 	    info->value_size != 8) {
892 		const char *map_type_str;
893 
894 		map_type_str = libbpf_bpf_map_type_str(info->type);
895 		p_info("Warning: cannot read values from %s map with value_size != 8",
896 		       map_type_str);
897 	}
898 	while (true) {
899 		err = bpf_map_get_next_key(fd, prev_key, key);
900 		if (err) {
901 			if (errno == ENOENT) {
902 				err = 0;
903 				break;
904 			}
905 			p_err("can't get next key: %s", bpf_strerror(errno));
906 			break;
907 		}
908 		if (!dump_map_elem(fd, key, value, info, btf, wtr,
909 				   cpu_ids, cpu_cnt))
910 			num_elems++;
911 		prev_key = key;
912 	}
913 
914 	if (wtr) {
915 		jsonw_end_array(wtr);	/* elements */
916 		if (show_header)
917 			jsonw_end_object(wtr);	/* map object */
918 	} else if (!err) {
919 		printf("Found %u element%s\n", num_elems,
920 		       num_elems != 1 ? "s" : "");
921 	}
922 
923 exit_free:
924 	free(key);
925 	free(value);
926 	free(cpu_ids);
927 	free_map_kv_btf(btf);
928 
929 	return err;
930 }
931 
932 static int do_dump(int argc, char **argv)
933 {
934 	json_writer_t *wtr = NULL, *btf_wtr = NULL;
935 	struct bpf_map_info info = {};
936 	int nb_fds, i = 0;
937 	__u32 len = sizeof(info);
938 	int *fds = NULL;
939 	int err = -1;
940 
941 	if (argc != 2)
942 		usage();
943 
944 	fds = malloc(sizeof(int));
945 	if (!fds) {
946 		p_err("mem alloc failed");
947 		return -1;
948 	}
949 	nb_fds = map_parse_fds(&argc, &argv, &fds, BPF_F_RDONLY);
950 	if (nb_fds < 1)
951 		goto exit_free;
952 
953 	if (json_output) {
954 		wtr = json_wtr;
955 	} else {
956 		int do_plain_btf;
957 
958 		do_plain_btf = maps_have_btf(fds, nb_fds);
959 		if (do_plain_btf < 0)
960 			goto exit_close;
961 
962 		if (do_plain_btf) {
963 			btf_wtr = get_btf_writer();
964 			wtr = btf_wtr;
965 			if (!btf_wtr)
966 				p_info("failed to create json writer for btf. falling back to plain output");
967 		}
968 	}
969 
970 	if (wtr && nb_fds > 1)
971 		jsonw_start_array(wtr);	/* root array */
972 	for (i = 0; i < nb_fds; i++) {
973 		if (bpf_map_get_info_by_fd(fds[i], &info, &len)) {
974 			p_err("can't get map info: %s", strerror(errno));
975 			err = -1;
976 			break;
977 		}
978 		err = map_dump(fds[i], &info, wtr, nb_fds > 1);
979 		if (!wtr && i != nb_fds - 1)
980 			printf("\n");
981 
982 		if (err)
983 			break;
984 		close(fds[i]);
985 	}
986 	if (wtr && nb_fds > 1)
987 		jsonw_end_array(wtr);	/* root array */
988 
989 	if (btf_wtr)
990 		jsonw_destroy(&btf_wtr);
991 exit_close:
992 	for (; i < nb_fds; i++)
993 		close(fds[i]);
994 exit_free:
995 	free(fds);
996 	free_btf_vmlinux();
997 	return err;
998 }
999 
1000 static int alloc_key_value(struct bpf_map_info *info, void **key, void **value)
1001 {
1002 	*key = NULL;
1003 	*value = NULL;
1004 
1005 	if (info->key_size) {
1006 		*key = malloc(info->key_size);
1007 		if (!*key) {
1008 			p_err("key mem alloc failed");
1009 			return -1;
1010 		}
1011 	}
1012 
1013 	if (info->value_size) {
1014 		*value = alloc_value(info);
1015 		if (!*value) {
1016 			p_err("value mem alloc failed");
1017 			free(*key);
1018 			*key = NULL;
1019 			return -1;
1020 		}
1021 	}
1022 
1023 	return 0;
1024 }
1025 
1026 static int do_update(int argc, char **argv)
1027 {
1028 	struct bpf_map_info info = {};
1029 	__u32 len = sizeof(info);
1030 	__u32 *value_fd = NULL;
1031 	__u32 flags = BPF_ANY;
1032 	void *key, *value;
1033 	int fd, err;
1034 
1035 	if (argc < 2)
1036 		usage();
1037 
1038 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, 0);
1039 	if (fd < 0)
1040 		return -1;
1041 
1042 	err = alloc_key_value(&info, &key, &value);
1043 	if (err)
1044 		goto exit_free;
1045 
1046 	err = parse_elem(argv, &info, key, value, info.key_size,
1047 			 info.value_size, &flags, &value_fd, 0);
1048 	if (err)
1049 		goto exit_free;
1050 
1051 	err = bpf_map_update_elem(fd, key, value, flags);
1052 	if (err) {
1053 		p_err("update failed: %s", bpf_strerror(errno));
1054 		goto exit_free;
1055 	}
1056 
1057 exit_free:
1058 	if (value_fd)
1059 		close(*value_fd);
1060 	free(key);
1061 	free(value);
1062 	close(fd);
1063 
1064 	if (!err && json_output)
1065 		jsonw_null(json_wtr);
1066 	return err;
1067 }
1068 
1069 static int print_key_value(struct bpf_map_info *info, void *key,
1070 			   void *value)
1071 {
1072 	json_writer_t *btf_wtr;
1073 	struct btf *btf;
1074 	int *cpu_ids = NULL;
1075 	int cpu_cnt = 0;
1076 	int err = 0;
1077 
1078 	if (map_is_per_cpu(info->type)) {
1079 		cpu_cnt = get_possible_cpu_ids(&cpu_ids);
1080 
1081 		if (cpu_cnt < 0) {
1082 			err = cpu_cnt;
1083 			goto out;
1084 		}
1085 	}
1086 
1087 	err = get_map_kv_btf(info, &btf);
1088 	if (err)
1089 		goto out;
1090 
1091 	if (json_output) {
1092 		print_entry_json(info, key, value, btf, cpu_ids, cpu_cnt);
1093 	} else if (btf) {
1094 		/* if here json_wtr wouldn't have been initialised,
1095 		 * so let's create separate writer for btf
1096 		 */
1097 		btf_wtr = get_btf_writer();
1098 		if (!btf_wtr) {
1099 			p_info("failed to create json writer for btf. falling back to plain output");
1100 			free_map_kv_btf(btf);
1101 			btf = NULL;
1102 			print_entry_plain(info, key, value, cpu_ids, cpu_cnt);
1103 		} else {
1104 			struct btf_dumper d = {
1105 				.btf = btf,
1106 				.jw = btf_wtr,
1107 				.is_plain_text = true,
1108 			};
1109 
1110 			do_dump_btf(&d, info, key, value, cpu_ids, cpu_cnt);
1111 			jsonw_destroy(&btf_wtr);
1112 		}
1113 	} else {
1114 		print_entry_plain(info, key, value, cpu_ids, cpu_cnt);
1115 	}
1116 	free_map_kv_btf(btf);
1117 out:
1118 	free(cpu_ids);
1119 	return err;
1120 }
1121 
1122 static int do_lookup(int argc, char **argv)
1123 {
1124 	struct bpf_map_info info = {};
1125 	__u32 len = sizeof(info);
1126 	void *key, *value;
1127 	int err;
1128 	int fd;
1129 
1130 	if (argc < 2)
1131 		usage();
1132 
1133 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, BPF_F_RDONLY);
1134 	if (fd < 0)
1135 		return -1;
1136 
1137 	err = alloc_key_value(&info, &key, &value);
1138 	if (err)
1139 		goto exit_free;
1140 
1141 	err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL,
1142 			 BPF_F_RDONLY);
1143 	if (err)
1144 		goto exit_free;
1145 
1146 	err = bpf_map_lookup_elem(fd, key, value);
1147 	if (err) {
1148 		if (errno == ENOENT) {
1149 			if (json_output) {
1150 				jsonw_null(json_wtr);
1151 			} else {
1152 				printf("key:\n");
1153 				fprint_hex(stdout, key, info.key_size, " ");
1154 				printf("\n\nNot found\n");
1155 			}
1156 		} else {
1157 			p_err("lookup failed: %s", bpf_strerror(errno));
1158 		}
1159 
1160 		goto exit_free;
1161 	}
1162 
1163 	/* here means bpf_map_lookup_elem() succeeded */
1164 	err = print_key_value(&info, key, value);
1165 
1166 exit_free:
1167 	free(key);
1168 	free(value);
1169 	close(fd);
1170 
1171 	return err;
1172 }
1173 
1174 static int do_getnext(int argc, char **argv)
1175 {
1176 	struct bpf_map_info info = {};
1177 	__u32 len = sizeof(info);
1178 	void *key, *nextkey;
1179 	int err;
1180 	int fd;
1181 
1182 	if (argc < 2)
1183 		usage();
1184 
1185 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, BPF_F_RDONLY);
1186 	if (fd < 0)
1187 		return -1;
1188 
1189 	key = malloc(info.key_size);
1190 	nextkey = malloc(info.key_size);
1191 	if (!key || !nextkey) {
1192 		p_err("mem alloc failed");
1193 		err = -1;
1194 		goto exit_free;
1195 	}
1196 
1197 	if (argc) {
1198 		err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL,
1199 				 NULL, BPF_F_RDONLY);
1200 		if (err)
1201 			goto exit_free;
1202 	} else {
1203 		free(key);
1204 		key = NULL;
1205 	}
1206 
1207 	err = bpf_map_get_next_key(fd, key, nextkey);
1208 	if (err) {
1209 		p_err("can't get next key: %s", bpf_strerror(errno));
1210 		goto exit_free;
1211 	}
1212 
1213 	if (json_output) {
1214 		jsonw_start_object(json_wtr);
1215 		if (key) {
1216 			jsonw_name(json_wtr, "key");
1217 			print_hex_data_json(key, info.key_size);
1218 		} else {
1219 			jsonw_null_field(json_wtr, "key");
1220 		}
1221 		jsonw_name(json_wtr, "next_key");
1222 		print_hex_data_json(nextkey, info.key_size);
1223 		jsonw_end_object(json_wtr);
1224 	} else {
1225 		if (key) {
1226 			printf("key:\n");
1227 			fprint_hex(stdout, key, info.key_size, " ");
1228 			printf("\n");
1229 		} else {
1230 			printf("key: None\n");
1231 		}
1232 		printf("next key:\n");
1233 		fprint_hex(stdout, nextkey, info.key_size, " ");
1234 		printf("\n");
1235 	}
1236 
1237 exit_free:
1238 	free(nextkey);
1239 	free(key);
1240 	close(fd);
1241 
1242 	return err;
1243 }
1244 
1245 static int do_delete(int argc, char **argv)
1246 {
1247 	struct bpf_map_info info = {};
1248 	__u32 len = sizeof(info);
1249 	void *key;
1250 	int err;
1251 	int fd;
1252 
1253 	if (argc < 2)
1254 		usage();
1255 
1256 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, 0);
1257 	if (fd < 0)
1258 		return -1;
1259 
1260 	key = malloc(info.key_size);
1261 	if (!key) {
1262 		p_err("mem alloc failed");
1263 		err = -1;
1264 		goto exit_free;
1265 	}
1266 
1267 	err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL,
1268 			 0);
1269 	if (err)
1270 		goto exit_free;
1271 
1272 	err = bpf_map_delete_elem(fd, key);
1273 	if (err)
1274 		p_err("delete failed: %s", bpf_strerror(errno));
1275 
1276 exit_free:
1277 	free(key);
1278 	close(fd);
1279 
1280 	if (!err && json_output)
1281 		jsonw_null(json_wtr);
1282 	return err;
1283 }
1284 
1285 static int map_parse_read_only_fd(int *argc, char ***argv)
1286 {
1287 	return map_parse_fd(argc, argv, BPF_F_RDONLY);
1288 }
1289 
1290 static int do_pin(int argc, char **argv)
1291 {
1292 	int err;
1293 
1294 	err = do_pin_any(argc, argv, map_parse_read_only_fd);
1295 	if (!err && json_output)
1296 		jsonw_null(json_wtr);
1297 	return err;
1298 }
1299 
1300 static int do_create(int argc, char **argv)
1301 {
1302 	LIBBPF_OPTS(bpf_map_create_opts, attr);
1303 	enum bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
1304 	__u32 key_size = 0, value_size = 0, max_entries = 0;
1305 	const char *map_name = NULL;
1306 	const char *pinfile;
1307 	int err = -1, fd;
1308 
1309 	if (!REQ_ARGS(7))
1310 		return -1;
1311 	pinfile = GET_ARG();
1312 
1313 	while (argc) {
1314 		if (!REQ_ARGS(2))
1315 			return -1;
1316 
1317 		if (is_prefix(*argv, "type")) {
1318 			NEXT_ARG();
1319 
1320 			if (map_type) {
1321 				p_err("map type already specified");
1322 				goto exit;
1323 			}
1324 
1325 			map_type = map_type_from_str(*argv);
1326 			if ((int)map_type < 0) {
1327 				p_err("unrecognized map type: %s", *argv);
1328 				goto exit;
1329 			}
1330 			NEXT_ARG();
1331 		} else if (is_prefix(*argv, "name")) {
1332 			NEXT_ARG();
1333 			map_name = GET_ARG();
1334 			if (strlen(map_name) > BPF_OBJ_NAME_LEN - 1) {
1335 				p_info("Warning: map name is longer than %u characters, it will be truncated.",
1336 				      BPF_OBJ_NAME_LEN - 1);
1337 			}
1338 		} else if (is_prefix(*argv, "key")) {
1339 			if (parse_u32_arg(&argc, &argv, &key_size,
1340 					  "key size"))
1341 				goto exit;
1342 		} else if (is_prefix(*argv, "value")) {
1343 			if (parse_u32_arg(&argc, &argv, &value_size,
1344 					  "value size"))
1345 				goto exit;
1346 		} else if (is_prefix(*argv, "entries")) {
1347 			if (parse_u32_arg(&argc, &argv, &max_entries,
1348 					  "max entries"))
1349 				goto exit;
1350 		} else if (is_prefix(*argv, "flags")) {
1351 			if (parse_u32_arg(&argc, &argv, &attr.map_flags,
1352 					  "flags"))
1353 				goto exit;
1354 		} else if (is_prefix(*argv, "dev")) {
1355 			p_info("Warning: 'bpftool map create [...] dev <ifname>' syntax is deprecated.\n"
1356 			       "Going further, please use 'offload_dev <ifname>' to request hardware offload for the map.");
1357 			goto offload_dev;
1358 		} else if (is_prefix(*argv, "offload_dev")) {
1359 offload_dev:
1360 			NEXT_ARG();
1361 
1362 			if (attr.map_ifindex) {
1363 				p_err("offload device already specified");
1364 				goto exit;
1365 			}
1366 
1367 			attr.map_ifindex = if_nametoindex(*argv);
1368 			if (!attr.map_ifindex) {
1369 				p_err("unrecognized netdevice '%s': %s",
1370 				      *argv, strerror(errno));
1371 				goto exit;
1372 			}
1373 			NEXT_ARG();
1374 		} else if (is_prefix(*argv, "inner_map")) {
1375 			struct bpf_map_info info = {};
1376 			__u32 len = sizeof(info);
1377 			int inner_map_fd;
1378 
1379 			NEXT_ARG();
1380 			if (!REQ_ARGS(2))
1381 				usage();
1382 			inner_map_fd = map_parse_fd_and_info(&argc, &argv,
1383 							     &info, &len, BPF_F_RDONLY);
1384 			if (inner_map_fd < 0)
1385 				return -1;
1386 			attr.inner_map_fd = inner_map_fd;
1387 		} else {
1388 			p_err("unknown arg %s", *argv);
1389 			goto exit;
1390 		}
1391 	}
1392 
1393 	if (!map_name) {
1394 		p_err("map name not specified");
1395 		goto exit;
1396 	}
1397 
1398 	set_max_rlimit();
1399 
1400 	fd = bpf_map_create(map_type, map_name, key_size, value_size, max_entries, &attr);
1401 	if (fd < 0) {
1402 		p_err("map create failed: %s", bpf_strerror(errno));
1403 		goto exit;
1404 	}
1405 
1406 	err = do_pin_fd(fd, pinfile);
1407 	close(fd);
1408 	if (err)
1409 		goto exit;
1410 
1411 	if (json_output)
1412 		jsonw_null(json_wtr);
1413 
1414 exit:
1415 	if (attr.inner_map_fd > 0)
1416 		close(attr.inner_map_fd);
1417 
1418 	return err;
1419 }
1420 
1421 static int do_pop_dequeue(int argc, char **argv)
1422 {
1423 	struct bpf_map_info info = {};
1424 	__u32 len = sizeof(info);
1425 	void *key, *value;
1426 	int err;
1427 	int fd;
1428 
1429 	if (argc < 2)
1430 		usage();
1431 
1432 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len, 0);
1433 	if (fd < 0)
1434 		return -1;
1435 
1436 	err = alloc_key_value(&info, &key, &value);
1437 	if (err)
1438 		goto exit_free;
1439 
1440 	err = bpf_map_lookup_and_delete_elem(fd, key, value);
1441 	if (err) {
1442 		if (errno == ENOENT) {
1443 			if (json_output)
1444 				jsonw_null(json_wtr);
1445 			else
1446 				printf("Error: empty map\n");
1447 		} else {
1448 			p_err("pop failed: %s", bpf_strerror(errno));
1449 		}
1450 
1451 		goto exit_free;
1452 	}
1453 
1454 	err = print_key_value(&info, key, value);
1455 
1456 exit_free:
1457 	free(key);
1458 	free(value);
1459 	close(fd);
1460 
1461 	return err;
1462 }
1463 
1464 static int do_freeze(int argc, char **argv)
1465 {
1466 	int err, fd;
1467 
1468 	if (!REQ_ARGS(2))
1469 		return -1;
1470 
1471 	fd = map_parse_fd(&argc, &argv, 0);
1472 	if (fd < 0)
1473 		return -1;
1474 
1475 	if (argc) {
1476 		close(fd);
1477 		return BAD_ARG();
1478 	}
1479 
1480 	err = bpf_map_freeze(fd);
1481 	close(fd);
1482 	if (err) {
1483 		p_err("failed to freeze map: %s", bpf_strerror(errno));
1484 		return err;
1485 	}
1486 
1487 	if (json_output)
1488 		jsonw_null(json_wtr);
1489 
1490 	return 0;
1491 }
1492 
1493 static int do_help(int argc, char **argv)
1494 {
1495 	if (json_output) {
1496 		jsonw_null(json_wtr);
1497 		return 0;
1498 	}
1499 
1500 	fprintf(stderr,
1501 		"Usage: %1$s %2$s { show | list }   [MAP]\n"
1502 		"       %1$s %2$s create     FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n"
1503 		"                                  entries MAX_ENTRIES name NAME [flags FLAGS] \\\n"
1504 		"                                  [inner_map MAP] [offload_dev NAME]\n"
1505 		"       %1$s %2$s dump       MAP\n"
1506 		"       %1$s %2$s update     MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n"
1507 		"       %1$s %2$s lookup     MAP [key DATA]\n"
1508 		"       %1$s %2$s getnext    MAP [key DATA]\n"
1509 		"       %1$s %2$s delete     MAP  key DATA\n"
1510 		"       %1$s %2$s pin        MAP  FILE\n"
1511 		"       %1$s %2$s event_pipe MAP [cpu N index M]\n"
1512 		"       %1$s %2$s peek       MAP\n"
1513 		"       %1$s %2$s push       MAP value VALUE\n"
1514 		"       %1$s %2$s pop        MAP\n"
1515 		"       %1$s %2$s enqueue    MAP value VALUE\n"
1516 		"       %1$s %2$s dequeue    MAP\n"
1517 		"       %1$s %2$s freeze     MAP\n"
1518 		"       %1$s %2$s help\n"
1519 		"\n"
1520 		"       " HELP_SPEC_MAP "\n"
1521 		"       DATA := { [hex] BYTES }\n"
1522 		"       " HELP_SPEC_PROGRAM "\n"
1523 		"       VALUE := { DATA | MAP | PROG }\n"
1524 		"       UPDATE_FLAGS := { any | exist | noexist }\n"
1525 		"       TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n"
1526 		"                 percpu_array | stack_trace | cgroup_array | lru_hash |\n"
1527 		"                 lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
1528 		"                 devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n"
1529 		"                 cgroup_storage | reuseport_sockarray | percpu_cgroup_storage |\n"
1530 		"                 queue | stack | sk_storage | struct_ops | ringbuf | inode_storage |\n"
1531 		"                 task_storage | bloom_filter | user_ringbuf | cgrp_storage | arena |\n"
1532 		"                 insn_array | rhash }\n"
1533 		"       " HELP_SPEC_OPTIONS " |\n"
1534 		"                    {-f|--bpffs} | {-n|--nomount} }\n"
1535 		"",
1536 		bin_name, argv[-2]);
1537 
1538 	return 0;
1539 }
1540 
1541 static const struct cmd cmds[] = {
1542 	{ "show",	do_show },
1543 	{ "list",	do_show },
1544 	{ "help",	do_help },
1545 	{ "dump",	do_dump },
1546 	{ "update",	do_update },
1547 	{ "lookup",	do_lookup },
1548 	{ "getnext",	do_getnext },
1549 	{ "delete",	do_delete },
1550 	{ "pin",	do_pin },
1551 	{ "event_pipe",	do_event_pipe },
1552 	{ "create",	do_create },
1553 	{ "peek",	do_lookup },
1554 	{ "push",	do_update },
1555 	{ "enqueue",	do_update },
1556 	{ "pop",	do_pop_dequeue },
1557 	{ "dequeue",	do_pop_dequeue },
1558 	{ "freeze",	do_freeze },
1559 	{ 0 }
1560 };
1561 
1562 int do_map(int argc, char **argv)
1563 {
1564 	return cmd_select(cmds, argc, argv, do_help);
1565 }
1566