]> asedeno.scripts.mit.edu Git - linux.git/blob - tools/bpf/bpftool/map.c
bpftool: add support for CGROUP_STORAGE maps
[linux.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  */
33
34 #include <assert.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <linux/err.h>
38 #include <stdbool.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45
46 #include <bpf.h>
47
48 #include "btf.h"
49 #include "json_writer.h"
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         [BPF_MAP_TYPE_CGROUP_STORAGE]   = "cgroup_storage",
72 };
73
74 static bool map_is_per_cpu(__u32 type)
75 {
76         return type == BPF_MAP_TYPE_PERCPU_HASH ||
77                type == BPF_MAP_TYPE_PERCPU_ARRAY ||
78                type == BPF_MAP_TYPE_LRU_PERCPU_HASH;
79 }
80
81 static bool map_is_map_of_maps(__u32 type)
82 {
83         return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
84                type == BPF_MAP_TYPE_HASH_OF_MAPS;
85 }
86
87 static bool map_is_map_of_progs(__u32 type)
88 {
89         return type == BPF_MAP_TYPE_PROG_ARRAY;
90 }
91
92 static void *alloc_value(struct bpf_map_info *info)
93 {
94         if (map_is_per_cpu(info->type))
95                 return malloc(info->value_size * get_possible_cpus());
96         else
97                 return malloc(info->value_size);
98 }
99
100 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 int do_dump_btf(const struct btf_dumper *d,
156                        struct bpf_map_info *map_info, void *key,
157                        void *value)
158 {
159         int ret;
160
161         /* start of key-value pair */
162         jsonw_start_object(d->jw);
163
164         jsonw_name(d->jw, "key");
165
166         ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
167         if (ret)
168                 goto err_end_obj;
169
170         jsonw_name(d->jw, "value");
171
172         ret = btf_dumper_type(d, map_info->btf_value_type_id, value);
173
174 err_end_obj:
175         /* end of key-value pair */
176         jsonw_end_object(d->jw);
177
178         return ret;
179 }
180
181 static int get_btf(struct bpf_map_info *map_info, struct btf **btf)
182 {
183         struct bpf_btf_info btf_info = { 0 };
184         __u32 len = sizeof(btf_info);
185         __u32 last_size;
186         int btf_fd;
187         void *ptr;
188         int err;
189
190         err = 0;
191         *btf = NULL;
192         btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id);
193         if (btf_fd < 0)
194                 return 0;
195
196         /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so
197          * let's start with a sane default - 4KiB here - and resize it only if
198          * bpf_obj_get_info_by_fd() needs a bigger buffer.
199          */
200         btf_info.btf_size = 4096;
201         last_size = btf_info.btf_size;
202         ptr = malloc(last_size);
203         if (!ptr) {
204                 err = -ENOMEM;
205                 goto exit_free;
206         }
207
208         bzero(ptr, last_size);
209         btf_info.btf = ptr_to_u64(ptr);
210         err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
211
212         if (!err && btf_info.btf_size > last_size) {
213                 void *temp_ptr;
214
215                 last_size = btf_info.btf_size;
216                 temp_ptr = realloc(ptr, last_size);
217                 if (!temp_ptr) {
218                         err = -ENOMEM;
219                         goto exit_free;
220                 }
221                 ptr = temp_ptr;
222                 bzero(ptr, last_size);
223                 btf_info.btf = ptr_to_u64(ptr);
224                 err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len);
225         }
226
227         if (err || btf_info.btf_size > last_size) {
228                 err = errno;
229                 goto exit_free;
230         }
231
232         *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL);
233         if (IS_ERR(*btf)) {
234                 err = PTR_ERR(*btf);
235                 *btf = NULL;
236         }
237
238 exit_free:
239         close(btf_fd);
240         free(ptr);
241
242         return err;
243 }
244
245 static json_writer_t *get_btf_writer(void)
246 {
247         json_writer_t *jw = jsonw_new(stdout);
248
249         if (!jw)
250                 return NULL;
251         jsonw_pretty(jw, true);
252
253         return jw;
254 }
255
256 static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
257                              unsigned char *value, struct btf *btf)
258 {
259         jsonw_start_object(json_wtr);
260
261         if (!map_is_per_cpu(info->type)) {
262                 jsonw_name(json_wtr, "key");
263                 print_hex_data_json(key, info->key_size);
264                 jsonw_name(json_wtr, "value");
265                 print_hex_data_json(value, info->value_size);
266                 if (btf) {
267                         struct btf_dumper d = {
268                                 .btf = btf,
269                                 .jw = json_wtr,
270                                 .is_plain_text = false,
271                         };
272
273                         jsonw_name(json_wtr, "formatted");
274                         do_dump_btf(&d, info, key, value);
275                 }
276         } else {
277                 unsigned int i, n;
278
279                 n = get_possible_cpus();
280
281                 jsonw_name(json_wtr, "key");
282                 print_hex_data_json(key, info->key_size);
283
284                 jsonw_name(json_wtr, "values");
285                 jsonw_start_array(json_wtr);
286                 for (i = 0; i < n; i++) {
287                         jsonw_start_object(json_wtr);
288
289                         jsonw_int_field(json_wtr, "cpu", i);
290
291                         jsonw_name(json_wtr, "value");
292                         print_hex_data_json(value + i * info->value_size,
293                                             info->value_size);
294
295                         jsonw_end_object(json_wtr);
296                 }
297                 jsonw_end_array(json_wtr);
298         }
299
300         jsonw_end_object(json_wtr);
301 }
302
303 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
304                               unsigned char *value)
305 {
306         if (!map_is_per_cpu(info->type)) {
307                 bool single_line, break_names;
308
309                 break_names = info->key_size > 16 || info->value_size > 16;
310                 single_line = info->key_size + info->value_size <= 24 &&
311                         !break_names;
312
313                 printf("key:%c", break_names ? '\n' : ' ');
314                 fprint_hex(stdout, key, info->key_size, " ");
315
316                 printf(single_line ? "  " : "\n");
317
318                 printf("value:%c", break_names ? '\n' : ' ');
319                 fprint_hex(stdout, value, info->value_size, " ");
320
321                 printf("\n");
322         } else {
323                 unsigned int i, n;
324
325                 n = get_possible_cpus();
326
327                 printf("key:\n");
328                 fprint_hex(stdout, key, info->key_size, " ");
329                 printf("\n");
330                 for (i = 0; i < n; i++) {
331                         printf("value (CPU %02d):%c",
332                                i, info->value_size > 16 ? '\n' : ' ');
333                         fprint_hex(stdout, value + i * info->value_size,
334                                    info->value_size, " ");
335                         printf("\n");
336                 }
337         }
338 }
339
340 static char **parse_bytes(char **argv, const char *name, unsigned char *val,
341                           unsigned int n)
342 {
343         unsigned int i = 0, base = 0;
344         char *endptr;
345
346         if (is_prefix(*argv, "hex")) {
347                 base = 16;
348                 argv++;
349         }
350
351         while (i < n && argv[i]) {
352                 val[i] = strtoul(argv[i], &endptr, base);
353                 if (*endptr) {
354                         p_err("error parsing byte: %s", argv[i]);
355                         return NULL;
356                 }
357                 i++;
358         }
359
360         if (i != n) {
361                 p_err("%s expected %d bytes got %d", name, n, i);
362                 return NULL;
363         }
364
365         return argv + i;
366 }
367
368 static int parse_elem(char **argv, struct bpf_map_info *info,
369                       void *key, void *value, __u32 key_size, __u32 value_size,
370                       __u32 *flags, __u32 **value_fd)
371 {
372         if (!*argv) {
373                 if (!key && !value)
374                         return 0;
375                 p_err("did not find %s", key ? "key" : "value");
376                 return -1;
377         }
378
379         if (is_prefix(*argv, "key")) {
380                 if (!key) {
381                         if (key_size)
382                                 p_err("duplicate key");
383                         else
384                                 p_err("unnecessary key");
385                         return -1;
386                 }
387
388                 argv = parse_bytes(argv + 1, "key", key, key_size);
389                 if (!argv)
390                         return -1;
391
392                 return parse_elem(argv, info, NULL, value, key_size, value_size,
393                                   flags, value_fd);
394         } else if (is_prefix(*argv, "value")) {
395                 int fd;
396
397                 if (!value) {
398                         if (value_size)
399                                 p_err("duplicate value");
400                         else
401                                 p_err("unnecessary value");
402                         return -1;
403                 }
404
405                 argv++;
406
407                 if (map_is_map_of_maps(info->type)) {
408                         int argc = 2;
409
410                         if (value_size != 4) {
411                                 p_err("value smaller than 4B for map in map?");
412                                 return -1;
413                         }
414                         if (!argv[0] || !argv[1]) {
415                                 p_err("not enough value arguments for map in map");
416                                 return -1;
417                         }
418
419                         fd = map_parse_fd(&argc, &argv);
420                         if (fd < 0)
421                                 return -1;
422
423                         *value_fd = value;
424                         **value_fd = fd;
425                 } else if (map_is_map_of_progs(info->type)) {
426                         int argc = 2;
427
428                         if (value_size != 4) {
429                                 p_err("value smaller than 4B for map of progs?");
430                                 return -1;
431                         }
432                         if (!argv[0] || !argv[1]) {
433                                 p_err("not enough value arguments for map of progs");
434                                 return -1;
435                         }
436
437                         fd = prog_parse_fd(&argc, &argv);
438                         if (fd < 0)
439                                 return -1;
440
441                         *value_fd = value;
442                         **value_fd = fd;
443                 } else {
444                         argv = parse_bytes(argv, "value", value, value_size);
445                         if (!argv)
446                                 return -1;
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
473 static int show_map_close_json(int fd, struct bpf_map_info *info)
474 {
475         char *memlock;
476
477         memlock = get_fdinfo(fd, "memlock");
478         close(fd);
479
480         jsonw_start_object(json_wtr);
481
482         jsonw_uint_field(json_wtr, "id", info->id);
483         if (info->type < ARRAY_SIZE(map_type_name))
484                 jsonw_string_field(json_wtr, "type",
485                                    map_type_name[info->type]);
486         else
487                 jsonw_uint_field(json_wtr, "type", info->type);
488
489         if (*info->name)
490                 jsonw_string_field(json_wtr, "name", info->name);
491
492         jsonw_name(json_wtr, "flags");
493         jsonw_printf(json_wtr, "%d", info->map_flags);
494
495         print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
496
497         jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
498         jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
499         jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
500
501         if (memlock)
502                 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
503         free(memlock);
504
505         if (!hash_empty(map_table.table)) {
506                 struct pinned_obj *obj;
507
508                 jsonw_name(json_wtr, "pinned");
509                 jsonw_start_array(json_wtr);
510                 hash_for_each_possible(map_table.table, obj, hash, info->id) {
511                         if (obj->id == info->id)
512                                 jsonw_string(json_wtr, obj->path);
513                 }
514                 jsonw_end_array(json_wtr);
515         }
516
517         jsonw_end_object(json_wtr);
518
519         return 0;
520 }
521
522 static int show_map_close_plain(int fd, struct bpf_map_info *info)
523 {
524         char *memlock;
525
526         memlock = get_fdinfo(fd, "memlock");
527         close(fd);
528
529         printf("%u: ", info->id);
530         if (info->type < ARRAY_SIZE(map_type_name))
531                 printf("%s  ", map_type_name[info->type]);
532         else
533                 printf("type %u  ", info->type);
534
535         if (*info->name)
536                 printf("name %s  ", info->name);
537
538         printf("flags 0x%x", info->map_flags);
539         print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
540         printf("\n");
541         printf("\tkey %uB  value %uB  max_entries %u",
542                info->key_size, info->value_size, info->max_entries);
543
544         if (memlock)
545                 printf("  memlock %sB", memlock);
546         free(memlock);
547
548         printf("\n");
549         if (!hash_empty(map_table.table)) {
550                 struct pinned_obj *obj;
551
552                 hash_for_each_possible(map_table.table, obj, hash, info->id) {
553                         if (obj->id == info->id)
554                                 printf("\tpinned %s\n", obj->path);
555                 }
556         }
557         return 0;
558 }
559
560 static int do_show(int argc, char **argv)
561 {
562         struct bpf_map_info info = {};
563         __u32 len = sizeof(info);
564         __u32 id = 0;
565         int err;
566         int fd;
567
568         if (show_pinned)
569                 build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
570
571         if (argc == 2) {
572                 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
573                 if (fd < 0)
574                         return -1;
575
576                 if (json_output)
577                         return show_map_close_json(fd, &info);
578                 else
579                         return show_map_close_plain(fd, &info);
580         }
581
582         if (argc)
583                 return BAD_ARG();
584
585         if (json_output)
586                 jsonw_start_array(json_wtr);
587         while (true) {
588                 err = bpf_map_get_next_id(id, &id);
589                 if (err) {
590                         if (errno == ENOENT)
591                                 break;
592                         p_err("can't get next map: %s%s", strerror(errno),
593                               errno == EINVAL ? " -- kernel too old?" : "");
594                         break;
595                 }
596
597                 fd = bpf_map_get_fd_by_id(id);
598                 if (fd < 0) {
599                         if (errno == ENOENT)
600                                 continue;
601                         p_err("can't get map by id (%u): %s",
602                               id, strerror(errno));
603                         break;
604                 }
605
606                 err = bpf_obj_get_info_by_fd(fd, &info, &len);
607                 if (err) {
608                         p_err("can't get map info: %s", strerror(errno));
609                         close(fd);
610                         break;
611                 }
612
613                 if (json_output)
614                         show_map_close_json(fd, &info);
615                 else
616                         show_map_close_plain(fd, &info);
617         }
618         if (json_output)
619                 jsonw_end_array(json_wtr);
620
621         return errno == ENOENT ? 0 : -1;
622 }
623
624 static int do_dump(int argc, char **argv)
625 {
626         struct bpf_map_info info = {};
627         void *key, *value, *prev_key;
628         unsigned int num_elems = 0;
629         __u32 len = sizeof(info);
630         json_writer_t *btf_wtr;
631         struct btf *btf = NULL;
632         int err;
633         int fd;
634
635         if (argc != 2)
636                 usage();
637
638         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
639         if (fd < 0)
640                 return -1;
641
642         if (map_is_map_of_maps(info.type) || map_is_map_of_progs(info.type)) {
643                 p_err("Dumping maps of maps and program maps not supported");
644                 close(fd);
645                 return -1;
646         }
647
648         key = malloc(info.key_size);
649         value = alloc_value(&info);
650         if (!key || !value) {
651                 p_err("mem alloc failed");
652                 err = -1;
653                 goto exit_free;
654         }
655
656         prev_key = NULL;
657
658         err = get_btf(&info, &btf);
659         if (err) {
660                 p_err("failed to get btf");
661                 goto exit_free;
662         }
663
664         if (json_output)
665                 jsonw_start_array(json_wtr);
666         else
667                 if (btf) {
668                         btf_wtr = get_btf_writer();
669                         if (!btf_wtr) {
670                                 p_info("failed to create json writer for btf. falling back to plain output");
671                                 btf__free(btf);
672                                 btf = NULL;
673                         } else {
674                                 jsonw_start_array(btf_wtr);
675                         }
676                 }
677
678         while (true) {
679                 err = bpf_map_get_next_key(fd, prev_key, key);
680                 if (err) {
681                         if (errno == ENOENT)
682                                 err = 0;
683                         break;
684                 }
685
686                 if (!bpf_map_lookup_elem(fd, key, value)) {
687                         if (json_output)
688                                 print_entry_json(&info, key, value, btf);
689                         else
690                                 if (btf) {
691                                         struct btf_dumper d = {
692                                                 .btf = btf,
693                                                 .jw = btf_wtr,
694                                                 .is_plain_text = true,
695                                         };
696
697                                         do_dump_btf(&d, &info, key, value);
698                                 } else {
699                                         print_entry_plain(&info, key, value);
700                                 }
701                 } else {
702                         if (json_output) {
703                                 jsonw_name(json_wtr, "key");
704                                 print_hex_data_json(key, info.key_size);
705                                 jsonw_name(json_wtr, "value");
706                                 jsonw_start_object(json_wtr);
707                                 jsonw_string_field(json_wtr, "error",
708                                                    "can't lookup element");
709                                 jsonw_end_object(json_wtr);
710                         } else {
711                                 p_info("can't lookup element with key: ");
712                                 fprint_hex(stderr, key, info.key_size, " ");
713                                 fprintf(stderr, "\n");
714                         }
715                 }
716
717                 prev_key = key;
718                 num_elems++;
719         }
720
721         if (json_output)
722                 jsonw_end_array(json_wtr);
723         else if (btf) {
724                 jsonw_end_array(btf_wtr);
725                 jsonw_destroy(&btf_wtr);
726         } else {
727                 printf("Found %u element%s\n", num_elems,
728                        num_elems != 1 ? "s" : "");
729         }
730
731 exit_free:
732         free(key);
733         free(value);
734         close(fd);
735         btf__free(btf);
736
737         return err;
738 }
739
740 static int do_update(int argc, char **argv)
741 {
742         struct bpf_map_info info = {};
743         __u32 len = sizeof(info);
744         __u32 *value_fd = NULL;
745         __u32 flags = BPF_ANY;
746         void *key, *value;
747         int fd, err;
748
749         if (argc < 2)
750                 usage();
751
752         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
753         if (fd < 0)
754                 return -1;
755
756         key = malloc(info.key_size);
757         value = alloc_value(&info);
758         if (!key || !value) {
759                 p_err("mem alloc failed");
760                 err = -1;
761                 goto exit_free;
762         }
763
764         err = parse_elem(argv, &info, key, value, info.key_size,
765                          info.value_size, &flags, &value_fd);
766         if (err)
767                 goto exit_free;
768
769         err = bpf_map_update_elem(fd, key, value, flags);
770         if (err) {
771                 p_err("update failed: %s", strerror(errno));
772                 goto exit_free;
773         }
774
775 exit_free:
776         if (value_fd)
777                 close(*value_fd);
778         free(key);
779         free(value);
780         close(fd);
781
782         if (!err && json_output)
783                 jsonw_null(json_wtr);
784         return err;
785 }
786
787 static int do_lookup(int argc, char **argv)
788 {
789         struct bpf_map_info info = {};
790         __u32 len = sizeof(info);
791         json_writer_t *btf_wtr;
792         struct btf *btf = NULL;
793         void *key, *value;
794         int err;
795         int fd;
796
797         if (argc < 2)
798                 usage();
799
800         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
801         if (fd < 0)
802                 return -1;
803
804         key = malloc(info.key_size);
805         value = alloc_value(&info);
806         if (!key || !value) {
807                 p_err("mem alloc failed");
808                 err = -1;
809                 goto exit_free;
810         }
811
812         err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
813         if (err)
814                 goto exit_free;
815
816         err = bpf_map_lookup_elem(fd, key, value);
817         if (err) {
818                 if (errno == ENOENT) {
819                         if (json_output) {
820                                 jsonw_null(json_wtr);
821                         } else {
822                                 printf("key:\n");
823                                 fprint_hex(stdout, key, info.key_size, " ");
824                                 printf("\n\nNot found\n");
825                         }
826                 } else {
827                         p_err("lookup failed: %s", strerror(errno));
828                 }
829
830                 goto exit_free;
831         }
832
833         /* here means bpf_map_lookup_elem() succeeded */
834         err = get_btf(&info, &btf);
835         if (err) {
836                 p_err("failed to get btf");
837                 goto exit_free;
838         }
839
840         if (json_output) {
841                 print_entry_json(&info, key, value, btf);
842         } else if (btf) {
843                 /* if here json_wtr wouldn't have been initialised,
844                  * so let's create separate writer for btf
845                  */
846                 btf_wtr = get_btf_writer();
847                 if (!btf_wtr) {
848                         p_info("failed to create json writer for btf. falling back to plain output");
849                         btf__free(btf);
850                         btf = NULL;
851                         print_entry_plain(&info, key, value);
852                 } else {
853                         struct btf_dumper d = {
854                                 .btf = btf,
855                                 .jw = btf_wtr,
856                                 .is_plain_text = true,
857                         };
858
859                         do_dump_btf(&d, &info, key, value);
860                         jsonw_destroy(&btf_wtr);
861                 }
862         } else {
863                 print_entry_plain(&info, key, value);
864         }
865
866 exit_free:
867         free(key);
868         free(value);
869         close(fd);
870         btf__free(btf);
871
872         return err;
873 }
874
875 static int do_getnext(int argc, char **argv)
876 {
877         struct bpf_map_info info = {};
878         __u32 len = sizeof(info);
879         void *key, *nextkey;
880         int err;
881         int fd;
882
883         if (argc < 2)
884                 usage();
885
886         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
887         if (fd < 0)
888                 return -1;
889
890         key = malloc(info.key_size);
891         nextkey = malloc(info.key_size);
892         if (!key || !nextkey) {
893                 p_err("mem alloc failed");
894                 err = -1;
895                 goto exit_free;
896         }
897
898         if (argc) {
899                 err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
900                                  NULL, NULL);
901                 if (err)
902                         goto exit_free;
903         } else {
904                 free(key);
905                 key = NULL;
906         }
907
908         err = bpf_map_get_next_key(fd, key, nextkey);
909         if (err) {
910                 p_err("can't get next key: %s", strerror(errno));
911                 goto exit_free;
912         }
913
914         if (json_output) {
915                 jsonw_start_object(json_wtr);
916                 if (key) {
917                         jsonw_name(json_wtr, "key");
918                         print_hex_data_json(key, info.key_size);
919                 } else {
920                         jsonw_null_field(json_wtr, "key");
921                 }
922                 jsonw_name(json_wtr, "next_key");
923                 print_hex_data_json(nextkey, info.key_size);
924                 jsonw_end_object(json_wtr);
925         } else {
926                 if (key) {
927                         printf("key:\n");
928                         fprint_hex(stdout, key, info.key_size, " ");
929                         printf("\n");
930                 } else {
931                         printf("key: None\n");
932                 }
933                 printf("next key:\n");
934                 fprint_hex(stdout, nextkey, info.key_size, " ");
935                 printf("\n");
936         }
937
938 exit_free:
939         free(nextkey);
940         free(key);
941         close(fd);
942
943         return err;
944 }
945
946 static int do_delete(int argc, char **argv)
947 {
948         struct bpf_map_info info = {};
949         __u32 len = sizeof(info);
950         void *key;
951         int err;
952         int fd;
953
954         if (argc < 2)
955                 usage();
956
957         fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
958         if (fd < 0)
959                 return -1;
960
961         key = malloc(info.key_size);
962         if (!key) {
963                 p_err("mem alloc failed");
964                 err = -1;
965                 goto exit_free;
966         }
967
968         err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
969         if (err)
970                 goto exit_free;
971
972         err = bpf_map_delete_elem(fd, key);
973         if (err)
974                 p_err("delete failed: %s", strerror(errno));
975
976 exit_free:
977         free(key);
978         close(fd);
979
980         if (!err && json_output)
981                 jsonw_null(json_wtr);
982         return err;
983 }
984
985 static int do_pin(int argc, char **argv)
986 {
987         int err;
988
989         err = do_pin_any(argc, argv, bpf_map_get_fd_by_id);
990         if (!err && json_output)
991                 jsonw_null(json_wtr);
992         return err;
993 }
994
995 static int do_help(int argc, char **argv)
996 {
997         if (json_output) {
998                 jsonw_null(json_wtr);
999                 return 0;
1000         }
1001
1002         fprintf(stderr,
1003                 "Usage: %s %s { show | list }   [MAP]\n"
1004                 "       %s %s dump       MAP\n"
1005                 "       %s %s update     MAP  key DATA value VALUE [UPDATE_FLAGS]\n"
1006                 "       %s %s lookup     MAP  key DATA\n"
1007                 "       %s %s getnext    MAP [key DATA]\n"
1008                 "       %s %s delete     MAP  key DATA\n"
1009                 "       %s %s pin        MAP  FILE\n"
1010                 "       %s %s event_pipe MAP [cpu N index M]\n"
1011                 "       %s %s help\n"
1012                 "\n"
1013                 "       " HELP_SPEC_MAP "\n"
1014                 "       DATA := { [hex] BYTES }\n"
1015                 "       " HELP_SPEC_PROGRAM "\n"
1016                 "       VALUE := { DATA | MAP | PROG }\n"
1017                 "       UPDATE_FLAGS := { any | exist | noexist }\n"
1018                 "       " HELP_SPEC_OPTIONS "\n"
1019                 "",
1020                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1021                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2],
1022                 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]);
1023
1024         return 0;
1025 }
1026
1027 static const struct cmd cmds[] = {
1028         { "show",       do_show },
1029         { "list",       do_show },
1030         { "help",       do_help },
1031         { "dump",       do_dump },
1032         { "update",     do_update },
1033         { "lookup",     do_lookup },
1034         { "getnext",    do_getnext },
1035         { "delete",     do_delete },
1036         { "pin",        do_pin },
1037         { "event_pipe", do_event_pipe },
1038         { 0 }
1039 };
1040
1041 int do_map(int argc, char **argv)
1042 {
1043         return cmd_select(cmds, argc, argv, do_help);
1044 }