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