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