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