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