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