]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - rpmsg/rpmsg.git/blob - tools/bpf/bpftool/map.c
Merge tag 'xfs-fixes-for-4.19-rc7' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[rpmsg/rpmsg.git] / tools / bpf / bpftool / map.c
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  */
34 #include <assert.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <linux/err.h>
38 #include <linux/kernel.h>
39 #include <stdbool.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
47 #include <bpf.h>
49 #include "btf.h"
50 #include "json_writer.h"
51 #include "main.h"
53 static const char * const map_type_name[] = {
54         [BPF_MAP_TYPE_UNSPEC]           = "unspec",
55         [BPF_MAP_TYPE_HASH]             = "hash",
56         [BPF_MAP_TYPE_ARRAY]            = "array",
57         [BPF_MAP_TYPE_PROG_ARRAY]       = "prog_array",
58         [BPF_MAP_TYPE_PERF_EVENT_ARRAY] = "perf_event_array",
59         [BPF_MAP_TYPE_PERCPU_HASH]      = "percpu_hash",
60         [BPF_MAP_TYPE_PERCPU_ARRAY]     = "percpu_array",
61         [BPF_MAP_TYPE_STACK_TRACE]      = "stack_trace",
62         [BPF_MAP_TYPE_CGROUP_ARRAY]     = "cgroup_array",
63         [BPF_MAP_TYPE_LRU_HASH]         = "lru_hash",
64         [BPF_MAP_TYPE_LRU_PERCPU_HASH]  = "lru_percpu_hash",
65         [BPF_MAP_TYPE_LPM_TRIE]         = "lpm_trie",
66         [BPF_MAP_TYPE_ARRAY_OF_MAPS]    = "array_of_maps",
67         [BPF_MAP_TYPE_HASH_OF_MAPS]     = "hash_of_maps",
68         [BPF_MAP_TYPE_DEVMAP]           = "devmap",
69         [BPF_MAP_TYPE_SOCKMAP]          = "sockmap",
70         [BPF_MAP_TYPE_CPUMAP]           = "cpumap",
71         [BPF_MAP_TYPE_XSKMAP]           = "xskmap",
72         [BPF_MAP_TYPE_SOCKHASH]         = "sockhash",
73         [BPF_MAP_TYPE_CGROUP_STORAGE]   = "cgroup_storage",
74 };
76 static bool map_is_per_cpu(__u32 type)
77 {
78         return type == BPF_MAP_TYPE_PERCPU_HASH ||
79                type == BPF_MAP_TYPE_PERCPU_ARRAY ||
80                type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
81 }
83 static bool map_is_map_of_maps(__u32 type)
84 {
85         return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
86                type == BPF_MAP_TYPE_HASH_OF_MAPS;
87 }
89 static bool map_is_map_of_progs(__u32 type)
90 {
91         return type == BPF_MAP_TYPE_PROG_ARRAY;
92 }
94 static void *alloc_value(struct bpf_map_info *info)
95 {
96         if (map_is_per_cpu(info->type))
97                 return malloc(round_up(info->value_size, 8) *
98                               get_possible_cpus());
99         else
100                 return malloc(info->value_size);
103 int map_parse_fd(int *argc, char ***argv)
105         int fd;
107         if (is_prefix(**argv, "id")) {
108                 unsigned int id;
109                 char *endptr;
111                 NEXT_ARGP();
113                 id = strtoul(**argv, &endptr, 0);
114                 if (*endptr) {
115                         p_err("can't parse %s as ID", **argv);
116                         return -1;
117                 }
118                 NEXT_ARGP();
120                 fd = bpf_map_get_fd_by_id(id);
121                 if (fd < 0)
122                         p_err("get map by id (%u): %s", id, strerror(errno));
123                 return fd;
124         } else if (is_prefix(**argv, "pinned")) {
125                 char *path;
127                 NEXT_ARGP();
129                 path = **argv;
130                 NEXT_ARGP();
132                 return open_obj_pinned_any(path, BPF_OBJ_MAP);
133         }
135         p_err("expected 'id' or 'pinned', got: '%s'?", **argv);
136         return -1;
139 int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len)
141         int err;
142         int fd;
144         fd = map_parse_fd(argc, argv);
145         if (fd < 0)
146                 return -1;
148         err = bpf_obj_get_info_by_fd(fd, info, info_len);
149         if (err) {
150                 p_err("can't get map info: %s", strerror(errno));
151                 close(fd);
152                 return err;
153         }
155         return fd;
158 static int do_dump_btf(const struct btf_dumper *d,
159                        struct bpf_map_info *map_info, void *key,
160                        void *value)
162         int ret;
164         /* start of key-value pair */
165         jsonw_start_object(d->jw);
167         jsonw_name(d->jw, "key");
169         ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
170         if (ret)
171                 goto err_end_obj;
173         jsonw_name(d->jw, "value");
175         ret = btf_dumper_type(d, map_info->btf_value_type_id, value);
177 err_end_obj:
178         /* end of key-value pair */
179         jsonw_end_object(d->jw);
181         return ret;
184 static int get_btf(struct bpf_map_info *map_info, struct btf **btf)
186         struct bpf_btf_info btf_info = { 0 };
187         __u32 len = sizeof(btf_info);
188         __u32 last_size;
189         int btf_fd;
190         void *ptr;
191         int err;
193         err = 0;
194         *btf = NULL;
195         btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id);
196         if (btf_fd < 0)
197                 return 0;
199         /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
200          * let's start with a sane default - 4KiB here - and resize it only if
201          * bpf_obj_get_info_by_fd() needs a bigger buffer.
202          */
203         btf_info.btf_size = 4096;
204         last_size = btf_info.btf_size;
205         ptr = malloc(last_size);
206         if (!ptr) {
207                 err = -ENOMEM;
208                 goto exit_free;
209         }
211         bzero(ptr, last_size);
212         btf_info.btf = ptr_to_u64(ptr);
213         err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
215         if (!err && btf_info.btf_size > last_size) {
216                 void *temp_ptr;
218                 last_size = btf_info.btf_size;
219                 temp_ptr = realloc(ptr, last_size);
220                 if (!temp_ptr) {
221                         err = -ENOMEM;
222                         goto exit_free;
223                 }
224                 ptr = temp_ptr;
225                 bzero(ptr, last_size);
226                 btf_info.btf = ptr_to_u64(ptr);
227                 err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
228         }
230         if (err || btf_info.btf_size > last_size) {
231                 err = errno;
232                 goto exit_free;
233         }
235         *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);
236         if (IS_ERR(*btf)) {
237                 err = PTR_ERR(*btf);
238                 *btf = NULL;
239         }
241 exit_free:
242         close(btf_fd);
243         free(ptr);
245         return err;
248 static json_writer_t *get_btf_writer(void)
250         json_writer_t *jw = jsonw_new(stdout);
252         if (!jw)
253                 return NULL;
254         jsonw_pretty(jw, true);
256         return jw;
259 static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
260                              unsigned char *value, struct btf *btf)
262         jsonw_start_object(json_wtr);
264         if (!map_is_per_cpu(info->type)) {
265                 jsonw_name(json_wtr, "key");
266                 print_hex_data_json(key, info->key_size);
267                 jsonw_name(json_wtr, "value");
268                 print_hex_data_json(value, info->value_size);
269                 if (btf) {
270                         struct btf_dumper d = {
271                                 .btf = btf,
272                                 .jw = json_wtr,
273                                 .is_plain_text = false,
274                         };
276                         jsonw_name(json_wtr, "formatted");
277                         do_dump_btf(&d, info, key, value);
278                 }
279         } else {
280                 unsigned int i, n, step;
282                 n = get_possible_cpus();
283                 step = round_up(info->value_size, 8);
285                 jsonw_name(json_wtr, "key");
286                 print_hex_data_json(key, info->key_size);
288                 jsonw_name(json_wtr, "values");
289                 jsonw_start_array(json_wtr);
290                 for (i = 0; i < n; i++) {
291                         jsonw_start_object(json_wtr);
293                         jsonw_int_field(json_wtr, "cpu", i);
295                         jsonw_name(json_wtr, "value");
296                         print_hex_data_json(value + i * step,
297                                             info->value_size);
299                         jsonw_end_object(json_wtr);
300                 }
301                 jsonw_end_array(json_wtr);
302         }
304         jsonw_end_object(json_wtr);
307 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
308                               unsigned char *value)
310         if (!map_is_per_cpu(info->type)) {
311                 bool single_line, break_names;
313                 break_names = info->key_size > 16 || info->value_size > 16;
314                 single_line = info->key_size + info->value_size <= 24 &&
315                         !break_names;
317                 printf("key:%c", break_names ? '\n' : ' ');
318                 fprint_hex(stdout, key, info->key_size, " ");
320                 printf(single_line ? "  " : "\n");
322                 printf("value:%c", break_names ? '\n' : ' ');
323                 fprint_hex(stdout, value, info->value_size, " ");
325                 printf("\n");
326         } else {
327                 unsigned int i, n, step;
329                 n = get_possible_cpus();
330                 step = round_up(info->value_size, 8);
332                 printf("key:\n");
333                 fprint_hex(stdout, key, info->key_size, " ");
334                 printf("\n");
335                 for (i = 0; i < n; i++) {
336                         printf("value (CPU %02d):%c",
337                                i, info->value_size > 16 ? '\n' : ' ');
338                         fprint_hex(stdout, value + i * step,
339                                    info->value_size, " ");
340                         printf("\n");
341                 }
342         }
345 static char **parse_bytes(char **argv, const char *name, unsigned char *val,
346                           unsigned int n)
348         unsigned int i = 0, base = 0;
349         char *endptr;
351         if (is_prefix(*argv, "hex")) {
352                 base = 16;
353                 argv++;
354         }
356         while (i < n && argv[i]) {
357                 val[i] = strtoul(argv[i], &endptr, base);
358                 if (*endptr) {
359                         p_err("error parsing byte: %s", argv[i]);
360                         return NULL;
361                 }
362                 i++;
363         }
365         if (i != n) {
366                 p_err("%s expected %d bytes got %d", name, n, i);
367                 return NULL;
368         }
370         return argv + i;
373 static int parse_elem(char **argv, struct bpf_map_info *info,
374                       void *key, void *value, __u32 key_size, __u32 value_size,
375                       __u32 *flags, __u32 **value_fd)
377         if (!*argv) {
378                 if (!key && !value)
379                         return 0;
380                 p_err("did not find %s", key ? "key" : "value");
381                 return -1;
382         }
384         if (is_prefix(*argv, "key")) {
385                 if (!key) {
386                         if (key_size)
387                                 p_err("duplicate key");
388                         else
389                                 p_err("unnecessary key");
390                         return -1;
391                 }
393                 argv = parse_bytes(argv + 1, "key", key, key_size);
394                 if (!argv)
395                         return -1;
397                 return parse_elem(argv, info, NULL, value, key_size, value_size,
398                                   flags, value_fd);
399         } else if (is_prefix(*argv, "value")) {
400                 int fd;
402                 if (!value) {
403                         if (value_size)
404                                 p_err("duplicate value");
405                         else
406                                 p_err("unnecessary value");
407                         return -1;
408                 }
410                 argv++;
412                 if (map_is_map_of_maps(info->type)) {
413                         int argc = 2;
415                         if (value_size != 4) {
416                                 p_err("value smaller than 4B for map in map?");
417                                 return -1;
418                         }
419                         if (!argv[0] || !argv[1]) {
420                                 p_err("not enough value arguments for map in map");
421                                 return -1;
422                         }
424                         fd = map_parse_fd(&argc, &argv);
425                         if (fd < 0)
426                                 return -1;
428                         *value_fd = value;
429                         **value_fd = fd;
430                 } else if (map_is_map_of_progs(info->type)) {
431                         int argc = 2;
433                         if (value_size != 4) {
434                                 p_err("value smaller than 4B for map of progs?");
435                                 return -1;
436                         }
437                         if (!argv[0] || !argv[1]) {
438                                 p_err("not enough value arguments for map of progs");
439                                 return -1;
440                         }
442                         fd = prog_parse_fd(&argc, &argv);
443                         if (fd < 0)
444                                 return -1;
446                         *value_fd = value;
447                         **value_fd = fd;
448                 } else {
449                         argv = parse_bytes(argv, "value", value, value_size);
450                         if (!argv)
451                                 return -1;
452                 }
454                 return parse_elem(argv, info, key, NULL, key_size, value_size,
455                                   flags, NULL);
456         } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
457                    is_prefix(*argv, "exist")) {
458                 if (!flags) {
459                         p_err("flags specified multiple times: %s", *argv);
460                         return -1;
461                 }
463                 if (is_prefix(*argv, "any"))
464                         *flags = BPF_ANY;
465                 else if (is_prefix(*argv, "noexist"))
466                         *flags = BPF_NOEXIST;
467                 else if (is_prefix(*argv, "exist"))
468                         *flags = BPF_EXIST;
470                 return parse_elem(argv + 1, info, key, value, key_size,
471                                   value_size, NULL, value_fd);
472         }
474         p_err("expected key or value, got: %s", *argv);
475         return -1;
478 static int show_map_close_json(int fd, struct bpf_map_info *info)
480         char *memlock;
482         memlock = get_fdinfo(fd, "memlock");
483         close(fd);
485         jsonw_start_object(json_wtr);
487         jsonw_uint_field(json_wtr, "id", info->id);
488         if (info->type < ARRAY_SIZE(map_type_name))
489                 jsonw_string_field(json_wtr, "type",
490                                    map_type_name[info->type]);
491         else
492                 jsonw_uint_field(json_wtr, "type", info->type);
494         if (*info->name)
495                 jsonw_string_field(json_wtr, "name", info->name);
497         jsonw_name(json_wtr, "flags");
498         jsonw_printf(json_wtr, "%d", info->map_flags);
500         print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
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);
506         if (memlock)
507                 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
508         free(memlock);
510         if (!hash_empty(map_table.table)) {
511                 struct pinned_obj *obj;
513                 jsonw_name(json_wtr, "pinned");
514                 jsonw_start_array(json_wtr);
515                 hash_for_each_possible(map_table.table, obj, hash, info->id) {
516                         if (obj->id == info->id)
517                                 jsonw_string(json_wtr, obj->path);
518                 }
519                 jsonw_end_array(json_wtr);
520         }
522         jsonw_end_object(json_wtr);
524         return 0;
527 static int show_map_close_plain(int fd, struct bpf_map_info *info)
529         char *memlock;
531         memlock = get_fdinfo(fd, "memlock");
532         close(fd);
534         printf("%u: ", info->id);
535         if (info->type < ARRAY_SIZE(map_type_name))
536                 printf("%s  ", map_type_name[info->type]);
537         else
538                 printf("type %u  ", info->type);
540         if (*info->name)
541                 printf("name %s  ", info->name);
543         printf("flags 0x%x", info->map_flags);
544         print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
545         printf("\n");
546         printf("\tkey %uB  value %uB  max_entries %u",
547                info->key_size, info->value_size, info->max_entries);
549         if (memlock)
550                 printf("  memlock %sB", memlock);
551         free(memlock);
553         printf("\n");
554         if (!hash_empty(map_table.table)) {
555                 struct pinned_obj *obj;
557                 hash_for_each_possible(map_table.table, obj, hash, info->id) {
558                         if (obj->id == info->id)
559                                 printf("\tpinned %s\n", obj->path);
560                 }
561         }
562         return 0;
565 static int do_show(int argc, char **argv)
567         struct bpf_map_info info = {};
568         __u32 len = sizeof(info);
569         __u32 id = 0;
570         int err;
571         int fd;
573         if (show_pinned)
574                 build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
576         if (argc == 2) {
577                 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
578                 if (fd < 0)
579                         return -1;
581                 if (json_output)
582                         return show_map_close_json(fd, &info);
583                 else
584                         return show_map_close_plain(fd, &info);
585         }
587         if (argc)
588                 return BAD_ARG();
590         if (json_output)
591                 jsonw_start_array(json_wtr);
592         while (true) {
593                 err = bpf_map_get_next_id(id, &id);
594                 if (err) {
595                         if (errno == ENOENT)
596                                 break;
597                         p_err("can't get next map: %s%s", strerror(errno),
598                               errno == EINVAL ? " -- kernel too old?" : "");
599                         break;
600                 }
602                 fd = bpf_map_get_fd_by_id(id);
603                 if (fd < 0) {
604                         if (errno == ENOENT)
605                                 continue;
606                         p_err("can't get map by id (%u): %s",
607                               id, strerror(errno));
608                         break;
609                 }
611                 err = bpf_obj_get_info_by_fd(fd, &info, &len);
612                 if (err) {
613                         p_err("can't get map info: %s", strerror(errno));
614                         close(fd);
615                         break;
616                 }
618                 if (json_output)
619                         show_map_close_json(fd, &info);
620                 else
621                         show_map_close_plain(fd, &info);
622         }
623         if (json_output)
624                 jsonw_end_array(json_wtr);
626         return errno == ENOENT ? 0 : -1;
629 static int do_dump(int argc, char **argv)
631         struct bpf_map_info info = {};
632         void *key, *value, *prev_key;
633         unsigned int num_elems = 0;
634         __u32 len = sizeof(info);
635         json_writer_t *btf_wtr;
636         struct btf *btf = NULL;
637         int err;
638         int fd;
640         if (argc != 2)
641                 usage();
643         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
644         if (fd < 0)
645                 return -1;
647         if (map_is_map_of_maps(info.type) || map_is_map_of_progs(info.type)) {
648                 p_err("Dumping maps of maps and program maps not supported");
649                 close(fd);
650                 return -1;
651         }
653         key = malloc(info.key_size);
654         value = alloc_value(&info);
655         if (!key || !value) {
656                 p_err("mem alloc failed");
657                 err = -1;
658                 goto exit_free;
659         }
661         prev_key = NULL;
663         err = get_btf(&info, &btf);
664         if (err) {
665                 p_err("failed to get btf");
666                 goto exit_free;
667         }
669         if (json_output)
670                 jsonw_start_array(json_wtr);
671         else
672                 if (btf) {
673                         btf_wtr = get_btf_writer();
674                         if (!btf_wtr) {
675                                 p_info("failed to create json writer for btf. falling back to plain output");
676                                 btf__free(btf);
677                                 btf = NULL;
678                         } else {
679                                 jsonw_start_array(btf_wtr);
680                         }
681                 }
683         while (true) {
684                 err = bpf_map_get_next_key(fd, prev_key, key);
685                 if (err) {
686                         if (errno == ENOENT)
687                                 err = 0;
688                         break;
689                 }
691                 if (!bpf_map_lookup_elem(fd, key, value)) {
692                         if (json_output)
693                                 print_entry_json(&info, key, value, btf);
694                         else
695                                 if (btf) {
696                                         struct btf_dumper d = {
697                                                 .btf = btf,
698                                                 .jw = btf_wtr,
699                                                 .is_plain_text = true,
700                                         };
702                                         do_dump_btf(&d, &info, key, value);
703                                 } else {
704                                         print_entry_plain(&info, key, value);
705                                 }
706                 } else {
707                         if (json_output) {
708                                 jsonw_name(json_wtr, "key");
709                                 print_hex_data_json(key, info.key_size);
710                                 jsonw_name(json_wtr, "value");
711                                 jsonw_start_object(json_wtr);
712                                 jsonw_string_field(json_wtr, "error",
713                                                    "can't lookup element");
714                                 jsonw_end_object(json_wtr);
715                         } else {
716                                 p_info("can't lookup element with key: ");
717                                 fprint_hex(stderr, key, info.key_size, " ");
718                                 fprintf(stderr, "\n");
719                         }
720                 }
722                 prev_key = key;
723                 num_elems++;
724         }
726         if (json_output)
727                 jsonw_end_array(json_wtr);
728         else if (btf) {
729                 jsonw_end_array(btf_wtr);
730                 jsonw_destroy(&btf_wtr);
731         } else {
732                 printf("Found %u element%s\n", num_elems,
733                        num_elems != 1 ? "s" : "");
734         }
736 exit_free:
737         free(key);
738         free(value);
739         close(fd);
740         btf__free(btf);
742         return err;
745 static int do_update(int argc, char **argv)
747         struct bpf_map_info info = {};
748         __u32 len = sizeof(info);
749         __u32 *value_fd = NULL;
750         __u32 flags = BPF_ANY;
751         void *key, *value;
752         int fd, err;
754         if (argc < 2)
755                 usage();
757         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
758         if (fd < 0)
759                 return -1;
761         key = malloc(info.key_size);
762         value = alloc_value(&info);
763         if (!key || !value) {
764                 p_err("mem alloc failed");
765                 err = -1;
766                 goto exit_free;
767         }
769         err = parse_elem(argv, &info, key, value, info.key_size,
770                          info.value_size, &flags, &value_fd);
771         if (err)
772                 goto exit_free;
774         err = bpf_map_update_elem(fd, key, value, flags);
775         if (err) {
776                 p_err("update failed: %s", strerror(errno));
777                 goto exit_free;
778         }
780 exit_free:
781         if (value_fd)
782                 close(*value_fd);
783         free(key);
784         free(value);
785         close(fd);
787         if (!err && json_output)
788                 jsonw_null(json_wtr);
789         return err;
792 static int do_lookup(int argc, char **argv)
794         struct bpf_map_info info = {};
795         __u32 len = sizeof(info);
796         json_writer_t *btf_wtr;
797         struct btf *btf = NULL;
798         void *key, *value;
799         int err;
800         int fd;
802         if (argc < 2)
803                 usage();
805         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
806         if (fd < 0)
807                 return -1;
809         key = malloc(info.key_size);
810         value = alloc_value(&info);
811         if (!key || !value) {
812                 p_err("mem alloc failed");
813                 err = -1;
814                 goto exit_free;
815         }
817         err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
818         if (err)
819                 goto exit_free;
821         err = bpf_map_lookup_elem(fd, key, value);
822         if (err) {
823                 if (errno == ENOENT) {
824                         if (json_output) {
825                                 jsonw_null(json_wtr);
826                         } else {
827                                 printf("key:\n");
828                                 fprint_hex(stdout, key, info.key_size, " ");
829                                 printf("\n\nNot found\n");
830                         }
831                 } else {
832                         p_err("lookup failed: %s", strerror(errno));
833                 }
835                 goto exit_free;
836         }
838         /* here means bpf_map_lookup_elem() succeeded */
839         err = get_btf(&info, &btf);
840         if (err) {
841                 p_err("failed to get btf");
842                 goto exit_free;
843         }
845         if (json_output) {
846                 print_entry_json(&info, key, value, btf);
847         } else if (btf) {
848                 /* if here json_wtr wouldn't have been initialised,
849                  * so let's create separate writer for btf
850                  */
851                 btf_wtr = get_btf_writer();
852                 if (!btf_wtr) {
853                         p_info("failed to create json writer for btf. falling back to plain output");
854                         btf__free(btf);
855                         btf = NULL;
856                         print_entry_plain(&info, key, value);
857                 } else {
858                         struct btf_dumper d = {
859                                 .btf = btf,
860                                 .jw = btf_wtr,
861                                 .is_plain_text = true,
862                         };
864                         do_dump_btf(&d, &info, key, value);
865                         jsonw_destroy(&btf_wtr);
866                 }
867         } else {
868                 print_entry_plain(&info, key, value);
869         }
871 exit_free:
872         free(key);
873         free(value);
874         close(fd);
875         btf__free(btf);
877         return err;
880 static int do_getnext(int argc, char **argv)
882         struct bpf_map_info info = {};
883         __u32 len = sizeof(info);
884         void *key, *nextkey;
885         int err;
886         int fd;
888         if (argc < 2)
889                 usage();
891         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
892         if (fd < 0)
893                 return -1;
895         key = malloc(info.key_size);
896         nextkey = malloc(info.key_size);
897         if (!key || !nextkey) {
898                 p_err("mem alloc failed");
899                 err = -1;
900                 goto exit_free;
901         }
903         if (argc) {
904                 err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
905                                  NULL, NULL);
906                 if (err)
907                         goto exit_free;
908         } else {
909                 free(key);
910                 key = NULL;
911         }
913         err = bpf_map_get_next_key(fd, key, nextkey);
914         if (err) {
915                 p_err("can't get next key: %s", strerror(errno));
916                 goto exit_free;
917         }
919         if (json_output) {
920                 jsonw_start_object(json_wtr);
921                 if (key) {
922                         jsonw_name(json_wtr, "key");
923                         print_hex_data_json(key, info.key_size);
924                 } else {
925                         jsonw_null_field(json_wtr, "key");
926                 }
927                 jsonw_name(json_wtr, "next_key");
928                 print_hex_data_json(nextkey, info.key_size);
929                 jsonw_end_object(json_wtr);
930         } else {
931                 if (key) {
932                         printf("key:\n");
933                         fprint_hex(stdout, key, info.key_size, " ");
934                         printf("\n");
935                 } else {
936                         printf("key: None\n");
937                 }
938                 printf("next key:\n");
939                 fprint_hex(stdout, nextkey, info.key_size, " ");
940                 printf("\n");
941         }
943 exit_free:
944         free(nextkey);
945         free(key);
946         close(fd);
948         return err;
951 static int do_delete(int argc, char **argv)
953         struct bpf_map_info info = {};
954         __u32 len = sizeof(info);
955         void *key;
956         int err;
957         int fd;
959         if (argc < 2)
960                 usage();
962         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
963         if (fd < 0)
964                 return -1;
966         key = malloc(info.key_size);
967         if (!key) {
968                 p_err("mem alloc failed");
969                 err = -1;
970                 goto exit_free;
971         }
973         err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
974         if (err)
975                 goto exit_free;
977         err = bpf_map_delete_elem(fd, key);
978         if (err)
979                 p_err("delete failed: %s", strerror(errno));
981 exit_free:
982         free(key);
983         close(fd);
985         if (!err && json_output)
986                 jsonw_null(json_wtr);
987         return err;
990 static int do_pin(int argc, char **argv)
992         int err;
994         err = do_pin_any(argc, argv, bpf_map_get_fd_by_id);
995         if (!err && json_output)
996                 jsonw_null(json_wtr);
997         return err;
1000 static int do_help(int argc, char **argv)
1002         if (json_output) {
1003                 jsonw_null(json_wtr);
1004                 return 0;
1005         }
1007         fprintf(stderr,
1008                 "Usage: %s %s { show | list }   [MAP]\n"
1009                 "       %s %s dump       MAP\n"
1010                 "       %s %s update     MAP  key DATA value VALUE [UPDATE_FLAGS]\n"
1011                 "       %s %s lookup     MAP  key DATA\n"
1012                 "       %s %s getnext    MAP [key DATA]\n"
1013                 "       %s %s delete     MAP  key DATA\n"
1014                 "       %s %s pin        MAP  FILE\n"
1015                 "       %s %s event_pipe MAP [cpu N index M]\n"
1016                 "       %s %s help\n"
1017                 "\n"
1018                 "       " HELP_SPEC_MAP "\n"
1019                 "       DATA := { [hex] BYTES }\n"
1020                 "       " HELP_SPEC_PROGRAM "\n"
1021                 "       VALUE := { DATA | MAP | PROG }\n"
1022                 "       UPDATE_FLAGS := { any | exist | noexist }\n"
1023                 "       " HELP_SPEC_OPTIONS "\n"
1024                 "",
1025                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1026                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1027                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]);
1029         return 0;
1032 static const struct cmd cmds[] = {
1033         { "show",       do_show },
1034         { "list",       do_show },
1035         { "help",       do_help },
1036         { "dump",       do_dump },
1037         { "update",     do_update },
1038         { "lookup",     do_lookup },
1039         { "getnext",    do_getnext },
1040         { "delete",     do_delete },
1041         { "pin",        do_pin },
1042         { "event_pipe", do_event_pipe },
1043         { 0 }
1044 };
1046 int do_map(int argc, char **argv)
1048         return cmd_select(cmds, argc, argv, do_help);