xref: /openbmc/linux/tools/bpf/bpftool/map.c (revision f79e4d5f)
1 /*
2  * Copyright (C) 2017-2018 Netronome Systems, Inc.
3  *
4  * This software is dual licensed under the GNU General License Version 2,
5  * June 1991 as shown in the file COPYING in the top-level directory of this
6  * source tree or the BSD 2-Clause License provided below.  You have the
7  * option to license this software under the complete terms of either license.
8  *
9  * The BSD 2-Clause License:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      1. Redistributions of source code must retain the above
16  *         copyright notice, this list of conditions and the following
17  *         disclaimer.
18  *
19  *      2. Redistributions in binary form must reproduce the above
20  *         copyright notice, this list of conditions and the following
21  *         disclaimer in the documentation and/or other materials
22  *         provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33 
34 /* Author: Jakub Kicinski <kubakici@wp.pl> */
35 
36 #include <assert.h>
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <linux/kernel.h>
40 #include <stdbool.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 
48 #include <bpf.h>
49 
50 #include "main.h"
51 
52 static const char * const map_type_name[] = {
53 	[BPF_MAP_TYPE_UNSPEC]		= "unspec",
54 	[BPF_MAP_TYPE_HASH]		= "hash",
55 	[BPF_MAP_TYPE_ARRAY]		= "array",
56 	[BPF_MAP_TYPE_PROG_ARRAY]	= "prog_array",
57 	[BPF_MAP_TYPE_PERF_EVENT_ARRAY]	= "perf_event_array",
58 	[BPF_MAP_TYPE_PERCPU_HASH]	= "percpu_hash",
59 	[BPF_MAP_TYPE_PERCPU_ARRAY]	= "percpu_array",
60 	[BPF_MAP_TYPE_STACK_TRACE]	= "stack_trace",
61 	[BPF_MAP_TYPE_CGROUP_ARRAY]	= "cgroup_array",
62 	[BPF_MAP_TYPE_LRU_HASH]		= "lru_hash",
63 	[BPF_MAP_TYPE_LRU_PERCPU_HASH]	= "lru_percpu_hash",
64 	[BPF_MAP_TYPE_LPM_TRIE]		= "lpm_trie",
65 	[BPF_MAP_TYPE_ARRAY_OF_MAPS]	= "array_of_maps",
66 	[BPF_MAP_TYPE_HASH_OF_MAPS]	= "hash_of_maps",
67 	[BPF_MAP_TYPE_DEVMAP]		= "devmap",
68 	[BPF_MAP_TYPE_SOCKMAP]		= "sockmap",
69 	[BPF_MAP_TYPE_CPUMAP]		= "cpumap",
70 	[BPF_MAP_TYPE_SOCKHASH]		= "sockhash",
71 };
72 
73 static bool map_is_per_cpu(__u32 type)
74 {
75 	return type == BPF_MAP_TYPE_PERCPU_HASH ||
76 	       type == BPF_MAP_TYPE_PERCPU_ARRAY ||
77 	       type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
78 }
79 
80 static bool map_is_map_of_maps(__u32 type)
81 {
82 	return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
83 	       type == BPF_MAP_TYPE_HASH_OF_MAPS;
84 }
85 
86 static bool map_is_map_of_progs(__u32 type)
87 {
88 	return type == BPF_MAP_TYPE_PROG_ARRAY;
89 }
90 
91 static void *alloc_value(struct bpf_map_info *info)
92 {
93 	if (map_is_per_cpu(info->type))
94 		return malloc(round_up(info->value_size, 8) *
95 			      get_possible_cpus());
96 	else
97 		return malloc(info->value_size);
98 }
99 
100 static int map_parse_fd(int *argc, char ***argv)
101 {
102 	int fd;
103 
104 	if (is_prefix(**argv, "id")) {
105 		unsigned int id;
106 		char *endptr;
107 
108 		NEXT_ARGP();
109 
110 		id = strtoul(**argv, &endptr, 0);
111 		if (*endptr) {
112 			p_err("can't parse %s as ID", **argv);
113 			return -1;
114 		}
115 		NEXT_ARGP();
116 
117 		fd = bpf_map_get_fd_by_id(id);
118 		if (fd < 0)
119 			p_err("get map by id (%u): %s", id, strerror(errno));
120 		return fd;
121 	} else if (is_prefix(**argv, "pinned")) {
122 		char *path;
123 
124 		NEXT_ARGP();
125 
126 		path = **argv;
127 		NEXT_ARGP();
128 
129 		return open_obj_pinned_any(path, BPF_OBJ_MAP);
130 	}
131 
132 	p_err("expected 'id' or 'pinned', got: '%s'?", **argv);
133 	return -1;
134 }
135 
136 int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
137 {
138 	int err;
139 	int fd;
140 
141 	fd = map_parse_fd(argc, argv);
142 	if (fd < 0)
143 		return -1;
144 
145 	err = bpf_obj_get_info_by_fd(fd, info, info_len);
146 	if (err) {
147 		p_err("can't get map info: %s", strerror(errno));
148 		close(fd);
149 		return err;
150 	}
151 
152 	return fd;
153 }
154 
155 static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
156 			     unsigned char *value)
157 {
158 	jsonw_start_object(json_wtr);
159 
160 	if (!map_is_per_cpu(info->type)) {
161 		jsonw_name(json_wtr, "key");
162 		print_hex_data_json(key, info->key_size);
163 		jsonw_name(json_wtr, "value");
164 		print_hex_data_json(value, info->value_size);
165 	} else {
166 		unsigned int i, n, step;
167 
168 		n = get_possible_cpus();
169 		step = round_up(info->value_size, 8);
170 
171 		jsonw_name(json_wtr, "key");
172 		print_hex_data_json(key, info->key_size);
173 
174 		jsonw_name(json_wtr, "values");
175 		jsonw_start_array(json_wtr);
176 		for (i = 0; i < n; i++) {
177 			jsonw_start_object(json_wtr);
178 
179 			jsonw_int_field(json_wtr, "cpu", i);
180 
181 			jsonw_name(json_wtr, "value");
182 			print_hex_data_json(value + i * step,
183 					    info->value_size);
184 
185 			jsonw_end_object(json_wtr);
186 		}
187 		jsonw_end_array(json_wtr);
188 	}
189 
190 	jsonw_end_object(json_wtr);
191 }
192 
193 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
194 			      unsigned char *value)
195 {
196 	if (!map_is_per_cpu(info->type)) {
197 		bool single_line, break_names;
198 
199 		break_names = info->key_size > 16 || info->value_size > 16;
200 		single_line = info->key_size + info->value_size <= 24 &&
201 			!break_names;
202 
203 		printf("key:%c", break_names ? '\n' : ' ');
204 		fprint_hex(stdout, key, info->key_size, " ");
205 
206 		printf(single_line ? "  " : "\n");
207 
208 		printf("value:%c", break_names ? '\n' : ' ');
209 		fprint_hex(stdout, value, info->value_size, " ");
210 
211 		printf("\n");
212 	} else {
213 		unsigned int i, n, step;
214 
215 		n = get_possible_cpus();
216 		step = round_up(info->value_size, 8);
217 
218 		printf("key:\n");
219 		fprint_hex(stdout, key, info->key_size, " ");
220 		printf("\n");
221 		for (i = 0; i < n; i++) {
222 			printf("value (CPU %02d):%c",
223 			       i, info->value_size > 16 ? '\n' : ' ');
224 			fprint_hex(stdout, value + i * step,
225 				   info->value_size, " ");
226 			printf("\n");
227 		}
228 	}
229 }
230 
231 static char **parse_bytes(char **argv, const char *name, unsigned char *val,
232 			  unsigned int n)
233 {
234 	unsigned int i = 0, base = 0;
235 	char *endptr;
236 
237 	if (is_prefix(*argv, "hex")) {
238 		base = 16;
239 		argv++;
240 	}
241 
242 	while (i < n && argv[i]) {
243 		val[i] = strtoul(argv[i], &endptr, base);
244 		if (*endptr) {
245 			p_err("error parsing byte: %s", argv[i]);
246 			return NULL;
247 		}
248 		i++;
249 	}
250 
251 	if (i != n) {
252 		p_err("%s expected %d bytes got %d", name, n, i);
253 		return NULL;
254 	}
255 
256 	return argv + i;
257 }
258 
259 static int parse_elem(char **argv, struct bpf_map_info *info,
260 		      void *key, void *value, __u32 key_size, __u32 value_size,
261 		      __u32 *flags, __u32 **value_fd)
262 {
263 	if (!*argv) {
264 		if (!key && !value)
265 			return 0;
266 		p_err("did not find %s", key ? "key" : "value");
267 		return -1;
268 	}
269 
270 	if (is_prefix(*argv, "key")) {
271 		if (!key) {
272 			if (key_size)
273 				p_err("duplicate key");
274 			else
275 				p_err("unnecessary key");
276 			return -1;
277 		}
278 
279 		argv = parse_bytes(argv + 1, "key", key, key_size);
280 		if (!argv)
281 			return -1;
282 
283 		return parse_elem(argv, info, NULL, value, key_size, value_size,
284 				  flags, value_fd);
285 	} else if (is_prefix(*argv, "value")) {
286 		int fd;
287 
288 		if (!value) {
289 			if (value_size)
290 				p_err("duplicate value");
291 			else
292 				p_err("unnecessary value");
293 			return -1;
294 		}
295 
296 		argv++;
297 
298 		if (map_is_map_of_maps(info->type)) {
299 			int argc = 2;
300 
301 			if (value_size != 4) {
302 				p_err("value smaller than 4B for map in map?");
303 				return -1;
304 			}
305 			if (!argv[0] || !argv[1]) {
306 				p_err("not enough value arguments for map in map");
307 				return -1;
308 			}
309 
310 			fd = map_parse_fd(&argc, &argv);
311 			if (fd < 0)
312 				return -1;
313 
314 			*value_fd = value;
315 			**value_fd = fd;
316 		} else if (map_is_map_of_progs(info->type)) {
317 			int argc = 2;
318 
319 			if (value_size != 4) {
320 				p_err("value smaller than 4B for map of progs?");
321 				return -1;
322 			}
323 			if (!argv[0] || !argv[1]) {
324 				p_err("not enough value arguments for map of progs");
325 				return -1;
326 			}
327 
328 			fd = prog_parse_fd(&argc, &argv);
329 			if (fd < 0)
330 				return -1;
331 
332 			*value_fd = value;
333 			**value_fd = fd;
334 		} else {
335 			argv = parse_bytes(argv, "value", value, value_size);
336 			if (!argv)
337 				return -1;
338 		}
339 
340 		return parse_elem(argv, info, key, NULL, key_size, value_size,
341 				  flags, NULL);
342 	} else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
343 		   is_prefix(*argv, "exist")) {
344 		if (!flags) {
345 			p_err("flags specified multiple times: %s", *argv);
346 			return -1;
347 		}
348 
349 		if (is_prefix(*argv, "any"))
350 			*flags = BPF_ANY;
351 		else if (is_prefix(*argv, "noexist"))
352 			*flags = BPF_NOEXIST;
353 		else if (is_prefix(*argv, "exist"))
354 			*flags = BPF_EXIST;
355 
356 		return parse_elem(argv + 1, info, key, value, key_size,
357 				  value_size, NULL, value_fd);
358 	}
359 
360 	p_err("expected key or value, got: %s", *argv);
361 	return -1;
362 }
363 
364 static int show_map_close_json(int fd, struct bpf_map_info *info)
365 {
366 	char *memlock;
367 
368 	memlock = get_fdinfo(fd, "memlock");
369 	close(fd);
370 
371 	jsonw_start_object(json_wtr);
372 
373 	jsonw_uint_field(json_wtr, "id", info->id);
374 	if (info->type < ARRAY_SIZE(map_type_name))
375 		jsonw_string_field(json_wtr, "type",
376 				   map_type_name[info->type]);
377 	else
378 		jsonw_uint_field(json_wtr, "type", info->type);
379 
380 	if (*info->name)
381 		jsonw_string_field(json_wtr, "name", info->name);
382 
383 	jsonw_name(json_wtr, "flags");
384 	jsonw_printf(json_wtr, "%d", info->map_flags);
385 
386 	print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
387 
388 	jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
389 	jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
390 	jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
391 
392 	if (memlock)
393 		jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
394 	free(memlock);
395 
396 	if (!hash_empty(map_table.table)) {
397 		struct pinned_obj *obj;
398 
399 		jsonw_name(json_wtr, "pinned");
400 		jsonw_start_array(json_wtr);
401 		hash_for_each_possible(map_table.table, obj, hash, info->id) {
402 			if (obj->id == info->id)
403 				jsonw_string(json_wtr, obj->path);
404 		}
405 		jsonw_end_array(json_wtr);
406 	}
407 
408 	jsonw_end_object(json_wtr);
409 
410 	return 0;
411 }
412 
413 static int show_map_close_plain(int fd, struct bpf_map_info *info)
414 {
415 	char *memlock;
416 
417 	memlock = get_fdinfo(fd, "memlock");
418 	close(fd);
419 
420 	printf("%u: ", info->id);
421 	if (info->type < ARRAY_SIZE(map_type_name))
422 		printf("%s  ", map_type_name[info->type]);
423 	else
424 		printf("type %u  ", info->type);
425 
426 	if (*info->name)
427 		printf("name %s  ", info->name);
428 
429 	printf("flags 0x%x", info->map_flags);
430 	print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
431 	printf("\n");
432 	printf("\tkey %uB  value %uB  max_entries %u",
433 	       info->key_size, info->value_size, info->max_entries);
434 
435 	if (memlock)
436 		printf("  memlock %sB", memlock);
437 	free(memlock);
438 
439 	printf("\n");
440 	if (!hash_empty(map_table.table)) {
441 		struct pinned_obj *obj;
442 
443 		hash_for_each_possible(map_table.table, obj, hash, info->id) {
444 			if (obj->id == info->id)
445 				printf("\tpinned %s\n", obj->path);
446 		}
447 	}
448 	return 0;
449 }
450 
451 static int do_show(int argc, char **argv)
452 {
453 	struct bpf_map_info info = {};
454 	__u32 len = sizeof(info);
455 	__u32 id = 0;
456 	int err;
457 	int fd;
458 
459 	if (show_pinned)
460 		build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
461 
462 	if (argc == 2) {
463 		fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
464 		if (fd < 0)
465 			return -1;
466 
467 		if (json_output)
468 			return show_map_close_json(fd, &info);
469 		else
470 			return show_map_close_plain(fd, &info);
471 	}
472 
473 	if (argc)
474 		return BAD_ARG();
475 
476 	if (json_output)
477 		jsonw_start_array(json_wtr);
478 	while (true) {
479 		err = bpf_map_get_next_id(id, &id);
480 		if (err) {
481 			if (errno == ENOENT)
482 				break;
483 			p_err("can't get next map: %s%s", strerror(errno),
484 			      errno == EINVAL ? " -- kernel too old?" : "");
485 			break;
486 		}
487 
488 		fd = bpf_map_get_fd_by_id(id);
489 		if (fd < 0) {
490 			if (errno == ENOENT)
491 				continue;
492 			p_err("can't get map by id (%u): %s",
493 			      id, strerror(errno));
494 			break;
495 		}
496 
497 		err = bpf_obj_get_info_by_fd(fd, &info, &len);
498 		if (err) {
499 			p_err("can't get map info: %s", strerror(errno));
500 			close(fd);
501 			break;
502 		}
503 
504 		if (json_output)
505 			show_map_close_json(fd, &info);
506 		else
507 			show_map_close_plain(fd, &info);
508 	}
509 	if (json_output)
510 		jsonw_end_array(json_wtr);
511 
512 	return errno == ENOENT ? 0 : -1;
513 }
514 
515 static int do_dump(int argc, char **argv)
516 {
517 	void *key, *value, *prev_key;
518 	unsigned int num_elems = 0;
519 	struct bpf_map_info info = {};
520 	__u32 len = sizeof(info);
521 	int err;
522 	int fd;
523 
524 	if (argc != 2)
525 		usage();
526 
527 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
528 	if (fd < 0)
529 		return -1;
530 
531 	if (map_is_map_of_maps(info.type) || map_is_map_of_progs(info.type)) {
532 		p_err("Dumping maps of maps and program maps not supported");
533 		close(fd);
534 		return -1;
535 	}
536 
537 	key = malloc(info.key_size);
538 	value = alloc_value(&info);
539 	if (!key || !value) {
540 		p_err("mem alloc failed");
541 		err = -1;
542 		goto exit_free;
543 	}
544 
545 	prev_key = NULL;
546 	if (json_output)
547 		jsonw_start_array(json_wtr);
548 	while (true) {
549 		err = bpf_map_get_next_key(fd, prev_key, key);
550 		if (err) {
551 			if (errno == ENOENT)
552 				err = 0;
553 			break;
554 		}
555 
556 		if (!bpf_map_lookup_elem(fd, key, value)) {
557 			if (json_output)
558 				print_entry_json(&info, key, value);
559 			else
560 				print_entry_plain(&info, key, value);
561 		} else {
562 			if (json_output) {
563 				jsonw_name(json_wtr, "key");
564 				print_hex_data_json(key, info.key_size);
565 				jsonw_name(json_wtr, "value");
566 				jsonw_start_object(json_wtr);
567 				jsonw_string_field(json_wtr, "error",
568 						   "can't lookup element");
569 				jsonw_end_object(json_wtr);
570 			} else {
571 				p_info("can't lookup element with key: ");
572 				fprint_hex(stderr, key, info.key_size, " ");
573 				fprintf(stderr, "\n");
574 			}
575 		}
576 
577 		prev_key = key;
578 		num_elems++;
579 	}
580 
581 	if (json_output)
582 		jsonw_end_array(json_wtr);
583 	else
584 		printf("Found %u element%s\n", num_elems,
585 		       num_elems != 1 ? "s" : "");
586 
587 exit_free:
588 	free(key);
589 	free(value);
590 	close(fd);
591 
592 	return err;
593 }
594 
595 static int do_update(int argc, char **argv)
596 {
597 	struct bpf_map_info info = {};
598 	__u32 len = sizeof(info);
599 	__u32 *value_fd = NULL;
600 	__u32 flags = BPF_ANY;
601 	void *key, *value;
602 	int fd, err;
603 
604 	if (argc < 2)
605 		usage();
606 
607 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
608 	if (fd < 0)
609 		return -1;
610 
611 	key = malloc(info.key_size);
612 	value = alloc_value(&info);
613 	if (!key || !value) {
614 		p_err("mem alloc failed");
615 		err = -1;
616 		goto exit_free;
617 	}
618 
619 	err = parse_elem(argv, &info, key, value, info.key_size,
620 			 info.value_size, &flags, &value_fd);
621 	if (err)
622 		goto exit_free;
623 
624 	err = bpf_map_update_elem(fd, key, value, flags);
625 	if (err) {
626 		p_err("update failed: %s", strerror(errno));
627 		goto exit_free;
628 	}
629 
630 exit_free:
631 	if (value_fd)
632 		close(*value_fd);
633 	free(key);
634 	free(value);
635 	close(fd);
636 
637 	if (!err && json_output)
638 		jsonw_null(json_wtr);
639 	return err;
640 }
641 
642 static int do_lookup(int argc, char **argv)
643 {
644 	struct bpf_map_info info = {};
645 	__u32 len = sizeof(info);
646 	void *key, *value;
647 	int err;
648 	int fd;
649 
650 	if (argc < 2)
651 		usage();
652 
653 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
654 	if (fd < 0)
655 		return -1;
656 
657 	key = malloc(info.key_size);
658 	value = alloc_value(&info);
659 	if (!key || !value) {
660 		p_err("mem alloc failed");
661 		err = -1;
662 		goto exit_free;
663 	}
664 
665 	err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
666 	if (err)
667 		goto exit_free;
668 
669 	err = bpf_map_lookup_elem(fd, key, value);
670 	if (!err) {
671 		if (json_output)
672 			print_entry_json(&info, key, value);
673 		else
674 			print_entry_plain(&info, key, value);
675 	} else if (errno == ENOENT) {
676 		if (json_output) {
677 			jsonw_null(json_wtr);
678 		} else {
679 			printf("key:\n");
680 			fprint_hex(stdout, key, info.key_size, " ");
681 			printf("\n\nNot found\n");
682 		}
683 	} else {
684 		p_err("lookup failed: %s", strerror(errno));
685 	}
686 
687 exit_free:
688 	free(key);
689 	free(value);
690 	close(fd);
691 
692 	return err;
693 }
694 
695 static int do_getnext(int argc, char **argv)
696 {
697 	struct bpf_map_info info = {};
698 	__u32 len = sizeof(info);
699 	void *key, *nextkey;
700 	int err;
701 	int fd;
702 
703 	if (argc < 2)
704 		usage();
705 
706 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
707 	if (fd < 0)
708 		return -1;
709 
710 	key = malloc(info.key_size);
711 	nextkey = malloc(info.key_size);
712 	if (!key || !nextkey) {
713 		p_err("mem alloc failed");
714 		err = -1;
715 		goto exit_free;
716 	}
717 
718 	if (argc) {
719 		err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
720 				 NULL, NULL);
721 		if (err)
722 			goto exit_free;
723 	} else {
724 		free(key);
725 		key = NULL;
726 	}
727 
728 	err = bpf_map_get_next_key(fd, key, nextkey);
729 	if (err) {
730 		p_err("can't get next key: %s", strerror(errno));
731 		goto exit_free;
732 	}
733 
734 	if (json_output) {
735 		jsonw_start_object(json_wtr);
736 		if (key) {
737 			jsonw_name(json_wtr, "key");
738 			print_hex_data_json(key, info.key_size);
739 		} else {
740 			jsonw_null_field(json_wtr, "key");
741 		}
742 		jsonw_name(json_wtr, "next_key");
743 		print_hex_data_json(nextkey, info.key_size);
744 		jsonw_end_object(json_wtr);
745 	} else {
746 		if (key) {
747 			printf("key:\n");
748 			fprint_hex(stdout, key, info.key_size, " ");
749 			printf("\n");
750 		} else {
751 			printf("key: None\n");
752 		}
753 		printf("next key:\n");
754 		fprint_hex(stdout, nextkey, info.key_size, " ");
755 		printf("\n");
756 	}
757 
758 exit_free:
759 	free(nextkey);
760 	free(key);
761 	close(fd);
762 
763 	return err;
764 }
765 
766 static int do_delete(int argc, char **argv)
767 {
768 	struct bpf_map_info info = {};
769 	__u32 len = sizeof(info);
770 	void *key;
771 	int err;
772 	int fd;
773 
774 	if (argc < 2)
775 		usage();
776 
777 	fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
778 	if (fd < 0)
779 		return -1;
780 
781 	key = malloc(info.key_size);
782 	if (!key) {
783 		p_err("mem alloc failed");
784 		err = -1;
785 		goto exit_free;
786 	}
787 
788 	err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
789 	if (err)
790 		goto exit_free;
791 
792 	err = bpf_map_delete_elem(fd, key);
793 	if (err)
794 		p_err("delete failed: %s", strerror(errno));
795 
796 exit_free:
797 	free(key);
798 	close(fd);
799 
800 	if (!err && json_output)
801 		jsonw_null(json_wtr);
802 	return err;
803 }
804 
805 static int do_pin(int argc, char **argv)
806 {
807 	int err;
808 
809 	err = do_pin_any(argc, argv, bpf_map_get_fd_by_id);
810 	if (!err && json_output)
811 		jsonw_null(json_wtr);
812 	return err;
813 }
814 
815 static int do_help(int argc, char **argv)
816 {
817 	if (json_output) {
818 		jsonw_null(json_wtr);
819 		return 0;
820 	}
821 
822 	fprintf(stderr,
823 		"Usage: %s %s { show | list }   [MAP]\n"
824 		"       %s %s dump       MAP\n"
825 		"       %s %s update     MAP  key DATA value VALUE [UPDATE_FLAGS]\n"
826 		"       %s %s lookup     MAP  key DATA\n"
827 		"       %s %s getnext    MAP [key DATA]\n"
828 		"       %s %s delete     MAP  key DATA\n"
829 		"       %s %s pin        MAP  FILE\n"
830 		"       %s %s event_pipe MAP [cpu N index M]\n"
831 		"       %s %s help\n"
832 		"\n"
833 		"       MAP := { id MAP_ID | pinned FILE }\n"
834 		"       DATA := { [hex] BYTES }\n"
835 		"       " HELP_SPEC_PROGRAM "\n"
836 		"       VALUE := { DATA | MAP | PROG }\n"
837 		"       UPDATE_FLAGS := { any | exist | noexist }\n"
838 		"       " HELP_SPEC_OPTIONS "\n"
839 		"",
840 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
841 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
842 		bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]);
843 
844 	return 0;
845 }
846 
847 static const struct cmd cmds[] = {
848 	{ "show",	do_show },
849 	{ "list",	do_show },
850 	{ "help",	do_help },
851 	{ "dump",	do_dump },
852 	{ "update",	do_update },
853 	{ "lookup",	do_lookup },
854 	{ "getnext",	do_getnext },
855 	{ "delete",	do_delete },
856 	{ "pin",	do_pin },
857 	{ "event_pipe",	do_event_pipe },
858 	{ 0 }
859 };
860 
861 int do_map(int argc, char **argv)
862 {
863 	return cmd_select(cmds, argc, argv, do_help);
864 }
865