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 fprint_hex(stdout, value, info->value_size, " "); 387 388 printf("\n"); 389 } else { 390 unsigned int i, n, step; 391 392 n = get_possible_cpus(); 393 step = round_up(info->value_size, 8); 394 395 printf("key:\n"); 396 fprint_hex(stdout, key, info->key_size, " "); 397 printf("\n"); 398 for (i = 0; i < n; i++) { 399 printf("value (CPU %02d):%c", 400 i, info->value_size > 16 ? '\n' : ' '); 401 fprint_hex(stdout, value + i * step, 402 info->value_size, " "); 403 printf("\n"); 404 } 405 } 406 } 407 408 static char **parse_bytes(char **argv, const char *name, unsigned char *val, 409 unsigned int n) 410 { 411 unsigned int i = 0, base = 0; 412 char *endptr; 413 414 if (is_prefix(*argv, "hex")) { 415 base = 16; 416 argv++; 417 } 418 419 while (i < n && argv[i]) { 420 val[i] = strtoul(argv[i], &endptr, base); 421 if (*endptr) { 422 p_err("error parsing byte: %s", argv[i]); 423 return NULL; 424 } 425 i++; 426 } 427 428 if (i != n) { 429 p_err("%s expected %d bytes got %d", name, n, i); 430 return NULL; 431 } 432 433 return argv + i; 434 } 435 436 static int parse_elem(char **argv, struct bpf_map_info *info, 437 void *key, void *value, __u32 key_size, __u32 value_size, 438 __u32 *flags, __u32 **value_fd) 439 { 440 if (!*argv) { 441 if (!key && !value) 442 return 0; 443 p_err("did not find %s", key ? "key" : "value"); 444 return -1; 445 } 446 447 if (is_prefix(*argv, "key")) { 448 if (!key) { 449 if (key_size) 450 p_err("duplicate key"); 451 else 452 p_err("unnecessary key"); 453 return -1; 454 } 455 456 argv = parse_bytes(argv + 1, "key", key, key_size); 457 if (!argv) 458 return -1; 459 460 return parse_elem(argv, info, NULL, value, key_size, value_size, 461 flags, value_fd); 462 } else if (is_prefix(*argv, "value")) { 463 int fd; 464 465 if (!value) { 466 if (value_size) 467 p_err("duplicate value"); 468 else 469 p_err("unnecessary value"); 470 return -1; 471 } 472 473 argv++; 474 475 if (map_is_map_of_maps(info->type)) { 476 int argc = 2; 477 478 if (value_size != 4) { 479 p_err("value smaller than 4B for map in map?"); 480 return -1; 481 } 482 if (!argv[0] || !argv[1]) { 483 p_err("not enough value arguments for map in map"); 484 return -1; 485 } 486 487 fd = map_parse_fd(&argc, &argv); 488 if (fd < 0) 489 return -1; 490 491 *value_fd = value; 492 **value_fd = fd; 493 } else if (map_is_map_of_progs(info->type)) { 494 int argc = 2; 495 496 if (value_size != 4) { 497 p_err("value smaller than 4B for map of progs?"); 498 return -1; 499 } 500 if (!argv[0] || !argv[1]) { 501 p_err("not enough value arguments for map of progs"); 502 return -1; 503 } 504 505 fd = prog_parse_fd(&argc, &argv); 506 if (fd < 0) 507 return -1; 508 509 *value_fd = value; 510 **value_fd = fd; 511 } else { 512 argv = parse_bytes(argv, "value", value, value_size); 513 if (!argv) 514 return -1; 515 } 516 517 return parse_elem(argv, info, key, NULL, key_size, value_size, 518 flags, NULL); 519 } else if (is_prefix(*argv, "any") || is_prefix(*argv, "noexist") || 520 is_prefix(*argv, "exist")) { 521 if (!flags) { 522 p_err("flags specified multiple times: %s", *argv); 523 return -1; 524 } 525 526 if (is_prefix(*argv, "any")) 527 *flags = BPF_ANY; 528 else if (is_prefix(*argv, "noexist")) 529 *flags = BPF_NOEXIST; 530 else if (is_prefix(*argv, "exist")) 531 *flags = BPF_EXIST; 532 533 return parse_elem(argv + 1, info, key, value, key_size, 534 value_size, NULL, value_fd); 535 } 536 537 p_err("expected key or value, got: %s", *argv); 538 return -1; 539 } 540 541 static int show_map_close_json(int fd, struct bpf_map_info *info) 542 { 543 char *memlock; 544 545 memlock = get_fdinfo(fd, "memlock"); 546 close(fd); 547 548 jsonw_start_object(json_wtr); 549 550 jsonw_uint_field(json_wtr, "id", info->id); 551 if (info->type < ARRAY_SIZE(map_type_name)) 552 jsonw_string_field(json_wtr, "type", 553 map_type_name[info->type]); 554 else 555 jsonw_uint_field(json_wtr, "type", info->type); 556 557 if (*info->name) 558 jsonw_string_field(json_wtr, "name", info->name); 559 560 jsonw_name(json_wtr, "flags"); 561 jsonw_printf(json_wtr, "%d", info->map_flags); 562 563 print_dev_json(info->ifindex, info->netns_dev, info->netns_ino); 564 565 jsonw_uint_field(json_wtr, "bytes_key", info->key_size); 566 jsonw_uint_field(json_wtr, "bytes_value", info->value_size); 567 jsonw_uint_field(json_wtr, "max_entries", info->max_entries); 568 569 if (memlock) 570 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock)); 571 free(memlock); 572 573 if (!hash_empty(map_table.table)) { 574 struct pinned_obj *obj; 575 576 jsonw_name(json_wtr, "pinned"); 577 jsonw_start_array(json_wtr); 578 hash_for_each_possible(map_table.table, obj, hash, info->id) { 579 if (obj->id == info->id) 580 jsonw_string(json_wtr, obj->path); 581 } 582 jsonw_end_array(json_wtr); 583 } 584 585 jsonw_end_object(json_wtr); 586 587 return 0; 588 } 589 590 static int show_map_close_plain(int fd, struct bpf_map_info *info) 591 { 592 char *memlock; 593 594 memlock = get_fdinfo(fd, "memlock"); 595 close(fd); 596 597 printf("%u: ", info->id); 598 if (info->type < ARRAY_SIZE(map_type_name)) 599 printf("%s ", map_type_name[info->type]); 600 else 601 printf("type %u ", info->type); 602 603 if (*info->name) 604 printf("name %s ", info->name); 605 606 printf("flags 0x%x", info->map_flags); 607 print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino); 608 printf("\n"); 609 printf("\tkey %uB value %uB max_entries %u", 610 info->key_size, info->value_size, info->max_entries); 611 612 if (memlock) 613 printf(" memlock %sB", memlock); 614 free(memlock); 615 616 printf("\n"); 617 if (!hash_empty(map_table.table)) { 618 struct pinned_obj *obj; 619 620 hash_for_each_possible(map_table.table, obj, hash, info->id) { 621 if (obj->id == info->id) 622 printf("\tpinned %s\n", obj->path); 623 } 624 } 625 return 0; 626 } 627 628 static int do_show(int argc, char **argv) 629 { 630 struct bpf_map_info info = {}; 631 __u32 len = sizeof(info); 632 __u32 id = 0; 633 int err; 634 int fd; 635 636 if (show_pinned) 637 build_pinned_obj_table(&map_table, BPF_OBJ_MAP); 638 639 if (argc == 2) { 640 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 641 if (fd < 0) 642 return -1; 643 644 if (json_output) 645 return show_map_close_json(fd, &info); 646 else 647 return show_map_close_plain(fd, &info); 648 } 649 650 if (argc) 651 return BAD_ARG(); 652 653 if (json_output) 654 jsonw_start_array(json_wtr); 655 while (true) { 656 err = bpf_map_get_next_id(id, &id); 657 if (err) { 658 if (errno == ENOENT) 659 break; 660 p_err("can't get next map: %s%s", strerror(errno), 661 errno == EINVAL ? " -- kernel too old?" : ""); 662 break; 663 } 664 665 fd = bpf_map_get_fd_by_id(id); 666 if (fd < 0) { 667 if (errno == ENOENT) 668 continue; 669 p_err("can't get map by id (%u): %s", 670 id, strerror(errno)); 671 break; 672 } 673 674 err = bpf_obj_get_info_by_fd(fd, &info, &len); 675 if (err) { 676 p_err("can't get map info: %s", strerror(errno)); 677 close(fd); 678 break; 679 } 680 681 if (json_output) 682 show_map_close_json(fd, &info); 683 else 684 show_map_close_plain(fd, &info); 685 } 686 if (json_output) 687 jsonw_end_array(json_wtr); 688 689 return errno == ENOENT ? 0 : -1; 690 } 691 692 static int dump_map_elem(int fd, void *key, void *value, 693 struct bpf_map_info *map_info, struct btf *btf, 694 json_writer_t *btf_wtr) 695 { 696 int num_elems = 0; 697 int lookup_errno; 698 699 if (!bpf_map_lookup_elem(fd, key, value)) { 700 if (json_output) { 701 print_entry_json(map_info, key, value, btf); 702 } else { 703 if (btf) { 704 struct btf_dumper d = { 705 .btf = btf, 706 .jw = btf_wtr, 707 .is_plain_text = true, 708 }; 709 710 do_dump_btf(&d, map_info, key, value); 711 } else { 712 print_entry_plain(map_info, key, value); 713 } 714 num_elems++; 715 } 716 return num_elems; 717 } 718 719 /* lookup error handling */ 720 lookup_errno = errno; 721 722 if (map_is_map_of_maps(map_info->type) || 723 map_is_map_of_progs(map_info->type)) 724 return 0; 725 726 if (json_output) { 727 jsonw_name(json_wtr, "key"); 728 print_hex_data_json(key, map_info->key_size); 729 jsonw_name(json_wtr, "value"); 730 jsonw_start_object(json_wtr); 731 jsonw_string_field(json_wtr, "error", strerror(lookup_errno)); 732 jsonw_end_object(json_wtr); 733 } else { 734 print_entry_error(map_info, key, strerror(lookup_errno)); 735 } 736 737 return 0; 738 } 739 740 static int do_dump(int argc, char **argv) 741 { 742 struct bpf_map_info info = {}; 743 void *key, *value, *prev_key; 744 unsigned int num_elems = 0; 745 __u32 len = sizeof(info); 746 json_writer_t *btf_wtr; 747 struct btf *btf = NULL; 748 int err; 749 int fd; 750 751 if (argc != 2) 752 usage(); 753 754 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 755 if (fd < 0) 756 return -1; 757 758 key = malloc(info.key_size); 759 value = alloc_value(&info); 760 if (!key || !value) { 761 p_err("mem alloc failed"); 762 err = -1; 763 goto exit_free; 764 } 765 766 prev_key = NULL; 767 768 err = get_btf(&info, &btf); 769 if (err) { 770 p_err("failed to get btf"); 771 goto exit_free; 772 } 773 774 if (json_output) 775 jsonw_start_array(json_wtr); 776 else 777 if (btf) { 778 btf_wtr = get_btf_writer(); 779 if (!btf_wtr) { 780 p_info("failed to create json writer for btf. falling back to plain output"); 781 btf__free(btf); 782 btf = NULL; 783 } else { 784 jsonw_start_array(btf_wtr); 785 } 786 } 787 788 while (true) { 789 err = bpf_map_get_next_key(fd, prev_key, key); 790 if (err) { 791 if (errno == ENOENT) 792 err = 0; 793 break; 794 } 795 num_elems += dump_map_elem(fd, key, value, &info, btf, btf_wtr); 796 prev_key = key; 797 } 798 799 if (json_output) 800 jsonw_end_array(json_wtr); 801 else if (btf) { 802 jsonw_end_array(btf_wtr); 803 jsonw_destroy(&btf_wtr); 804 } else { 805 printf("Found %u element%s\n", num_elems, 806 num_elems != 1 ? "s" : ""); 807 } 808 809 exit_free: 810 free(key); 811 free(value); 812 close(fd); 813 btf__free(btf); 814 815 return err; 816 } 817 818 static int do_update(int argc, char **argv) 819 { 820 struct bpf_map_info info = {}; 821 __u32 len = sizeof(info); 822 __u32 *value_fd = NULL; 823 __u32 flags = BPF_ANY; 824 void *key, *value; 825 int fd, err; 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, value, info.key_size, 843 info.value_size, &flags, &value_fd); 844 if (err) 845 goto exit_free; 846 847 err = bpf_map_update_elem(fd, key, value, flags); 848 if (err) { 849 p_err("update failed: %s", strerror(errno)); 850 goto exit_free; 851 } 852 853 exit_free: 854 if (value_fd) 855 close(*value_fd); 856 free(key); 857 free(value); 858 close(fd); 859 860 if (!err && json_output) 861 jsonw_null(json_wtr); 862 return err; 863 } 864 865 static int do_lookup(int argc, char **argv) 866 { 867 struct bpf_map_info info = {}; 868 __u32 len = sizeof(info); 869 json_writer_t *btf_wtr; 870 struct btf *btf = NULL; 871 void *key, *value; 872 int err; 873 int fd; 874 875 if (argc < 2) 876 usage(); 877 878 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 879 if (fd < 0) 880 return -1; 881 882 key = malloc(info.key_size); 883 value = alloc_value(&info); 884 if (!key || !value) { 885 p_err("mem alloc failed"); 886 err = -1; 887 goto exit_free; 888 } 889 890 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL); 891 if (err) 892 goto exit_free; 893 894 err = bpf_map_lookup_elem(fd, key, value); 895 if (err) { 896 if (errno == ENOENT) { 897 if (json_output) { 898 jsonw_null(json_wtr); 899 } else { 900 printf("key:\n"); 901 fprint_hex(stdout, key, info.key_size, " "); 902 printf("\n\nNot found\n"); 903 } 904 } else { 905 p_err("lookup failed: %s", strerror(errno)); 906 } 907 908 goto exit_free; 909 } 910 911 /* here means bpf_map_lookup_elem() succeeded */ 912 err = get_btf(&info, &btf); 913 if (err) { 914 p_err("failed to get btf"); 915 goto exit_free; 916 } 917 918 if (json_output) { 919 print_entry_json(&info, key, value, btf); 920 } else if (btf) { 921 /* if here json_wtr wouldn't have been initialised, 922 * so let's create separate writer for btf 923 */ 924 btf_wtr = get_btf_writer(); 925 if (!btf_wtr) { 926 p_info("failed to create json writer for btf. falling back to plain output"); 927 btf__free(btf); 928 btf = NULL; 929 print_entry_plain(&info, key, value); 930 } else { 931 struct btf_dumper d = { 932 .btf = btf, 933 .jw = btf_wtr, 934 .is_plain_text = true, 935 }; 936 937 do_dump_btf(&d, &info, key, value); 938 jsonw_destroy(&btf_wtr); 939 } 940 } else { 941 print_entry_plain(&info, key, value); 942 } 943 944 exit_free: 945 free(key); 946 free(value); 947 close(fd); 948 btf__free(btf); 949 950 return err; 951 } 952 953 static int do_getnext(int argc, char **argv) 954 { 955 struct bpf_map_info info = {}; 956 __u32 len = sizeof(info); 957 void *key, *nextkey; 958 int err; 959 int fd; 960 961 if (argc < 2) 962 usage(); 963 964 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 965 if (fd < 0) 966 return -1; 967 968 key = malloc(info.key_size); 969 nextkey = malloc(info.key_size); 970 if (!key || !nextkey) { 971 p_err("mem alloc failed"); 972 err = -1; 973 goto exit_free; 974 } 975 976 if (argc) { 977 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, 978 NULL, NULL); 979 if (err) 980 goto exit_free; 981 } else { 982 free(key); 983 key = NULL; 984 } 985 986 err = bpf_map_get_next_key(fd, key, nextkey); 987 if (err) { 988 p_err("can't get next key: %s", strerror(errno)); 989 goto exit_free; 990 } 991 992 if (json_output) { 993 jsonw_start_object(json_wtr); 994 if (key) { 995 jsonw_name(json_wtr, "key"); 996 print_hex_data_json(key, info.key_size); 997 } else { 998 jsonw_null_field(json_wtr, "key"); 999 } 1000 jsonw_name(json_wtr, "next_key"); 1001 print_hex_data_json(nextkey, info.key_size); 1002 jsonw_end_object(json_wtr); 1003 } else { 1004 if (key) { 1005 printf("key:\n"); 1006 fprint_hex(stdout, key, info.key_size, " "); 1007 printf("\n"); 1008 } else { 1009 printf("key: None\n"); 1010 } 1011 printf("next key:\n"); 1012 fprint_hex(stdout, nextkey, info.key_size, " "); 1013 printf("\n"); 1014 } 1015 1016 exit_free: 1017 free(nextkey); 1018 free(key); 1019 close(fd); 1020 1021 return err; 1022 } 1023 1024 static int do_delete(int argc, char **argv) 1025 { 1026 struct bpf_map_info info = {}; 1027 __u32 len = sizeof(info); 1028 void *key; 1029 int err; 1030 int fd; 1031 1032 if (argc < 2) 1033 usage(); 1034 1035 fd = map_parse_fd_and_info(&argc, &argv, &info, &len); 1036 if (fd < 0) 1037 return -1; 1038 1039 key = malloc(info.key_size); 1040 if (!key) { 1041 p_err("mem alloc failed"); 1042 err = -1; 1043 goto exit_free; 1044 } 1045 1046 err = parse_elem(argv, &info, key, NULL, info.key_size, 0, NULL, NULL); 1047 if (err) 1048 goto exit_free; 1049 1050 err = bpf_map_delete_elem(fd, key); 1051 if (err) 1052 p_err("delete failed: %s", strerror(errno)); 1053 1054 exit_free: 1055 free(key); 1056 close(fd); 1057 1058 if (!err && json_output) 1059 jsonw_null(json_wtr); 1060 return err; 1061 } 1062 1063 static int do_pin(int argc, char **argv) 1064 { 1065 int err; 1066 1067 err = do_pin_any(argc, argv, bpf_map_get_fd_by_id); 1068 if (!err && json_output) 1069 jsonw_null(json_wtr); 1070 return err; 1071 } 1072 1073 static int do_create(int argc, char **argv) 1074 { 1075 struct bpf_create_map_attr attr = { NULL, }; 1076 const char *pinfile; 1077 int err, fd; 1078 1079 if (!REQ_ARGS(7)) 1080 return -1; 1081 pinfile = GET_ARG(); 1082 1083 while (argc) { 1084 if (!REQ_ARGS(2)) 1085 return -1; 1086 1087 if (is_prefix(*argv, "type")) { 1088 NEXT_ARG(); 1089 1090 if (attr.map_type) { 1091 p_err("map type already specified"); 1092 return -1; 1093 } 1094 1095 attr.map_type = map_type_from_str(*argv); 1096 if ((int)attr.map_type < 0) { 1097 p_err("unrecognized map type: %s", *argv); 1098 return -1; 1099 } 1100 NEXT_ARG(); 1101 } else if (is_prefix(*argv, "name")) { 1102 NEXT_ARG(); 1103 attr.name = GET_ARG(); 1104 } else if (is_prefix(*argv, "key")) { 1105 if (parse_u32_arg(&argc, &argv, &attr.key_size, 1106 "key size")) 1107 return -1; 1108 } else if (is_prefix(*argv, "value")) { 1109 if (parse_u32_arg(&argc, &argv, &attr.value_size, 1110 "value size")) 1111 return -1; 1112 } else if (is_prefix(*argv, "entries")) { 1113 if (parse_u32_arg(&argc, &argv, &attr.max_entries, 1114 "max entries")) 1115 return -1; 1116 } else if (is_prefix(*argv, "flags")) { 1117 if (parse_u32_arg(&argc, &argv, &attr.map_flags, 1118 "flags")) 1119 return -1; 1120 } else if (is_prefix(*argv, "dev")) { 1121 NEXT_ARG(); 1122 1123 if (attr.map_ifindex) { 1124 p_err("offload device already specified"); 1125 return -1; 1126 } 1127 1128 attr.map_ifindex = if_nametoindex(*argv); 1129 if (!attr.map_ifindex) { 1130 p_err("unrecognized netdevice '%s': %s", 1131 *argv, strerror(errno)); 1132 return -1; 1133 } 1134 NEXT_ARG(); 1135 } 1136 } 1137 1138 if (!attr.name) { 1139 p_err("map name not specified"); 1140 return -1; 1141 } 1142 1143 fd = bpf_create_map_xattr(&attr); 1144 if (fd < 0) { 1145 p_err("map create failed: %s", strerror(errno)); 1146 return -1; 1147 } 1148 1149 err = do_pin_fd(fd, pinfile); 1150 close(fd); 1151 if (err) 1152 return err; 1153 1154 if (json_output) 1155 jsonw_null(json_wtr); 1156 return 0; 1157 } 1158 1159 static int do_help(int argc, char **argv) 1160 { 1161 if (json_output) { 1162 jsonw_null(json_wtr); 1163 return 0; 1164 } 1165 1166 fprintf(stderr, 1167 "Usage: %s %s { show | list } [MAP]\n" 1168 " %s %s create FILE type TYPE key KEY_SIZE value VALUE_SIZE \\\n" 1169 " entries MAX_ENTRIES name NAME [flags FLAGS] \\\n" 1170 " [dev NAME]\n" 1171 " %s %s dump MAP\n" 1172 " %s %s update MAP key DATA value VALUE [UPDATE_FLAGS]\n" 1173 " %s %s lookup MAP key DATA\n" 1174 " %s %s getnext MAP [key DATA]\n" 1175 " %s %s delete MAP key DATA\n" 1176 " %s %s pin MAP FILE\n" 1177 " %s %s event_pipe MAP [cpu N index M]\n" 1178 " %s %s help\n" 1179 "\n" 1180 " " HELP_SPEC_MAP "\n" 1181 " DATA := { [hex] BYTES }\n" 1182 " " HELP_SPEC_PROGRAM "\n" 1183 " VALUE := { DATA | MAP | PROG }\n" 1184 " UPDATE_FLAGS := { any | exist | noexist }\n" 1185 " TYPE := { hash | array | prog_array | perf_event_array | percpu_hash |\n" 1186 " percpu_array | stack_trace | cgroup_array | lru_hash |\n" 1187 " lru_percpu_hash | lpm_trie | array_of_maps | hash_of_maps |\n" 1188 " devmap | sockmap | cpumap | xskmap | sockhash |\n" 1189 " cgroup_storage | reuseport_sockarray | percpu_cgroup_storage }\n" 1190 " " HELP_SPEC_OPTIONS "\n" 1191 "", 1192 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1193 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1194 bin_name, argv[-2], bin_name, argv[-2], bin_name, argv[-2], 1195 bin_name, argv[-2]); 1196 1197 return 0; 1198 } 1199 1200 static const struct cmd cmds[] = { 1201 { "show", do_show }, 1202 { "list", do_show }, 1203 { "help", do_help }, 1204 { "dump", do_dump }, 1205 { "update", do_update }, 1206 { "lookup", do_lookup }, 1207 { "getnext", do_getnext }, 1208 { "delete", do_delete }, 1209 { "pin", do_pin }, 1210 { "event_pipe", do_event_pipe }, 1211 { "create", do_create }, 1212 { 0 } 1213 }; 1214 1215 int do_map(int argc, char **argv) 1216 { 1217 return cmd_select(cmds, argc, argv, do_help); 1218 } 1219