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