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