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