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 int err, i; 919 920 for (i = 0; i < nb_fds; i++) { 921 err = bpf_obj_get_info_by_fd(fds[i], &info, &len); 922 if (err) { 923 p_err("can't get map info: %s", strerror(errno)); 924 return -1; 925 } 926 927 if (!info.btf_id) 928 return 0; 929 } 930 931 return 1; 932 } 933 934 static int 935 map_dump(int fd, struct bpf_map_info *info, json_writer_t *wtr, 936 bool show_header) 937 { 938 void *key, *value, *prev_key; 939 unsigned int num_elems = 0; 940 struct btf *btf = NULL; 941 int err; 942 943 key = malloc(info->key_size); 944 value = alloc_value(info); 945 if (!key || !value) { 946 p_err("mem alloc failed"); 947 err = -1; 948 goto exit_free; 949 } 950 951 prev_key = NULL; 952 953 if (wtr) { 954 if (info->btf_id) { 955 err = btf__get_from_id(info->btf_id, &btf); 956 if (err || !btf) { 957 err = err ? : -ESRCH; 958 p_err("failed to get btf"); 959 goto exit_free; 960 } 961 } 962 963 if (show_header) { 964 jsonw_start_object(wtr); /* map object */ 965 show_map_header_json(info, wtr); 966 jsonw_name(wtr, "elements"); 967 } 968 jsonw_start_array(wtr); /* elements */ 969 } else if (show_header) { 970 show_map_header_plain(info); 971 } 972 973 if (info->type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY && 974 info->value_size != 8) 975 p_info("Warning: cannot read values from %s map with value_size != 8", 976 map_type_name[info->type]); 977 while (true) { 978 err = bpf_map_get_next_key(fd, prev_key, key); 979 if (err) { 980 if (errno == ENOENT) 981 err = 0; 982 break; 983 } 984 num_elems += dump_map_elem(fd, key, value, info, btf, wtr); 985 prev_key = key; 986 } 987 988 if (wtr) { 989 jsonw_end_array(wtr); /* elements */ 990 if (show_header) 991 jsonw_end_object(wtr); /* map object */ 992 } else { 993 printf("Found %u element%s\n", num_elems, 994 num_elems != 1 ? "s" : ""); 995 } 996 997 exit_free: 998 free(key); 999 free(value); 1000 close(fd); 1001 btf__free(btf); 1002 1003 return err; 1004 } 1005 1006 static int do_dump(int argc, char **argv) 1007 { 1008 json_writer_t *wtr = NULL, *btf_wtr = NULL; 1009 struct bpf_map_info info = {}; 1010 int nb_fds, i = 0; 1011 __u32 len = sizeof(info); 1012 int *fds = NULL; 1013 int err = -1; 1014 1015 if (argc != 2) 1016 usage(); 1017 1018 fds = malloc(sizeof(int)); 1019 if (!fds) { 1020 p_err("mem alloc failed"); 1021 return -1; 1022 } 1023 nb_fds = map_parse_fds(&argc, &argv, &fds); 1024 if (nb_fds < 1) 1025 goto exit_free; 1026 1027 if (json_output) { 1028 wtr = json_wtr; 1029 } else { 1030 int do_plain_btf; 1031 1032 do_plain_btf = maps_have_btf(fds, nb_fds); 1033 if (do_plain_btf < 0) 1034 goto exit_close; 1035 1036 if (do_plain_btf) { 1037 btf_wtr = get_btf_writer(); 1038 wtr = btf_wtr; 1039 if (!btf_wtr) 1040 p_info("failed to create json writer for btf. falling back to plain output"); 1041 } 1042 } 1043 1044 if (wtr && nb_fds > 1) 1045 jsonw_start_array(wtr); /* root array */ 1046 for (i = 0; i < nb_fds; i++) { 1047 if (bpf_obj_get_info_by_fd(fds[i], &info, &len)) { 1048 p_err("can't get map info: %s", strerror(errno)); 1049 break; 1050 } 1051 err = map_dump(fds[i], &info, wtr, nb_fds > 1); 1052 if (!wtr && i != nb_fds - 1) 1053 printf("\n"); 1054 1055 if (err) 1056 break; 1057 close(fds[i]); 1058 } 1059 if (wtr && nb_fds > 1) 1060 jsonw_end_array(wtr); /* root array */ 1061 1062 if (btf_wtr) 1063 jsonw_destroy(&btf_wtr); 1064 exit_close: 1065 for (; i < nb_fds; i++) 1066 close(fds[i]); 1067 exit_free: 1068 free(fds); 1069 return err; 1070 } 1071 1072 static int alloc_key_value(struct bpf_map_info *info, void **key, void **value) 1073 { 1074 *key = NULL; 1075 *value = NULL; 1076 1077 if (info->key_size) { 1078 *key = malloc(info->key_size); 1079 if (!*key) { 1080 p_err("key mem alloc failed"); 1081 return -1; 1082 } 1083 } 1084 1085 if (info->value_size) { 1086 *value = alloc_value(info); 1087 if (!*value) { 1088 p_err("value mem alloc failed"); 1089 free(*key); 1090 *key = NULL; 1091 return -1; 1092 } 1093 } 1094 1095 return 0; 1096 } 1097 1098 static int do_update(int argc, char **argv) 1099 { 1100 struct bpf_map_info info = {}; 1101 __u32 len = sizeof(info); 1102 __u32 *value_fd = NULL; 1103 __u32 flags = BPF_ANY; 1104 void *key, *value; 1105 int fd, err; 1106 1107 if (argc < 2) 1108 usage(); 1109 1110 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 1111 if (fd < 0) 1112 return -1; 1113 1114 err = alloc_key_value(&info, &key, &value); 1115 if (err) 1116 goto exit_free; 1117 1118 err = parse_elem(argv, &info, key, value, info.key_size, 1119 info.value_size, &flags, &value_fd); 1120 if (err) 1121 goto exit_free; 1122 1123 err = bpf_map_update_elem(fd, key, value, flags); 1124 if (err) { 1125 p_err("update failed: %s", strerror(errno)); 1126 goto exit_free; 1127 } 1128 1129 exit_free: 1130 if (value_fd) 1131 close(*value_fd); 1132 free(key); 1133 free(value); 1134 close(fd); 1135 1136 if (!err && json_output) 1137 jsonw_null(json_wtr); 1138 return err; 1139 } 1140 1141 static void print_key_value(struct bpf_map_info *info, void *key, 1142 void *value) 1143 { 1144 json_writer_t *btf_wtr; 1145 struct btf *btf = NULL; 1146 int err; 1147 1148 err = btf__get_from_id(info->btf_id, &btf); 1149 if (err) { 1150 p_err("failed to get btf"); 1151 return; 1152 } 1153 1154 if (json_output) { 1155 print_entry_json(info, key, value, btf); 1156 } else if (btf) { 1157 /* if here json_wtr wouldn't have been initialised, 1158 * so let's create separate writer for btf 1159 */ 1160 btf_wtr = get_btf_writer(); 1161 if (!btf_wtr) { 1162 p_info("failed to create json writer for btf. falling back to plain output"); 1163 btf__free(btf); 1164 btf = NULL; 1165 print_entry_plain(info, key, value); 1166 } else { 1167 struct btf_dumper d = { 1168 .btf = btf, 1169 .jw = btf_wtr, 1170 .is_plain_text = true, 1171 }; 1172 1173 do_dump_btf(&d, info, key, value); 1174 jsonw_destroy(&btf_wtr); 1175 } 1176 } else { 1177 print_entry_plain(info, key, value); 1178 } 1179 btf__free(btf); 1180 } 1181 1182 static int do_lookup(int argc, char **argv) 1183 { 1184 struct bpf_map_info info = {}; 1185 __u32 len = sizeof(info); 1186 void *key, *value; 1187 int err; 1188 int fd; 1189 1190 if (argc < 2) 1191 usage(); 1192 1193 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 1194 if (fd < 0) 1195 return -1; 1196 1197 err = alloc_key_value(&info, &key, &value); 1198 if (err) 1199 goto exit_free; 1200 1201 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL); 1202 if (err) 1203 goto exit_free; 1204 1205 err = bpf_map_lookup_elem(fd, key, value); 1206 if (err) { 1207 if (errno == ENOENT) { 1208 if (json_output) { 1209 jsonw_null(json_wtr); 1210 } else { 1211 printf("key:\n"); 1212 fprint_hex(stdout, key, info.key_size, " "); 1213 printf("\n\nNot found\n"); 1214 } 1215 } else { 1216 p_err("lookup failed: %s", strerror(errno)); 1217 } 1218 1219 goto exit_free; 1220 } 1221 1222 /* here means bpf_map_lookup_elem() succeeded */ 1223 print_key_value(&info, key, value); 1224 1225 exit_free: 1226 free(key); 1227 free(value); 1228 close(fd); 1229 1230 return err; 1231 } 1232 1233 static int do_getnext(int argc, char **argv) 1234 { 1235 struct bpf_map_info info = {}; 1236 __u32 len = sizeof(info); 1237 void *key, *nextkey; 1238 int err; 1239 int fd; 1240 1241 if (argc < 2) 1242 usage(); 1243 1244 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 1245 if (fd < 0) 1246 return -1; 1247 1248 key = malloc(info.key_size); 1249 nextkey = malloc(info.key_size); 1250 if (!key || !nextkey) { 1251 p_err("mem alloc failed"); 1252 err = -1; 1253 goto exit_free; 1254 } 1255 1256 if (argc) { 1257 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, 1258 NULL, NULL); 1259 if (err) 1260 goto exit_free; 1261 } else { 1262 free(key); 1263 key = NULL; 1264 } 1265 1266 err = bpf_map_get_next_key(fd, key, nextkey); 1267 if (err) { 1268 p_err("can't get next key: %s", strerror(errno)); 1269 goto exit_free; 1270 } 1271 1272 if (json_output) { 1273 jsonw_start_object(json_wtr); 1274 if (key) { 1275 jsonw_name(json_wtr, "key"); 1276 print_hex_data_json(key, info.key_size); 1277 } else { 1278 jsonw_null_field(json_wtr, "key"); 1279 } 1280 jsonw_name(json_wtr, "next_key"); 1281 print_hex_data_json(nextkey, info.key_size); 1282 jsonw_end_object(json_wtr); 1283 } else { 1284 if (key) { 1285 printf("key:\n"); 1286 fprint_hex(stdout, key, info.key_size, " "); 1287 printf("\n"); 1288 } else { 1289 printf("key: None\n"); 1290 } 1291 printf("next key:\n"); 1292 fprint_hex(stdout, nextkey, info.key_size, " "); 1293 printf("\n"); 1294 } 1295 1296 exit_free: 1297 free(nextkey); 1298 free(key); 1299 close(fd); 1300 1301 return err; 1302 } 1303 1304 static int do_delete(int argc, char **argv) 1305 { 1306 struct bpf_map_info info = {}; 1307 __u32 len = sizeof(info); 1308 void *key; 1309 int err; 1310 int fd; 1311 1312 if (argc < 2) 1313 usage(); 1314 1315 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 1316 if (fd < 0) 1317 return -1; 1318 1319 key = malloc(info.key_size); 1320 if (!key) { 1321 p_err("mem alloc failed"); 1322 err = -1; 1323 goto exit_free; 1324 } 1325 1326 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL); 1327 if (err) 1328 goto exit_free; 1329 1330 err = bpf_map_delete_elem(fd, key); 1331 if (err) 1332 p_err("delete failed: %s", strerror(errno)); 1333 1334 exit_free: 1335 free(key); 1336 close(fd); 1337 1338 if (!err && json_output) 1339 jsonw_null(json_wtr); 1340 return err; 1341 } 1342 1343 static int do_pin(int argc, char **argv) 1344 { 1345 int err; 1346 1347 err = do_pin_any(argc, argv, bpf_map_get_fd_by_id); 1348 if (!err && json_output) 1349 jsonw_null(json_wtr); 1350 return err; 1351 } 1352 1353 static int do_create(int argc, char **argv) 1354 { 1355 struct bpf_create_map_attr attr = { NULL, }; 1356 const char *pinfile; 1357 int err, fd; 1358 1359 if (!REQ_ARGS(7)) 1360 return -1; 1361 pinfile = GET_ARG(); 1362 1363 while (argc) { 1364 if (!REQ_ARGS(2)) 1365 return -1; 1366 1367 if (is_prefix(*argv, "type")) { 1368 NEXT_ARG(); 1369 1370 if (attr.map_type) { 1371 p_err("map type already specified"); 1372 return -1; 1373 } 1374 1375 attr.map_type = map_type_from_str(*argv); 1376 if ((int)attr.map_type < 0) { 1377 p_err("unrecognized map type: %s", *argv); 1378 return -1; 1379 } 1380 NEXT_ARG(); 1381 } else if (is_prefix(*argv, "name")) { 1382 NEXT_ARG(); 1383 attr.name = GET_ARG(); 1384 } else if (is_prefix(*argv, "key")) { 1385 if (parse_u32_arg(&argc, &argv, &attr.key_size, 1386 "key size")) 1387 return -1; 1388 } else if (is_prefix(*argv, "value")) { 1389 if (parse_u32_arg(&argc, &argv, &attr.value_size, 1390 "value size")) 1391 return -1; 1392 } else if (is_prefix(*argv, "entries")) { 1393 if (parse_u32_arg(&argc, &argv, &attr.max_entries, 1394 "max entries")) 1395 return -1; 1396 } else if (is_prefix(*argv, "flags")) { 1397 if (parse_u32_arg(&argc, &argv, &attr.map_flags, 1398 "flags")) 1399 return -1; 1400 } else if (is_prefix(*argv, "dev")) { 1401 NEXT_ARG(); 1402 1403 if (attr.map_ifindex) { 1404 p_err("offload device already specified"); 1405 return -1; 1406 } 1407 1408 attr.map_ifindex = if_nametoindex(*argv); 1409 if (!attr.map_ifindex) { 1410 p_err("unrecognized netdevice '%s': %s", 1411 *argv, strerror(errno)); 1412 return -1; 1413 } 1414 NEXT_ARG(); 1415 } else { 1416 p_err("unknown arg %s", *argv); 1417 return -1; 1418 } 1419 } 1420 1421 if (!attr.name) { 1422 p_err("map name not specified"); 1423 return -1; 1424 } 1425 1426 set_max_rlimit(); 1427 1428 fd = bpf_create_map_xattr(&attr); 1429 if (fd < 0) { 1430 p_err("map create failed: %s", strerror(errno)); 1431 return -1; 1432 } 1433 1434 err = do_pin_fd(fd, pinfile); 1435 close(fd); 1436 if (err) 1437 return err; 1438 1439 if (json_output) 1440 jsonw_null(json_wtr); 1441 return 0; 1442 } 1443 1444 static int do_pop_dequeue(int argc, char **argv) 1445 { 1446 struct bpf_map_info info = {}; 1447 __u32 len = sizeof(info); 1448 void *key, *value; 1449 int err; 1450 int fd; 1451 1452 if (argc < 2) 1453 usage(); 1454 1455 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 1456 if (fd < 0) 1457 return -1; 1458 1459 err = alloc_key_value(&info, &key, &value); 1460 if (err) 1461 goto exit_free; 1462 1463 err = bpf_map_lookup_and_delete_elem(fd, key, value); 1464 if (err) { 1465 if (errno == ENOENT) { 1466 if (json_output) 1467 jsonw_null(json_wtr); 1468 else 1469 printf("Error: empty map\n"); 1470 } else { 1471 p_err("pop failed: %s", strerror(errno)); 1472 } 1473 1474 goto exit_free; 1475 } 1476 1477 print_key_value(&info, key, value); 1478 1479 exit_free: 1480 free(key); 1481 free(value); 1482 close(fd); 1483 1484 return err; 1485 } 1486 1487 static int do_freeze(int argc, char **argv) 1488 { 1489 int err, fd; 1490 1491 if (!REQ_ARGS(2)) 1492 return -1; 1493 1494 fd = map_parse_fd(&argc, &argv); 1495 if (fd < 0) 1496 return -1; 1497 1498 if (argc) { 1499 close(fd); 1500 return BAD_ARG(); 1501 } 1502 1503 err = bpf_map_freeze(fd); 1504 close(fd); 1505 if (err) { 1506 p_err("failed to freeze map: %s", strerror(errno)); 1507 return err; 1508 } 1509 1510 if (json_output) 1511 jsonw_null(json_wtr); 1512 1513 return 0; 1514 } 1515 1516 static int do_help(int argc, char **argv) 1517 { 1518 if (json_output) { 1519 jsonw_null(json_wtr); 1520 return 0; 1521 } 1522 1523 fprintf(stderr, 1524 "Usage: %s %s { show | list } [MAP]\n" 1525 " %s %s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n" 1526 " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n" 1527 " [dev NAME]\n" 1528 " %s %s dump MAP\n" 1529 " %s %s update MAP [key DATA] [value VALUE] [UPDATE_FLAGS]\n" 1530 " %s %s lookup MAP [key DATA]\n" 1531 " %s %s getnext MAP [key DATA]\n" 1532 " %s %s delete MAP key DATA\n" 1533 " %s %s pin MAP FILE\n" 1534 " %s %s event_pipe MAP [cpu N index M]\n" 1535 " %s %s peek MAP\n" 1536 " %s %s push MAP value VALUE\n" 1537 " %s %s pop MAP\n" 1538 " %s %s enqueue MAP value VALUE\n" 1539 " %s %s dequeue MAP\n" 1540 " %s %s freeze MAP\n" 1541 " %s %s help\n" 1542 "\n" 1543 " " HELP_SPEC_MAP "\n" 1544 " DATA := { [hex] BYTES }\n" 1545 " " HELP_SPEC_PROGRAM "\n" 1546 " VALUE := { DATA | MAP | PROG }\n" 1547 " UPDATE_FLAGS := { any | exist | noexist }\n" 1548 " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n" 1549 " percpu_array | stack_trace | cgroup_array | lru_hash |\n" 1550 " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n" 1551 " devmap | devmap_hash | sockmap | cpumap | xskmap | sockhash |\n" 1552 " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n" 1553 " " HELP_SPEC_OPTIONS "\n" 1554 "", 1555 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1556 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1557 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1558 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1559 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1560 bin_name, argv[-2]); 1561 1562 return 0; 1563 } 1564 1565 static const struct cmd cmds[] = { 1566 { "show", do_show }, 1567 { "list", do_show }, 1568 { "help", do_help }, 1569 { "dump", do_dump }, 1570 { "update", do_update }, 1571 { "lookup", do_lookup }, 1572 { "getnext", do_getnext }, 1573 { "delete", do_delete }, 1574 { "pin", do_pin }, 1575 { "event_pipe", do_event_pipe }, 1576 { "create", do_create }, 1577 { "peek", do_lookup }, 1578 { "push", do_update }, 1579 { "enqueue", do_update }, 1580 { "pop", do_pop_dequeue }, 1581 { "dequeue", do_pop_dequeue }, 1582 { "freeze", do_freeze }, 1583 { 0 } 1584 }; 1585 1586 int do_map(int argc, char **argv) 1587 { 1588 return cmd_select(cmds, argc, argv, do_help); 1589 } 1590