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