aboutsummaryrefslogtreecommitdiffstats
path: root/tools/bpf
diff options
context:
space:
mode:
authorQuentin Monnet <quentin.monnet@netronome.com>2017-10-23 12:24:08 -0400
committerDavid S. Miller <davem@davemloft.net>2017-10-23 20:25:08 -0400
commit743cc665d5f62d2c75eceb59c461e653ad6ea58c (patch)
tree1977c8d47d0674d8d1601bdc4a0252a3ab0a4936 /tools/bpf
parentd35efba99d9221d9fe1715a23247ad9b703544ec (diff)
tools: bpftool: add JSON output for `bpftool prog show *` command
Reuse the json_writer API introduced in an earlier commit to make bpftool able to generate JSON output on `bpftool prog show *` commands. For readability, the code from show_prog() has been split into two functions, one for plain output, one for JSON. Outputs from sample programs have been successfully tested against a JSON validator. Signed-off-by: Quentin Monnet <quentin.monnet@netronome.com> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/bpf')
-rw-r--r--tools/bpf/bpftool/prog.c139
1 files changed, 107 insertions, 32 deletions
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 7838206a455b..f373f2baef5a 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -195,51 +195,100 @@ static void show_prog_maps(int fd, u32 num_maps)
195 if (err || !info.nr_map_ids) 195 if (err || !info.nr_map_ids)
196 return; 196 return;
197 197
198 printf(" map_ids "); 198 if (json_output) {
199 for (i = 0; i < info.nr_map_ids; i++) 199 jsonw_name(json_wtr, "map_ids");
200 printf("%u%s", map_ids[i], 200 jsonw_start_array(json_wtr);
201 i == info.nr_map_ids - 1 ? "" : ","); 201 for (i = 0; i < info.nr_map_ids; i++)
202 jsonw_uint(json_wtr, map_ids[i]);
203 jsonw_end_array(json_wtr);
204 } else {
205 printf(" map_ids ");
206 for (i = 0; i < info.nr_map_ids; i++)
207 printf("%u%s", map_ids[i],
208 i == info.nr_map_ids - 1 ? "" : ",");
209 }
202} 210}
203 211
204static int show_prog(int fd) 212static void print_prog_json(struct bpf_prog_info *info, int fd)
205{ 213{
206 struct bpf_prog_info info = {};
207 __u32 len = sizeof(info);
208 char *memlock; 214 char *memlock;
209 int err;
210 215
211 err = bpf_obj_get_info_by_fd(fd, &info, &len); 216 jsonw_start_object(json_wtr);
212 if (err) { 217 jsonw_uint_field(json_wtr, "id", info->id);
213 err("can't get prog info: %s\n", strerror(errno)); 218 if (info->type < ARRAY_SIZE(prog_type_name))
214 return -1; 219 jsonw_string_field(json_wtr, "type",
220 prog_type_name[info->type]);
221 else
222 jsonw_uint_field(json_wtr, "type", info->type);
223
224 if (*info->name)
225 jsonw_string_field(json_wtr, "name", info->name);
226
227 jsonw_name(json_wtr, "tag");
228 jsonw_printf(json_wtr, "\"" BPF_TAG_FMT "\"",
229 info->tag[0], info->tag[1], info->tag[2], info->tag[3],
230 info->tag[4], info->tag[5], info->tag[6], info->tag[7]);
231
232 if (info->load_time) {
233 char buf[32];
234
235 print_boot_time(info->load_time, buf, sizeof(buf));
236
237 /* Piggy back on load_time, since 0 uid is a valid one */
238 jsonw_string_field(json_wtr, "loaded_at", buf);
239 jsonw_uint_field(json_wtr, "uid", info->created_by_uid);
215 } 240 }
216 241
217 printf("%u: ", info.id); 242 jsonw_uint_field(json_wtr, "bytes_xlated", info->xlated_prog_len);
218 if (info.type < ARRAY_SIZE(prog_type_name)) 243
219 printf("%s ", prog_type_name[info.type]); 244 if (info->jited_prog_len) {
245 jsonw_bool_field(json_wtr, "jited", true);
246 jsonw_uint_field(json_wtr, "bytes_jited", info->jited_prog_len);
247 } else {
248 jsonw_bool_field(json_wtr, "jited", false);
249 }
250
251 memlock = get_fdinfo(fd, "memlock");
252 if (memlock)
253 jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
254 free(memlock);
255
256 if (info->nr_map_ids)
257 show_prog_maps(fd, info->nr_map_ids);
258
259 jsonw_end_object(json_wtr);
260}
261
262static void print_prog_plain(struct bpf_prog_info *info, int fd)
263{
264 char *memlock;
265
266 printf("%u: ", info->id);
267 if (info->type < ARRAY_SIZE(prog_type_name))
268 printf("%s ", prog_type_name[info->type]);
220 else 269 else
221 printf("type %u ", info.type); 270 printf("type %u ", info->type);
222 271
223 if (*info.name) 272 if (*info->name)
224 printf("name %s ", info.name); 273 printf("name %s ", info->name);
225 274
226 printf("tag "); 275 printf("tag ");
227 fprint_hex(stdout, info.tag, BPF_TAG_SIZE, ""); 276 fprint_hex(stdout, info->tag, BPF_TAG_SIZE, "");
228 printf("\n"); 277 printf("\n");
229 278
230 if (info.load_time) { 279 if (info->load_time) {
231 char buf[32]; 280 char buf[32];
232 281
233 print_boot_time(info.load_time, buf, sizeof(buf)); 282 print_boot_time(info->load_time, buf, sizeof(buf));
234 283
235 /* Piggy back on load_time, since 0 uid is a valid one */ 284 /* Piggy back on load_time, since 0 uid is a valid one */
236 printf("\tloaded_at %s uid %u\n", buf, info.created_by_uid); 285 printf("\tloaded_at %s uid %u\n", buf, info->created_by_uid);
237 } 286 }
238 287
239 printf("\txlated %uB", info.xlated_prog_len); 288 printf("\txlated %uB", info->xlated_prog_len);
240 289
241 if (info.jited_prog_len) 290 if (info->jited_prog_len)
242 printf(" jited %uB", info.jited_prog_len); 291 printf(" jited %uB", info->jited_prog_len);
243 else 292 else
244 printf(" not jited"); 293 printf(" not jited");
245 294
@@ -248,16 +297,35 @@ static int show_prog(int fd)
248 printf(" memlock %sB", memlock); 297 printf(" memlock %sB", memlock);
249 free(memlock); 298 free(memlock);
250 299
251 if (info.nr_map_ids) 300 if (info->nr_map_ids)
252 show_prog_maps(fd, info.nr_map_ids); 301 show_prog_maps(fd, info->nr_map_ids);
253 302
254 printf("\n"); 303 printf("\n");
304}
305
306static int show_prog(int fd)
307{
308 struct bpf_prog_info info = {};
309 __u32 len = sizeof(info);
310 int err;
311
312 err = bpf_obj_get_info_by_fd(fd, &info, &len);
313 if (err) {
314 err("can't get prog info: %s\n", strerror(errno));
315 return -1;
316 }
317
318 if (json_output)
319 print_prog_json(&info, fd);
320 else
321 print_prog_plain(&info, fd);
255 322
256 return 0; 323 return 0;
257} 324}
258 325
259static int do_show(int argc, char **argv) 326static int do_show(int argc, char **argv)
260{ __u32 id = 0; 327{
328 __u32 id = 0;
261 int err; 329 int err;
262 int fd; 330 int fd;
263 331
@@ -272,6 +340,8 @@ static int do_show(int argc, char **argv)
272 if (argc) 340 if (argc)
273 return BAD_ARG(); 341 return BAD_ARG();
274 342
343 if (json_output)
344 jsonw_start_array(json_wtr);
275 while (true) { 345 while (true) {
276 err = bpf_prog_get_next_id(id, &id); 346 err = bpf_prog_get_next_id(id, &id);
277 if (err) { 347 if (err) {
@@ -282,23 +352,28 @@ static int do_show(int argc, char **argv)
282 err("can't get next program: %s\n", strerror(errno)); 352 err("can't get next program: %s\n", strerror(errno));
283 if (errno == EINVAL) 353 if (errno == EINVAL)
284 err("kernel too old?\n"); 354 err("kernel too old?\n");
285 return -1; 355 err = -1;
356 break;
286 } 357 }
287 358
288 fd = bpf_prog_get_fd_by_id(id); 359 fd = bpf_prog_get_fd_by_id(id);
289 if (fd < 0) { 360 if (fd < 0) {
290 err("can't get prog by id (%u): %s\n", 361 err("can't get prog by id (%u): %s\n",
291 id, strerror(errno)); 362 id, strerror(errno));
292 return -1; 363 err = -1;
364 break;
293 } 365 }
294 366
295 err = show_prog(fd); 367 err = show_prog(fd);
296 close(fd); 368 close(fd);
297 if (err) 369 if (err)
298 return err; 370 break;
299 } 371 }
300 372
301 return 0; 373 if (json_output)
374 jsonw_end_array(json_wtr);
375
376 return err;
302} 377}
303 378
304static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...) 379static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)