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