1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ 3 4 #include <assert.h> 5 #include <errno.h> 6 #include <fcntl.h> 7 #include <linux/err.h> 8 #include <linux/kernel.h> 9 #include <net/if.h> 10 #include <stdbool.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 18 #include <bpf/bpf.h> 19 #include <bpf/btf.h> 20 #include <bpf/hashmap.h> 21 22 #include "json_writer.h" 23 #include "main.h" 24 25 static struct hashmap *map_table; 26 27 static bool map_is_per_cpu(__u32 type) 28 { 29 return type == BPF_MAP_TYPE_PERCPU_HASH || 30 type == BPF_MAP_TYPE_PERCPU_ARRAY || 31 type == BPF_MAP_TYPE_LRU_PERCPU_HASH || 32 type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE; 33 } 34 35 static bool map_is_map_of_maps(__u32 type) 36 { 37 return type == BPF_MAP_TYPE_ARRAY_OF_MAPS || 38 type == BPF_MAP_TYPE_HASH_OF_MAPS; 39 } 40 41 static bool map_is_map_of_progs(__u32 type) 42 { 43 return type == BPF_MAP_TYPE_PROG_ARRAY; 44 } 45 46 static int map_type_from_str(const char *type) 47 { 48 const char *map_type_str; 49 unsigned int i; 50 51 for (i = 0; ; i++) { 52 map_type_str = libbpf_bpf_map_type_str(i); 53 if (!map_type_str) 54 break; 55 56 /* Don't allow prefixing in case of possible future shadowing */ 57 if (!strcmp(map_type_str, type)) 58 return i; 59 } 60 return -1; 61 } 62 63 static void *alloc_value(struct bpf_map_info *info) 64 { 65 if (map_is_per_cpu(info->type)) 66 return malloc(round_up(info->value_size, 8) * 67 get_possible_cpus()); 68 else 69 return malloc(info->value_size); 70 } 71 72 static int do_dump_btf(const struct btf_dumper *d, 73 struct bpf_map_info *map_info, void *key, 74 void *value) 75 { 76 __u32 value_id; 77 int ret = 0; 78 79 /* start of key-value pair */ 80 jsonw_start_object(d->jw); 81 82 if (map_info->btf_key_type_id) { 83 jsonw_name(d->jw, "key"); 84 85 ret = btf_dumper_type(d, map_info->btf_key_type_id, key); 86 if (ret) 87 goto err_end_obj; 88 } 89 90 value_id = map_info->btf_vmlinux_value_type_id ? 91 : map_info->btf_value_type_id; 92 93 if (!map_is_per_cpu(map_info->type)) { 94 jsonw_name(d->jw, "value"); 95 ret = btf_dumper_type(d, value_id, value); 96 } else { 97 unsigned int i, n, step; 98 99 jsonw_name(d->jw, "values"); 100 jsonw_start_array(d->jw); 101 n = get_possible_cpus(); 102 step = round_up(map_info->value_size, 8); 103 for (i = 0; i < n; i++) { 104 jsonw_start_object(d->jw); 105 jsonw_int_field(d->jw, "cpu", i); 106 jsonw_name(d->jw, "value"); 107 ret = btf_dumper_type(d, value_id, value + i * step); 108 jsonw_end_object(d->jw); 109 if (ret) 110 break; 111 } 112 jsonw_end_array(d->jw); 113 } 114 115 err_end_obj: 116 /* end of key-value pair */ 117 jsonw_end_object(d->jw); 118 119 return ret; 120 } 121 122 static json_writer_t *get_btf_writer(void) 123 { 124 json_writer_t *jw = jsonw_new(stdout); 125 126 if (!jw) 127 return NULL; 128 jsonw_pretty(jw, true); 129 130 return jw; 131 } 132 133 static void print_entry_json(struct bpf_map_info *info, unsigned char *key, 134 unsigned char *value, struct btf *btf) 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 (btf) { 144 struct btf_dumper d = { 145 .btf = btf, 146 .jw = json_wtr, 147 .is_plain_text = false, 148 }; 149 150 jsonw_name(json_wtr, "formatted"); 151 do_dump_btf(&d, info, key, value); 152 } 153 } else { 154 unsigned int i, n, step; 155 156 n = get_possible_cpus(); 157 step = round_up(info->value_size, 8); 158 159 jsonw_name(json_wtr, "key"); 160 print_hex_data_json(key, info->key_size); 161 162 jsonw_name(json_wtr, "values"); 163 jsonw_start_array(json_wtr); 164 for (i = 0; i < n; i++) { 165 jsonw_start_object(json_wtr); 166 167 jsonw_int_field(json_wtr, "cpu", i); 168 169 jsonw_name(json_wtr, "value"); 170 print_hex_data_json(value + i * step, 171 info->value_size); 172 173 jsonw_end_object(json_wtr); 174 } 175 jsonw_end_array(json_wtr); 176 if (btf) { 177 struct btf_dumper d = { 178 .btf = btf, 179 .jw = json_wtr, 180 .is_plain_text = false, 181 }; 182 183 jsonw_name(json_wtr, "formatted"); 184 do_dump_btf(&d, info, key, value); 185 } 186 } 187 188 jsonw_end_object(json_wtr); 189 } 190 191 static void 192 print_entry_error_msg(struct bpf_map_info *info, unsigned char *key, 193 const char *error_msg) 194 { 195 int msg_size = strlen(error_msg); 196 bool single_line, break_names; 197 198 break_names = info->key_size > 16 || msg_size > 16; 199 single_line = info->key_size + msg_size <= 24 && !break_names; 200 201 printf("key:%c", break_names ? '\n' : ' '); 202 fprint_hex(stdout, key, info->key_size, " "); 203 204 printf(single_line ? " " : "\n"); 205 206 printf("value:%c%s", break_names ? '\n' : ' ', error_msg); 207 208 printf("\n"); 209 } 210 211 static void 212 print_entry_error(struct bpf_map_info *map_info, void *key, int lookup_errno) 213 { 214 /* For prog_array maps or arrays of maps, failure to lookup the value 215 * means there is no entry for that key. Do not print an error message 216 * in that case. 217 */ 218 if ((map_is_map_of_maps(map_info->type) || 219 map_is_map_of_progs(map_info->type)) && lookup_errno == ENOENT) 220 return; 221 222 if (json_output) { 223 jsonw_start_object(json_wtr); /* entry */ 224 jsonw_name(json_wtr, "key"); 225 print_hex_data_json(key, map_info->key_size); 226 jsonw_name(json_wtr, "value"); 227 jsonw_start_object(json_wtr); /* error */ 228 jsonw_string_field(json_wtr, "error", strerror(lookup_errno)); 229 jsonw_end_object(json_wtr); /* error */ 230 jsonw_end_object(json_wtr); /* entry */ 231 } else { 232 const char *msg = NULL; 233 234 if (lookup_errno == ENOENT) 235 msg = "<no entry>"; 236 else if (lookup_errno == ENOSPC && 237 map_info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) 238 msg = "<cannot read>"; 239 240 print_entry_error_msg(map_info, key, 241 msg ? : strerror(lookup_errno)); 242 } 243 } 244 245 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key, 246 unsigned char *value) 247 { 248 if (!map_is_per_cpu(info->type)) { 249 bool single_line, break_names; 250 251 break_names = info->key_size > 16 || info->value_size > 16; 252 single_line = info->key_size + info->value_size <= 24 && 253 !break_names; 254 255 if (info->key_size) { 256 printf("key:%c", break_names ? '\n' : ' '); 257 fprint_hex(stdout, key, info->key_size, " "); 258 259 printf(single_line ? " " : "\n"); 260 } 261 262 if (info->value_size) { 263 printf("value:%c", break_names ? '\n' : ' '); 264 fprint_hex(stdout, value, info->value_size, " "); 265 } 266 267 printf("\n"); 268 } else { 269 unsigned int i, n, step; 270 271 n = get_possible_cpus(); 272 step = round_up(info->value_size, 8); 273 274 if (info->key_size) { 275 printf("key:\n"); 276 fprint_hex(stdout, key, info->key_size, " "); 277 printf("\n"); 278 } 279 if (info->value_size) { 280 for (i = 0; i < n; i++) { 281 printf("value (CPU %02d):%c", 282 i, info->value_size > 16 ? '\n' : ' '); 283 fprint_hex(stdout, value + i * step, 284 info->value_size, " "); 285 printf("\n"); 286 } 287 } 288 } 289 } 290 291 static char **parse_bytes(char **argv, const char *name, unsigned char *val, 292 unsigned int n) 293 { 294 unsigned int i = 0, base = 0; 295 char *endptr; 296 297 if (is_prefix(*argv, "hex")) { 298 base = 16; 299 argv++; 300 } 301 302 while (i < n && argv[i]) { 303 val[i] = strtoul(argv[i], &endptr, base); 304 if (*endptr) { 305 p_err("error parsing byte: %s", argv[i]); 306 return NULL; 307 } 308 i++; 309 } 310 311 if (i != n) { 312 p_err("%s expected %d bytes got %d", name, n, i); 313 return NULL; 314 } 315 316 return argv + i; 317 } 318 319 /* on per cpu maps we must copy the provided value on all value instances */ 320 static void fill_per_cpu_value(struct bpf_map_info *info, void *value) 321 { 322 unsigned int i, n, step; 323 324 if (!map_is_per_cpu(info->type)) 325 return; 326 327 n = get_possible_cpus(); 328 step = round_up(info->value_size, 8); 329 for (i = 1; i < n; i++) 330 memcpy(value + i * step, value, info->value_size); 331 } 332 333 static int parse_elem(char **argv, struct bpf_map_info *info, 334 void *key, void *value, __u32 key_size, __u32 value_size, 335 __u32 *flags, __u32 **value_fd) 336 { 337 if (!*argv) { 338 if (!key && !value) 339 return 0; 340 p_err("did not find %s", key ? "key" : "value"); 341 return -1; 342 } 343 344 if (is_prefix(*argv, "key")) { 345 if (!key) { 346 if (key_size) 347 p_err("duplicate key"); 348 else 349 p_err("unnecessary key"); 350 return -1; 351 } 352 353 argv = parse_bytes(argv + 1, "key", key, key_size); 354 if (!argv) 355 return -1; 356 357 return parse_elem(argv, info, NULL, value, key_size, value_size, 358 flags, value_fd); 359 } else if (is_prefix(*argv, "value")) { 360 int fd; 361 362 if (!value) { 363 if (value_size) 364 p_err("duplicate value"); 365 else 366 p_err("unnecessary value"); 367 return -1; 368 } 369 370 argv++; 371 372 if (map_is_map_of_maps(info->type)) { 373 int argc = 2; 374 375 if (value_size != 4) { 376 p_err("value smaller than 4B for map in map?"); 377 return -1; 378 } 379 if (!argv[0] || !argv[1]) { 380 p_err("not enough value arguments for map in map"); 381 return -1; 382 } 383 384 fd = map_parse_fd(&argc, &argv); 385 if (fd < 0) 386 return -1; 387 388 *value_fd = value; 389 **value_fd = fd; 390 } else if (map_is_map_of_progs(info->type)) { 391 int argc = 2; 392 393 if (value_size != 4) { 394 p_err("value smaller than 4B for map of progs?"); 395 return -1; 396 } 397 if (!argv[0] || !argv[1]) { 398 p_err("not enough value arguments for map of progs"); 399 return -1; 400 } 401 if (is_prefix(*argv, "id")) 402 p_info("Warning: updating program array via MAP_ID, make sure this map is kept open\n" 403 " by some process or pinned otherwise update will be lost"); 404 405 fd = prog_parse_fd(&argc, &argv); 406 if (fd < 0) 407 return -1; 408 409 *value_fd = value; 410 **value_fd = fd; 411 } else { 412 argv = parse_bytes(argv, "value", value, value_size); 413 if (!argv) 414 return -1; 415 416 fill_per_cpu_value(info, value); 417 } 418 419 return parse_elem(argv, info, key, NULL, key_size, value_size, 420 flags, NULL); 421 } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") || 422 is_prefix(*argv, "exist")) { 423 if (!flags) { 424 p_err("flags specified multiple times: %s", *argv); 425 return -1; 426 } 427 428 if (is_prefix(*argv, "any")) 429 *flags = BPF_ANY; 430 else if (is_prefix(*argv, "noexist")) 431 *flags = BPF_NOEXIST; 432 else if (is_prefix(*argv, "exist")) 433 *flags = BPF_EXIST; 434 435 return parse_elem(argv + 1, info, key, value, key_size, 436 value_size, NULL, value_fd); 437 } 438 439 p_err("expected key or value, got: %s", *argv); 440 return -1; 441 } 442 443 static void show_map_header_json(struct bpf_map_info *info, json_writer_t *wtr) 444 { 445 const char *map_type_str; 446 447 jsonw_uint_field(wtr, "id", info->id); 448 map_type_str = libbpf_bpf_map_type_str(info->type); 449 if (map_type_str) 450 jsonw_string_field(wtr, "type", map_type_str); 451 else 452 jsonw_uint_field(wtr, "type", info->type); 453 454 if (*info->name) 455 jsonw_string_field(wtr, "name", info->name); 456 457 jsonw_name(wtr, "flags"); 458 jsonw_printf(wtr, "%d", info->map_flags); 459 } 460 461 static int show_map_close_json(int fd, struct bpf_map_info *info) 462 { 463 char *memlock, *frozen_str; 464 int frozen = 0; 465 466 memlock = get_fdinfo(fd, "memlock"); 467 frozen_str = get_fdinfo(fd, "frozen"); 468 469 jsonw_start_object(json_wtr); 470 471 show_map_header_json(info, json_wtr); 472 473 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino); 474 475 jsonw_uint_field(json_wtr, "bytes_key", info->key_size); 476 jsonw_uint_field(json_wtr, "bytes_value", info->value_size); 477 jsonw_uint_field(json_wtr, "max_entries", info->max_entries); 478 479 if (memlock) 480 jsonw_int_field(json_wtr, "bytes_memlock", atoll(memlock)); 481 free(memlock); 482 483 if (info->type == BPF_MAP_TYPE_PROG_ARRAY) { 484 char *owner_prog_type = get_fdinfo(fd, "owner_prog_type"); 485 char *owner_jited = get_fdinfo(fd, "owner_jited"); 486 487 if (owner_prog_type) { 488 unsigned int prog_type = atoi(owner_prog_type); 489 const char *prog_type_str; 490 491 prog_type_str = libbpf_bpf_prog_type_str(prog_type); 492 if (prog_type_str) 493 jsonw_string_field(json_wtr, "owner_prog_type", 494 prog_type_str); 495 else 496 jsonw_uint_field(json_wtr, "owner_prog_type", 497 prog_type); 498 } 499 if (owner_jited) 500 jsonw_bool_field(json_wtr, "owner_jited", 501 !!atoi(owner_jited)); 502 503 free(owner_prog_type); 504 free(owner_jited); 505 } 506 close(fd); 507 508 if (frozen_str) { 509 frozen = atoi(frozen_str); 510 free(frozen_str); 511 } 512 jsonw_int_field(json_wtr, "frozen", frozen); 513 514 if (info->btf_id) 515 jsonw_int_field(json_wtr, "btf_id", info->btf_id); 516 517 if (!hashmap__empty(map_table)) { 518 struct hashmap_entry *entry; 519 520 jsonw_name(json_wtr, "pinned"); 521 jsonw_start_array(json_wtr); 522 hashmap__for_each_key_entry(map_table, entry, 523 u32_as_hash_field(info->id)) 524 jsonw_string(json_wtr, entry->value); 525 jsonw_end_array(json_wtr); 526 } 527 528 emit_obj_refs_json(refs_table, info->id, json_wtr); 529 530 jsonw_end_object(json_wtr); 531 532 return 0; 533 } 534 535 static void show_map_header_plain(struct bpf_map_info *info) 536 { 537 const char *map_type_str; 538 539 printf("%u: ", info->id); 540 541 map_type_str = libbpf_bpf_map_type_str(info->type); 542 if (map_type_str) 543 printf("%s ", map_type_str); 544 else 545 printf("type %u ", info->type); 546 547 if (*info->name) 548 printf("name %s ", info->name); 549 550 printf("flags 0x%x", info->map_flags); 551 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino); 552 printf("\n"); 553 } 554 555 static int show_map_close_plain(int fd, struct bpf_map_info *info) 556 { 557 char *memlock, *frozen_str; 558 int frozen = 0; 559 560 memlock = get_fdinfo(fd, "memlock"); 561 frozen_str = get_fdinfo(fd, "frozen"); 562 563 show_map_header_plain(info); 564 printf("\tkey %uB value %uB max_entries %u", 565 info->key_size, info->value_size, info->max_entries); 566 567 if (memlock) 568 printf(" memlock %sB", memlock); 569 free(memlock); 570 571 if (info->type == BPF_MAP_TYPE_PROG_ARRAY) { 572 char *owner_prog_type = get_fdinfo(fd, "owner_prog_type"); 573 char *owner_jited = get_fdinfo(fd, "owner_jited"); 574 575 if (owner_prog_type || owner_jited) 576 printf("\n\t"); 577 if (owner_prog_type) { 578 unsigned int prog_type = atoi(owner_prog_type); 579 const char *prog_type_str; 580 581 prog_type_str = libbpf_bpf_prog_type_str(prog_type); 582 if (prog_type_str) 583 printf("owner_prog_type %s ", prog_type_str); 584 else 585 printf("owner_prog_type %d ", prog_type); 586 } 587 if (owner_jited) 588 printf("owner%s jited", 589 atoi(owner_jited) ? "" : " not"); 590 591 free(owner_prog_type); 592 free(owner_jited); 593 } 594 close(fd); 595 596 if (!hashmap__empty(map_table)) { 597 struct hashmap_entry *entry; 598 599 hashmap__for_each_key_entry(map_table, entry, 600 u32_as_hash_field(info->id)) 601 printf("\n\tpinned %s", (char *)entry->value); 602 } 603 604 if (frozen_str) { 605 frozen = atoi(frozen_str); 606 free(frozen_str); 607 } 608 609 if (info->btf_id || frozen) 610 printf("\n\t"); 611 612 if (info->btf_id) 613 printf("btf_id %d", info->btf_id); 614 615 if (frozen) 616 printf("%sfrozen", info->btf_id ? " " : ""); 617 618 emit_obj_refs_plain(refs_table, info->id, "\n\tpids "); 619 620 printf("\n"); 621 return 0; 622 } 623 624 static int do_show_subset(int argc, char **argv) 625 { 626 struct bpf_map_info info = {}; 627 __u32 len = sizeof(info); 628 int *fds = NULL; 629 int nb_fds, i; 630 int err = -1; 631 632 fds = malloc(sizeof(int)); 633 if (!fds) { 634 p_err("mem alloc failed"); 635 return -1; 636 } 637 nb_fds = map_parse_fds(&argc, &argv, &fds); 638 if (nb_fds < 1) 639 goto exit_free; 640 641 if (json_output && nb_fds > 1) 642 jsonw_start_array(json_wtr); /* root array */ 643 for (i = 0; i < nb_fds; i++) { 644 err = bpf_obj_get_info_by_fd(fds[i], &info, &len); 645 if (err) { 646 p_err("can't get map info: %s", 647 strerror(errno)); 648 for (; i < nb_fds; i++) 649 close(fds[i]); 650 break; 651 } 652 653 if (json_output) 654 show_map_close_json(fds[i], &info); 655 else 656 show_map_close_plain(fds[i], &info); 657 658 close(fds[i]); 659 } 660 if (json_output && nb_fds > 1) 661 jsonw_end_array(json_wtr); /* root array */ 662 663 exit_free: 664 free(fds); 665 return err; 666 } 667 668 static int do_show(int argc, char **argv) 669 { 670 struct bpf_map_info info = {}; 671 __u32 len = sizeof(info); 672 __u32 id = 0; 673 int err; 674 int fd; 675 676 if (show_pinned) { 677 map_table = hashmap__new(hash_fn_for_key_as_id, 678 equal_fn_for_key_as_id, NULL); 679 if (IS_ERR(map_table)) { 680 p_err("failed to create hashmap for pinned paths"); 681 return -1; 682 } 683 build_pinned_obj_table(map_table, BPF_OBJ_MAP); 684 } 685 build_obj_refs_table(&refs_table, BPF_OBJ_MAP); 686 687 if (argc == 2) 688 return do_show_subset(argc, argv); 689 690 if (argc) 691 return BAD_ARG(); 692 693 if (json_output) 694 jsonw_start_array(json_wtr); 695 while (true) { 696 err = bpf_map_get_next_id(id, &id); 697 if (err) { 698 if (errno == ENOENT) 699 break; 700 p_err("can't get next map: %s%s", strerror(errno), 701 errno == EINVAL ? " -- kernel too old?" : ""); 702 break; 703 } 704 705 fd = bpf_map_get_fd_by_id(id); 706 if (fd < 0) { 707 if (errno == ENOENT) 708 continue; 709 p_err("can't get map by id (%u): %s", 710 id, strerror(errno)); 711 break; 712 } 713 714 err = bpf_obj_get_info_by_fd(fd, &info, &len); 715 if (err) { 716 p_err("can't get map info: %s", strerror(errno)); 717 close(fd); 718 break; 719 } 720 721 if (json_output) 722 show_map_close_json(fd, &info); 723 else 724 show_map_close_plain(fd, &info); 725 } 726 if (json_output) 727 jsonw_end_array(json_wtr); 728 729 delete_obj_refs_table(refs_table); 730 731 if (show_pinned) 732 delete_pinned_obj_table(map_table); 733 734 return errno == ENOENT ? 0 : -1; 735 } 736 737 static int dump_map_elem(int fd, void *key, void *value, 738 struct bpf_map_info *map_info, struct btf *btf, 739 json_writer_t *btf_wtr) 740 { 741 if (bpf_map_lookup_elem(fd, key, value)) { 742 print_entry_error(map_info, key, errno); 743 return -1; 744 } 745 746 if (json_output) { 747 print_entry_json(map_info, key, value, btf); 748 } else if (btf) { 749 struct btf_dumper d = { 750 .btf = btf, 751 .jw = btf_wtr, 752 .is_plain_text = true, 753 }; 754 755 do_dump_btf(&d, map_info, key, value); 756 } else { 757 print_entry_plain(map_info, key, value); 758 } 759 760 return 0; 761 } 762 763 static int maps_have_btf(int *fds, int nb_fds) 764 { 765 struct bpf_map_info info = {}; 766 __u32 len = sizeof(info); 767 int err, i; 768 769 for (i = 0; i < nb_fds; i++) { 770 err = bpf_obj_get_info_by_fd(fds[i], &info, &len); 771 if (err) { 772 p_err("can't get map info: %s", strerror(errno)); 773 return -1; 774 } 775 776 if (!info.btf_id) 777 return 0; 778 } 779 780 return 1; 781 } 782 783 static struct btf *btf_vmlinux; 784 785 static int get_map_kv_btf(const struct bpf_map_info *info, struct btf **btf) 786 { 787 int err = 0; 788 789 if (info->btf_vmlinux_value_type_id) { 790 if (!btf_vmlinux) { 791 btf_vmlinux = libbpf_find_kernel_btf(); 792 err = libbpf_get_error(btf_vmlinux); 793 if (err) { 794 p_err("failed to get kernel btf"); 795 return err; 796 } 797 } 798 *btf = btf_vmlinux; 799 } else if (info->btf_value_type_id) { 800 *btf = btf__load_from_kernel_by_id(info->btf_id); 801 err = libbpf_get_error(*btf); 802 if (err) 803 p_err("failed to get btf"); 804 } else { 805 *btf = NULL; 806 } 807 808 return err; 809 } 810 811 static void free_map_kv_btf(struct btf *btf) 812 { 813 if (!libbpf_get_error(btf) && btf != btf_vmlinux) 814 btf__free(btf); 815 } 816 817 static void free_btf_vmlinux(void) 818 { 819 if (!libbpf_get_error(btf_vmlinux)) 820 btf__free(btf_vmlinux); 821 } 822 823 static int 824 map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr, 825 bool show_header) 826 { 827 void *key, *value, *prev_key; 828 unsigned int num_elems = 0; 829 struct btf *btf = NULL; 830 int err; 831 832 key = malloc(info->key_size); 833 value = alloc_value(info); 834 if (!key || !value) { 835 p_err("mem alloc failed"); 836 err = -1; 837 goto exit_free; 838 } 839 840 prev_key = NULL; 841 842 if (wtr) { 843 err = get_map_kv_btf(info, &btf); 844 if (err) { 845 goto exit_free; 846 } 847 848 if (show_header) { 849 jsonw_start_object(wtr); /* map object */ 850 show_map_header_json(info, wtr); 851 jsonw_name(wtr, "elements"); 852 } 853 jsonw_start_array(wtr); /* elements */ 854 } else if (show_header) { 855 show_map_header_plain(info); 856 } 857 858 if (info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY && 859 info->value_size != 8) { 860 const char *map_type_str; 861 862 map_type_str = libbpf_bpf_map_type_str(info->type); 863 p_info("Warning: cannot read values from %s map with value_size != 8", 864 map_type_str); 865 } 866 while (true) { 867 err = bpf_map_get_next_key(fd, prev_key, key); 868 if (err) { 869 if (errno == ENOENT) 870 err = 0; 871 break; 872 } 873 if (!dump_map_elem(fd, key, value, info, btf, wtr)) 874 num_elems++; 875 prev_key = key; 876 } 877 878 if (wtr) { 879 jsonw_end_array(wtr); /* elements */ 880 if (show_header) 881 jsonw_end_object(wtr); /* map object */ 882 } else { 883 printf("Found %u element%s\n", num_elems, 884 num_elems != 1 ? "s" : ""); 885 } 886 887 exit_free: 888 free(key); 889 free(value); 890 close(fd); 891 free_map_kv_btf(btf); 892 893 return err; 894 } 895 896 static int do_dump(int argc, char **argv) 897 { 898 json_writer_t *wtr = NULL, *btf_wtr = NULL; 899 struct bpf_map_info info = {}; 900 int nb_fds, i = 0; 901 __u32 len = sizeof(info); 902 int *fds = NULL; 903 int err = -1; 904 905 if (argc != 2) 906 usage(); 907 908 fds = malloc(sizeof(int)); 909 if (!fds) { 910 p_err("mem alloc failed"); 911 return -1; 912 } 913 nb_fds = map_parse_fds(&argc, &argv, &fds); 914 if (nb_fds < 1) 915 goto exit_free; 916 917 if (json_output) { 918 wtr = json_wtr; 919 } else { 920 int do_plain_btf; 921 922 do_plain_btf = maps_have_btf(fds, nb_fds); 923 if (do_plain_btf < 0) 924 goto exit_close; 925 926 if (do_plain_btf) { 927 btf_wtr = get_btf_writer(); 928 wtr = btf_wtr; 929 if (!btf_wtr) 930 p_info("failed to create json writer for btf. falling back to plain output"); 931 } 932 } 933 934 if (wtr && nb_fds > 1) 935 jsonw_start_array(wtr); /* root array */ 936 for (i = 0; i < nb_fds; i++) { 937 if (bpf_obj_get_info_by_fd(fds[i], &info, &len)) { 938 p_err("can't get map info: %s", strerror(errno)); 939 break; 940 } 941 err = map_dump(fds[i], &info, wtr, nb_fds > 1); 942 if (!wtr && i != nb_fds - 1) 943 printf("\n"); 944 945 if (err) 946 break; 947 close(fds[i]); 948 } 949 if (wtr && nb_fds > 1) 950 jsonw_end_array(wtr); /* root array */ 951 952 if (btf_wtr) 953 jsonw_destroy(&btf_wtr); 954 exit_close: 955 for (; i < nb_fds; i++) 956 close(fds[i]); 957 exit_free: 958 free(fds); 959 free_btf_vmlinux(); 960 return err; 961 } 962 963 static int alloc_key_value(struct bpf_map_info *info, void **key, void **value) 964 { 965 *key = NULL; 966 *value = NULL; 967 968 if (info->key_size) { 969 *key = malloc(info->key_size); 970 if (!*key) { 971 p_err("key mem alloc failed"); 972 return -1; 973 } 974 } 975 976 if (info->value_size) { 977 *value = alloc_value(info); 978 if (!*value) { 979 p_err("value mem alloc failed"); 980 free(*key); 981 *key = NULL; 982 return -1; 983 } 984 } 985 986 return 0; 987 } 988 989 static int do_update(int argc, char **argv) 990 { 991 struct bpf_map_info info = {}; 992 __u32 len = sizeof(info); 993 __u32 *value_fd = NULL; 994 __u32 flags = BPF_ANY; 995 void *key, *value; 996 int fd, err; 997 998 if (argc < 2) 999 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 /* if here json_wtr wouldn't have been initialised, 1045 * so let's create separate writer for btf 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 /* here means bpf_map_lookup_elem() succeeded */ 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 | user_ringbuf }\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 } 1496