Skip to content

Commit 2c76238

Browse files
qmonnetborkmann
authored andcommitted
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: Quentin Monnet <quentin@isovalent.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/bpf/20221020100332.69563-1-quentin@isovalent.com
1 parent 7e5eb72 commit 2c76238

File tree

1 file changed

+49
-32
lines changed

1 file changed

+49
-32
lines changed

tools/bpf/bpftool/main.c

Lines changed: 49 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,27 @@ static int do_help(int argc, char **argv)
7171
return 0;
7272
}
7373

74+
static int do_batch(int argc, char **argv);
75+
static int do_version(int argc, char **argv);
76+
77+
static const struct cmd commands[] = {
78+
{ "help", do_help },
79+
{ "batch", do_batch },
80+
{ "prog", do_prog },
81+
{ "map", do_map },
82+
{ "link", do_link },
83+
{ "cgroup", do_cgroup },
84+
{ "perf", do_perf },
85+
{ "net", do_net },
86+
{ "feature", do_feature },
87+
{ "btf", do_btf },
88+
{ "gen", do_gen },
89+
{ "struct_ops", do_struct_ops },
90+
{ "iter", do_iter },
91+
{ "version", do_version },
92+
{ 0 }
93+
};
94+
7495
#ifndef BPFTOOL_VERSION
7596
/* bpftool's major and minor version numbers are aligned on libbpf's. There is
7697
* 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)
82103
#define BPFTOOL_PATCH_VERSION 0
83104
#endif
84105

106+
static void
107+
print_feature(const char *feature, bool state, unsigned int *nb_features)
108+
{
109+
if (state) {
110+
printf("%s %s", *nb_features ? "," : "", feature);
111+
*nb_features = *nb_features + 1;
112+
}
113+
}
114+
85115
static int do_version(int argc, char **argv)
86116
{
87117
#ifdef HAVE_LIBBFD_SUPPORT
@@ -94,6 +124,18 @@ static int do_version(int argc, char **argv)
94124
#else
95125
const bool has_skeletons = true;
96126
#endif
127+
bool bootstrap = false;
128+
int i;
129+
130+
for (i = 0; commands[i].cmd; i++) {
131+
if (!strcmp(commands[i].cmd, "prog")) {
132+
/* Assume we run a bootstrap version if "bpftool prog"
133+
* is not available.
134+
*/
135+
bootstrap = !commands[i].func;
136+
break;
137+
}
138+
}
97139

98140
if (json_output) {
99141
jsonw_start_object(json_wtr); /* root object */
@@ -114,6 +156,7 @@ static int do_version(int argc, char **argv)
114156
jsonw_bool_field(json_wtr, "libbfd", has_libbfd);
115157
jsonw_bool_field(json_wtr, "libbpf_strict", !legacy_libbpf);
116158
jsonw_bool_field(json_wtr, "skeletons", has_skeletons);
159+
jsonw_bool_field(json_wtr, "bootstrap", bootstrap);
117160
jsonw_end_object(json_wtr); /* features */
118161

119162
jsonw_end_object(json_wtr); /* root object */
@@ -128,16 +171,10 @@ static int do_version(int argc, char **argv)
128171
#endif
129172
printf("using libbpf %s\n", libbpf_version_string());
130173
printf("features:");
131-
if (has_libbfd) {
132-
printf(" libbfd");
133-
nb_features++;
134-
}
135-
if (!legacy_libbpf) {
136-
printf("%s libbpf_strict", nb_features++ ? "," : "");
137-
nb_features++;
138-
}
139-
if (has_skeletons)
140-
printf("%s skeletons", nb_features++ ? "," : "");
174+
print_feature("libbfd", has_libbfd, &nb_features);
175+
print_feature("libbpf_strict", !legacy_libbpf, &nb_features);
176+
print_feature("skeletons", has_skeletons, &nb_features);
177+
print_feature("bootstrap", bootstrap, &nb_features);
141178
printf("\n");
142179
}
143180
return 0;
@@ -279,26 +316,6 @@ static int make_args(char *line, char *n_argv[], int maxargs, int cmd_nb)
279316
return n_argc;
280317
}
281318

282-
static int do_batch(int argc, char **argv);
283-
284-
static const struct cmd cmds[] = {
285-
{ "help", do_help },
286-
{ "batch", do_batch },
287-
{ "prog", do_prog },
288-
{ "map", do_map },
289-
{ "link", do_link },
290-
{ "cgroup", do_cgroup },
291-
{ "perf", do_perf },
292-
{ "net", do_net },
293-
{ "feature", do_feature },
294-
{ "btf", do_btf },
295-
{ "gen", do_gen },
296-
{ "struct_ops", do_struct_ops },
297-
{ "iter", do_iter },
298-
{ "version", do_version },
299-
{ 0 }
300-
};
301-
302319
static int do_batch(int argc, char **argv)
303320
{
304321
char buf[BATCH_LINE_LEN_MAX], contline[BATCH_LINE_LEN_MAX];
@@ -386,7 +403,7 @@ static int do_batch(int argc, char **argv)
386403
jsonw_name(json_wtr, "output");
387404
}
388405

389-
err = cmd_select(cmds, n_argc, n_argv, do_help);
406+
err = cmd_select(commands, n_argc, n_argv, do_help);
390407

391408
if (json_output)
392409
jsonw_end_object(json_wtr);
@@ -528,7 +545,7 @@ int main(int argc, char **argv)
528545
if (version_requested)
529546
return do_version(argc, argv);
530547

531-
ret = cmd_select(cmds, argc, argv, do_help);
548+
ret = cmd_select(commands, argc, argv, do_help);
532549

533550
if (json_output)
534551
jsonw_destroy(&json_wtr);

0 commit comments

Comments
 (0)