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