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 <stdbool.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 46 #include <bpf.h> 47 48 #include "btf.h" 49 #include "json_writer.h" 50 #include "main.h" 51 52 static const char * const map_type_name[] = { 53 [BPF_MAP_TYPE_UNSPEC] = "unspec", 54 [BPF_MAP_TYPE_HASH] = "hash", 55 [BPF_MAP_TYPE_ARRAY] = "array", 56 [BPF_MAP_TYPE_PROG_ARRAY] = "prog_array", 57 [BPF_MAP_TYPE_PERF_EVENT_ARRAY] = "perf_event_array", 58 [BPF_MAP_TYPE_PERCPU_HASH] = "percpu_hash", 59 [BPF_MAP_TYPE_PERCPU_ARRAY] = "percpu_array", 60 [BPF_MAP_TYPE_STACK_TRACE] = "stack_trace", 61 [BPF_MAP_TYPE_CGROUP_ARRAY] = "cgroup_array", 62 [BPF_MAP_TYPE_LRU_HASH] = "lru_hash", 63 [BPF_MAP_TYPE_LRU_PERCPU_HASH] = "lru_percpu_hash", 64 [BPF_MAP_TYPE_LPM_TRIE] = "lpm_trie", 65 [BPF_MAP_TYPE_ARRAY_OF_MAPS] = "array_of_maps", 66 [BPF_MAP_TYPE_HASH_OF_MAPS] = "hash_of_maps", 67 [BPF_MAP_TYPE_DEVMAP] = "devmap", 68 [BPF_MAP_TYPE_SOCKMAP] = "sockmap", 69 [BPF_MAP_TYPE_CPUMAP] = "cpumap", 70 [BPF_MAP_TYPE_SOCKHASH] = "sockhash", 71 }; 72 73 static bool map_is_per_cpu(__u32 type) 74 { 75 return type == BPF_MAP_TYPE_PERCPU_HASH || 76 type == BPF_MAP_TYPE_PERCPU_ARRAY || 77 type == BPF_MAP_TYPE_LRU_PERCPU_HASH; 78 } 79 80 static bool map_is_map_of_maps(__u32 type) 81 { 82 return type == BPF_MAP_TYPE_ARRAY_OF_MAPS || 83 type == BPF_MAP_TYPE_HASH_OF_MAPS; 84 } 85 86 static bool map_is_map_of_progs(__u32 type) 87 { 88 return type == BPF_MAP_TYPE_PROG_ARRAY; 89 } 90 91 static void *alloc_value(struct bpf_map_info *info) 92 { 93 if (map_is_per_cpu(info->type)) 94 return malloc(info->value_size * get_possible_cpus()); 95 else 96 return malloc(info->value_size); 97 } 98 99 int map_parse_fd(int *argc, char ***argv) 100 { 101 int fd; 102 103 if (is_prefix(**argv, "id")) { 104 unsigned int id; 105 char *endptr; 106 107 NEXT_ARGP(); 108 109 id = strtoul(**argv, &endptr, 0); 110 if (*endptr) { 111 p_err("can't parse %s as ID", **argv); 112 return -1; 113 } 114 NEXT_ARGP(); 115 116 fd = bpf_map_get_fd_by_id(id); 117 if (fd < 0) 118 p_err("get map by id (%u): %s", id, strerror(errno)); 119 return fd; 120 } else if (is_prefix(**argv, "pinned")) { 121 char *path; 122 123 NEXT_ARGP(); 124 125 path = **argv; 126 NEXT_ARGP(); 127 128 return open_obj_pinned_any(path, BPF_OBJ_MAP); 129 } 130 131 p_err("expected 'id' or 'pinned', got: '%s'?", **argv); 132 return -1; 133 } 134 135 int map_parse_fd_and_info(int *argc, char ***argv, void *info, __u32 *info_len) 136 { 137 int err; 138 int fd; 139 140 fd = map_parse_fd(argc, argv); 141 if (fd < 0) 142 return -1; 143 144 err = bpf_obj_get_info_by_fd(fd, info, info_len); 145 if (err) { 146 p_err("can't get map info: %s", strerror(errno)); 147 close(fd); 148 return err; 149 } 150 151 return fd; 152 } 153 154 static int do_dump_btf(const struct btf_dumper *d, 155 struct bpf_map_info *map_info, void *key, 156 void *value) 157 { 158 int ret; 159 160 /* start of key-value pair */ 161 jsonw_start_object(d->jw); 162 163 jsonw_name(d->jw, "key"); 164 165 ret = btf_dumper_type(d, map_info->btf_key_type_id, key); 166 if (ret) 167 goto err_end_obj; 168 169 jsonw_name(d->jw, "value"); 170 171 ret = btf_dumper_type(d, map_info->btf_value_type_id, value); 172 173 err_end_obj: 174 /* end of key-value pair */ 175 jsonw_end_object(d->jw); 176 177 return ret; 178 } 179 180 static int get_btf(struct bpf_map_info *map_info, struct btf **btf) 181 { 182 struct bpf_btf_info btf_info = { 0 }; 183 __u32 len = sizeof(btf_info); 184 __u32 last_size; 185 int btf_fd; 186 void *ptr; 187 int err; 188 189 err = 0; 190 *btf = NULL; 191 btf_fd = bpf_btf_get_fd_by_id(map_info->btf_id); 192 if (btf_fd < 0) 193 return 0; 194 195 /* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so 196 * let's start with a sane default - 4KiB here - and resize it only if 197 * bpf_obj_get_info_by_fd() needs a bigger buffer. 198 */ 199 btf_info.btf_size = 4096; 200 last_size = btf_info.btf_size; 201 ptr = malloc(last_size); 202 if (!ptr) { 203 err = -ENOMEM; 204 goto exit_free; 205 } 206 207 bzero(ptr, last_size); 208 btf_info.btf = ptr_to_u64(ptr); 209 err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len); 210 211 if (!err && btf_info.btf_size > last_size) { 212 void *temp_ptr; 213 214 last_size = btf_info.btf_size; 215 temp_ptr = realloc(ptr, last_size); 216 if (!temp_ptr) { 217 err = -ENOMEM; 218 goto exit_free; 219 } 220 ptr = temp_ptr; 221 bzero(ptr, last_size); 222 btf_info.btf = ptr_to_u64(ptr); 223 err = bpf_obj_get_info_by_fd(btf_fd, &btf_info, &len); 224 } 225 226 if (err || btf_info.btf_size > last_size) { 227 err = errno; 228 goto exit_free; 229 } 230 231 *btf = btf__new((__u8 *)btf_info.btf, btf_info.btf_size, NULL); 232 if (IS_ERR(*btf)) { 233 err = PTR_ERR(btf); 234 *btf = NULL; 235 } 236 237 exit_free: 238 close(btf_fd); 239 free(ptr); 240 241 return err; 242 } 243 244 static json_writer_t *get_btf_writer(void) 245 { 246 json_writer_t *jw = jsonw_new(stdout); 247 248 if (!jw) 249 return NULL; 250 jsonw_pretty(jw, true); 251 252 return jw; 253 } 254 255 static void print_entry_json(struct bpf_map_info *info, unsigned char *key, 256 unsigned char *value, struct btf *btf) 257 { 258 jsonw_start_object(json_wtr); 259 260 if (!map_is_per_cpu(info->type)) { 261 jsonw_name(json_wtr, "key"); 262 print_hex_data_json(key, info->key_size); 263 jsonw_name(json_wtr, "value"); 264 print_hex_data_json(value, info->value_size); 265 if (btf) { 266 struct btf_dumper d = { 267 .btf = btf, 268 .jw = json_wtr, 269 .is_plain_text = false, 270 }; 271 272 jsonw_name(json_wtr, "formatted"); 273 do_dump_btf(&d, info, key, value); 274 } 275 } else { 276 unsigned int i, n; 277 278 n = get_possible_cpus(); 279 280 jsonw_name(json_wtr, "key"); 281 print_hex_data_json(key, info->key_size); 282 283 jsonw_name(json_wtr, "values"); 284 jsonw_start_array(json_wtr); 285 for (i = 0; i < n; i++) { 286 jsonw_start_object(json_wtr); 287 288 jsonw_int_field(json_wtr, "cpu", i); 289 290 jsonw_name(json_wtr, "value"); 291 print_hex_data_json(value + i * info->value_size, 292 info->value_size); 293 294 jsonw_end_object(json_wtr); 295 } 296 jsonw_end_array(json_wtr); 297 } 298 299 jsonw_end_object(json_wtr); 300 } 301 302 static void print_entry_plain(struct bpf_map_info *info, unsigned char *key, 303 unsigned char *value) 304 { 305 if (!map_is_per_cpu(info->type)) { 306 bool single_line, break_names; 307 308 break_names = info->key_size > 16 || info->value_size > 16; 309 single_line = info->key_size + info->value_size <= 24 && 310 !break_names; 311 312 printf("key:%c", break_names ? '\n' : ' '); 313 fprint_hex(stdout, key, info->key_size, " "); 314 315 printf(single_line ? " " : "\n"); 316 317 printf("value:%c", break_names ? '\n' : ' '); 318 fprint_hex(stdout, value, info->value_size, " "); 319 320 printf("\n"); 321 } else { 322 unsigned int i, n; 323 324 n = get_possible_cpus(); 325 326 printf("key:\n"); 327 fprint_hex(stdout, key, info->key_size, " "); 328 printf("\n"); 329 for (i = 0; i < n; i++) { 330 printf("value (CPU %02d):%c", 331 i, info->value_size > 16 ? '\n' : ' '); 332 fprint_hex(stdout, value + i * info->value_size, 333 info->value_size, " "); 334 printf("\n"); 335 } 336 } 337 } 338 339 static char **parse_bytes(char **argv, const char *name, unsigned char *val, 340 unsigned int n) 341 { 342 unsigned int i = 0, base = 0; 343 char *endptr; 344 345 if (is_prefix(*argv, "hex")) { 346 base = 16; 347 argv++; 348 } 349 350 while (i < n && argv[i]) { 351 val[i] = strtoul(argv[i], &endptr, base); 352 if (*endptr) { 353 p_err("error parsing byte: %s", argv[i]); 354 return NULL; 355 } 356 i++; 357 } 358 359 if (i != n) { 360 p_err("%s expected %d bytes got %d", name, n, i); 361 return NULL; 362 } 363 364 return argv + i; 365 } 366 367 static int parse_elem(char **argv, struct bpf_map_info *info, 368 void *key, void *value, __u32 key_size, __u32 value_size, 369 __u32 *flags, __u32 **value_fd) 370 { 371 if (!*argv) { 372 if (!key && !value) 373 return 0; 374 p_err("did not find %s", key ? "key" : "value"); 375 return -1; 376 } 377 378 if (is_prefix(*argv, "key")) { 379 if (!key) { 380 if (key_size) 381 p_err("duplicate key"); 382 else 383 p_err("unnecessary key"); 384 return -1; 385 } 386 387 argv = parse_bytes(argv + 1, "key", key, key_size); 388 if (!argv) 389 return -1; 390 391 return parse_elem(argv, info, NULL, value, key_size, value_size, 392 flags, value_fd); 393 } else if (is_prefix(*argv, "value")) { 394 int fd; 395 396 if (!value) { 397 if (value_size) 398 p_err("duplicate value"); 399 else 400 p_err("unnecessary value"); 401 return -1; 402 } 403 404 argv++; 405 406 if (map_is_map_of_maps(info->type)) { 407 int argc = 2; 408 409 if (value_size != 4) { 410 p_err("value smaller than 4B for map in map?"); 411 return -1; 412 } 413 if (!argv[0] || !argv[1]) { 414 p_err("not enough value arguments for map in map"); 415 return -1; 416 } 417 418 fd = map_parse_fd(&argc, &argv); 419 if (fd < 0) 420 return -1; 421 422 *value_fd = value; 423 **value_fd = fd; 424 } else if (map_is_map_of_progs(info->type)) { 425 int argc = 2; 426 427 if (value_size != 4) { 428 p_err("value smaller than 4B for map of progs?"); 429 return -1; 430 } 431 if (!argv[0] || !argv[1]) { 432 p_err("not enough value arguments for map of progs"); 433 return -1; 434 } 435 436 fd = prog_parse_fd(&argc, &argv); 437 if (fd < 0) 438 return -1; 439 440 *value_fd = value; 441 **value_fd = fd; 442 } else { 443 argv = parse_bytes(argv, "value", value, value_size); 444 if (!argv) 445 return -1; 446 } 447 448 return parse_elem(argv, info, key, NULL, key_size, value_size, 449 flags, NULL); 450 } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") || 451 is_prefix(*argv, "exist")) { 452 if (!flags) { 453 p_err("flags specified multiple times: %s", *argv); 454 return -1; 455 } 456 457 if (is_prefix(*argv, "any")) 458 *flags = BPF_ANY; 459 else if (is_prefix(*argv, "noexist")) 460 *flags = BPF_NOEXIST; 461 else if (is_prefix(*argv, "exist")) 462 *flags = BPF_EXIST; 463 464 return parse_elem(argv + 1, info, key, value, key_size, 465 value_size, NULL, value_fd); 466 } 467 468 p_err("expected key or value, got: %s", *argv); 469 return -1; 470 } 471 472 static int show_map_close_json(int fd, struct bpf_map_info *info) 473 { 474 char *memlock; 475 476 memlock = get_fdinfo(fd, "memlock"); 477 close(fd); 478 479 jsonw_start_object(json_wtr); 480 481 jsonw_uint_field(json_wtr, "id", info->id); 482 if (info->type < ARRAY_SIZE(map_type_name)) 483 jsonw_string_field(json_wtr, "type", 484 map_type_name[info->type]); 485 else 486 jsonw_uint_field(json_wtr, "type", info->type); 487 488 if (*info->name) 489 jsonw_string_field(json_wtr, "name", info->name); 490 491 jsonw_name(json_wtr, "flags"); 492 jsonw_printf(json_wtr, "%d", info->map_flags); 493 494 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino); 495 496 jsonw_uint_field(json_wtr, "bytes_key", info->key_size); 497 jsonw_uint_field(json_wtr, "bytes_value", info->value_size); 498 jsonw_uint_field(json_wtr, "max_entries", info->max_entries); 499 500 if (memlock) 501 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock)); 502 free(memlock); 503 504 if (!hash_empty(map_table.table)) { 505 struct pinned_obj *obj; 506 507 jsonw_name(json_wtr, "pinned"); 508 jsonw_start_array(json_wtr); 509 hash_for_each_possible(map_table.table, obj, hash, info->id) { 510 if (obj->id == info->id) 511 jsonw_string(json_wtr, obj->path); 512 } 513 jsonw_end_array(json_wtr); 514 } 515 516 jsonw_end_object(json_wtr); 517 518 return 0; 519 } 520 521 static int show_map_close_plain(int fd, struct bpf_map_info *info) 522 { 523 char *memlock; 524 525 memlock = get_fdinfo(fd, "memlock"); 526 close(fd); 527 528 printf("%u: ", info->id); 529 if (info->type < ARRAY_SIZE(map_type_name)) 530 printf("%s ", map_type_name[info->type]); 531 else 532 printf("type %u ", info->type); 533 534 if (*info->name) 535 printf("name %s ", info->name); 536 537 printf("flags 0x%x", info->map_flags); 538 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino); 539 printf("\n"); 540 printf("\tkey %uB value %uB max_entries %u", 541 info->key_size, info->value_size, info->max_entries); 542 543 if (memlock) 544 printf(" memlock %sB", memlock); 545 free(memlock); 546 547 printf("\n"); 548 if (!hash_empty(map_table.table)) { 549 struct pinned_obj *obj; 550 551 hash_for_each_possible(map_table.table, obj, hash, info->id) { 552 if (obj->id == info->id) 553 printf("\tpinned %s\n", obj->path); 554 } 555 } 556 return 0; 557 } 558 559 static int do_show(int argc, char **argv) 560 { 561 struct bpf_map_info info = {}; 562 __u32 len = sizeof(info); 563 __u32 id = 0; 564 int err; 565 int fd; 566 567 if (show_pinned) 568 build_pinned_obj_table(&map_table, BPF_OBJ_MAP); 569 570 if (argc == 2) { 571 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 572 if (fd < 0) 573 return -1; 574 575 if (json_output) 576 return show_map_close_json(fd, &info); 577 else 578 return show_map_close_plain(fd, &info); 579 } 580 581 if (argc) 582 return BAD_ARG(); 583 584 if (json_output) 585 jsonw_start_array(json_wtr); 586 while (true) { 587 err = bpf_map_get_next_id(id, &id); 588 if (err) { 589 if (errno == ENOENT) 590 break; 591 p_err("can't get next map: %s%s", strerror(errno), 592 errno == EINVAL ? " -- kernel too old?" : ""); 593 break; 594 } 595 596 fd = bpf_map_get_fd_by_id(id); 597 if (fd < 0) { 598 if (errno == ENOENT) 599 continue; 600 p_err("can't get map by id (%u): %s", 601 id, strerror(errno)); 602 break; 603 } 604 605 err = bpf_obj_get_info_by_fd(fd, &info, &len); 606 if (err) { 607 p_err("can't get map info: %s", strerror(errno)); 608 close(fd); 609 break; 610 } 611 612 if (json_output) 613 show_map_close_json(fd, &info); 614 else 615 show_map_close_plain(fd, &info); 616 } 617 if (json_output) 618 jsonw_end_array(json_wtr); 619 620 return errno == ENOENT ? 0 : -1; 621 } 622 623 static int do_dump(int argc, char **argv) 624 { 625 struct bpf_map_info info = {}; 626 void *key, *value, *prev_key; 627 unsigned int num_elems = 0; 628 __u32 len = sizeof(info); 629 json_writer_t *btf_wtr; 630 struct btf *btf = NULL; 631 int err; 632 int fd; 633 634 if (argc != 2) 635 usage(); 636 637 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 638 if (fd < 0) 639 return -1; 640 641 if (map_is_map_of_maps(info.type) || map_is_map_of_progs(info.type)) { 642 p_err("Dumping maps of maps and program maps not supported"); 643 close(fd); 644 return -1; 645 } 646 647 key = malloc(info.key_size); 648 value = alloc_value(&info); 649 if (!key || !value) { 650 p_err("mem alloc failed"); 651 err = -1; 652 goto exit_free; 653 } 654 655 prev_key = NULL; 656 657 err = get_btf(&info, &btf); 658 if (err) { 659 p_err("failed to get btf"); 660 goto exit_free; 661 } 662 663 if (json_output) 664 jsonw_start_array(json_wtr); 665 else 666 if (btf) { 667 btf_wtr = get_btf_writer(); 668 if (!btf_wtr) { 669 p_info("failed to create json writer for btf. falling back to plain output"); 670 btf__free(btf); 671 btf = NULL; 672 } else { 673 jsonw_start_array(btf_wtr); 674 } 675 } 676 677 while (true) { 678 err = bpf_map_get_next_key(fd, prev_key, key); 679 if (err) { 680 if (errno == ENOENT) 681 err = 0; 682 break; 683 } 684 685 if (!bpf_map_lookup_elem(fd, key, value)) { 686 if (json_output) 687 print_entry_json(&info, key, value, btf); 688 else 689 if (btf) { 690 struct btf_dumper d = { 691 .btf = btf, 692 .jw = btf_wtr, 693 .is_plain_text = true, 694 }; 695 696 do_dump_btf(&d, &info, key, value); 697 } else { 698 print_entry_plain(&info, key, value); 699 } 700 } else { 701 if (json_output) { 702 jsonw_name(json_wtr, "key"); 703 print_hex_data_json(key, info.key_size); 704 jsonw_name(json_wtr, "value"); 705 jsonw_start_object(json_wtr); 706 jsonw_string_field(json_wtr, "error", 707 "can't lookup element"); 708 jsonw_end_object(json_wtr); 709 } else { 710 p_info("can't lookup element with key: "); 711 fprint_hex(stderr, key, info.key_size, " "); 712 fprintf(stderr, "\n"); 713 } 714 } 715 716 prev_key = key; 717 num_elems++; 718 } 719 720 if (json_output) 721 jsonw_end_array(json_wtr); 722 else if (btf) { 723 jsonw_end_array(btf_wtr); 724 jsonw_destroy(&btf_wtr); 725 } else { 726 printf("Found %u element%s\n", num_elems, 727 num_elems != 1 ? "s" : ""); 728 } 729 730 exit_free: 731 free(key); 732 free(value); 733 close(fd); 734 btf__free(btf); 735 736 return err; 737 } 738 739 static int do_update(int argc, char **argv) 740 { 741 struct bpf_map_info info = {}; 742 __u32 len = sizeof(info); 743 __u32 *value_fd = NULL; 744 __u32 flags = BPF_ANY; 745 void *key, *value; 746 int fd, err; 747 748 if (argc < 2) 749 usage(); 750 751 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 752 if (fd < 0) 753 return -1; 754 755 key = malloc(info.key_size); 756 value = alloc_value(&info); 757 if (!key || !value) { 758 p_err("mem alloc failed"); 759 err = -1; 760 goto exit_free; 761 } 762 763 err = parse_elem(argv, &info, key, value, info.key_size, 764 info.value_size, &flags, &value_fd); 765 if (err) 766 goto exit_free; 767 768 err = bpf_map_update_elem(fd, key, value, flags); 769 if (err) { 770 p_err("update failed: %s", strerror(errno)); 771 goto exit_free; 772 } 773 774 exit_free: 775 if (value_fd) 776 close(*value_fd); 777 free(key); 778 free(value); 779 close(fd); 780 781 if (!err && json_output) 782 jsonw_null(json_wtr); 783 return err; 784 } 785 786 static int do_lookup(int argc, char **argv) 787 { 788 struct bpf_map_info info = {}; 789 __u32 len = sizeof(info); 790 json_writer_t *btf_wtr; 791 struct btf *btf = NULL; 792 void *key, *value; 793 int err; 794 int fd; 795 796 if (argc < 2) 797 usage(); 798 799 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 800 if (fd < 0) 801 return -1; 802 803 key = malloc(info.key_size); 804 value = alloc_value(&info); 805 if (!key || !value) { 806 p_err("mem alloc failed"); 807 err = -1; 808 goto exit_free; 809 } 810 811 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL); 812 if (err) 813 goto exit_free; 814 815 err = bpf_map_lookup_elem(fd, key, value); 816 if (err) { 817 if (errno == ENOENT) { 818 if (json_output) { 819 jsonw_null(json_wtr); 820 } else { 821 printf("key:\n"); 822 fprint_hex(stdout, key, info.key_size, " "); 823 printf("\n\nNot found\n"); 824 } 825 } else { 826 p_err("lookup failed: %s", strerror(errno)); 827 } 828 829 goto exit_free; 830 } 831 832 /* here means bpf_map_lookup_elem() succeeded */ 833 err = get_btf(&info, &btf); 834 if (err) { 835 p_err("failed to get btf"); 836 goto exit_free; 837 } 838 839 if (json_output) { 840 print_entry_json(&info, key, value, btf); 841 } else if (btf) { 842 /* if here json_wtr wouldn't have been initialised, 843 * so let's create separate writer for btf 844 */ 845 btf_wtr = get_btf_writer(); 846 if (!btf_wtr) { 847 p_info("failed to create json writer for btf. falling back to plain output"); 848 btf__free(btf); 849 btf = NULL; 850 print_entry_plain(&info, key, value); 851 } else { 852 struct btf_dumper d = { 853 .btf = btf, 854 .jw = btf_wtr, 855 .is_plain_text = true, 856 }; 857 858 do_dump_btf(&d, &info, key, value); 859 jsonw_destroy(&btf_wtr); 860 } 861 } else { 862 print_entry_plain(&info, key, value); 863 } 864 865 exit_free: 866 free(key); 867 free(value); 868 close(fd); 869 btf__free(btf); 870 871 return err; 872 } 873 874 static int do_getnext(int argc, char **argv) 875 { 876 struct bpf_map_info info = {}; 877 __u32 len = sizeof(info); 878 void *key, *nextkey; 879 int err; 880 int fd; 881 882 if (argc < 2) 883 usage(); 884 885 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 886 if (fd < 0) 887 return -1; 888 889 key = malloc(info.key_size); 890 nextkey = malloc(info.key_size); 891 if (!key || !nextkey) { 892 p_err("mem alloc failed"); 893 err = -1; 894 goto exit_free; 895 } 896 897 if (argc) { 898 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, 899 NULL, NULL); 900 if (err) 901 goto exit_free; 902 } else { 903 free(key); 904 key = NULL; 905 } 906 907 err = bpf_map_get_next_key(fd, key, nextkey); 908 if (err) { 909 p_err("can't get next key: %s", strerror(errno)); 910 goto exit_free; 911 } 912 913 if (json_output) { 914 jsonw_start_object(json_wtr); 915 if (key) { 916 jsonw_name(json_wtr, "key"); 917 print_hex_data_json(key, info.key_size); 918 } else { 919 jsonw_null_field(json_wtr, "key"); 920 } 921 jsonw_name(json_wtr, "next_key"); 922 print_hex_data_json(nextkey, info.key_size); 923 jsonw_end_object(json_wtr); 924 } else { 925 if (key) { 926 printf("key:\n"); 927 fprint_hex(stdout, key, info.key_size, " "); 928 printf("\n"); 929 } else { 930 printf("key: None\n"); 931 } 932 printf("next key:\n"); 933 fprint_hex(stdout, nextkey, info.key_size, " "); 934 printf("\n"); 935 } 936 937 exit_free: 938 free(nextkey); 939 free(key); 940 close(fd); 941 942 return err; 943 } 944 945 static int do_delete(int argc, char **argv) 946 { 947 struct bpf_map_info info = {}; 948 __u32 len = sizeof(info); 949 void *key; 950 int err; 951 int fd; 952 953 if (argc < 2) 954 usage(); 955 956 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 957 if (fd < 0) 958 return -1; 959 960 key = malloc(info.key_size); 961 if (!key) { 962 p_err("mem alloc failed"); 963 err = -1; 964 goto exit_free; 965 } 966 967 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL); 968 if (err) 969 goto exit_free; 970 971 err = bpf_map_delete_elem(fd, key); 972 if (err) 973 p_err("delete failed: %s", strerror(errno)); 974 975 exit_free: 976 free(key); 977 close(fd); 978 979 if (!err && json_output) 980 jsonw_null(json_wtr); 981 return err; 982 } 983 984 static int do_pin(int argc, char **argv) 985 { 986 int err; 987 988 err = do_pin_any(argc, argv, bpf_map_get_fd_by_id); 989 if (!err && json_output) 990 jsonw_null(json_wtr); 991 return err; 992 } 993 994 static int do_help(int argc, char **argv) 995 { 996 if (json_output) { 997 jsonw_null(json_wtr); 998 return 0; 999 } 1000 1001 fprintf(stderr, 1002 "Usage: %s %s { show | list } [MAP]\n" 1003 " %s %s dump MAP\n" 1004 " %s %s update MAP key DATA value VALUE [UPDATE_FLAGS]\n" 1005 " %s %s lookup MAP key DATA\n" 1006 " %s %s getnext MAP [key DATA]\n" 1007 " %s %s delete MAP key DATA\n" 1008 " %s %s pin MAP FILE\n" 1009 " %s %s event_pipe MAP [cpu N index M]\n" 1010 " %s %s help\n" 1011 "\n" 1012 " " HELP_SPEC_MAP "\n" 1013 " DATA := { [hex] BYTES }\n" 1014 " " HELP_SPEC_PROGRAM "\n" 1015 " VALUE := { DATA | MAP | PROG }\n" 1016 " UPDATE_FLAGS := { any | exist | noexist }\n" 1017 " " HELP_SPEC_OPTIONS "\n" 1018 "", 1019 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1020 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1021 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2]); 1022 1023 return 0; 1024 } 1025 1026 static const struct cmd cmds[] = { 1027 { "show", do_show }, 1028 { "list", do_show }, 1029 { "help", do_help }, 1030 { "dump", do_dump }, 1031 { "update", do_update }, 1032 { "lookup", do_lookup }, 1033 { "getnext", do_getnext }, 1034 { "delete", do_delete }, 1035 { "pin", do_pin }, 1036 { "event_pipe", do_event_pipe }, 1037 { 0 } 1038 }; 1039 1040 int do_map(int argc, char **argv) 1041 { 1042 return cmd_select(cmds, argc, argv, do_help); 1043 } 1044