Commit d937a74b authored by Daniel Borkmann's avatar Daniel Borkmann Committed by Stephen Hemminger

tc: {m, f}_ebpf: add option for dumping verifier log

Currently, only on error we get a log dump, but I found it useful when
working with eBPF to have an option to also dump the log on success.
Also spotted a typo in a header comment, which is fixed here as well.
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Acked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
parent d7bd2db5
...@@ -40,7 +40,8 @@ static void explain(void) ...@@ -40,7 +40,8 @@ static void explain(void)
fprintf(stderr, " bytecode-file FILE\n"); fprintf(stderr, " bytecode-file FILE\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "eBPF use case:\n"); fprintf(stderr, "eBPF use case:\n");
fprintf(stderr, " object-file FILE [ section CLS_NAME ] [ export UDS_FILE ]\n"); fprintf(stderr, " object-file FILE [ section CLS_NAME ] [ export UDS_FILE ]");
fprintf(stderr, " [ verbose ]\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Common remaining options:\n"); fprintf(stderr, "Common remaining options:\n");
fprintf(stderr, " [ action ACTION_SPEC ]\n"); fprintf(stderr, " [ action ACTION_SPEC ]\n");
...@@ -94,12 +95,13 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle, ...@@ -94,12 +95,13 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle,
while (argc > 0) { while (argc > 0) {
if (matches(*argv, "run") == 0) { if (matches(*argv, "run") == 0) {
struct sock_filter bpf_ops[BPF_MAXINSNS]; struct sock_filter bpf_ops[BPF_MAXINSNS];
bool from_file, ebpf; bool from_file, ebpf, bpf_verbose;
int ret; int ret;
NEXT_ARG(); NEXT_ARG();
opt_bpf: opt_bpf:
bpf_sec_name = bpf_default_section(bpf_type); bpf_sec_name = bpf_default_section(bpf_type);
bpf_verbose = false;
ebpf = false; ebpf = false;
seen_run = true; seen_run = true;
...@@ -135,11 +137,17 @@ opt_bpf: ...@@ -135,11 +137,17 @@ opt_bpf:
bpf_uds_name = *argv; bpf_uds_name = *argv;
NEXT_ARG(); NEXT_ARG();
} }
if (strcmp(*argv, "verbose") == 0 ||
strcmp(*argv, "verb") == 0) {
bpf_verbose = true;
NEXT_ARG();
}
PREV_ARG(); PREV_ARG();
} }
ret = ebpf ? bpf_open_object(bpf_obj, bpf_type, bpf_sec_name) : ret = ebpf ? bpf_open_object(bpf_obj, bpf_type, bpf_sec_name,
bpf_verbose) :
bpf_parse_ops(argc, argv, bpf_ops, from_file); bpf_parse_ops(argc, argv, bpf_ops, from_file);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "%s\n", ebpf ? fprintf(stderr, "%s\n", ebpf ?
......
/* /*
* m_bpf.c BFP based action module * m_bpf.c BPF based action module
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
...@@ -35,7 +35,8 @@ static void explain(void) ...@@ -35,7 +35,8 @@ static void explain(void)
fprintf(stderr, " bytecode-file FILE\n"); fprintf(stderr, " bytecode-file FILE\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "eBPF use case:\n"); fprintf(stderr, "eBPF use case:\n");
fprintf(stderr, " object-file FILE [ section ACT_NAME ] [ export UDS_FILE ]\n"); fprintf(stderr, " object-file FILE [ section ACT_NAME ] [ export UDS_FILE ]");
fprintf(stderr, " [ verbose ]\n");
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n"); fprintf(stderr, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
fprintf(stderr, "c,t,f,k and s are decimals; s denotes number of 4-tuples\n"); fprintf(stderr, "c,t,f,k and s are decimals; s denotes number of 4-tuples\n");
...@@ -78,12 +79,13 @@ static int parse_bpf(struct action_util *a, int *argc_p, char ***argv_p, ...@@ -78,12 +79,13 @@ static int parse_bpf(struct action_util *a, int *argc_p, char ***argv_p,
while (argc > 0) { while (argc > 0) {
if (matches(*argv, "run") == 0) { if (matches(*argv, "run") == 0) {
bool from_file; bool from_file, bpf_verbose;
int ret; int ret;
NEXT_ARG(); NEXT_ARG();
opt_bpf: opt_bpf:
bpf_sec_name = bpf_default_section(bpf_type); bpf_sec_name = bpf_default_section(bpf_type);
bpf_verbose = false;
seen_run = true; seen_run = true;
if (strcmp(*argv, "bytecode-file") == 0 || if (strcmp(*argv, "bytecode-file") == 0 ||
...@@ -118,11 +120,17 @@ opt_bpf: ...@@ -118,11 +120,17 @@ opt_bpf:
bpf_uds_name = *argv; bpf_uds_name = *argv;
NEXT_ARG(); NEXT_ARG();
} }
if (strcmp(*argv, "verbose") == 0 ||
strcmp(*argv, "verb") == 0) {
bpf_verbose = true;
NEXT_ARG();
}
PREV_ARG(); PREV_ARG();
} }
ret = ebpf ? bpf_open_object(bpf_obj, bpf_type, bpf_sec_name) : ret = ebpf ? bpf_open_object(bpf_obj, bpf_type, bpf_sec_name,
bpf_verbose) :
bpf_parse_ops(argc, argv, bpf_ops, from_file); bpf_parse_ops(argc, argv, bpf_ops, from_file);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "%s\n", ebpf ? fprintf(stderr, "%s\n", ebpf ?
......
...@@ -192,6 +192,7 @@ struct bpf_map_data { ...@@ -192,6 +192,7 @@ struct bpf_map_data {
* verifier we still want to hand something descriptive to the user. * verifier we still want to hand something descriptive to the user.
*/ */
static char bpf_log_buf[65536]; static char bpf_log_buf[65536];
static bool bpf_verbose;
static struct bpf_elf_st bpf_st; static struct bpf_elf_st bpf_st;
...@@ -207,8 +208,10 @@ static void bpf_dump_error(const char *format, ...) ...@@ -207,8 +208,10 @@ static void bpf_dump_error(const char *format, ...)
vfprintf(stderr, format, vl); vfprintf(stderr, format, vl);
va_end(vl); va_end(vl);
if (bpf_log_buf[0]) {
fprintf(stderr, "%s\n", bpf_log_buf); fprintf(stderr, "%s\n", bpf_log_buf);
memset(bpf_log_buf, 0, sizeof(bpf_log_buf)); memset(bpf_log_buf, 0, sizeof(bpf_log_buf));
}
} }
static void bpf_save_finfo(int file_fd) static void bpf_save_finfo(int file_fd)
...@@ -284,8 +287,11 @@ static int bpf_prog_attach(enum bpf_prog_type type, const struct bpf_insn *insns ...@@ -284,8 +287,11 @@ static int bpf_prog_attach(enum bpf_prog_type type, const struct bpf_insn *insns
{ {
int prog_fd = bpf_prog_load(type, insns, size, license); int prog_fd = bpf_prog_load(type, insns, size, license);
if (prog_fd < 0) if (prog_fd < 0 || bpf_verbose) {
bpf_dump_error("BPF program rejected: %s\n", strerror(errno)); bpf_dump_error("%s: %s\n", prog_fd < 0 ?
"BPF program rejected" :
"BPF program verification", strerror(errno));
}
return prog_fd; return prog_fd;
} }
...@@ -555,7 +561,8 @@ static int bpf_fetch_prog(Elf *elf_fd, GElf_Ehdr *elf_hdr, bool *sec_seen, ...@@ -555,7 +561,8 @@ static int bpf_fetch_prog(Elf *elf_fd, GElf_Ehdr *elf_hdr, bool *sec_seen,
return prog_fd; return prog_fd;
} }
int bpf_open_object(const char *path, enum bpf_prog_type type, const char *sec) int bpf_open_object(const char *path, enum bpf_prog_type type,
const char *sec, bool verbose)
{ {
char license[ELF_MAX_LICENSE_LEN]; char license[ELF_MAX_LICENSE_LEN];
int file_fd, prog_fd = -1, ret; int file_fd, prog_fd = -1, ret;
...@@ -589,6 +596,8 @@ int bpf_open_object(const char *path, enum bpf_prog_type type, const char *sec) ...@@ -589,6 +596,8 @@ int bpf_open_object(const char *path, enum bpf_prog_type type, const char *sec)
} }
memset(license, 0, sizeof(license)); memset(license, 0, sizeof(license));
bpf_verbose = verbose;
if (!bpf_may_skip_map_creation(file_fd)) if (!bpf_may_skip_map_creation(file_fd))
bpf_maps_init(); bpf_maps_init();
......
...@@ -36,7 +36,7 @@ const char *bpf_default_section(const enum bpf_prog_type type); ...@@ -36,7 +36,7 @@ const char *bpf_default_section(const enum bpf_prog_type type);
#ifdef HAVE_ELF #ifdef HAVE_ELF
int bpf_open_object(const char *path, enum bpf_prog_type type, int bpf_open_object(const char *path, enum bpf_prog_type type,
const char *sec); const char *sec, bool verbose);
int bpf_send_map_fds(const char *path, const char *obj); int bpf_send_map_fds(const char *path, const char *obj);
int bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux, int bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux,
...@@ -59,7 +59,7 @@ static inline int bpf(int cmd, union bpf_attr *attr, unsigned int size) ...@@ -59,7 +59,7 @@ static inline int bpf(int cmd, union bpf_attr *attr, unsigned int size)
} }
#else #else
static inline int bpf_open_object(const char *path, enum bpf_prog_type type, static inline int bpf_open_object(const char *path, enum bpf_prog_type type,
const char *sec) const char *sec, bool verbose)
{ {
fprintf(stderr, "No ELF library support compiled in.\n"); fprintf(stderr, "No ELF library support compiled in.\n");
errno = ENOSYS; errno = ENOSYS;
......
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