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