.. | .. |
---|
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 | | - */ |
---|
| 1 | +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
---|
| 2 | +/* Copyright (C) 2017-2018 Netronome Systems, Inc. */ |
---|
33 | 3 | |
---|
34 | | -#include <bfd.h> |
---|
35 | 4 | #include <ctype.h> |
---|
36 | 5 | #include <errno.h> |
---|
37 | 6 | #include <getopt.h> |
---|
.. | .. |
---|
40 | 9 | #include <stdlib.h> |
---|
41 | 10 | #include <string.h> |
---|
42 | 11 | |
---|
43 | | -#include <bpf.h> |
---|
| 12 | +#include <bpf/bpf.h> |
---|
| 13 | +#include <bpf/libbpf.h> |
---|
44 | 14 | |
---|
45 | 15 | #include "main.h" |
---|
46 | 16 | |
---|
.. | .. |
---|
55 | 25 | bool pretty_output; |
---|
56 | 26 | bool json_output; |
---|
57 | 27 | bool show_pinned; |
---|
| 28 | +bool block_mount; |
---|
| 29 | +bool verifier_logs; |
---|
| 30 | +bool relaxed_maps; |
---|
58 | 31 | struct pinned_obj_table prog_table; |
---|
59 | 32 | struct pinned_obj_table map_table; |
---|
| 33 | +struct pinned_obj_table link_table; |
---|
| 34 | +struct obj_refs_table refs_table; |
---|
60 | 35 | |
---|
61 | 36 | static void __noreturn clean_and_exit(int i) |
---|
62 | 37 | { |
---|
.. | .. |
---|
85 | 60 | " %s batch file FILE\n" |
---|
86 | 61 | " %s version\n" |
---|
87 | 62 | "\n" |
---|
88 | | - " OBJECT := { prog | map | cgroup | perf }\n" |
---|
| 63 | + " OBJECT := { prog | map | link | cgroup | perf | net | feature | btf | gen | struct_ops | iter }\n" |
---|
89 | 64 | " " HELP_SPEC_OPTIONS "\n" |
---|
90 | 65 | "", |
---|
91 | 66 | bin_name, bin_name, bin_name); |
---|
.. | .. |
---|
95 | 70 | |
---|
96 | 71 | static int do_version(int argc, char **argv) |
---|
97 | 72 | { |
---|
| 73 | +#ifdef HAVE_LIBBFD_SUPPORT |
---|
| 74 | + const bool has_libbfd = true; |
---|
| 75 | +#else |
---|
| 76 | + const bool has_libbfd = false; |
---|
| 77 | +#endif |
---|
| 78 | +#ifdef BPFTOOL_WITHOUT_SKELETONS |
---|
| 79 | + const bool has_skeletons = false; |
---|
| 80 | +#else |
---|
| 81 | + const bool has_skeletons = true; |
---|
| 82 | +#endif |
---|
| 83 | + |
---|
98 | 84 | if (json_output) { |
---|
99 | | - jsonw_start_object(json_wtr); |
---|
| 85 | + jsonw_start_object(json_wtr); /* root object */ |
---|
| 86 | + |
---|
100 | 87 | jsonw_name(json_wtr, "version"); |
---|
101 | 88 | jsonw_printf(json_wtr, "\"%s\"", BPFTOOL_VERSION); |
---|
102 | | - jsonw_end_object(json_wtr); |
---|
| 89 | + |
---|
| 90 | + jsonw_name(json_wtr, "features"); |
---|
| 91 | + jsonw_start_object(json_wtr); /* features */ |
---|
| 92 | + jsonw_bool_field(json_wtr, "libbfd", has_libbfd); |
---|
| 93 | + jsonw_bool_field(json_wtr, "skeletons", has_skeletons); |
---|
| 94 | + jsonw_end_object(json_wtr); /* features */ |
---|
| 95 | + |
---|
| 96 | + jsonw_end_object(json_wtr); /* root object */ |
---|
103 | 97 | } else { |
---|
| 98 | + unsigned int nb_features = 0; |
---|
| 99 | + |
---|
104 | 100 | printf("%s v%s\n", bin_name, BPFTOOL_VERSION); |
---|
| 101 | + printf("features:"); |
---|
| 102 | + if (has_libbfd) { |
---|
| 103 | + printf(" libbfd"); |
---|
| 104 | + nb_features++; |
---|
| 105 | + } |
---|
| 106 | + if (has_skeletons) |
---|
| 107 | + printf("%s skeletons", nb_features++ ? "," : ""); |
---|
| 108 | + printf("\n"); |
---|
105 | 109 | } |
---|
106 | 110 | return 0; |
---|
107 | 111 | } |
---|
.. | .. |
---|
118 | 122 | if (argc < 1 && cmds[0].func) |
---|
119 | 123 | return cmds[0].func(argc, argv); |
---|
120 | 124 | |
---|
121 | | - for (i = 0; cmds[i].func; i++) |
---|
122 | | - if (is_prefix(*argv, cmds[i].cmd)) |
---|
| 125 | + for (i = 0; cmds[i].cmd; i++) { |
---|
| 126 | + if (is_prefix(*argv, cmds[i].cmd)) { |
---|
| 127 | + if (!cmds[i].func) { |
---|
| 128 | + p_err("command '%s' is not supported in bootstrap mode", |
---|
| 129 | + cmds[i].cmd); |
---|
| 130 | + return -1; |
---|
| 131 | + } |
---|
123 | 132 | return cmds[i].func(argc - 1, argv + 1); |
---|
| 133 | + } |
---|
| 134 | + } |
---|
124 | 135 | |
---|
125 | 136 | help(argc - 1, argv + 1); |
---|
126 | 137 | |
---|
.. | .. |
---|
135 | 146 | return false; |
---|
136 | 147 | |
---|
137 | 148 | return !memcmp(str, pfx, strlen(pfx)); |
---|
| 149 | +} |
---|
| 150 | + |
---|
| 151 | +/* Last argument MUST be NULL pointer */ |
---|
| 152 | +int detect_common_prefix(const char *arg, ...) |
---|
| 153 | +{ |
---|
| 154 | + unsigned int count = 0; |
---|
| 155 | + const char *ref; |
---|
| 156 | + char msg[256]; |
---|
| 157 | + va_list ap; |
---|
| 158 | + |
---|
| 159 | + snprintf(msg, sizeof(msg), "ambiguous prefix: '%s' could be '", arg); |
---|
| 160 | + va_start(ap, arg); |
---|
| 161 | + while ((ref = va_arg(ap, const char *))) { |
---|
| 162 | + if (!is_prefix(arg, ref)) |
---|
| 163 | + continue; |
---|
| 164 | + count++; |
---|
| 165 | + if (count > 1) |
---|
| 166 | + strncat(msg, "' or '", sizeof(msg) - strlen(msg) - 1); |
---|
| 167 | + strncat(msg, ref, sizeof(msg) - strlen(msg) - 1); |
---|
| 168 | + } |
---|
| 169 | + va_end(ap); |
---|
| 170 | + strncat(msg, "'", sizeof(msg) - strlen(msg) - 1); |
---|
| 171 | + |
---|
| 172 | + if (count >= 2) { |
---|
| 173 | + p_err("%s", msg); |
---|
| 174 | + return -1; |
---|
| 175 | + } |
---|
| 176 | + |
---|
| 177 | + return 0; |
---|
138 | 178 | } |
---|
139 | 179 | |
---|
140 | 180 | void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep) |
---|
.. | .. |
---|
213 | 253 | { "batch", do_batch }, |
---|
214 | 254 | { "prog", do_prog }, |
---|
215 | 255 | { "map", do_map }, |
---|
| 256 | + { "link", do_link }, |
---|
216 | 257 | { "cgroup", do_cgroup }, |
---|
217 | 258 | { "perf", do_perf }, |
---|
| 259 | + { "net", do_net }, |
---|
| 260 | + { "feature", do_feature }, |
---|
| 261 | + { "btf", do_btf }, |
---|
| 262 | + { "gen", do_gen }, |
---|
| 263 | + { "struct_ops", do_struct_ops }, |
---|
| 264 | + { "iter", do_iter }, |
---|
218 | 265 | { "version", do_version }, |
---|
219 | 266 | { 0 } |
---|
220 | 267 | }; |
---|
.. | .. |
---|
227 | 274 | int n_argc; |
---|
228 | 275 | FILE *fp; |
---|
229 | 276 | char *cp; |
---|
230 | | - int err; |
---|
| 277 | + int err = 0; |
---|
231 | 278 | int i; |
---|
232 | 279 | |
---|
233 | 280 | if (argc < 2) { |
---|
.. | .. |
---|
321 | 368 | p_err("reading batch file failed: %s", strerror(errno)); |
---|
322 | 369 | err = -1; |
---|
323 | 370 | } else { |
---|
324 | | - p_info("processed %d commands", lines); |
---|
325 | | - err = 0; |
---|
| 371 | + if (!json_output) |
---|
| 372 | + printf("processed %d commands\n", lines); |
---|
326 | 373 | } |
---|
327 | 374 | err_close: |
---|
328 | 375 | if (fp != stdin) |
---|
.. | .. |
---|
342 | 389 | { "pretty", no_argument, NULL, 'p' }, |
---|
343 | 390 | { "version", no_argument, NULL, 'V' }, |
---|
344 | 391 | { "bpffs", no_argument, NULL, 'f' }, |
---|
| 392 | + { "mapcompat", no_argument, NULL, 'm' }, |
---|
| 393 | + { "nomount", no_argument, NULL, 'n' }, |
---|
| 394 | + { "debug", no_argument, NULL, 'd' }, |
---|
345 | 395 | { 0 } |
---|
346 | 396 | }; |
---|
347 | 397 | int opt, ret; |
---|
| 398 | + |
---|
| 399 | + setlinebuf(stdout); |
---|
| 400 | + |
---|
| 401 | +#ifdef USE_LIBCAP |
---|
| 402 | + /* Libcap < 2.63 hooks before main() to compute the number of |
---|
| 403 | + * capabilities of the running kernel, and doing so it calls prctl() |
---|
| 404 | + * which may fail and set errno to non-zero. |
---|
| 405 | + * Let's reset errno to make sure this does not interfere with the |
---|
| 406 | + * batch mode. |
---|
| 407 | + */ |
---|
| 408 | + errno = 0; |
---|
| 409 | +#endif |
---|
348 | 410 | |
---|
349 | 411 | last_do_help = do_help; |
---|
350 | 412 | pretty_output = false; |
---|
351 | 413 | json_output = false; |
---|
352 | 414 | show_pinned = false; |
---|
| 415 | + block_mount = false; |
---|
353 | 416 | bin_name = argv[0]; |
---|
354 | 417 | |
---|
355 | 418 | hash_init(prog_table.table); |
---|
356 | 419 | hash_init(map_table.table); |
---|
| 420 | + hash_init(link_table.table); |
---|
357 | 421 | |
---|
358 | 422 | opterr = 0; |
---|
359 | | - while ((opt = getopt_long(argc, argv, "Vhpjf", |
---|
| 423 | + while ((opt = getopt_long(argc, argv, "Vhpjfmnd", |
---|
360 | 424 | options, NULL)) >= 0) { |
---|
361 | 425 | switch (opt) { |
---|
362 | 426 | case 'V': |
---|
.. | .. |
---|
380 | 444 | case 'f': |
---|
381 | 445 | show_pinned = true; |
---|
382 | 446 | break; |
---|
| 447 | + case 'm': |
---|
| 448 | + relaxed_maps = true; |
---|
| 449 | + break; |
---|
| 450 | + case 'n': |
---|
| 451 | + block_mount = true; |
---|
| 452 | + break; |
---|
| 453 | + case 'd': |
---|
| 454 | + libbpf_set_print(print_all_levels); |
---|
| 455 | + verifier_logs = true; |
---|
| 456 | + break; |
---|
383 | 457 | default: |
---|
384 | 458 | p_err("unrecognized option '%s'", argv[optind - 1]); |
---|
385 | 459 | if (json_output) |
---|
.. | .. |
---|
394 | 468 | if (argc < 0) |
---|
395 | 469 | usage(); |
---|
396 | 470 | |
---|
397 | | - bfd_init(); |
---|
398 | | - |
---|
399 | 471 | ret = cmd_select(cmds, argc, argv, do_help); |
---|
400 | 472 | |
---|
401 | 473 | if (json_output) |
---|
.. | .. |
---|
404 | 476 | if (show_pinned) { |
---|
405 | 477 | delete_pinned_obj_table(&prog_table); |
---|
406 | 478 | delete_pinned_obj_table(&map_table); |
---|
| 479 | + delete_pinned_obj_table(&link_table); |
---|
407 | 480 | } |
---|
408 | 481 | |
---|
409 | 482 | return ret; |
---|