xref: /openbmc/linux/tools/bpf/bpftool/map.c (revision 197c2dac)
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 	close(fd);
491 
492 	jsonw_start_object(json_wtr);
493 
494 	jsonw_uint_field(json_wtr, "id", info->id);
495 	if (info->type < ARRAY_SIZE(map_type_name))
496 		jsonw_string_field(json_wtr, "type",
497 				   map_type_name[info->type]);
498 	else
499 		jsonw_uint_field(json_wtr, "type", info->type);
500 
501 	if (*info->name)
502 		jsonw_string_field(json_wtr, "name", info->name);
503 
504 	jsonw_name(json_wtr, "flags");
505 	jsonw_printf(json_wtr, "%d", info->map_flags);
506 
507 	print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
508 
509 	jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
510 	jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
511 	jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
512 
513 	if (memlock)
514 		jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
515 	free(memlock);
516 
517 	if (!hash_empty(map_table.table)) {
518 		struct pinned_obj *obj;
519 
520 		jsonw_name(json_wtr, "pinned");
521 		jsonw_start_array(json_wtr);
522 		hash_for_each_possible(map_table.table, obj, hash, info->id) {
523 			if (obj->id == info->id)
524 				jsonw_string(json_wtr, obj->path);
525 		}
526 		jsonw_end_array(json_wtr);
527 	}
528 
529 	jsonw_end_object(json_wtr);
530 
531 	return 0;
532 }
533 
534 static int show_map_close_plain(int fd, struct bpf_map_info *info)
535 {
536 	char *memlock;
537 
538 	memlock = get_fdinfo(fd, "memlock");
539 	close(fd);
540 
541 	printf("%u: ", info->id);
542 	if (info->type < ARRAY_SIZE(map_type_name))
543 		printf("%s  ", map_type_name[info->type]);
544 	else
545 		printf("type %u  ", info->type);
546 
547 	if (*info->name)
548 		printf("name %s  ", info->name);
549 
550 	printf("flags 0x%x", info->map_flags);
551 	print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
552 	printf("\n");
553 	printf("\tkey %uB  value %uB  max_entries %u",
554 	       info->key_size, info->value_size, info->max_entries);
555 
556 	if (memlock)
557 		printf("  memlock %sB", memlock);
558 	free(memlock);
559 
560 	printf("\n");
561 	if (!hash_empty(map_table.table)) {
562 		struct pinned_obj *obj;
563 
564 		hash_for_each_possible(map_table.table, obj, hash, info->id) {
565 			if (obj->id == info->id)
566 				printf("\tpinned %s\n", obj->path);
567 		}
568 	}
569 	return 0;
570 }
571 
572 static int do_show(int argc, char **argv)
573 {
574 	struct bpf_map_info info = {};
575 	__u32 len = sizeof(info);
576 	__u32 id = 0;
577 	int err;
578 	int fd;
579 
580 	if (show_pinned)
581 		build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
582 
583 	if (argc == 2) {
584 		fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
585 		if (fd < 0)
586 			return -1;
587 
588 		if (json_output)
589 			return show_map_close_json(fd, &info);
590 		else
591 			return show_map_close_plain(fd, &info);
592 	}
593 
594 	if (argc)
595 		return BAD_ARG();
596 
597 	if (json_output)
598 		jsonw_start_array(json_wtr);
599 	while (true) {
600 		err = bpf_map_get_next_id(id, &id);
601 		if (err) {
602 			if (errno == ENOENT)
603 				break;
604 			p_err("can't get next map: %s%s", strerror(errno),
605 			      errno == EINVAL ? " -- kernel too old?" : "");
606 			break;
607 		}
608 
609 		fd = bpf_map_get_fd_by_id(id);
610 		if (fd < 0) {
611 			if (errno == ENOENT)
612 				continue;
613 			p_err("can't get map by id (%u): %s",
614 			      id, strerror(errno));
615 			break;
616 		}
617 
618 		err = bpf_obj_get_info_by_fd(fd, &info, &len);
619 		if (err) {
620 			p_err("can't get map info: %s", strerror(errno));
621 			close(fd);
622 			break;
623 		}
624 
625 		if (json_output)
626 			show_map_close_json(fd, &info);
627 		else
628 			show_map_close_plain(fd, &info);
629 	}
630 	if (json_output)
631 		jsonw_end_array(json_wtr);
632 
633 	return errno == ENOENT ? 0 : -1;
634 }
635 
636 static int dump_map_elem(int fd, void *key, void *value,
637 			 struct bpf_map_info *map_info, struct btf *btf,
638 			 json_writer_t *btf_wtr)
639 {
640 	int num_elems = 0;
641 	int lookup_errno;
642 
643 	if (!bpf_map_lookup_elem(fd, key, value)) {
644 		if (json_output) {
645 			print_entry_json(map_info, key, value, btf);
646 		} else {
647 			if (btf) {
648 				struct btf_dumper d = {
649 					.btf = btf,
650 					.jw = btf_wtr,
651 					.is_plain_text = true,
652 				};
653 
654 				do_dump_btf(&d, map_info, key, value);
655 			} else {
656 				print_entry_plain(map_info, key, value);
657 			}
658 			num_elems++;
659 		}
660 		return num_elems;
661 	}
662 
663 	/* lookup error handling */
664 	lookup_errno = errno;
665 
666 	if (map_is_map_of_maps(map_info->type) ||
667 	    map_is_map_of_progs(map_info->type))
668 		return 0;
669 
670 	if (json_output) {
671 		jsonw_name(json_wtr, "key");
672 		print_hex_data_json(key, map_info->key_size);
673 		jsonw_name(json_wtr, "value");
674 		jsonw_start_object(json_wtr);
675 		jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
676 		jsonw_end_object(json_wtr);
677 	} else {
678 		if (errno == ENOENT)
679 			print_entry_plain(map_info, key, NULL);
680 		else
681 			print_entry_error(map_info, key,
682 					  strerror(lookup_errno));
683 	}
684 
685 	return 0;
686 }
687 
688 static int do_dump(int argc, char **argv)
689 {
690 	struct bpf_map_info info = {};
691 	void *key, *value, *prev_key;
692 	unsigned int num_elems = 0;
693 	__u32 len = sizeof(info);
694 	json_writer_t *btf_wtr;
695 	struct btf *btf = NULL;
696 	int err;
697 	int fd;
698 
699 	if (argc != 2)
700 		usage();
701 
702 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
703 	if (fd < 0)
704 		return -1;
705 
706 	key = malloc(info.key_size);
707 	value = alloc_value(&info);
708 	if (!key || !value) {
709 		p_err("mem alloc failed");
710 		err = -1;
711 		goto exit_free;
712 	}
713 
714 	prev_key = NULL;
715 
716 	err = btf_get_from_id(info.btf_id, &btf);
717 	if (err) {
718 		p_err("failed to get btf");
719 		goto exit_free;
720 	}
721 
722 	if (json_output)
723 		jsonw_start_array(json_wtr);
724 	else
725 		if (btf) {
726 			btf_wtr = get_btf_writer();
727 			if (!btf_wtr) {
728 				p_info("failed to create json writer for btf. falling back to plain output");
729 				btf__free(btf);
730 				btf = NULL;
731 			} else {
732 				jsonw_start_array(btf_wtr);
733 			}
734 		}
735 
736 	while (true) {
737 		err = bpf_map_get_next_key(fd, prev_key, key);
738 		if (err) {
739 			if (errno == ENOENT)
740 				err = 0;
741 			break;
742 		}
743 		num_elems += dump_map_elem(fd, key, value, &info, btf, btf_wtr);
744 		prev_key = key;
745 	}
746 
747 	if (json_output)
748 		jsonw_end_array(json_wtr);
749 	else if (btf) {
750 		jsonw_end_array(btf_wtr);
751 		jsonw_destroy(&btf_wtr);
752 	} else {
753 		printf("Found %u element%s\n", num_elems,
754 		       num_elems != 1 ? "s" : "");
755 	}
756 
757 exit_free:
758 	free(key);
759 	free(value);
760 	close(fd);
761 	btf__free(btf);
762 
763 	return err;
764 }
765 
766 static int do_update(int argc, char **argv)
767 {
768 	struct bpf_map_info info = {};
769 	__u32 len = sizeof(info);
770 	__u32 *value_fd = NULL;
771 	__u32 flags = BPF_ANY;
772 	void *key, *value;
773 	int fd, err;
774 
775 	if (argc < 2)
776 		usage();
777 
778 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
779 	if (fd < 0)
780 		return -1;
781 
782 	key = malloc(info.key_size);
783 	value = alloc_value(&info);
784 	if (!key || !value) {
785 		p_err("mem alloc failed");
786 		err = -1;
787 		goto exit_free;
788 	}
789 
790 	err = parse_elem(argv, &info, key, value, info.key_size,
791 			 info.value_size, &flags, &value_fd);
792 	if (err)
793 		goto exit_free;
794 
795 	err = bpf_map_update_elem(fd, key, value, flags);
796 	if (err) {
797 		p_err("update failed: %s", strerror(errno));
798 		goto exit_free;
799 	}
800 
801 exit_free:
802 	if (value_fd)
803 		close(*value_fd);
804 	free(key);
805 	free(value);
806 	close(fd);
807 
808 	if (!err && json_output)
809 		jsonw_null(json_wtr);
810 	return err;
811 }
812 
813 static int do_lookup(int argc, char **argv)
814 {
815 	struct bpf_map_info info = {};
816 	__u32 len = sizeof(info);
817 	json_writer_t *btf_wtr;
818 	struct btf *btf = NULL;
819 	void *key, *value;
820 	int err;
821 	int fd;
822 
823 	if (argc < 2)
824 		usage();
825 
826 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
827 	if (fd < 0)
828 		return -1;
829 
830 	key = malloc(info.key_size);
831 	value = alloc_value(&info);
832 	if (!key || !value) {
833 		p_err("mem alloc failed");
834 		err = -1;
835 		goto exit_free;
836 	}
837 
838 	err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
839 	if (err)
840 		goto exit_free;
841 
842 	err = bpf_map_lookup_elem(fd, key, value);
843 	if (err) {
844 		if (errno == ENOENT) {
845 			if (json_output) {
846 				jsonw_null(json_wtr);
847 			} else {
848 				printf("key:\n");
849 				fprint_hex(stdout, key, info.key_size, " ");
850 				printf("\n\nNot found\n");
851 			}
852 		} else {
853 			p_err("lookup failed: %s", strerror(errno));
854 		}
855 
856 		goto exit_free;
857 	}
858 
859 	/* here means bpf_map_lookup_elem() succeeded */
860 	err = btf_get_from_id(info.btf_id, &btf);
861 	if (err) {
862 		p_err("failed to get btf");
863 		goto exit_free;
864 	}
865 
866 	if (json_output) {
867 		print_entry_json(&info, key, value, btf);
868 	} else if (btf) {
869 		/* if here json_wtr wouldn't have been initialised,
870 		 * so let's create separate writer for btf
871 		 */
872 		btf_wtr = get_btf_writer();
873 		if (!btf_wtr) {
874 			p_info("failed to create json writer for btf. falling back to plain output");
875 			btf__free(btf);
876 			btf = NULL;
877 			print_entry_plain(&info, key, value);
878 		} else {
879 			struct btf_dumper d = {
880 				.btf = btf,
881 				.jw = btf_wtr,
882 				.is_plain_text = true,
883 			};
884 
885 			do_dump_btf(&d, &info, key, value);
886 			jsonw_destroy(&btf_wtr);
887 		}
888 	} else {
889 		print_entry_plain(&info, key, value);
890 	}
891 
892 exit_free:
893 	free(key);
894 	free(value);
895 	close(fd);
896 	btf__free(btf);
897 
898 	return err;
899 }
900 
901 static int do_getnext(int argc, char **argv)
902 {
903 	struct bpf_map_info info = {};
904 	__u32 len = sizeof(info);
905 	void *key, *nextkey;
906 	int err;
907 	int fd;
908 
909 	if (argc < 2)
910 		usage();
911 
912 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
913 	if (fd < 0)
914 		return -1;
915 
916 	key = malloc(info.key_size);
917 	nextkey = malloc(info.key_size);
918 	if (!key || !nextkey) {
919 		p_err("mem alloc failed");
920 		err = -1;
921 		goto exit_free;
922 	}
923 
924 	if (argc) {
925 		err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
926 				 NULL, NULL);
927 		if (err)
928 			goto exit_free;
929 	} else {
930 		free(key);
931 		key = NULL;
932 	}
933 
934 	err = bpf_map_get_next_key(fd, key, nextkey);
935 	if (err) {
936 		p_err("can't get next key: %s", strerror(errno));
937 		goto exit_free;
938 	}
939 
940 	if (json_output) {
941 		jsonw_start_object(json_wtr);
942 		if (key) {
943 			jsonw_name(json_wtr, "key");
944 			print_hex_data_json(key, info.key_size);
945 		} else {
946 			jsonw_null_field(json_wtr, "key");
947 		}
948 		jsonw_name(json_wtr, "next_key");
949 		print_hex_data_json(nextkey, info.key_size);
950 		jsonw_end_object(json_wtr);
951 	} else {
952 		if (key) {
953 			printf("key:\n");
954 			fprint_hex(stdout, key, info.key_size, " ");
955 			printf("\n");
956 		} else {
957 			printf("key: None\n");
958 		}
959 		printf("next key:\n");
960 		fprint_hex(stdout, nextkey, info.key_size, " ");
961 		printf("\n");
962 	}
963 
964 exit_free:
965 	free(nextkey);
966 	free(key);
967 	close(fd);
968 
969 	return err;
970 }
971 
972 static int do_delete(int argc, char **argv)
973 {
974 	struct bpf_map_info info = {};
975 	__u32 len = sizeof(info);
976 	void *key;
977 	int err;
978 	int fd;
979 
980 	if (argc < 2)
981 		usage();
982 
983 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
984 	if (fd < 0)
985 		return -1;
986 
987 	key = malloc(info.key_size);
988 	if (!key) {
989 		p_err("mem alloc failed");
990 		err = -1;
991 		goto exit_free;
992 	}
993 
994 	err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
995 	if (err)
996 		goto exit_free;
997 
998 	err = bpf_map_delete_elem(fd, key);
999 	if (err)
1000 		p_err("delete failed: %s", strerror(errno));
1001 
1002 exit_free:
1003 	free(key);
1004 	close(fd);
1005 
1006 	if (!err && json_output)
1007 		jsonw_null(json_wtr);
1008 	return err;
1009 }
1010 
1011 static int do_pin(int argc, char **argv)
1012 {
1013 	int err;
1014 
1015 	err = do_pin_any(argc, argv, bpf_map_get_fd_by_id);
1016 	if (!err && json_output)
1017 		jsonw_null(json_wtr);
1018 	return err;
1019 }
1020 
1021 static int do_create(int argc, char **argv)
1022 {
1023 	struct bpf_create_map_attr attr = { NULL, };
1024 	const char *pinfile;
1025 	int err, fd;
1026 
1027 	if (!REQ_ARGS(7))
1028 		return -1;
1029 	pinfile = GET_ARG();
1030 
1031 	while (argc) {
1032 		if (!REQ_ARGS(2))
1033 			return -1;
1034 
1035 		if (is_prefix(*argv, "type")) {
1036 			NEXT_ARG();
1037 
1038 			if (attr.map_type) {
1039 				p_err("map type already specified");
1040 				return -1;
1041 			}
1042 
1043 			attr.map_type = map_type_from_str(*argv);
1044 			if ((int)attr.map_type < 0) {
1045 				p_err("unrecognized map type: %s", *argv);
1046 				return -1;
1047 			}
1048 			NEXT_ARG();
1049 		} else if (is_prefix(*argv, "name")) {
1050 			NEXT_ARG();
1051 			attr.name = GET_ARG();
1052 		} else if (is_prefix(*argv, "key")) {
1053 			if (parse_u32_arg(&argc, &argv, &attr.key_size,
1054 					  "key size"))
1055 				return -1;
1056 		} else if (is_prefix(*argv, "value")) {
1057 			if (parse_u32_arg(&argc, &argv, &attr.value_size,
1058 					  "value size"))
1059 				return -1;
1060 		} else if (is_prefix(*argv, "entries")) {
1061 			if (parse_u32_arg(&argc, &argv, &attr.max_entries,
1062 					  "max entries"))
1063 				return -1;
1064 		} else if (is_prefix(*argv, "flags")) {
1065 			if (parse_u32_arg(&argc, &argv, &attr.map_flags,
1066 					  "flags"))
1067 				return -1;
1068 		} else if (is_prefix(*argv, "dev")) {
1069 			NEXT_ARG();
1070 
1071 			if (attr.map_ifindex) {
1072 				p_err("offload device already specified");
1073 				return -1;
1074 			}
1075 
1076 			attr.map_ifindex = if_nametoindex(*argv);
1077 			if (!attr.map_ifindex) {
1078 				p_err("unrecognized netdevice '%s': %s",
1079 				      *argv, strerror(errno));
1080 				return -1;
1081 			}
1082 			NEXT_ARG();
1083 		}
1084 	}
1085 
1086 	if (!attr.name) {
1087 		p_err("map name not specified");
1088 		return -1;
1089 	}
1090 
1091 	set_max_rlimit();
1092 
1093 	fd = bpf_create_map_xattr(&attr);
1094 	if (fd < 0) {
1095 		p_err("map create failed: %s", strerror(errno));
1096 		return -1;
1097 	}
1098 
1099 	err = do_pin_fd(fd, pinfile);
1100 	close(fd);
1101 	if (err)
1102 		return err;
1103 
1104 	if (json_output)
1105 		jsonw_null(json_wtr);
1106 	return 0;
1107 }
1108 
1109 static int do_help(int argc, char **argv)
1110 {
1111 	if (json_output) {
1112 		jsonw_null(json_wtr);
1113 		return 0;
1114 	}
1115 
1116 	fprintf(stderr,
1117 		"Usage: %s %s { show | list }   [MAP]\n"
1118 		"       %s %s create     FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n"
1119 		"                              entries MAX_ENTRIES name NAME [flags FLAGS] \\\n"
1120 		"                              [dev NAME]\n"
1121 		"       %s %s dump       MAP\n"
1122 		"       %s %s update     MAP  key DATA value VALUE [UPDATE_FLAGS]\n"
1123 		"       %s %s lookup     MAP  key DATA\n"
1124 		"       %s %s getnext    MAP [key DATA]\n"
1125 		"       %s %s delete     MAP  key DATA\n"
1126 		"       %s %s pin        MAP  FILE\n"
1127 		"       %s %s event_pipe MAP [cpu N index M]\n"
1128 		"       %s %s help\n"
1129 		"\n"
1130 		"       " HELP_SPEC_MAP "\n"
1131 		"       DATA := { [hex] BYTES }\n"
1132 		"       " HELP_SPEC_PROGRAM "\n"
1133 		"       VALUE := { DATA | MAP | PROG }\n"
1134 		"       UPDATE_FLAGS := { any | exist | noexist }\n"
1135 		"       TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n"
1136 		"                 percpu_array | stack_trace | cgroup_array | lru_hash |\n"
1137 		"                 lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
1138 		"                 devmap | sockmap | cpumap | xskmap | sockhash |\n"
1139 		"                 cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n"
1140 		"       " HELP_SPEC_OPTIONS "\n"
1141 		"",
1142 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1143 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1144 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1145 		bin_name, argv[-2]);
1146 
1147 	return 0;
1148 }
1149 
1150 static const struct cmd cmds[] = {
1151 	{ "show",	do_show },
1152 	{ "list",	do_show },
1153 	{ "help",	do_help },
1154 	{ "dump",	do_dump },
1155 	{ "update",	do_update },
1156 	{ "lookup",	do_lookup },
1157 	{ "getnext",	do_getnext },
1158 	{ "delete",	do_delete },
1159 	{ "pin",	do_pin },
1160 	{ "event_pipe",	do_event_pipe },
1161 	{ "create",	do_create },
1162 	{ 0 }
1163 };
1164 
1165 int do_map(int argc, char **argv)
1166 {
1167 	return cmd_select(cmds, argc, argv, do_help);
1168 }
1169