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; 485 486 memlock = get_fdinfo(fd, "memlock"); 487 488 jsonw_start_object(json_wtr); 489 490 jsonw_uint_field(json_wtr, "id", info->id); 491 if (info->type < ARRAY_SIZE(map_type_name)) 492 jsonw_string_field(json_wtr, "type", 493 map_type_name[info->type]); 494 else 495 jsonw_uint_field(json_wtr, "type", info->type); 496 497 if (*info->name) 498 jsonw_string_field(json_wtr, "name", info->name); 499 500 jsonw_name(json_wtr, "flags"); 501 jsonw_printf(json_wtr, "%d", info->map_flags); 502 503 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino); 504 505 jsonw_uint_field(json_wtr, "bytes_key", info->key_size); 506 jsonw_uint_field(json_wtr, "bytes_value", info->value_size); 507 jsonw_uint_field(json_wtr, "max_entries", info->max_entries); 508 509 if (memlock) 510 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock)); 511 free(memlock); 512 513 if (info->type == BPF_MAP_TYPE_PROG_ARRAY) { 514 char *owner_prog_type = get_fdinfo(fd, "owner_prog_type"); 515 char *owner_jited = get_fdinfo(fd, "owner_jited"); 516 517 if (owner_prog_type) { 518 unsigned int prog_type = atoi(owner_prog_type); 519 520 if (prog_type < ARRAY_SIZE(prog_type_name)) 521 jsonw_string_field(json_wtr, "owner_prog_type", 522 prog_type_name[prog_type]); 523 else 524 jsonw_uint_field(json_wtr, "owner_prog_type", 525 prog_type); 526 } 527 if (owner_jited) 528 jsonw_bool_field(json_wtr, "owner_jited", 529 !!atoi(owner_jited)); 530 531 free(owner_prog_type); 532 free(owner_jited); 533 } 534 close(fd); 535 536 if (info->btf_id) 537 jsonw_int_field(json_wtr, "btf_id", info->btf_id); 538 539 if (!hash_empty(map_table.table)) { 540 struct pinned_obj *obj; 541 542 jsonw_name(json_wtr, "pinned"); 543 jsonw_start_array(json_wtr); 544 hash_for_each_possible(map_table.table, obj, hash, info->id) { 545 if (obj->id == info->id) 546 jsonw_string(json_wtr, obj->path); 547 } 548 jsonw_end_array(json_wtr); 549 } 550 551 jsonw_end_object(json_wtr); 552 553 return 0; 554 } 555 556 static int show_map_close_plain(int fd, struct bpf_map_info *info) 557 { 558 char *memlock; 559 560 memlock = get_fdinfo(fd, "memlock"); 561 562 printf("%u: ", info->id); 563 if (info->type < ARRAY_SIZE(map_type_name)) 564 printf("%s ", map_type_name[info->type]); 565 else 566 printf("type %u ", info->type); 567 568 if (*info->name) 569 printf("name %s ", info->name); 570 571 printf("flags 0x%x", info->map_flags); 572 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino); 573 printf("\n"); 574 printf("\tkey %uB value %uB max_entries %u", 575 info->key_size, info->value_size, info->max_entries); 576 577 if (memlock) 578 printf(" memlock %sB", memlock); 579 free(memlock); 580 581 if (info->type == BPF_MAP_TYPE_PROG_ARRAY) { 582 char *owner_prog_type = get_fdinfo(fd, "owner_prog_type"); 583 char *owner_jited = get_fdinfo(fd, "owner_jited"); 584 585 if (owner_prog_type || owner_jited) 586 printf("\n\t"); 587 if (owner_prog_type) { 588 unsigned int prog_type = atoi(owner_prog_type); 589 590 if (prog_type < ARRAY_SIZE(prog_type_name)) 591 printf("owner_prog_type %s ", 592 prog_type_name[prog_type]); 593 else 594 printf("owner_prog_type %d ", prog_type); 595 } 596 if (owner_jited) 597 printf("owner%s jited", 598 atoi(owner_jited) ? "" : " not"); 599 600 free(owner_prog_type); 601 free(owner_jited); 602 } 603 close(fd); 604 605 if (!hash_empty(map_table.table)) { 606 struct pinned_obj *obj; 607 608 hash_for_each_possible(map_table.table, obj, hash, info->id) { 609 if (obj->id == info->id) 610 printf("\n\tpinned %s", obj->path); 611 } 612 } 613 614 if (info->btf_id) 615 printf("\n\tbtf_id %d", info->btf_id); 616 617 printf("\n"); 618 return 0; 619 } 620 621 static int do_show(int argc, char **argv) 622 { 623 struct bpf_map_info info = {}; 624 __u32 len = sizeof(info); 625 __u32 id = 0; 626 int err; 627 int fd; 628 629 if (show_pinned) 630 build_pinned_obj_table(&map_table, BPF_OBJ_MAP); 631 632 if (argc == 2) { 633 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 634 if (fd < 0) 635 return -1; 636 637 if (json_output) 638 return show_map_close_json(fd, &info); 639 else 640 return show_map_close_plain(fd, &info); 641 } 642 643 if (argc) 644 return BAD_ARG(); 645 646 if (json_output) 647 jsonw_start_array(json_wtr); 648 while (true) { 649 err = bpf_map_get_next_id(id, &id); 650 if (err) { 651 if (errno == ENOENT) 652 break; 653 p_err("can't get next map: %s%s", strerror(errno), 654 errno == EINVAL ? " -- kernel too old?" : ""); 655 break; 656 } 657 658 fd = bpf_map_get_fd_by_id(id); 659 if (fd < 0) { 660 if (errno == ENOENT) 661 continue; 662 p_err("can't get map by id (%u): %s", 663 id, strerror(errno)); 664 break; 665 } 666 667 err = bpf_obj_get_info_by_fd(fd, &info, &len); 668 if (err) { 669 p_err("can't get map info: %s", strerror(errno)); 670 close(fd); 671 break; 672 } 673 674 if (json_output) 675 show_map_close_json(fd, &info); 676 else 677 show_map_close_plain(fd, &info); 678 } 679 if (json_output) 680 jsonw_end_array(json_wtr); 681 682 return errno == ENOENT ? 0 : -1; 683 } 684 685 static int dump_map_elem(int fd, void *key, void *value, 686 struct bpf_map_info *map_info, struct btf *btf, 687 json_writer_t *btf_wtr) 688 { 689 int num_elems = 0; 690 int lookup_errno; 691 692 if (!bpf_map_lookup_elem(fd, key, value)) { 693 if (json_output) { 694 print_entry_json(map_info, key, value, btf); 695 } else { 696 if (btf) { 697 struct btf_dumper d = { 698 .btf = btf, 699 .jw = btf_wtr, 700 .is_plain_text = true, 701 }; 702 703 do_dump_btf(&d, map_info, key, value); 704 } else { 705 print_entry_plain(map_info, key, value); 706 } 707 num_elems++; 708 } 709 return num_elems; 710 } 711 712 /* lookup error handling */ 713 lookup_errno = errno; 714 715 if (map_is_map_of_maps(map_info->type) || 716 map_is_map_of_progs(map_info->type)) 717 return 0; 718 719 if (json_output) { 720 jsonw_start_object(json_wtr); 721 jsonw_name(json_wtr, "key"); 722 print_hex_data_json(key, map_info->key_size); 723 jsonw_name(json_wtr, "value"); 724 jsonw_start_object(json_wtr); 725 jsonw_string_field(json_wtr, "error", strerror(lookup_errno)); 726 jsonw_end_object(json_wtr); 727 jsonw_end_object(json_wtr); 728 } else { 729 const char *msg = NULL; 730 731 if (lookup_errno == ENOENT) 732 msg = "<no entry>"; 733 else if (lookup_errno == ENOSPC && 734 map_info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) 735 msg = "<cannot read>"; 736 737 print_entry_error(map_info, key, 738 msg ? : strerror(lookup_errno)); 739 } 740 741 return 0; 742 } 743 744 static int do_dump(int argc, char **argv) 745 { 746 struct bpf_map_info info = {}; 747 void *key, *value, *prev_key; 748 unsigned int num_elems = 0; 749 __u32 len = sizeof(info); 750 json_writer_t *btf_wtr; 751 struct btf *btf = NULL; 752 int err; 753 int fd; 754 755 if (argc != 2) 756 usage(); 757 758 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 759 if (fd < 0) 760 return -1; 761 762 key = malloc(info.key_size); 763 value = alloc_value(&info); 764 if (!key || !value) { 765 p_err("mem alloc failed"); 766 err = -1; 767 goto exit_free; 768 } 769 770 prev_key = NULL; 771 772 err = btf__get_from_id(info.btf_id, &btf); 773 if (err) { 774 p_err("failed to get btf"); 775 goto exit_free; 776 } 777 778 if (json_output) 779 jsonw_start_array(json_wtr); 780 else 781 if (btf) { 782 btf_wtr = get_btf_writer(); 783 if (!btf_wtr) { 784 p_info("failed to create json writer for btf. falling back to plain output"); 785 btf__free(btf); 786 btf = NULL; 787 } else { 788 jsonw_start_array(btf_wtr); 789 } 790 } 791 792 if (info.type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY && 793 info.value_size != 8) 794 p_info("Warning: cannot read values from %s map with value_size != 8", 795 map_type_name[info.type]); 796 while (true) { 797 err = bpf_map_get_next_key(fd, prev_key, key); 798 if (err) { 799 if (errno == ENOENT) 800 err = 0; 801 break; 802 } 803 num_elems += dump_map_elem(fd, key, value, &info, btf, btf_wtr); 804 prev_key = key; 805 } 806 807 if (json_output) 808 jsonw_end_array(json_wtr); 809 else if (btf) { 810 jsonw_end_array(btf_wtr); 811 jsonw_destroy(&btf_wtr); 812 } else { 813 printf("Found %u element%s\n", num_elems, 814 num_elems != 1 ? "s" : ""); 815 } 816 817 exit_free: 818 free(key); 819 free(value); 820 close(fd); 821 btf__free(btf); 822 823 return err; 824 } 825 826 static int alloc_key_value(struct bpf_map_info *info, void **key, void **value) 827 { 828 *key = NULL; 829 *value = NULL; 830 831 if (info->key_size) { 832 *key = malloc(info->key_size); 833 if (!*key) { 834 p_err("key mem alloc failed"); 835 return -1; 836 } 837 } 838 839 if (info->value_size) { 840 *value = alloc_value(info); 841 if (!*value) { 842 p_err("value mem alloc failed"); 843 free(*key); 844 *key = NULL; 845 return -1; 846 } 847 } 848 849 return 0; 850 } 851 852 static int do_update(int argc, char **argv) 853 { 854 struct bpf_map_info info = {}; 855 __u32 len = sizeof(info); 856 __u32 *value_fd = NULL; 857 __u32 flags = BPF_ANY; 858 void *key, *value; 859 int fd, err; 860 861 if (argc < 2) 862 usage(); 863 864 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 865 if (fd < 0) 866 return -1; 867 868 err = alloc_key_value(&info, &key, &value); 869 if (err) 870 goto exit_free; 871 872 err = parse_elem(argv, &info, key, value, info.key_size, 873 info.value_size, &flags, &value_fd); 874 if (err) 875 goto exit_free; 876 877 err = bpf_map_update_elem(fd, key, value, flags); 878 if (err) { 879 p_err("update failed: %s", strerror(errno)); 880 goto exit_free; 881 } 882 883 exit_free: 884 if (value_fd) 885 close(*value_fd); 886 free(key); 887 free(value); 888 close(fd); 889 890 if (!err && json_output) 891 jsonw_null(json_wtr); 892 return err; 893 } 894 895 static void print_key_value(struct bpf_map_info *info, void *key, 896 void *value) 897 { 898 json_writer_t *btf_wtr; 899 struct btf *btf = NULL; 900 int err; 901 902 err = btf__get_from_id(info->btf_id, &btf); 903 if (err) { 904 p_err("failed to get btf"); 905 return; 906 } 907 908 if (json_output) { 909 print_entry_json(info, key, value, btf); 910 } else if (btf) { 911 /* if here json_wtr wouldn't have been initialised, 912 * so let's create separate writer for btf 913 */ 914 btf_wtr = get_btf_writer(); 915 if (!btf_wtr) { 916 p_info("failed to create json writer for btf. falling back to plain output"); 917 btf__free(btf); 918 btf = NULL; 919 print_entry_plain(info, key, value); 920 } else { 921 struct btf_dumper d = { 922 .btf = btf, 923 .jw = btf_wtr, 924 .is_plain_text = true, 925 }; 926 927 do_dump_btf(&d, info, key, value); 928 jsonw_destroy(&btf_wtr); 929 } 930 } else { 931 print_entry_plain(info, key, value); 932 } 933 btf__free(btf); 934 } 935 936 static int do_lookup(int argc, char **argv) 937 { 938 struct bpf_map_info info = {}; 939 __u32 len = sizeof(info); 940 void *key, *value; 941 int err; 942 int fd; 943 944 if (argc < 2) 945 usage(); 946 947 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 948 if (fd < 0) 949 return -1; 950 951 err = alloc_key_value(&info, &key, &value); 952 if (err) 953 goto exit_free; 954 955 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL); 956 if (err) 957 goto exit_free; 958 959 err = bpf_map_lookup_elem(fd, key, value); 960 if (err) { 961 if (errno == ENOENT) { 962 if (json_output) { 963 jsonw_null(json_wtr); 964 } else { 965 printf("key:\n"); 966 fprint_hex(stdout, key, info.key_size, " "); 967 printf("\n\nNot found\n"); 968 } 969 } else { 970 p_err("lookup failed: %s", strerror(errno)); 971 } 972 973 goto exit_free; 974 } 975 976 /* here means bpf_map_lookup_elem() succeeded */ 977 print_key_value(&info, key, value); 978 979 exit_free: 980 free(key); 981 free(value); 982 close(fd); 983 984 return err; 985 } 986 987 static int do_getnext(int argc, char **argv) 988 { 989 struct bpf_map_info info = {}; 990 __u32 len = sizeof(info); 991 void *key, *nextkey; 992 int err; 993 int fd; 994 995 if (argc < 2) 996 usage(); 997 998 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 999 if (fd < 0) 1000 return -1; 1001 1002 key = malloc(info.key_size); 1003 nextkey = malloc(info.key_size); 1004 if (!key || !nextkey) { 1005 p_err("mem alloc failed"); 1006 err = -1; 1007 goto exit_free; 1008 } 1009 1010 if (argc) { 1011 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, 1012 NULL, NULL); 1013 if (err) 1014 goto exit_free; 1015 } else { 1016 free(key); 1017 key = NULL; 1018 } 1019 1020 err = bpf_map_get_next_key(fd, key, nextkey); 1021 if (err) { 1022 p_err("can't get next key: %s", strerror(errno)); 1023 goto exit_free; 1024 } 1025 1026 if (json_output) { 1027 jsonw_start_object(json_wtr); 1028 if (key) { 1029 jsonw_name(json_wtr, "key"); 1030 print_hex_data_json(key, info.key_size); 1031 } else { 1032 jsonw_null_field(json_wtr, "key"); 1033 } 1034 jsonw_name(json_wtr, "next_key"); 1035 print_hex_data_json(nextkey, info.key_size); 1036 jsonw_end_object(json_wtr); 1037 } else { 1038 if (key) { 1039 printf("key:\n"); 1040 fprint_hex(stdout, key, info.key_size, " "); 1041 printf("\n"); 1042 } else { 1043 printf("key: None\n"); 1044 } 1045 printf("next key:\n"); 1046 fprint_hex(stdout, nextkey, info.key_size, " "); 1047 printf("\n"); 1048 } 1049 1050 exit_free: 1051 free(nextkey); 1052 free(key); 1053 close(fd); 1054 1055 return err; 1056 } 1057 1058 static int do_delete(int argc, char **argv) 1059 { 1060 struct bpf_map_info info = {}; 1061 __u32 len = sizeof(info); 1062 void *key; 1063 int err; 1064 int fd; 1065 1066 if (argc < 2) 1067 usage(); 1068 1069 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 1070 if (fd < 0) 1071 return -1; 1072 1073 key = malloc(info.key_size); 1074 if (!key) { 1075 p_err("mem alloc failed"); 1076 err = -1; 1077 goto exit_free; 1078 } 1079 1080 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL); 1081 if (err) 1082 goto exit_free; 1083 1084 err = bpf_map_delete_elem(fd, key); 1085 if (err) 1086 p_err("delete failed: %s", strerror(errno)); 1087 1088 exit_free: 1089 free(key); 1090 close(fd); 1091 1092 if (!err && json_output) 1093 jsonw_null(json_wtr); 1094 return err; 1095 } 1096 1097 static int do_pin(int argc, char **argv) 1098 { 1099 int err; 1100 1101 err = do_pin_any(argc, argv, bpf_map_get_fd_by_id); 1102 if (!err && json_output) 1103 jsonw_null(json_wtr); 1104 return err; 1105 } 1106 1107 static int do_create(int argc, char **argv) 1108 { 1109 struct bpf_create_map_attr attr = { NULL, }; 1110 const char *pinfile; 1111 int err, fd; 1112 1113 if (!REQ_ARGS(7)) 1114 return -1; 1115 pinfile = GET_ARG(); 1116 1117 while (argc) { 1118 if (!REQ_ARGS(2)) 1119 return -1; 1120 1121 if (is_prefix(*argv, "type")) { 1122 NEXT_ARG(); 1123 1124 if (attr.map_type) { 1125 p_err("map type already specified"); 1126 return -1; 1127 } 1128 1129 attr.map_type = map_type_from_str(*argv); 1130 if ((int)attr.map_type < 0) { 1131 p_err("unrecognized map type: %s", *argv); 1132 return -1; 1133 } 1134 NEXT_ARG(); 1135 } else if (is_prefix(*argv, "name")) { 1136 NEXT_ARG(); 1137 attr.name = GET_ARG(); 1138 } else if (is_prefix(*argv, "key")) { 1139 if (parse_u32_arg(&argc, &argv, &attr.key_size, 1140 "key size")) 1141 return -1; 1142 } else if (is_prefix(*argv, "value")) { 1143 if (parse_u32_arg(&argc, &argv, &attr.value_size, 1144 "value size")) 1145 return -1; 1146 } else if (is_prefix(*argv, "entries")) { 1147 if (parse_u32_arg(&argc, &argv, &attr.max_entries, 1148 "max entries")) 1149 return -1; 1150 } else if (is_prefix(*argv, "flags")) { 1151 if (parse_u32_arg(&argc, &argv, &attr.map_flags, 1152 "flags")) 1153 return -1; 1154 } else if (is_prefix(*argv, "dev")) { 1155 NEXT_ARG(); 1156 1157 if (attr.map_ifindex) { 1158 p_err("offload device already specified"); 1159 return -1; 1160 } 1161 1162 attr.map_ifindex = if_nametoindex(*argv); 1163 if (!attr.map_ifindex) { 1164 p_err("unrecognized netdevice '%s': %s", 1165 *argv, strerror(errno)); 1166 return -1; 1167 } 1168 NEXT_ARG(); 1169 } else { 1170 p_err("unknown arg %s", *argv); 1171 return -1; 1172 } 1173 } 1174 1175 if (!attr.name) { 1176 p_err("map name not specified"); 1177 return -1; 1178 } 1179 1180 set_max_rlimit(); 1181 1182 fd = bpf_create_map_xattr(&attr); 1183 if (fd < 0) { 1184 p_err("map create failed: %s", strerror(errno)); 1185 return -1; 1186 } 1187 1188 err = do_pin_fd(fd, pinfile); 1189 close(fd); 1190 if (err) 1191 return err; 1192 1193 if (json_output) 1194 jsonw_null(json_wtr); 1195 return 0; 1196 } 1197 1198 static int do_pop_dequeue(int argc, char **argv) 1199 { 1200 struct bpf_map_info info = {}; 1201 __u32 len = sizeof(info); 1202 void *key, *value; 1203 int err; 1204 int fd; 1205 1206 if (argc < 2) 1207 usage(); 1208 1209 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 1210 if (fd < 0) 1211 return -1; 1212 1213 err = alloc_key_value(&info, &key, &value); 1214 if (err) 1215 goto exit_free; 1216 1217 err = bpf_map_lookup_and_delete_elem(fd, key, value); 1218 if (err) { 1219 if (errno == ENOENT) { 1220 if (json_output) 1221 jsonw_null(json_wtr); 1222 else 1223 printf("Error: empty map\n"); 1224 } else { 1225 p_err("pop failed: %s", strerror(errno)); 1226 } 1227 1228 goto exit_free; 1229 } 1230 1231 print_key_value(&info, key, value); 1232 1233 exit_free: 1234 free(key); 1235 free(value); 1236 close(fd); 1237 1238 return err; 1239 } 1240 1241 static int do_help(int argc, char **argv) 1242 { 1243 if (json_output) { 1244 jsonw_null(json_wtr); 1245 return 0; 1246 } 1247 1248 fprintf(stderr, 1249 "Usage: %s %s { show | list } [MAP]\n" 1250 " %s %s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n" 1251 " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n" 1252 " [dev NAME]\n" 1253 " %s %s dump MAP\n" 1254 " %s %s update MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n" 1255 " %s %s lookup MAP [key DATA]\n" 1256 " %s %s getnext MAP [key DATA]\n" 1257 " %s %s delete MAP key DATA\n" 1258 " %s %s pin MAP FILE\n" 1259 " %s %s event_pipe MAP [cpu N index M]\n" 1260 " %s %s peek MAP\n" 1261 " %s %s push MAP value VALUE\n" 1262 " %s %s pop MAP\n" 1263 " %s %s enqueue MAP value VALUE\n" 1264 " %s %s dequeue MAP\n" 1265 " %s %s help\n" 1266 "\n" 1267 " " HELP_SPEC_MAP "\n" 1268 " DATA := { [hex] BYTES }\n" 1269 " " HELP_SPEC_PROGRAM "\n" 1270 " VALUE := { DATA | MAP | PROG }\n" 1271 " UPDATE_FLAGS := { any | exist | noexist }\n" 1272 " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n" 1273 " percpu_array | stack_trace | cgroup_array | lru_hash |\n" 1274 " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n" 1275 " devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n" 1276 " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n" 1277 " " HELP_SPEC_OPTIONS "\n" 1278 "", 1279 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1280 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1281 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1282 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1283 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); 1284 1285 return 0; 1286 } 1287 1288 static const struct cmd cmds[] = { 1289 { "show", do_show }, 1290 { "list", do_show }, 1291 { "help", do_help }, 1292 { "dump", do_dump }, 1293 { "update", do_update }, 1294 { "lookup", do_lookup }, 1295 { "getnext", do_getnext }, 1296 { "delete", do_delete }, 1297 { "pin", do_pin }, 1298 { "event_pipe", do_event_pipe }, 1299 { "create", do_create }, 1300 { "peek", do_lookup }, 1301 { "push", do_update }, 1302 { "enqueue", do_update }, 1303 { "pop", do_pop_dequeue }, 1304 { "dequeue", do_pop_dequeue }, 1305 { 0 } 1306 }; 1307 1308 int do_map(int argc, char **argv) 1309 { 1310 return cmd_select(cmds, argc, argv, do_help); 1311 } 1312