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