Commit 2c76238e authored by Quentin Monnet's avatar Quentin Monnet Committed by Daniel Borkmann

bpftool: Add "bootstrap" feature to version output

Along with the version number, "bpftool version" displays a list of
features that were selected at compilation time for bpftool. It would be
useful to indicate in that list whether a binary is a bootstrap version
of bpftool. Given that an increasing number of components rely on
bootstrap versions for generating skeletons, this could help understand
what a binary is capable of if it has been copied outside of the usual
"bootstrap" directory.

To detect a bootstrap version, we simply rely on the absence of
implementation for the do_prog() function. To do this, we must move the
(unchanged) list of commands before do_version(), which in turn requires
renaming this "cmds" array to avoid shadowing it with the "cmds"
argument in cmd_select().
Signed-off-by: default avatarQuentin Monnet <quentin@isovalent.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20221020100332.69563-1-quentin@isovalent.com
parent 7e5eb725
...@@ -71,6 +71,27 @@ static int do_help(int argc, char **argv) ...@@ -71,6 +71,27 @@ static int do_help(int argc, char **argv)
return 0; return 0;
} }
static int do_batch(int argc, char **argv);
static int do_version(int argc, char **argv);
static const struct cmd commands[] = {
{ "help", do_help },
{ "batch", do_batch },
{ "prog", do_prog },
{ "map", do_map },
{ "link", do_link },
{ "cgroup", do_cgroup },
{ "perf", do_perf },
{ "net", do_net },
{ "feature", do_feature },
{ "btf", do_btf },
{ "gen", do_gen },
{ "struct_ops", do_struct_ops },
{ "iter", do_iter },
{ "version", do_version },
{ 0 }
};
#ifndef BPFTOOL_VERSION #ifndef BPFTOOL_VERSION
/* bpftool's major and minor version numbers are aligned on libbpf's. There is /* bpftool's major and minor version numbers are aligned on libbpf's. There is
* an offset of 6 for the version number, because bpftool's version was higher * an offset of 6 for the version number, because bpftool's version was higher
...@@ -82,6 +103,15 @@ static int do_help(int argc, char **argv) ...@@ -82,6 +103,15 @@ static int do_help(int argc, char **argv)
#define BPFTOOL_PATCH_VERSION 0 #define BPFTOOL_PATCH_VERSION 0
#endif #endif
static void
print_feature(const char *feature, bool state, unsigned int *nb_features)
{
if (state) {
printf("%s %s", *nb_features ? "," : "", feature);
*nb_features = *nb_features + 1;
}
}
static int do_version(int argc, char **argv) static int do_version(int argc, char **argv)
{ {
#ifdef HAVE_LIBBFD_SUPPORT #ifdef HAVE_LIBBFD_SUPPORT
...@@ -94,6 +124,18 @@ static int do_version(int argc, char **argv) ...@@ -94,6 +124,18 @@ static int do_version(int argc, char **argv)
#else #else
const bool has_skeletons = true; const bool has_skeletons = true;
#endif #endif
bool bootstrap = false;
int i;
for (i = 0; commands[i].cmd; i++) {
if (!strcmp(commands[i].cmd, "prog")) {
/* Assume we run a bootstrap version if "bpftool prog"
* is not available.
*/
bootstrap = !commands[i].func;
break;
}
}
if (json_output) { if (json_output) {
jsonw_start_object(json_wtr); /* root object */ jsonw_start_object(json_wtr); /* root object */
...@@ -114,6 +156,7 @@ static int do_version(int argc, char **argv) ...@@ -114,6 +156,7 @@ static int do_version(int argc, char **argv)
jsonw_bool_field(json_wtr, "libbfd", has_libbfd); jsonw_bool_field(json_wtr, "libbfd", has_libbfd);
jsonw_bool_field(json_wtr, "libbpf_strict", !legacy_libbpf); jsonw_bool_field(json_wtr, "libbpf_strict", !legacy_libbpf);
jsonw_bool_field(json_wtr, "skeletons", has_skeletons); jsonw_bool_field(json_wtr, "skeletons", has_skeletons);
jsonw_bool_field(json_wtr, "bootstrap", bootstrap);
jsonw_end_object(json_wtr); /* features */ jsonw_end_object(json_wtr); /* features */
jsonw_end_object(json_wtr); /* root object */ jsonw_end_object(json_wtr); /* root object */
...@@ -128,16 +171,10 @@ static int do_version(int argc, char **argv) ...@@ -128,16 +171,10 @@ static int do_version(int argc, char **argv)
#endif #endif
printf("using libbpf %s\n", libbpf_version_string()); printf("using libbpf %s\n", libbpf_version_string());
printf("features:"); printf("features:");
if (has_libbfd) { print_feature("libbfd", has_libbfd, &nb_features);
printf(" libbfd"); print_feature("libbpf_strict", !legacy_libbpf, &nb_features);
nb_features++; print_feature("skeletons", has_skeletons, &nb_features);
} print_feature("bootstrap", bootstrap, &nb_features);
if (!legacy_libbpf) {
printf("%s libbpf_strict", nb_features++ ? "," : "");
nb_features++;
}
if (has_skeletons)
printf("%s skeletons", nb_features++ ? "," : "");
printf("\n"); printf("\n");
} }
return 0; return 0;
...@@ -279,26 +316,6 @@ static int make_args(char *line, char *n_argv[], int maxargs, int cmd_nb) ...@@ -279,26 +316,6 @@ static int make_args(char *line, char *n_argv[], int maxargs, int cmd_nb)
return n_argc; return n_argc;
} }
static int do_batch(int argc, char **argv);
static const struct cmd cmds[] = {
{ "help", do_help },
{ "batch", do_batch },
{ "prog", do_prog },
{ "map", do_map },
{ "link", do_link },
{ "cgroup", do_cgroup },
{ "perf", do_perf },
{ "net", do_net },
{ "feature", do_feature },
{ "btf", do_btf },
{ "gen", do_gen },
{ "struct_ops", do_struct_ops },
{ "iter", do_iter },
{ "version", do_version },
{ 0 }
};
static int do_batch(int argc, char **argv) static int do_batch(int argc, char **argv)
{ {
char buf[BATCH_LINE_LEN_MAX], contline[BATCH_LINE_LEN_MAX]; char buf[BATCH_LINE_LEN_MAX], contline[BATCH_LINE_LEN_MAX];
...@@ -386,7 +403,7 @@ static int do_batch(int argc, char **argv) ...@@ -386,7 +403,7 @@ static int do_batch(int argc, char **argv)
jsonw_name(json_wtr, "output"); jsonw_name(json_wtr, "output");
} }
err = cmd_select(cmds, n_argc, n_argv, do_help); err = cmd_select(commands, n_argc, n_argv, do_help);
if (json_output) if (json_output)
jsonw_end_object(json_wtr); jsonw_end_object(json_wtr);
...@@ -528,7 +545,7 @@ int main(int argc, char **argv) ...@@ -528,7 +545,7 @@ int main(int argc, char **argv)
if (version_requested) if (version_requested)
return do_version(argc, argv); return do_version(argc, argv);
ret = cmd_select(cmds, argc, argv, do_help); ret = cmd_select(commands, argc, argv, do_help);
if (json_output) if (json_output)
jsonw_destroy(&json_wtr); jsonw_destroy(&json_wtr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment