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