xref: /linux/tools/bpf/bpftool/map.c (revision 036b9e7caeb09598afb297a6d4fb36b477a4f6b2)
1 /*
2  * Copyright (C) 2017-2018 Netronome Systems, Inc.
3  *
4  * This software is dual licensed under the GNU General License Version 2,
5  * June 1991 as shown in the file COPYING in the top-level directory of this
6  * source tree or the BSD 2-Clause License provided below.  You have the
7  * option to license this software under the complete terms of either license.
8  *
9  * The BSD 2-Clause License:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      1. Redistributions of source code must retain the above
16  *         copyright notice, this list of conditions and the following
17  *         disclaimer.
18  *
19  *      2. Redistributions in binary form must reproduce the above
20  *         copyright notice, this list of conditions and the following
21  *         disclaimer in the documentation and/or other materials
22  *         provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33 
34 #include <assert.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <linux/err.h>
38 #include <linux/kernel.h>
39 #include <net/if.h>
40 #include <stdbool.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 
48 #include <bpf.h>
49 
50 #include "btf.h"
51 #include "json_writer.h"
52 #include "main.h"
53 
54 static const char * const map_type_name[] = {
55 	[BPF_MAP_TYPE_UNSPEC]			= "unspec",
56 	[BPF_MAP_TYPE_HASH]			= "hash",
57 	[BPF_MAP_TYPE_ARRAY]			= "array",
58 	[BPF_MAP_TYPE_PROG_ARRAY]		= "prog_array",
59 	[BPF_MAP_TYPE_PERF_EVENT_ARRAY]		= "perf_event_array",
60 	[BPF_MAP_TYPE_PERCPU_HASH]		= "percpu_hash",
61 	[BPF_MAP_TYPE_PERCPU_ARRAY]		= "percpu_array",
62 	[BPF_MAP_TYPE_STACK_TRACE]		= "stack_trace",
63 	[BPF_MAP_TYPE_CGROUP_ARRAY]		= "cgroup_array",
64 	[BPF_MAP_TYPE_LRU_HASH]			= "lru_hash",
65 	[BPF_MAP_TYPE_LRU_PERCPU_HASH]		= "lru_percpu_hash",
66 	[BPF_MAP_TYPE_LPM_TRIE]			= "lpm_trie",
67 	[BPF_MAP_TYPE_ARRAY_OF_MAPS]		= "array_of_maps",
68 	[BPF_MAP_TYPE_HASH_OF_MAPS]		= "hash_of_maps",
69 	[BPF_MAP_TYPE_DEVMAP]			= "devmap",
70 	[BPF_MAP_TYPE_SOCKMAP]			= "sockmap",
71 	[BPF_MAP_TYPE_CPUMAP]			= "cpumap",
72 	[BPF_MAP_TYPE_XSKMAP]			= "xskmap",
73 	[BPF_MAP_TYPE_SOCKHASH]			= "sockhash",
74 	[BPF_MAP_TYPE_CGROUP_STORAGE]		= "cgroup_storage",
75 	[BPF_MAP_TYPE_REUSEPORT_SOCKARRAY]	= "reuseport_sockarray",
76 	[BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE]	= "percpu_cgroup_storage",
77 	[BPF_MAP_TYPE_QUEUE]			= "queue",
78 	[BPF_MAP_TYPE_STACK]			= "stack",
79 };
80 
81 static bool map_is_per_cpu(__u32 type)
82 {
83 	return type == BPF_MAP_TYPE_PERCPU_HASH ||
84 	       type == BPF_MAP_TYPE_PERCPU_ARRAY ||
85 	       type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
86 	       type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
87 }
88 
89 static bool map_is_map_of_maps(__u32 type)
90 {
91 	return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
92 	       type == BPF_MAP_TYPE_HASH_OF_MAPS;
93 }
94 
95 static bool map_is_map_of_progs(__u32 type)
96 {
97 	return type == BPF_MAP_TYPE_PROG_ARRAY;
98 }
99 
100 static int map_type_from_str(const char *type)
101 {
102 	unsigned int i;
103 
104 	for (i = 0; i < ARRAY_SIZE(map_type_name); i++)
105 		/* Don't allow prefixing in case of possible future shadowing */
106 		if (map_type_name[i] && !strcmp(map_type_name[i], type))
107 			return i;
108 	return -1;
109 }
110 
111 static void *alloc_value(struct bpf_map_info *info)
112 {
113 	if (map_is_per_cpu(info->type))
114 		return malloc(round_up(info->value_size, 8) *
115 			      get_possible_cpus());
116 	else
117 		return malloc(info->value_size);
118 }
119 
120 int map_parse_fd(int *argc, char ***argv)
121 {
122 	int fd;
123 
124 	if (is_prefix(**argv, "id")) {
125 		unsigned int id;
126 		char *endptr;
127 
128 		NEXT_ARGP();
129 
130 		id = strtoul(**argv, &endptr, 0);
131 		if (*endptr) {
132 			p_err("can't parse %s as ID", **argv);
133 			return -1;
134 		}
135 		NEXT_ARGP();
136 
137 		fd = bpf_map_get_fd_by_id(id);
138 		if (fd < 0)
139 			p_err("get map by id (%u): %s", id, strerror(errno));
140 		return fd;
141 	} else if (is_prefix(**argv, "pinned")) {
142 		char *path;
143 
144 		NEXT_ARGP();
145 
146 		path = **argv;
147 		NEXT_ARGP();
148 
149 		return open_obj_pinned_any(path, BPF_OBJ_MAP);
150 	}
151 
152 	p_err("expected 'id' or 'pinned', got: '%s'?", **argv);
153 	return -1;
154 }
155 
156 int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
157 {
158 	int err;
159 	int fd;
160 
161 	fd = map_parse_fd(argc, argv);
162 	if (fd < 0)
163 		return -1;
164 
165 	err = bpf_obj_get_info_by_fd(fd, info, info_len);
166 	if (err) {
167 		p_err("can't get map info: %s", strerror(errno));
168 		close(fd);
169 		return err;
170 	}
171 
172 	return fd;
173 }
174 
175 static int do_dump_btf(const struct btf_dumper *d,
176 		       struct bpf_map_info *map_info, void *key,
177 		       void *value)
178 {
179 	int ret;
180 
181 	/* start of key-value pair */
182 	jsonw_start_object(d->jw);
183 
184 	jsonw_name(d->jw, "key");
185 
186 	ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
187 	if (ret)
188 		goto err_end_obj;
189 
190 	if (!map_is_per_cpu(map_info->type)) {
191 		jsonw_name(d->jw, "value");
192 		ret = btf_dumper_type(d, map_info->btf_value_type_id, value);
193 	} else {
194 		unsigned int i, n, step;
195 
196 		jsonw_name(d->jw, "values");
197 		jsonw_start_array(d->jw);
198 		n = get_possible_cpus();
199 		step = round_up(map_info->value_size, 8);
200 		for (i = 0; i < n; i++) {
201 			jsonw_start_object(d->jw);
202 			jsonw_int_field(d->jw, "cpu", i);
203 			jsonw_name(d->jw, "value");
204 			ret = btf_dumper_type(d, map_info->btf_value_type_id,
205 					      value + i * step);
206 			jsonw_end_object(d->jw);
207 			if (ret)
208 				break;
209 		}
210 		jsonw_end_array(d->jw);
211 	}
212 
213 err_end_obj:
214 	/* end of key-value pair */
215 	jsonw_end_object(d->jw);
216 
217 	return ret;
218 }
219 
220 static json_writer_t *get_btf_writer(void)
221 {
222 	json_writer_t *jw = jsonw_new(stdout);
223 
224 	if (!jw)
225 		return NULL;
226 	jsonw_pretty(jw, true);
227 
228 	return jw;
229 }
230 
231 static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
232 			     unsigned char *value, struct btf *btf)
233 {
234 	jsonw_start_object(json_wtr);
235 
236 	if (!map_is_per_cpu(info->type)) {
237 		jsonw_name(json_wtr, "key");
238 		print_hex_data_json(key, info->key_size);
239 		jsonw_name(json_wtr, "value");
240 		print_hex_data_json(value, info->value_size);
241 		if (btf) {
242 			struct btf_dumper d = {
243 				.btf = btf,
244 				.jw = json_wtr,
245 				.is_plain_text = false,
246 			};
247 
248 			jsonw_name(json_wtr, "formatted");
249 			do_dump_btf(&d, info, key, value);
250 		}
251 	} else {
252 		unsigned int i, n, step;
253 
254 		n = get_possible_cpus();
255 		step = round_up(info->value_size, 8);
256 
257 		jsonw_name(json_wtr, "key");
258 		print_hex_data_json(key, info->key_size);
259 
260 		jsonw_name(json_wtr, "values");
261 		jsonw_start_array(json_wtr);
262 		for (i = 0; i < n; i++) {
263 			jsonw_start_object(json_wtr);
264 
265 			jsonw_int_field(json_wtr, "cpu", i);
266 
267 			jsonw_name(json_wtr, "value");
268 			print_hex_data_json(value + i * step,
269 					    info->value_size);
270 
271 			jsonw_end_object(json_wtr);
272 		}
273 		jsonw_end_array(json_wtr);
274 		if (btf) {
275 			struct btf_dumper d = {
276 				.btf = btf,
277 				.jw = json_wtr,
278 				.is_plain_text = false,
279 			};
280 
281 			jsonw_name(json_wtr, "formatted");
282 			do_dump_btf(&d, info, key, value);
283 		}
284 	}
285 
286 	jsonw_end_object(json_wtr);
287 }
288 
289 static void print_entry_error(struct bpf_map_info *info, unsigned char *key,
290 			      const char *value)
291 {
292 	int value_size = strlen(value);
293 	bool single_line, break_names;
294 
295 	break_names = info->key_size > 16 || value_size > 16;
296 	single_line = info->key_size + value_size <= 24 && !break_names;
297 
298 	printf("key:%c", break_names ? '\n' : ' ');
299 	fprint_hex(stdout, key, info->key_size, " ");
300 
301 	printf(single_line ? "  " : "\n");
302 
303 	printf("value:%c%s", break_names ? '\n' : ' ', value);
304 
305 	printf("\n");
306 }
307 
308 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
309 			      unsigned char *value)
310 {
311 	if (!map_is_per_cpu(info->type)) {
312 		bool single_line, break_names;
313 
314 		break_names = info->key_size > 16 || info->value_size > 16;
315 		single_line = info->key_size + info->value_size <= 24 &&
316 			!break_names;
317 
318 		printf("key:%c", break_names ? '\n' : ' ');
319 		fprint_hex(stdout, key, info->key_size, " ");
320 
321 		printf(single_line ? "  " : "\n");
322 
323 		printf("value:%c", break_names ? '\n' : ' ');
324 		if (value)
325 			fprint_hex(stdout, value, info->value_size, " ");
326 		else
327 			printf("<no entry>");
328 
329 		printf("\n");
330 	} else {
331 		unsigned int i, n, step;
332 
333 		n = get_possible_cpus();
334 		step = round_up(info->value_size, 8);
335 
336 		printf("key:\n");
337 		fprint_hex(stdout, key, info->key_size, " ");
338 		printf("\n");
339 		for (i = 0; i < n; i++) {
340 			printf("value (CPU %02d):%c",
341 			       i, info->value_size > 16 ? '\n' : ' ');
342 			if (value)
343 				fprint_hex(stdout, value + i * step,
344 					   info->value_size, " ");
345 			else
346 				printf("<no entry>");
347 			printf("\n");
348 		}
349 	}
350 }
351 
352 static char **parse_bytes(char **argv, const char *name, unsigned char *val,
353 			  unsigned int n)
354 {
355 	unsigned int i = 0, base = 0;
356 	char *endptr;
357 
358 	if (is_prefix(*argv, "hex")) {
359 		base = 16;
360 		argv++;
361 	}
362 
363 	while (i < n && argv[i]) {
364 		val[i] = strtoul(argv[i], &endptr, base);
365 		if (*endptr) {
366 			p_err("error parsing byte: %s", argv[i]);
367 			return NULL;
368 		}
369 		i++;
370 	}
371 
372 	if (i != n) {
373 		p_err("%s expected %d bytes got %d", name, n, i);
374 		return NULL;
375 	}
376 
377 	return argv + i;
378 }
379 
380 static int parse_elem(char **argv, struct bpf_map_info *info,
381 		      void *key, void *value, __u32 key_size, __u32 value_size,
382 		      __u32 *flags, __u32 **value_fd)
383 {
384 	if (!*argv) {
385 		if (!key && !value)
386 			return 0;
387 		p_err("did not find %s", key ? "key" : "value");
388 		return -1;
389 	}
390 
391 	if (is_prefix(*argv, "key")) {
392 		if (!key) {
393 			if (key_size)
394 				p_err("duplicate key");
395 			else
396 				p_err("unnecessary key");
397 			return -1;
398 		}
399 
400 		argv = parse_bytes(argv + 1, "key", key, key_size);
401 		if (!argv)
402 			return -1;
403 
404 		return parse_elem(argv, info, NULL, value, key_size, value_size,
405 				  flags, value_fd);
406 	} else if (is_prefix(*argv, "value")) {
407 		int fd;
408 
409 		if (!value) {
410 			if (value_size)
411 				p_err("duplicate value");
412 			else
413 				p_err("unnecessary value");
414 			return -1;
415 		}
416 
417 		argv++;
418 
419 		if (map_is_map_of_maps(info->type)) {
420 			int argc = 2;
421 
422 			if (value_size != 4) {
423 				p_err("value smaller than 4B for map in map?");
424 				return -1;
425 			}
426 			if (!argv[0] || !argv[1]) {
427 				p_err("not enough value arguments for map in map");
428 				return -1;
429 			}
430 
431 			fd = map_parse_fd(&argc, &argv);
432 			if (fd < 0)
433 				return -1;
434 
435 			*value_fd = value;
436 			**value_fd = fd;
437 		} else if (map_is_map_of_progs(info->type)) {
438 			int argc = 2;
439 
440 			if (value_size != 4) {
441 				p_err("value smaller than 4B for map of progs?");
442 				return -1;
443 			}
444 			if (!argv[0] || !argv[1]) {
445 				p_err("not enough value arguments for map of progs");
446 				return -1;
447 			}
448 
449 			fd = prog_parse_fd(&argc, &argv);
450 			if (fd < 0)
451 				return -1;
452 
453 			*value_fd = value;
454 			**value_fd = fd;
455 		} else {
456 			argv = parse_bytes(argv, "value", value, value_size);
457 			if (!argv)
458 				return -1;
459 		}
460 
461 		return parse_elem(argv, info, key, NULL, key_size, value_size,
462 				  flags, NULL);
463 	} else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
464 		   is_prefix(*argv, "exist")) {
465 		if (!flags) {
466 			p_err("flags specified multiple times: %s", *argv);
467 			return -1;
468 		}
469 
470 		if (is_prefix(*argv, "any"))
471 			*flags = BPF_ANY;
472 		else if (is_prefix(*argv, "noexist"))
473 			*flags = BPF_NOEXIST;
474 		else if (is_prefix(*argv, "exist"))
475 			*flags = BPF_EXIST;
476 
477 		return parse_elem(argv + 1, info, key, value, key_size,
478 				  value_size, NULL, value_fd);
479 	}
480 
481 	p_err("expected key or value, got: %s", *argv);
482 	return -1;
483 }
484 
485 static int show_map_close_json(int fd, struct bpf_map_info *info)
486 {
487 	char *memlock;
488 
489 	memlock = get_fdinfo(fd, "memlock");
490 
491 	jsonw_start_object(json_wtr);
492 
493 	jsonw_uint_field(json_wtr, "id", info->id);
494 	if (info->type < ARRAY_SIZE(map_type_name))
495 		jsonw_string_field(json_wtr, "type",
496 				   map_type_name[info->type]);
497 	else
498 		jsonw_uint_field(json_wtr, "type", info->type);
499 
500 	if (*info->name)
501 		jsonw_string_field(json_wtr, "name", info->name);
502 
503 	jsonw_name(json_wtr, "flags");
504 	jsonw_printf(json_wtr, "%d", info->map_flags);
505 
506 	print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
507 
508 	jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
509 	jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
510 	jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
511 
512 	if (memlock)
513 		jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
514 	free(memlock);
515 
516 	if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
517 		char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
518 		char *owner_jited = get_fdinfo(fd, "owner_jited");
519 
520 		if (owner_prog_type) {
521 			unsigned int prog_type = atoi(owner_prog_type);
522 
523 			if (prog_type < ARRAY_SIZE(prog_type_name))
524 				jsonw_string_field(json_wtr, "owner_prog_type",
525 						   prog_type_name[prog_type]);
526 			else
527 				jsonw_uint_field(json_wtr, "owner_prog_type",
528 						 prog_type);
529 		}
530 		if (atoi(owner_jited))
531 			jsonw_bool_field(json_wtr, "owner_jited", true);
532 		else
533 			jsonw_bool_field(json_wtr, "owner_jited", false);
534 
535 		free(owner_prog_type);
536 		free(owner_jited);
537 	}
538 	close(fd);
539 
540 	if (!hash_empty(map_table.table)) {
541 		struct pinned_obj *obj;
542 
543 		jsonw_name(json_wtr, "pinned");
544 		jsonw_start_array(json_wtr);
545 		hash_for_each_possible(map_table.table, obj, hash, info->id) {
546 			if (obj->id == info->id)
547 				jsonw_string(json_wtr, obj->path);
548 		}
549 		jsonw_end_array(json_wtr);
550 	}
551 
552 	jsonw_end_object(json_wtr);
553 
554 	return 0;
555 }
556 
557 static int show_map_close_plain(int fd, struct bpf_map_info *info)
558 {
559 	char *memlock;
560 
561 	memlock = get_fdinfo(fd, "memlock");
562 
563 	printf("%u: ", info->id);
564 	if (info->type < ARRAY_SIZE(map_type_name))
565 		printf("%s  ", map_type_name[info->type]);
566 	else
567 		printf("type %u  ", info->type);
568 
569 	if (*info->name)
570 		printf("name %s  ", info->name);
571 
572 	printf("flags 0x%x", info->map_flags);
573 	print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
574 	printf("\n");
575 	printf("\tkey %uB  value %uB  max_entries %u",
576 	       info->key_size, info->value_size, info->max_entries);
577 
578 	if (memlock)
579 		printf("  memlock %sB", memlock);
580 	free(memlock);
581 
582 	if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
583 		char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
584 		char *owner_jited = get_fdinfo(fd, "owner_jited");
585 
586 		printf("\n\t");
587 		if (owner_prog_type) {
588 			unsigned int prog_type = atoi(owner_prog_type);
589 
590 			if (prog_type < ARRAY_SIZE(prog_type_name))
591 				printf("owner_prog_type %s  ",
592 				       prog_type_name[prog_type]);
593 			else
594 				printf("owner_prog_type %d  ", prog_type);
595 		}
596 		if (atoi(owner_jited))
597 			printf("owner jited");
598 		else
599 			printf("owner not jited");
600 
601 		free(owner_prog_type);
602 		free(owner_jited);
603 	}
604 	close(fd);
605 
606 	printf("\n");
607 	if (!hash_empty(map_table.table)) {
608 		struct pinned_obj *obj;
609 
610 		hash_for_each_possible(map_table.table, obj, hash, info->id) {
611 			if (obj->id == info->id)
612 				printf("\tpinned %s\n", obj->path);
613 		}
614 	}
615 	return 0;
616 }
617 
618 static int do_show(int argc, char **argv)
619 {
620 	struct bpf_map_info info = {};
621 	__u32 len = sizeof(info);
622 	__u32 id = 0;
623 	int err;
624 	int fd;
625 
626 	if (show_pinned)
627 		build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
628 
629 	if (argc == 2) {
630 		fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
631 		if (fd < 0)
632 			return -1;
633 
634 		if (json_output)
635 			return show_map_close_json(fd, &info);
636 		else
637 			return show_map_close_plain(fd, &info);
638 	}
639 
640 	if (argc)
641 		return BAD_ARG();
642 
643 	if (json_output)
644 		jsonw_start_array(json_wtr);
645 	while (true) {
646 		err = bpf_map_get_next_id(id, &id);
647 		if (err) {
648 			if (errno == ENOENT)
649 				break;
650 			p_err("can't get next map: %s%s", strerror(errno),
651 			      errno == EINVAL ? " -- kernel too old?" : "");
652 			break;
653 		}
654 
655 		fd = bpf_map_get_fd_by_id(id);
656 		if (fd < 0) {
657 			if (errno == ENOENT)
658 				continue;
659 			p_err("can't get map by id (%u): %s",
660 			      id, strerror(errno));
661 			break;
662 		}
663 
664 		err = bpf_obj_get_info_by_fd(fd, &info, &len);
665 		if (err) {
666 			p_err("can't get map info: %s", strerror(errno));
667 			close(fd);
668 			break;
669 		}
670 
671 		if (json_output)
672 			show_map_close_json(fd, &info);
673 		else
674 			show_map_close_plain(fd, &info);
675 	}
676 	if (json_output)
677 		jsonw_end_array(json_wtr);
678 
679 	return errno == ENOENT ? 0 : -1;
680 }
681 
682 static int dump_map_elem(int fd, void *key, void *value,
683 			 struct bpf_map_info *map_info, struct btf *btf,
684 			 json_writer_t *btf_wtr)
685 {
686 	int num_elems = 0;
687 	int lookup_errno;
688 
689 	if (!bpf_map_lookup_elem(fd, key, value)) {
690 		if (json_output) {
691 			print_entry_json(map_info, key, value, btf);
692 		} else {
693 			if (btf) {
694 				struct btf_dumper d = {
695 					.btf = btf,
696 					.jw = btf_wtr,
697 					.is_plain_text = true,
698 				};
699 
700 				do_dump_btf(&d, map_info, key, value);
701 			} else {
702 				print_entry_plain(map_info, key, value);
703 			}
704 			num_elems++;
705 		}
706 		return num_elems;
707 	}
708 
709 	/* lookup error handling */
710 	lookup_errno = errno;
711 
712 	if (map_is_map_of_maps(map_info->type) ||
713 	    map_is_map_of_progs(map_info->type))
714 		return 0;
715 
716 	if (json_output) {
717 		jsonw_name(json_wtr, "key");
718 		print_hex_data_json(key, map_info->key_size);
719 		jsonw_name(json_wtr, "value");
720 		jsonw_start_object(json_wtr);
721 		jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
722 		jsonw_end_object(json_wtr);
723 	} else {
724 		if (errno == ENOENT)
725 			print_entry_plain(map_info, key, NULL);
726 		else
727 			print_entry_error(map_info, key,
728 					  strerror(lookup_errno));
729 	}
730 
731 	return 0;
732 }
733 
734 static int do_dump(int argc, char **argv)
735 {
736 	struct bpf_map_info info = {};
737 	void *key, *value, *prev_key;
738 	unsigned int num_elems = 0;
739 	__u32 len = sizeof(info);
740 	json_writer_t *btf_wtr;
741 	struct btf *btf = NULL;
742 	int err;
743 	int fd;
744 
745 	if (argc != 2)
746 		usage();
747 
748 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
749 	if (fd < 0)
750 		return -1;
751 
752 	key = malloc(info.key_size);
753 	value = alloc_value(&info);
754 	if (!key || !value) {
755 		p_err("mem alloc failed");
756 		err = -1;
757 		goto exit_free;
758 	}
759 
760 	prev_key = NULL;
761 
762 	err = btf__get_from_id(info.btf_id, &btf);
763 	if (err) {
764 		p_err("failed to get btf");
765 		goto exit_free;
766 	}
767 
768 	if (json_output)
769 		jsonw_start_array(json_wtr);
770 	else
771 		if (btf) {
772 			btf_wtr = get_btf_writer();
773 			if (!btf_wtr) {
774 				p_info("failed to create json writer for btf. falling back to plain output");
775 				btf__free(btf);
776 				btf = NULL;
777 			} else {
778 				jsonw_start_array(btf_wtr);
779 			}
780 		}
781 
782 	while (true) {
783 		err = bpf_map_get_next_key(fd, prev_key, key);
784 		if (err) {
785 			if (errno == ENOENT)
786 				err = 0;
787 			break;
788 		}
789 		num_elems += dump_map_elem(fd, key, value, &info, btf, btf_wtr);
790 		prev_key = key;
791 	}
792 
793 	if (json_output)
794 		jsonw_end_array(json_wtr);
795 	else if (btf) {
796 		jsonw_end_array(btf_wtr);
797 		jsonw_destroy(&btf_wtr);
798 	} else {
799 		printf("Found %u element%s\n", num_elems,
800 		       num_elems != 1 ? "s" : "");
801 	}
802 
803 exit_free:
804 	free(key);
805 	free(value);
806 	close(fd);
807 	btf__free(btf);
808 
809 	return err;
810 }
811 
812 static int do_update(int argc, char **argv)
813 {
814 	struct bpf_map_info info = {};
815 	__u32 len = sizeof(info);
816 	__u32 *value_fd = NULL;
817 	__u32 flags = BPF_ANY;
818 	void *key, *value;
819 	int fd, err;
820 
821 	if (argc < 2)
822 		usage();
823 
824 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
825 	if (fd < 0)
826 		return -1;
827 
828 	key = malloc(info.key_size);
829 	value = alloc_value(&info);
830 	if (!key || !value) {
831 		p_err("mem alloc failed");
832 		err = -1;
833 		goto exit_free;
834 	}
835 
836 	err = parse_elem(argv, &info, key, value, info.key_size,
837 			 info.value_size, &flags, &value_fd);
838 	if (err)
839 		goto exit_free;
840 
841 	err = bpf_map_update_elem(fd, key, value, flags);
842 	if (err) {
843 		p_err("update failed: %s", strerror(errno));
844 		goto exit_free;
845 	}
846 
847 exit_free:
848 	if (value_fd)
849 		close(*value_fd);
850 	free(key);
851 	free(value);
852 	close(fd);
853 
854 	if (!err && json_output)
855 		jsonw_null(json_wtr);
856 	return err;
857 }
858 
859 static int do_lookup(int argc, char **argv)
860 {
861 	struct bpf_map_info info = {};
862 	__u32 len = sizeof(info);
863 	json_writer_t *btf_wtr;
864 	struct btf *btf = NULL;
865 	void *key, *value;
866 	int err;
867 	int fd;
868 
869 	if (argc < 2)
870 		usage();
871 
872 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
873 	if (fd < 0)
874 		return -1;
875 
876 	key = malloc(info.key_size);
877 	value = alloc_value(&info);
878 	if (!key || !value) {
879 		p_err("mem alloc failed");
880 		err = -1;
881 		goto exit_free;
882 	}
883 
884 	err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
885 	if (err)
886 		goto exit_free;
887 
888 	err = bpf_map_lookup_elem(fd, key, value);
889 	if (err) {
890 		if (errno == ENOENT) {
891 			if (json_output) {
892 				jsonw_null(json_wtr);
893 			} else {
894 				printf("key:\n");
895 				fprint_hex(stdout, key, info.key_size, " ");
896 				printf("\n\nNot found\n");
897 			}
898 		} else {
899 			p_err("lookup failed: %s", strerror(errno));
900 		}
901 
902 		goto exit_free;
903 	}
904 
905 	/* here means bpf_map_lookup_elem() succeeded */
906 	err = btf__get_from_id(info.btf_id, &btf);
907 	if (err) {
908 		p_err("failed to get btf");
909 		goto exit_free;
910 	}
911 
912 	if (json_output) {
913 		print_entry_json(&info, key, value, btf);
914 	} else if (btf) {
915 		/* if here json_wtr wouldn't have been initialised,
916 		 * so let's create separate writer for btf
917 		 */
918 		btf_wtr = get_btf_writer();
919 		if (!btf_wtr) {
920 			p_info("failed to create json writer for btf. falling back to plain output");
921 			btf__free(btf);
922 			btf = NULL;
923 			print_entry_plain(&info, key, value);
924 		} else {
925 			struct btf_dumper d = {
926 				.btf = btf,
927 				.jw = btf_wtr,
928 				.is_plain_text = true,
929 			};
930 
931 			do_dump_btf(&d, &info, key, value);
932 			jsonw_destroy(&btf_wtr);
933 		}
934 	} else {
935 		print_entry_plain(&info, key, value);
936 	}
937 
938 exit_free:
939 	free(key);
940 	free(value);
941 	close(fd);
942 	btf__free(btf);
943 
944 	return err;
945 }
946 
947 static int do_getnext(int argc, char **argv)
948 {
949 	struct bpf_map_info info = {};
950 	__u32 len = sizeof(info);
951 	void *key, *nextkey;
952 	int err;
953 	int fd;
954 
955 	if (argc < 2)
956 		usage();
957 
958 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
959 	if (fd < 0)
960 		return -1;
961 
962 	key = malloc(info.key_size);
963 	nextkey = malloc(info.key_size);
964 	if (!key || !nextkey) {
965 		p_err("mem alloc failed");
966 		err = -1;
967 		goto exit_free;
968 	}
969 
970 	if (argc) {
971 		err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
972 				 NULL, NULL);
973 		if (err)
974 			goto exit_free;
975 	} else {
976 		free(key);
977 		key = NULL;
978 	}
979 
980 	err = bpf_map_get_next_key(fd, key, nextkey);
981 	if (err) {
982 		p_err("can't get next key: %s", strerror(errno));
983 		goto exit_free;
984 	}
985 
986 	if (json_output) {
987 		jsonw_start_object(json_wtr);
988 		if (key) {
989 			jsonw_name(json_wtr, "key");
990 			print_hex_data_json(key, info.key_size);
991 		} else {
992 			jsonw_null_field(json_wtr, "key");
993 		}
994 		jsonw_name(json_wtr, "next_key");
995 		print_hex_data_json(nextkey, info.key_size);
996 		jsonw_end_object(json_wtr);
997 	} else {
998 		if (key) {
999 			printf("key:\n");
1000 			fprint_hex(stdout, key, info.key_size, " ");
1001 			printf("\n");
1002 		} else {
1003 			printf("key: None\n");
1004 		}
1005 		printf("next key:\n");
1006 		fprint_hex(stdout, nextkey, info.key_size, " ");
1007 		printf("\n");
1008 	}
1009 
1010 exit_free:
1011 	free(nextkey);
1012 	free(key);
1013 	close(fd);
1014 
1015 	return err;
1016 }
1017 
1018 static int do_delete(int argc, char **argv)
1019 {
1020 	struct bpf_map_info info = {};
1021 	__u32 len = sizeof(info);
1022 	void *key;
1023 	int err;
1024 	int fd;
1025 
1026 	if (argc < 2)
1027 		usage();
1028 
1029 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1030 	if (fd < 0)
1031 		return -1;
1032 
1033 	key = malloc(info.key_size);
1034 	if (!key) {
1035 		p_err("mem alloc failed");
1036 		err = -1;
1037 		goto exit_free;
1038 	}
1039 
1040 	err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
1041 	if (err)
1042 		goto exit_free;
1043 
1044 	err = bpf_map_delete_elem(fd, key);
1045 	if (err)
1046 		p_err("delete failed: %s", strerror(errno));
1047 
1048 exit_free:
1049 	free(key);
1050 	close(fd);
1051 
1052 	if (!err && json_output)
1053 		jsonw_null(json_wtr);
1054 	return err;
1055 }
1056 
1057 static int do_pin(int argc, char **argv)
1058 {
1059 	int err;
1060 
1061 	err = do_pin_any(argc, argv, bpf_map_get_fd_by_id);
1062 	if (!err && json_output)
1063 		jsonw_null(json_wtr);
1064 	return err;
1065 }
1066 
1067 static int do_create(int argc, char **argv)
1068 {
1069 	struct bpf_create_map_attr attr = { NULL, };
1070 	const char *pinfile;
1071 	int err, fd;
1072 
1073 	if (!REQ_ARGS(7))
1074 		return -1;
1075 	pinfile = GET_ARG();
1076 
1077 	while (argc) {
1078 		if (!REQ_ARGS(2))
1079 			return -1;
1080 
1081 		if (is_prefix(*argv, "type")) {
1082 			NEXT_ARG();
1083 
1084 			if (attr.map_type) {
1085 				p_err("map type already specified");
1086 				return -1;
1087 			}
1088 
1089 			attr.map_type = map_type_from_str(*argv);
1090 			if ((int)attr.map_type < 0) {
1091 				p_err("unrecognized map type: %s", *argv);
1092 				return -1;
1093 			}
1094 			NEXT_ARG();
1095 		} else if (is_prefix(*argv, "name")) {
1096 			NEXT_ARG();
1097 			attr.name = GET_ARG();
1098 		} else if (is_prefix(*argv, "key")) {
1099 			if (parse_u32_arg(&argc, &argv, &attr.key_size,
1100 					  "key size"))
1101 				return -1;
1102 		} else if (is_prefix(*argv, "value")) {
1103 			if (parse_u32_arg(&argc, &argv, &attr.value_size,
1104 					  "value size"))
1105 				return -1;
1106 		} else if (is_prefix(*argv, "entries")) {
1107 			if (parse_u32_arg(&argc, &argv, &attr.max_entries,
1108 					  "max entries"))
1109 				return -1;
1110 		} else if (is_prefix(*argv, "flags")) {
1111 			if (parse_u32_arg(&argc, &argv, &attr.map_flags,
1112 					  "flags"))
1113 				return -1;
1114 		} else if (is_prefix(*argv, "dev")) {
1115 			NEXT_ARG();
1116 
1117 			if (attr.map_ifindex) {
1118 				p_err("offload device already specified");
1119 				return -1;
1120 			}
1121 
1122 			attr.map_ifindex = if_nametoindex(*argv);
1123 			if (!attr.map_ifindex) {
1124 				p_err("unrecognized netdevice '%s': %s",
1125 				      *argv, strerror(errno));
1126 				return -1;
1127 			}
1128 			NEXT_ARG();
1129 		}
1130 	}
1131 
1132 	if (!attr.name) {
1133 		p_err("map name not specified");
1134 		return -1;
1135 	}
1136 
1137 	set_max_rlimit();
1138 
1139 	fd = bpf_create_map_xattr(&attr);
1140 	if (fd < 0) {
1141 		p_err("map create failed: %s", strerror(errno));
1142 		return -1;
1143 	}
1144 
1145 	err = do_pin_fd(fd, pinfile);
1146 	close(fd);
1147 	if (err)
1148 		return err;
1149 
1150 	if (json_output)
1151 		jsonw_null(json_wtr);
1152 	return 0;
1153 }
1154 
1155 static int do_help(int argc, char **argv)
1156 {
1157 	if (json_output) {
1158 		jsonw_null(json_wtr);
1159 		return 0;
1160 	}
1161 
1162 	fprintf(stderr,
1163 		"Usage: %s %s { show | list }   [MAP]\n"
1164 		"       %s %s create     FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n"
1165 		"                              entries MAX_ENTRIES name NAME [flags FLAGS] \\\n"
1166 		"                              [dev NAME]\n"
1167 		"       %s %s dump       MAP\n"
1168 		"       %s %s update     MAP  key DATA value VALUE [UPDATE_FLAGS]\n"
1169 		"       %s %s lookup     MAP  key DATA\n"
1170 		"       %s %s getnext    MAP [key DATA]\n"
1171 		"       %s %s delete     MAP  key DATA\n"
1172 		"       %s %s pin        MAP  FILE\n"
1173 		"       %s %s event_pipe MAP [cpu N index M]\n"
1174 		"       %s %s help\n"
1175 		"\n"
1176 		"       " HELP_SPEC_MAP "\n"
1177 		"       DATA := { [hex] BYTES }\n"
1178 		"       " HELP_SPEC_PROGRAM "\n"
1179 		"       VALUE := { DATA | MAP | PROG }\n"
1180 		"       UPDATE_FLAGS := { any | exist | noexist }\n"
1181 		"       TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n"
1182 		"                 percpu_array | stack_trace | cgroup_array | lru_hash |\n"
1183 		"                 lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
1184 		"                 devmap | sockmap | cpumap | xskmap | sockhash |\n"
1185 		"                 cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n"
1186 		"       " HELP_SPEC_OPTIONS "\n"
1187 		"",
1188 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1189 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1190 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1191 		bin_name, argv[-2]);
1192 
1193 	return 0;
1194 }
1195 
1196 static const struct cmd cmds[] = {
1197 	{ "show",	do_show },
1198 	{ "list",	do_show },
1199 	{ "help",	do_help },
1200 	{ "dump",	do_dump },
1201 	{ "update",	do_update },
1202 	{ "lookup",	do_lookup },
1203 	{ "getnext",	do_getnext },
1204 	{ "delete",	do_delete },
1205 	{ "pin",	do_pin },
1206 	{ "event_pipe",	do_event_pipe },
1207 	{ "create",	do_create },
1208 	{ 0 }
1209 };
1210 
1211 int do_map(int argc, char **argv)
1212 {
1213 	return cmd_select(cmds, argc, argv, do_help);
1214 }
1215