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