0001
0002
0003
0004 #include <assert.h>
0005 #include <errno.h>
0006 #include <fcntl.h>
0007 #include <linux/err.h>
0008 #include <linux/kernel.h>
0009 #include <net/if.h>
0010 #include <stdbool.h>
0011 #include <stdio.h>
0012 #include <stdlib.h>
0013 #include <string.h>
0014 #include <unistd.h>
0015 #include <sys/types.h>
0016 #include <sys/stat.h>
0017
0018 #include <bpf/bpf.h>
0019 #include <bpf/btf.h>
0020 #include <bpf/hashmap.h>
0021
0022 #include "json_writer.h"
0023 #include "main.h"
0024
0025 static struct hashmap *map_table;
0026
0027 static bool map_is_per_cpu(__u32 type)
0028 {
0029 return type == BPF_MAP_TYPE_PERCPU_HASH ||
0030 type == BPF_MAP_TYPE_PERCPU_ARRAY ||
0031 type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
0032 type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
0033 }
0034
0035 static bool map_is_map_of_maps(__u32 type)
0036 {
0037 return type == BPF_MAP_TYPE_ARRAY_OF_MAPS ||
0038 type == BPF_MAP_TYPE_HASH_OF_MAPS;
0039 }
0040
0041 static bool map_is_map_of_progs(__u32 type)
0042 {
0043 return type == BPF_MAP_TYPE_PROG_ARRAY;
0044 }
0045
0046 static int map_type_from_str(const char *type)
0047 {
0048 const char *map_type_str;
0049 unsigned int i;
0050
0051 for (i = 0; ; i++) {
0052 map_type_str = libbpf_bpf_map_type_str(i);
0053 if (!map_type_str)
0054 break;
0055
0056
0057 if (!strcmp(map_type_str, type))
0058 return i;
0059 }
0060 return -1;
0061 }
0062
0063 static void *alloc_value(struct bpf_map_info *info)
0064 {
0065 if (map_is_per_cpu(info->type))
0066 return malloc(round_up(info->value_size, 8) *
0067 get_possible_cpus());
0068 else
0069 return malloc(info->value_size);
0070 }
0071
0072 static int do_dump_btf(const struct btf_dumper *d,
0073 struct bpf_map_info *map_info, void *key,
0074 void *value)
0075 {
0076 __u32 value_id;
0077 int ret = 0;
0078
0079
0080 jsonw_start_object(d->jw);
0081
0082 if (map_info->btf_key_type_id) {
0083 jsonw_name(d->jw, "key");
0084
0085 ret = btf_dumper_type(d, map_info->btf_key_type_id, key);
0086 if (ret)
0087 goto err_end_obj;
0088 }
0089
0090 value_id = map_info->btf_vmlinux_value_type_id ?
0091 : map_info->btf_value_type_id;
0092
0093 if (!map_is_per_cpu(map_info->type)) {
0094 jsonw_name(d->jw, "value");
0095 ret = btf_dumper_type(d, value_id, value);
0096 } else {
0097 unsigned int i, n, step;
0098
0099 jsonw_name(d->jw, "values");
0100 jsonw_start_array(d->jw);
0101 n = get_possible_cpus();
0102 step = round_up(map_info->value_size, 8);
0103 for (i = 0; i < n; i++) {
0104 jsonw_start_object(d->jw);
0105 jsonw_int_field(d->jw, "cpu", i);
0106 jsonw_name(d->jw, "value");
0107 ret = btf_dumper_type(d, value_id, value + i * step);
0108 jsonw_end_object(d->jw);
0109 if (ret)
0110 break;
0111 }
0112 jsonw_end_array(d->jw);
0113 }
0114
0115 err_end_obj:
0116
0117 jsonw_end_object(d->jw);
0118
0119 return ret;
0120 }
0121
0122 static json_writer_t *get_btf_writer(void)
0123 {
0124 json_writer_t *jw = jsonw_new(stdout);
0125
0126 if (!jw)
0127 return NULL;
0128 jsonw_pretty(jw, true);
0129
0130 return jw;
0131 }
0132
0133 static void print_entry_json(struct bpf_map_info *info, unsigned char *key,
0134 unsigned char *value, struct btf *btf)
0135 {
0136 jsonw_start_object(json_wtr);
0137
0138 if (!map_is_per_cpu(info->type)) {
0139 jsonw_name(json_wtr, "key");
0140 print_hex_data_json(key, info->key_size);
0141 jsonw_name(json_wtr, "value");
0142 print_hex_data_json(value, info->value_size);
0143 if (btf) {
0144 struct btf_dumper d = {
0145 .btf = btf,
0146 .jw = json_wtr,
0147 .is_plain_text = false,
0148 };
0149
0150 jsonw_name(json_wtr, "formatted");
0151 do_dump_btf(&d, info, key, value);
0152 }
0153 } else {
0154 unsigned int i, n, step;
0155
0156 n = get_possible_cpus();
0157 step = round_up(info->value_size, 8);
0158
0159 jsonw_name(json_wtr, "key");
0160 print_hex_data_json(key, info->key_size);
0161
0162 jsonw_name(json_wtr, "values");
0163 jsonw_start_array(json_wtr);
0164 for (i = 0; i < n; i++) {
0165 jsonw_start_object(json_wtr);
0166
0167 jsonw_int_field(json_wtr, "cpu", i);
0168
0169 jsonw_name(json_wtr, "value");
0170 print_hex_data_json(value + i * step,
0171 info->value_size);
0172
0173 jsonw_end_object(json_wtr);
0174 }
0175 jsonw_end_array(json_wtr);
0176 if (btf) {
0177 struct btf_dumper d = {
0178 .btf = btf,
0179 .jw = json_wtr,
0180 .is_plain_text = false,
0181 };
0182
0183 jsonw_name(json_wtr, "formatted");
0184 do_dump_btf(&d, info, key, value);
0185 }
0186 }
0187
0188 jsonw_end_object(json_wtr);
0189 }
0190
0191 static void
0192 print_entry_error_msg(struct bpf_map_info *info, unsigned char *key,
0193 const char *error_msg)
0194 {
0195 int msg_size = strlen(error_msg);
0196 bool single_line, break_names;
0197
0198 break_names = info->key_size > 16 || msg_size > 16;
0199 single_line = info->key_size + msg_size <= 24 && !break_names;
0200
0201 printf("key:%c", break_names ? '\n' : ' ');
0202 fprint_hex(stdout, key, info->key_size, " ");
0203
0204 printf(single_line ? " " : "\n");
0205
0206 printf("value:%c%s", break_names ? '\n' : ' ', error_msg);
0207
0208 printf("\n");
0209 }
0210
0211 static void
0212 print_entry_error(struct bpf_map_info *map_info, void *key, int lookup_errno)
0213 {
0214
0215
0216
0217
0218 if ((map_is_map_of_maps(map_info->type) ||
0219 map_is_map_of_progs(map_info->type)) && lookup_errno == ENOENT)
0220 return;
0221
0222 if (json_output) {
0223 jsonw_start_object(json_wtr);
0224 jsonw_name(json_wtr, "key");
0225 print_hex_data_json(key, map_info->key_size);
0226 jsonw_name(json_wtr, "value");
0227 jsonw_start_object(json_wtr);
0228 jsonw_string_field(json_wtr, "error", strerror(lookup_errno));
0229 jsonw_end_object(json_wtr);
0230 jsonw_end_object(json_wtr);
0231 } else {
0232 const char *msg = NULL;
0233
0234 if (lookup_errno == ENOENT)
0235 msg = "<no entry>";
0236 else if (lookup_errno == ENOSPC &&
0237 map_info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY)
0238 msg = "<cannot read>";
0239
0240 print_entry_error_msg(map_info, key,
0241 msg ? : strerror(lookup_errno));
0242 }
0243 }
0244
0245 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key,
0246 unsigned char *value)
0247 {
0248 if (!map_is_per_cpu(info->type)) {
0249 bool single_line, break_names;
0250
0251 break_names = info->key_size > 16 || info->value_size > 16;
0252 single_line = info->key_size + info->value_size <= 24 &&
0253 !break_names;
0254
0255 if (info->key_size) {
0256 printf("key:%c", break_names ? '\n' : ' ');
0257 fprint_hex(stdout, key, info->key_size, " ");
0258
0259 printf(single_line ? " " : "\n");
0260 }
0261
0262 if (info->value_size) {
0263 printf("value:%c", break_names ? '\n' : ' ');
0264 fprint_hex(stdout, value, info->value_size, " ");
0265 }
0266
0267 printf("\n");
0268 } else {
0269 unsigned int i, n, step;
0270
0271 n = get_possible_cpus();
0272 step = round_up(info->value_size, 8);
0273
0274 if (info->key_size) {
0275 printf("key:\n");
0276 fprint_hex(stdout, key, info->key_size, " ");
0277 printf("\n");
0278 }
0279 if (info->value_size) {
0280 for (i = 0; i < n; i++) {
0281 printf("value (CPU %02d):%c",
0282 i, info->value_size > 16 ? '\n' : ' ');
0283 fprint_hex(stdout, value + i * step,
0284 info->value_size, " ");
0285 printf("\n");
0286 }
0287 }
0288 }
0289 }
0290
0291 static char **parse_bytes(char **argv, const char *name, unsigned char *val,
0292 unsigned int n)
0293 {
0294 unsigned int i = 0, base = 0;
0295 char *endptr;
0296
0297 if (is_prefix(*argv, "hex")) {
0298 base = 16;
0299 argv++;
0300 }
0301
0302 while (i < n && argv[i]) {
0303 val[i] = strtoul(argv[i], &endptr, base);
0304 if (*endptr) {
0305 p_err("error parsing byte: %s", argv[i]);
0306 return NULL;
0307 }
0308 i++;
0309 }
0310
0311 if (i != n) {
0312 p_err("%s expected %d bytes got %d", name, n, i);
0313 return NULL;
0314 }
0315
0316 return argv + i;
0317 }
0318
0319
0320 static void fill_per_cpu_value(struct bpf_map_info *info, void *value)
0321 {
0322 unsigned int i, n, step;
0323
0324 if (!map_is_per_cpu(info->type))
0325 return;
0326
0327 n = get_possible_cpus();
0328 step = round_up(info->value_size, 8);
0329 for (i = 1; i < n; i++)
0330 memcpy(value + i * step, value, info->value_size);
0331 }
0332
0333 static int parse_elem(char **argv, struct bpf_map_info *info,
0334 void *key, void *value, __u32 key_size, __u32 value_size,
0335 __u32 *flags, __u32 **value_fd)
0336 {
0337 if (!*argv) {
0338 if (!key && !value)
0339 return 0;
0340 p_err("did not find %s", key ? "key" : "value");
0341 return -1;
0342 }
0343
0344 if (is_prefix(*argv, "key")) {
0345 if (!key) {
0346 if (key_size)
0347 p_err("duplicate key");
0348 else
0349 p_err("unnecessary key");
0350 return -1;
0351 }
0352
0353 argv = parse_bytes(argv + 1, "key", key, key_size);
0354 if (!argv)
0355 return -1;
0356
0357 return parse_elem(argv, info, NULL, value, key_size, value_size,
0358 flags, value_fd);
0359 } else if (is_prefix(*argv, "value")) {
0360 int fd;
0361
0362 if (!value) {
0363 if (value_size)
0364 p_err("duplicate value");
0365 else
0366 p_err("unnecessary value");
0367 return -1;
0368 }
0369
0370 argv++;
0371
0372 if (map_is_map_of_maps(info->type)) {
0373 int argc = 2;
0374
0375 if (value_size != 4) {
0376 p_err("value smaller than 4B for map in map?");
0377 return -1;
0378 }
0379 if (!argv[0] || !argv[1]) {
0380 p_err("not enough value arguments for map in map");
0381 return -1;
0382 }
0383
0384 fd = map_parse_fd(&argc, &argv);
0385 if (fd < 0)
0386 return -1;
0387
0388 *value_fd = value;
0389 **value_fd = fd;
0390 } else if (map_is_map_of_progs(info->type)) {
0391 int argc = 2;
0392
0393 if (value_size != 4) {
0394 p_err("value smaller than 4B for map of progs?");
0395 return -1;
0396 }
0397 if (!argv[0] || !argv[1]) {
0398 p_err("not enough value arguments for map of progs");
0399 return -1;
0400 }
0401 if (is_prefix(*argv, "id"))
0402 p_info("Warning: updating program array via MAP_ID, make sure this map is kept open\n"
0403 " by some process or pinned otherwise update will be lost");
0404
0405 fd = prog_parse_fd(&argc, &argv);
0406 if (fd < 0)
0407 return -1;
0408
0409 *value_fd = value;
0410 **value_fd = fd;
0411 } else {
0412 argv = parse_bytes(argv, "value", value, value_size);
0413 if (!argv)
0414 return -1;
0415
0416 fill_per_cpu_value(info, value);
0417 }
0418
0419 return parse_elem(argv, info, key, NULL, key_size, value_size,
0420 flags, NULL);
0421 } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") ||
0422 is_prefix(*argv, "exist")) {
0423 if (!flags) {
0424 p_err("flags specified multiple times: %s", *argv);
0425 return -1;
0426 }
0427
0428 if (is_prefix(*argv, "any"))
0429 *flags = BPF_ANY;
0430 else if (is_prefix(*argv, "noexist"))
0431 *flags = BPF_NOEXIST;
0432 else if (is_prefix(*argv, "exist"))
0433 *flags = BPF_EXIST;
0434
0435 return parse_elem(argv + 1, info, key, value, key_size,
0436 value_size, NULL, value_fd);
0437 }
0438
0439 p_err("expected key or value, got: %s", *argv);
0440 return -1;
0441 }
0442
0443 static void show_map_header_json(struct bpf_map_info *info, json_writer_t *wtr)
0444 {
0445 const char *map_type_str;
0446
0447 jsonw_uint_field(wtr, "id", info->id);
0448 map_type_str = libbpf_bpf_map_type_str(info->type);
0449 if (map_type_str)
0450 jsonw_string_field(wtr, "type", map_type_str);
0451 else
0452 jsonw_uint_field(wtr, "type", info->type);
0453
0454 if (*info->name)
0455 jsonw_string_field(wtr, "name", info->name);
0456
0457 jsonw_name(wtr, "flags");
0458 jsonw_printf(wtr, "%d", info->map_flags);
0459 }
0460
0461 static int show_map_close_json(int fd, struct bpf_map_info *info)
0462 {
0463 char *memlock, *frozen_str;
0464 int frozen = 0;
0465
0466 memlock = get_fdinfo(fd, "memlock");
0467 frozen_str = get_fdinfo(fd, "frozen");
0468
0469 jsonw_start_object(json_wtr);
0470
0471 show_map_header_json(info, json_wtr);
0472
0473 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
0474
0475 jsonw_uint_field(json_wtr, "bytes_key", info->key_size);
0476 jsonw_uint_field(json_wtr, "bytes_value", info->value_size);
0477 jsonw_uint_field(json_wtr, "max_entries", info->max_entries);
0478
0479 if (memlock)
0480 jsonw_int_field(json_wtr, "bytes_memlock", atoll(memlock));
0481 free(memlock);
0482
0483 if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
0484 char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
0485 char *owner_jited = get_fdinfo(fd, "owner_jited");
0486
0487 if (owner_prog_type) {
0488 unsigned int prog_type = atoi(owner_prog_type);
0489 const char *prog_type_str;
0490
0491 prog_type_str = libbpf_bpf_prog_type_str(prog_type);
0492 if (prog_type_str)
0493 jsonw_string_field(json_wtr, "owner_prog_type",
0494 prog_type_str);
0495 else
0496 jsonw_uint_field(json_wtr, "owner_prog_type",
0497 prog_type);
0498 }
0499 if (owner_jited)
0500 jsonw_bool_field(json_wtr, "owner_jited",
0501 !!atoi(owner_jited));
0502
0503 free(owner_prog_type);
0504 free(owner_jited);
0505 }
0506 close(fd);
0507
0508 if (frozen_str) {
0509 frozen = atoi(frozen_str);
0510 free(frozen_str);
0511 }
0512 jsonw_int_field(json_wtr, "frozen", frozen);
0513
0514 if (info->btf_id)
0515 jsonw_int_field(json_wtr, "btf_id", info->btf_id);
0516
0517 if (!hashmap__empty(map_table)) {
0518 struct hashmap_entry *entry;
0519
0520 jsonw_name(json_wtr, "pinned");
0521 jsonw_start_array(json_wtr);
0522 hashmap__for_each_key_entry(map_table, entry,
0523 u32_as_hash_field(info->id))
0524 jsonw_string(json_wtr, entry->value);
0525 jsonw_end_array(json_wtr);
0526 }
0527
0528 emit_obj_refs_json(refs_table, info->id, json_wtr);
0529
0530 jsonw_end_object(json_wtr);
0531
0532 return 0;
0533 }
0534
0535 static void show_map_header_plain(struct bpf_map_info *info)
0536 {
0537 const char *map_type_str;
0538
0539 printf("%u: ", info->id);
0540
0541 map_type_str = libbpf_bpf_map_type_str(info->type);
0542 if (map_type_str)
0543 printf("%s ", map_type_str);
0544 else
0545 printf("type %u ", info->type);
0546
0547 if (*info->name)
0548 printf("name %s ", info->name);
0549
0550 printf("flags 0x%x", info->map_flags);
0551 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
0552 printf("\n");
0553 }
0554
0555 static int show_map_close_plain(int fd, struct bpf_map_info *info)
0556 {
0557 char *memlock, *frozen_str;
0558 int frozen = 0;
0559
0560 memlock = get_fdinfo(fd, "memlock");
0561 frozen_str = get_fdinfo(fd, "frozen");
0562
0563 show_map_header_plain(info);
0564 printf("\tkey %uB value %uB max_entries %u",
0565 info->key_size, info->value_size, info->max_entries);
0566
0567 if (memlock)
0568 printf(" memlock %sB", memlock);
0569 free(memlock);
0570
0571 if (info->type == BPF_MAP_TYPE_PROG_ARRAY) {
0572 char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
0573 char *owner_jited = get_fdinfo(fd, "owner_jited");
0574
0575 if (owner_prog_type || owner_jited)
0576 printf("\n\t");
0577 if (owner_prog_type) {
0578 unsigned int prog_type = atoi(owner_prog_type);
0579 const char *prog_type_str;
0580
0581 prog_type_str = libbpf_bpf_prog_type_str(prog_type);
0582 if (prog_type_str)
0583 printf("owner_prog_type %s ", prog_type_str);
0584 else
0585 printf("owner_prog_type %d ", prog_type);
0586 }
0587 if (owner_jited)
0588 printf("owner%s jited",
0589 atoi(owner_jited) ? "" : " not");
0590
0591 free(owner_prog_type);
0592 free(owner_jited);
0593 }
0594 close(fd);
0595
0596 if (!hashmap__empty(map_table)) {
0597 struct hashmap_entry *entry;
0598
0599 hashmap__for_each_key_entry(map_table, entry,
0600 u32_as_hash_field(info->id))
0601 printf("\n\tpinned %s", (char *)entry->value);
0602 }
0603
0604 if (frozen_str) {
0605 frozen = atoi(frozen_str);
0606 free(frozen_str);
0607 }
0608
0609 if (info->btf_id || frozen)
0610 printf("\n\t");
0611
0612 if (info->btf_id)
0613 printf("btf_id %d", info->btf_id);
0614
0615 if (frozen)
0616 printf("%sfrozen", info->btf_id ? " " : "");
0617
0618 emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
0619
0620 printf("\n");
0621 return 0;
0622 }
0623
0624 static int do_show_subset(int argc, char **argv)
0625 {
0626 struct bpf_map_info info = {};
0627 __u32 len = sizeof(info);
0628 int *fds = NULL;
0629 int nb_fds, i;
0630 int err = -1;
0631
0632 fds = malloc(sizeof(int));
0633 if (!fds) {
0634 p_err("mem alloc failed");
0635 return -1;
0636 }
0637 nb_fds = map_parse_fds(&argc, &argv, &fds);
0638 if (nb_fds < 1)
0639 goto exit_free;
0640
0641 if (json_output && nb_fds > 1)
0642 jsonw_start_array(json_wtr);
0643 for (i = 0; i < nb_fds; i++) {
0644 err = bpf_obj_get_info_by_fd(fds[i], &info, &len);
0645 if (err) {
0646 p_err("can't get map info: %s",
0647 strerror(errno));
0648 for (; i < nb_fds; i++)
0649 close(fds[i]);
0650 break;
0651 }
0652
0653 if (json_output)
0654 show_map_close_json(fds[i], &info);
0655 else
0656 show_map_close_plain(fds[i], &info);
0657
0658 close(fds[i]);
0659 }
0660 if (json_output && nb_fds > 1)
0661 jsonw_end_array(json_wtr);
0662
0663 exit_free:
0664 free(fds);
0665 return err;
0666 }
0667
0668 static int do_show(int argc, char **argv)
0669 {
0670 struct bpf_map_info info = {};
0671 __u32 len = sizeof(info);
0672 __u32 id = 0;
0673 int err;
0674 int fd;
0675
0676 if (show_pinned) {
0677 map_table = hashmap__new(hash_fn_for_key_as_id,
0678 equal_fn_for_key_as_id, NULL);
0679 if (IS_ERR(map_table)) {
0680 p_err("failed to create hashmap for pinned paths");
0681 return -1;
0682 }
0683 build_pinned_obj_table(map_table, BPF_OBJ_MAP);
0684 }
0685 build_obj_refs_table(&refs_table, BPF_OBJ_MAP);
0686
0687 if (argc == 2)
0688 return do_show_subset(argc, argv);
0689
0690 if (argc)
0691 return BAD_ARG();
0692
0693 if (json_output)
0694 jsonw_start_array(json_wtr);
0695 while (true) {
0696 err = bpf_map_get_next_id(id, &id);
0697 if (err) {
0698 if (errno == ENOENT)
0699 break;
0700 p_err("can't get next map: %s%s", strerror(errno),
0701 errno == EINVAL ? " -- kernel too old?" : "");
0702 break;
0703 }
0704
0705 fd = bpf_map_get_fd_by_id(id);
0706 if (fd < 0) {
0707 if (errno == ENOENT)
0708 continue;
0709 p_err("can't get map by id (%u): %s",
0710 id, strerror(errno));
0711 break;
0712 }
0713
0714 err = bpf_obj_get_info_by_fd(fd, &info, &len);
0715 if (err) {
0716 p_err("can't get map info: %s", strerror(errno));
0717 close(fd);
0718 break;
0719 }
0720
0721 if (json_output)
0722 show_map_close_json(fd, &info);
0723 else
0724 show_map_close_plain(fd, &info);
0725 }
0726 if (json_output)
0727 jsonw_end_array(json_wtr);
0728
0729 delete_obj_refs_table(refs_table);
0730
0731 if (show_pinned)
0732 delete_pinned_obj_table(map_table);
0733
0734 return errno == ENOENT ? 0 : -1;
0735 }
0736
0737 static int dump_map_elem(int fd, void *key, void *value,
0738 struct bpf_map_info *map_info, struct btf *btf,
0739 json_writer_t *btf_wtr)
0740 {
0741 if (bpf_map_lookup_elem(fd, key, value)) {
0742 print_entry_error(map_info, key, errno);
0743 return -1;
0744 }
0745
0746 if (json_output) {
0747 print_entry_json(map_info, key, value, btf);
0748 } else if (btf) {
0749 struct btf_dumper d = {
0750 .btf = btf,
0751 .jw = btf_wtr,
0752 .is_plain_text = true,
0753 };
0754
0755 do_dump_btf(&d, map_info, key, value);
0756 } else {
0757 print_entry_plain(map_info, key, value);
0758 }
0759
0760 return 0;
0761 }
0762
0763 static int maps_have_btf(int *fds, int nb_fds)
0764 {
0765 struct bpf_map_info info = {};
0766 __u32 len = sizeof(info);
0767 int err, i;
0768
0769 for (i = 0; i < nb_fds; i++) {
0770 err = bpf_obj_get_info_by_fd(fds[i], &info, &len);
0771 if (err) {
0772 p_err("can't get map info: %s", strerror(errno));
0773 return -1;
0774 }
0775
0776 if (!info.btf_id)
0777 return 0;
0778 }
0779
0780 return 1;
0781 }
0782
0783 static struct btf *btf_vmlinux;
0784
0785 static int get_map_kv_btf(const struct bpf_map_info *info, struct btf **btf)
0786 {
0787 int err = 0;
0788
0789 if (info->btf_vmlinux_value_type_id) {
0790 if (!btf_vmlinux) {
0791 btf_vmlinux = libbpf_find_kernel_btf();
0792 err = libbpf_get_error(btf_vmlinux);
0793 if (err) {
0794 p_err("failed to get kernel btf");
0795 return err;
0796 }
0797 }
0798 *btf = btf_vmlinux;
0799 } else if (info->btf_value_type_id) {
0800 *btf = btf__load_from_kernel_by_id(info->btf_id);
0801 err = libbpf_get_error(*btf);
0802 if (err)
0803 p_err("failed to get btf");
0804 } else {
0805 *btf = NULL;
0806 }
0807
0808 return err;
0809 }
0810
0811 static void free_map_kv_btf(struct btf *btf)
0812 {
0813 if (!libbpf_get_error(btf) && btf != btf_vmlinux)
0814 btf__free(btf);
0815 }
0816
0817 static void free_btf_vmlinux(void)
0818 {
0819 if (!libbpf_get_error(btf_vmlinux))
0820 btf__free(btf_vmlinux);
0821 }
0822
0823 static int
0824 map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr,
0825 bool show_header)
0826 {
0827 void *key, *value, *prev_key;
0828 unsigned int num_elems = 0;
0829 struct btf *btf = NULL;
0830 int err;
0831
0832 key = malloc(info->key_size);
0833 value = alloc_value(info);
0834 if (!key || !value) {
0835 p_err("mem alloc failed");
0836 err = -1;
0837 goto exit_free;
0838 }
0839
0840 prev_key = NULL;
0841
0842 if (wtr) {
0843 err = get_map_kv_btf(info, &btf);
0844 if (err) {
0845 goto exit_free;
0846 }
0847
0848 if (show_header) {
0849 jsonw_start_object(wtr);
0850 show_map_header_json(info, wtr);
0851 jsonw_name(wtr, "elements");
0852 }
0853 jsonw_start_array(wtr);
0854 } else if (show_header) {
0855 show_map_header_plain(info);
0856 }
0857
0858 if (info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY &&
0859 info->value_size != 8) {
0860 const char *map_type_str;
0861
0862 map_type_str = libbpf_bpf_map_type_str(info->type);
0863 p_info("Warning: cannot read values from %s map with value_size != 8",
0864 map_type_str);
0865 }
0866 while (true) {
0867 err = bpf_map_get_next_key(fd, prev_key, key);
0868 if (err) {
0869 if (errno == ENOENT)
0870 err = 0;
0871 break;
0872 }
0873 if (!dump_map_elem(fd, key, value, info, btf, wtr))
0874 num_elems++;
0875 prev_key = key;
0876 }
0877
0878 if (wtr) {
0879 jsonw_end_array(wtr);
0880 if (show_header)
0881 jsonw_end_object(wtr);
0882 } else {
0883 printf("Found %u element%s\n", num_elems,
0884 num_elems != 1 ? "s" : "");
0885 }
0886
0887 exit_free:
0888 free(key);
0889 free(value);
0890 close(fd);
0891 free_map_kv_btf(btf);
0892
0893 return err;
0894 }
0895
0896 static int do_dump(int argc, char **argv)
0897 {
0898 json_writer_t *wtr = NULL, *btf_wtr = NULL;
0899 struct bpf_map_info info = {};
0900 int nb_fds, i = 0;
0901 __u32 len = sizeof(info);
0902 int *fds = NULL;
0903 int err = -1;
0904
0905 if (argc != 2)
0906 usage();
0907
0908 fds = malloc(sizeof(int));
0909 if (!fds) {
0910 p_err("mem alloc failed");
0911 return -1;
0912 }
0913 nb_fds = map_parse_fds(&argc, &argv, &fds);
0914 if (nb_fds < 1)
0915 goto exit_free;
0916
0917 if (json_output) {
0918 wtr = json_wtr;
0919 } else {
0920 int do_plain_btf;
0921
0922 do_plain_btf = maps_have_btf(fds, nb_fds);
0923 if (do_plain_btf < 0)
0924 goto exit_close;
0925
0926 if (do_plain_btf) {
0927 btf_wtr = get_btf_writer();
0928 wtr = btf_wtr;
0929 if (!btf_wtr)
0930 p_info("failed to create json writer for btf. falling back to plain output");
0931 }
0932 }
0933
0934 if (wtr && nb_fds > 1)
0935 jsonw_start_array(wtr);
0936 for (i = 0; i < nb_fds; i++) {
0937 if (bpf_obj_get_info_by_fd(fds[i], &info, &len)) {
0938 p_err("can't get map info: %s", strerror(errno));
0939 break;
0940 }
0941 err = map_dump(fds[i], &info, wtr, nb_fds > 1);
0942 if (!wtr && i != nb_fds - 1)
0943 printf("\n");
0944
0945 if (err)
0946 break;
0947 close(fds[i]);
0948 }
0949 if (wtr && nb_fds > 1)
0950 jsonw_end_array(wtr);
0951
0952 if (btf_wtr)
0953 jsonw_destroy(&btf_wtr);
0954 exit_close:
0955 for (; i < nb_fds; i++)
0956 close(fds[i]);
0957 exit_free:
0958 free(fds);
0959 free_btf_vmlinux();
0960 return err;
0961 }
0962
0963 static int alloc_key_value(struct bpf_map_info *info, void **key, void **value)
0964 {
0965 *key = NULL;
0966 *value = NULL;
0967
0968 if (info->key_size) {
0969 *key = malloc(info->key_size);
0970 if (!*key) {
0971 p_err("key mem alloc failed");
0972 return -1;
0973 }
0974 }
0975
0976 if (info->value_size) {
0977 *value = alloc_value(info);
0978 if (!*value) {
0979 p_err("value mem alloc failed");
0980 free(*key);
0981 *key = NULL;
0982 return -1;
0983 }
0984 }
0985
0986 return 0;
0987 }
0988
0989 static int do_update(int argc, char **argv)
0990 {
0991 struct bpf_map_info info = {};
0992 __u32 len = sizeof(info);
0993 __u32 *value_fd = NULL;
0994 __u32 flags = BPF_ANY;
0995 void *key, *value;
0996 int fd, err;
0997
0998 if (argc < 2)
0999 usage();
1000
1001 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1002 if (fd < 0)
1003 return -1;
1004
1005 err = alloc_key_value(&info, &key, &value);
1006 if (err)
1007 goto exit_free;
1008
1009 err = parse_elem(argv, &info, key, value, info.key_size,
1010 info.value_size, &flags, &value_fd);
1011 if (err)
1012 goto exit_free;
1013
1014 err = bpf_map_update_elem(fd, key, value, flags);
1015 if (err) {
1016 p_err("update failed: %s", strerror(errno));
1017 goto exit_free;
1018 }
1019
1020 exit_free:
1021 if (value_fd)
1022 close(*value_fd);
1023 free(key);
1024 free(value);
1025 close(fd);
1026
1027 if (!err && json_output)
1028 jsonw_null(json_wtr);
1029 return err;
1030 }
1031
1032 static void print_key_value(struct bpf_map_info *info, void *key,
1033 void *value)
1034 {
1035 json_writer_t *btf_wtr;
1036 struct btf *btf;
1037
1038 if (get_map_kv_btf(info, &btf))
1039 return;
1040
1041 if (json_output) {
1042 print_entry_json(info, key, value, btf);
1043 } else if (btf) {
1044
1045
1046
1047 btf_wtr = get_btf_writer();
1048 if (!btf_wtr) {
1049 p_info("failed to create json writer for btf. falling back to plain output");
1050 btf__free(btf);
1051 btf = NULL;
1052 print_entry_plain(info, key, value);
1053 } else {
1054 struct btf_dumper d = {
1055 .btf = btf,
1056 .jw = btf_wtr,
1057 .is_plain_text = true,
1058 };
1059
1060 do_dump_btf(&d, info, key, value);
1061 jsonw_destroy(&btf_wtr);
1062 }
1063 } else {
1064 print_entry_plain(info, key, value);
1065 }
1066 btf__free(btf);
1067 }
1068
1069 static int do_lookup(int argc, char **argv)
1070 {
1071 struct bpf_map_info info = {};
1072 __u32 len = sizeof(info);
1073 void *key, *value;
1074 int err;
1075 int fd;
1076
1077 if (argc < 2)
1078 usage();
1079
1080 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1081 if (fd < 0)
1082 return -1;
1083
1084 err = alloc_key_value(&info, &key, &value);
1085 if (err)
1086 goto exit_free;
1087
1088 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
1089 if (err)
1090 goto exit_free;
1091
1092 err = bpf_map_lookup_elem(fd, key, value);
1093 if (err) {
1094 if (errno == ENOENT) {
1095 if (json_output) {
1096 jsonw_null(json_wtr);
1097 } else {
1098 printf("key:\n");
1099 fprint_hex(stdout, key, info.key_size, " ");
1100 printf("\n\nNot found\n");
1101 }
1102 } else {
1103 p_err("lookup failed: %s", strerror(errno));
1104 }
1105
1106 goto exit_free;
1107 }
1108
1109
1110 print_key_value(&info, key, value);
1111
1112 exit_free:
1113 free(key);
1114 free(value);
1115 close(fd);
1116
1117 return err;
1118 }
1119
1120 static int do_getnext(int argc, char **argv)
1121 {
1122 struct bpf_map_info info = {};
1123 __u32 len = sizeof(info);
1124 void *key, *nextkey;
1125 int err;
1126 int fd;
1127
1128 if (argc < 2)
1129 usage();
1130
1131 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1132 if (fd < 0)
1133 return -1;
1134
1135 key = malloc(info.key_size);
1136 nextkey = malloc(info.key_size);
1137 if (!key || !nextkey) {
1138 p_err("mem alloc failed");
1139 err = -1;
1140 goto exit_free;
1141 }
1142
1143 if (argc) {
1144 err = parse_elem(argv, &info, key, NULL, info.key_size, 0,
1145 NULL, NULL);
1146 if (err)
1147 goto exit_free;
1148 } else {
1149 free(key);
1150 key = NULL;
1151 }
1152
1153 err = bpf_map_get_next_key(fd, key, nextkey);
1154 if (err) {
1155 p_err("can't get next key: %s", strerror(errno));
1156 goto exit_free;
1157 }
1158
1159 if (json_output) {
1160 jsonw_start_object(json_wtr);
1161 if (key) {
1162 jsonw_name(json_wtr, "key");
1163 print_hex_data_json(key, info.key_size);
1164 } else {
1165 jsonw_null_field(json_wtr, "key");
1166 }
1167 jsonw_name(json_wtr, "next_key");
1168 print_hex_data_json(nextkey, info.key_size);
1169 jsonw_end_object(json_wtr);
1170 } else {
1171 if (key) {
1172 printf("key:\n");
1173 fprint_hex(stdout, key, info.key_size, " ");
1174 printf("\n");
1175 } else {
1176 printf("key: None\n");
1177 }
1178 printf("next key:\n");
1179 fprint_hex(stdout, nextkey, info.key_size, " ");
1180 printf("\n");
1181 }
1182
1183 exit_free:
1184 free(nextkey);
1185 free(key);
1186 close(fd);
1187
1188 return err;
1189 }
1190
1191 static int do_delete(int argc, char **argv)
1192 {
1193 struct bpf_map_info info = {};
1194 __u32 len = sizeof(info);
1195 void *key;
1196 int err;
1197 int fd;
1198
1199 if (argc < 2)
1200 usage();
1201
1202 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1203 if (fd < 0)
1204 return -1;
1205
1206 key = malloc(info.key_size);
1207 if (!key) {
1208 p_err("mem alloc failed");
1209 err = -1;
1210 goto exit_free;
1211 }
1212
1213 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL);
1214 if (err)
1215 goto exit_free;
1216
1217 err = bpf_map_delete_elem(fd, key);
1218 if (err)
1219 p_err("delete failed: %s", strerror(errno));
1220
1221 exit_free:
1222 free(key);
1223 close(fd);
1224
1225 if (!err && json_output)
1226 jsonw_null(json_wtr);
1227 return err;
1228 }
1229
1230 static int do_pin(int argc, char **argv)
1231 {
1232 int err;
1233
1234 err = do_pin_any(argc, argv, map_parse_fd);
1235 if (!err && json_output)
1236 jsonw_null(json_wtr);
1237 return err;
1238 }
1239
1240 static int do_create(int argc, char **argv)
1241 {
1242 LIBBPF_OPTS(bpf_map_create_opts, attr);
1243 enum bpf_map_type map_type = BPF_MAP_TYPE_UNSPEC;
1244 __u32 key_size = 0, value_size = 0, max_entries = 0;
1245 const char *map_name = NULL;
1246 const char *pinfile;
1247 int err = -1, fd;
1248
1249 if (!REQ_ARGS(7))
1250 return -1;
1251 pinfile = GET_ARG();
1252
1253 while (argc) {
1254 if (!REQ_ARGS(2))
1255 return -1;
1256
1257 if (is_prefix(*argv, "type")) {
1258 NEXT_ARG();
1259
1260 if (map_type) {
1261 p_err("map type already specified");
1262 goto exit;
1263 }
1264
1265 map_type = map_type_from_str(*argv);
1266 if ((int)map_type < 0) {
1267 p_err("unrecognized map type: %s", *argv);
1268 goto exit;
1269 }
1270 NEXT_ARG();
1271 } else if (is_prefix(*argv, "name")) {
1272 NEXT_ARG();
1273 map_name = GET_ARG();
1274 } else if (is_prefix(*argv, "key")) {
1275 if (parse_u32_arg(&argc, &argv, &key_size,
1276 "key size"))
1277 goto exit;
1278 } else if (is_prefix(*argv, "value")) {
1279 if (parse_u32_arg(&argc, &argv, &value_size,
1280 "value size"))
1281 goto exit;
1282 } else if (is_prefix(*argv, "entries")) {
1283 if (parse_u32_arg(&argc, &argv, &max_entries,
1284 "max entries"))
1285 goto exit;
1286 } else if (is_prefix(*argv, "flags")) {
1287 if (parse_u32_arg(&argc, &argv, &attr.map_flags,
1288 "flags"))
1289 goto exit;
1290 } else if (is_prefix(*argv, "dev")) {
1291 NEXT_ARG();
1292
1293 if (attr.map_ifindex) {
1294 p_err("offload device already specified");
1295 goto exit;
1296 }
1297
1298 attr.map_ifindex = if_nametoindex(*argv);
1299 if (!attr.map_ifindex) {
1300 p_err("unrecognized netdevice '%s': %s",
1301 *argv, strerror(errno));
1302 goto exit;
1303 }
1304 NEXT_ARG();
1305 } else if (is_prefix(*argv, "inner_map")) {
1306 struct bpf_map_info info = {};
1307 __u32 len = sizeof(info);
1308 int inner_map_fd;
1309
1310 NEXT_ARG();
1311 if (!REQ_ARGS(2))
1312 usage();
1313 inner_map_fd = map_parse_fd_and_info(&argc, &argv,
1314 &info, &len);
1315 if (inner_map_fd < 0)
1316 return -1;
1317 attr.inner_map_fd = inner_map_fd;
1318 } else {
1319 p_err("unknown arg %s", *argv);
1320 goto exit;
1321 }
1322 }
1323
1324 if (!map_name) {
1325 p_err("map name not specified");
1326 goto exit;
1327 }
1328
1329 set_max_rlimit();
1330
1331 fd = bpf_map_create(map_type, map_name, key_size, value_size, max_entries, &attr);
1332 if (fd < 0) {
1333 p_err("map create failed: %s", strerror(errno));
1334 goto exit;
1335 }
1336
1337 err = do_pin_fd(fd, pinfile);
1338 close(fd);
1339 if (err)
1340 goto exit;
1341
1342 if (json_output)
1343 jsonw_null(json_wtr);
1344
1345 exit:
1346 if (attr.inner_map_fd > 0)
1347 close(attr.inner_map_fd);
1348
1349 return err;
1350 }
1351
1352 static int do_pop_dequeue(int argc, char **argv)
1353 {
1354 struct bpf_map_info info = {};
1355 __u32 len = sizeof(info);
1356 void *key, *value;
1357 int err;
1358 int fd;
1359
1360 if (argc < 2)
1361 usage();
1362
1363 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
1364 if (fd < 0)
1365 return -1;
1366
1367 err = alloc_key_value(&info, &key, &value);
1368 if (err)
1369 goto exit_free;
1370
1371 err = bpf_map_lookup_and_delete_elem(fd, key, value);
1372 if (err) {
1373 if (errno == ENOENT) {
1374 if (json_output)
1375 jsonw_null(json_wtr);
1376 else
1377 printf("Error: empty map\n");
1378 } else {
1379 p_err("pop failed: %s", strerror(errno));
1380 }
1381
1382 goto exit_free;
1383 }
1384
1385 print_key_value(&info, key, value);
1386
1387 exit_free:
1388 free(key);
1389 free(value);
1390 close(fd);
1391
1392 return err;
1393 }
1394
1395 static int do_freeze(int argc, char **argv)
1396 {
1397 int err, fd;
1398
1399 if (!REQ_ARGS(2))
1400 return -1;
1401
1402 fd = map_parse_fd(&argc, &argv);
1403 if (fd < 0)
1404 return -1;
1405
1406 if (argc) {
1407 close(fd);
1408 return BAD_ARG();
1409 }
1410
1411 err = bpf_map_freeze(fd);
1412 close(fd);
1413 if (err) {
1414 p_err("failed to freeze map: %s", strerror(errno));
1415 return err;
1416 }
1417
1418 if (json_output)
1419 jsonw_null(json_wtr);
1420
1421 return 0;
1422 }
1423
1424 static int do_help(int argc, char **argv)
1425 {
1426 if (json_output) {
1427 jsonw_null(json_wtr);
1428 return 0;
1429 }
1430
1431 fprintf(stderr,
1432 "Usage: %1$s %2$s { show | list } [MAP]\n"
1433 " %1$s %2$s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n"
1434 " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n"
1435 " [inner_map MAP] [dev NAME]\n"
1436 " %1$s %2$s dump MAP\n"
1437 " %1$s %2$s update MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n"
1438 " %1$s %2$s lookup MAP [key DATA]\n"
1439 " %1$s %2$s getnext MAP [key DATA]\n"
1440 " %1$s %2$s delete MAP key DATA\n"
1441 " %1$s %2$s pin MAP FILE\n"
1442 " %1$s %2$s event_pipe MAP [cpu N index M]\n"
1443 " %1$s %2$s peek MAP\n"
1444 " %1$s %2$s push MAP value VALUE\n"
1445 " %1$s %2$s pop MAP\n"
1446 " %1$s %2$s enqueue MAP value VALUE\n"
1447 " %1$s %2$s dequeue MAP\n"
1448 " %1$s %2$s freeze MAP\n"
1449 " %1$s %2$s help\n"
1450 "\n"
1451 " " HELP_SPEC_MAP "\n"
1452 " DATA := { [hex] BYTES }\n"
1453 " " HELP_SPEC_PROGRAM "\n"
1454 " VALUE := { DATA | MAP | PROG }\n"
1455 " UPDATE_FLAGS := { any | exist | noexist }\n"
1456 " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n"
1457 " percpu_array | stack_trace | cgroup_array | lru_hash |\n"
1458 " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n"
1459 " devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n"
1460 " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage |\n"
1461 " queue | stack | sk_storage | struct_ops | ringbuf | inode_storage |\n"
1462 " task_storage | bloom_filter }\n"
1463 " " HELP_SPEC_OPTIONS " |\n"
1464 " {-f|--bpffs} | {-n|--nomount} }\n"
1465 "",
1466 bin_name, argv[-2]);
1467
1468 return 0;
1469 }
1470
1471 static const struct cmd cmds[] = {
1472 { "show", do_show },
1473 { "list", do_show },
1474 { "help", do_help },
1475 { "dump", do_dump },
1476 { "update", do_update },
1477 { "lookup", do_lookup },
1478 { "getnext", do_getnext },
1479 { "delete", do_delete },
1480 { "pin", do_pin },
1481 { "event_pipe", do_event_pipe },
1482 { "create", do_create },
1483 { "peek", do_lookup },
1484 { "push", do_update },
1485 { "enqueue", do_update },
1486 { "pop", do_pop_dequeue },
1487 { "dequeue", do_pop_dequeue },
1488 { "freeze", do_freeze },
1489 { 0 }
1490 };
1491
1492 int do_map(int argc, char **argv)
1493 {
1494 return cmd_select(cmds, argc, argv, do_help);
1495 }