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