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