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