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