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