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