All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] tc, bpf: add option to dump bpf verifier as C program fragment
@ 2018-06-17  8:48 Ophir Munk
  2018-06-18 20:18 ` Jakub Kicinski
  0 siblings, 1 reply; 5+ messages in thread
From: Ophir Munk @ 2018-06-17  8:48 UTC (permalink / raw)
  To: netdev, Stephen Hemminger, David Ahern
  Cc: Thomas Monjalon, Olga Shern, Ophir Munk

Similar to cbpf used within tcpdump utility with a "-d" option to dump
the compiled packet-matching code in a human readable form - tc has the
"verbose" option to dump ebpf verifier output.
Another useful option of cbpf using tcpdump "-dd" option is to dump
packet-matching code a C program fragment. Similar to this - this commit
adds a new tc ebpf option named "code" to dump ebpf verifier as C program
fragment.

Existing "verbose" option sample output:

Verifier analysis:
0: (61) r2 = *(u32 *)(r1 +52)
1: (18) r3 = 0xdeadbeef
3: (63) *(u32 *)(r10 -4) = r3
.
.
11: (63) *(u32 *)(r1 +52) = r2
12: (18) r0 = 0xffffffff
14: (95) exit

New "code" option sample output:

/* struct bpf_insn cls_q_code[] = { */
{0x61,    2,    1,       52, 0x00000000},
{0x18,    3,    0,        0, 0xdeadbeef},
{0x00,    0,    0,        0, 0x00000000},
.
.
{0x63,    1,    2,       52, 0x00000000},
{0x18,    0,    0,        0, 0xffffffff},
{0x00,    0,    0,        0, 0x00000000},
{0x95,    0,    0,        0, 0x00000000},

Signed-off-by: Ophir Munk <ophirmu@mellanox.com>
---
 include/bpf_util.h |  1 +
 lib/bpf.c          | 35 +++++++++++++++++++++++++++++------
 tc/m_bpf.c         |  3 ++-
 3 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/include/bpf_util.h b/include/bpf_util.h
index 219beb4..cf611c5 100644
--- a/include/bpf_util.h
+++ b/include/bpf_util.h
@@ -72,6 +72,7 @@ struct bpf_cfg_in {
 	enum bpf_mode mode;
 	__u32 ifindex;
 	bool verbose;
+	bool code;	
 	int argc;
 	char **argv;
 	struct sock_filter opcodes[BPF_MAXINSNS];
diff --git a/lib/bpf.c b/lib/bpf.c
index c38d92d..b13ec3f 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -113,10 +113,10 @@ const char *bpf_prog_to_default_section(enum bpf_prog_type type)
 
 #ifdef HAVE_ELF
 static int bpf_obj_open(const char *path, enum bpf_prog_type type,
-			const char *sec, __u32 ifindex, bool verbose);
+			const char *sec, __u32 ifindex, bool verbose, bool code);
 #else
 static int bpf_obj_open(const char *path, enum bpf_prog_type type,
-			const char *sec, __u32 ifindex, bool verbose)
+			const char *sec, __u32 ifindex, bool verbose, bool code)
 {
 	fprintf(stderr, "No ELF library support compiled in.\n");
 	errno = ENOSYS;
@@ -809,6 +809,7 @@ static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl)
 {
 	const char *file, *section, *uds_name;
 	bool verbose = false;
+	bool code = false;	
 	int i, ret, argc;
 	char **argv;
 
@@ -890,6 +891,11 @@ static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl)
 			NEXT_ARG_FWD();
 		}
 
+		if (argc > 0 && matches(*argv, "code") == 0) {
+			code = true;
+			NEXT_ARG_FWD();
+		}
+
 		PREV_ARG();
 	}
 
@@ -911,6 +917,7 @@ static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl)
 	cfg->uds     = uds_name;
 	cfg->argc    = argc;
 	cfg->argv    = argv;
+	cfg->code    = code;
 	cfg->verbose = verbose;
 
 	return ret;
@@ -921,7 +928,7 @@ static int bpf_do_load(struct bpf_cfg_in *cfg)
 	if (cfg->mode == EBPF_OBJECT) {
 		cfg->prog_fd = bpf_obj_open(cfg->object, cfg->type,
 					    cfg->section, cfg->ifindex,
-					    cfg->verbose);
+					    cfg->verbose, cfg->code);
 		return cfg->prog_fd;
 	}
 	return 0;
@@ -1133,6 +1140,7 @@ struct bpf_elf_ctx {
 	enum bpf_prog_type	type;
 	__u32			ifindex;
 	bool			verbose;
+	bool			code;
 	struct bpf_elf_st	stat;
 	struct bpf_hash_entry	*ht[256];
 	char			*log;
@@ -1179,6 +1187,17 @@ bpf_dump_error(struct bpf_elf_ctx *ctx, const char *format, ...)
 	}
 }
 
+static void bpf_dump_code(const char *section, const struct bpf_insn *insns, unsigned int cnt)
+{
+	int i;
+	fprintf(stderr, "/* struct bpf_insn %s_code[] = { */\n", section);
+	for (i=0; i < cnt; i++) {
+		fprintf(stderr, "\t{0x%.2x, %4u, %4u, %8d, 0x%.8x},\n",
+		insns[i].code, insns[i].dst_reg, insns[i].src_reg, insns[i].off, insns[i].imm);
+	}
+	fprintf(stderr, "\n");
+}
+
 static int bpf_log_realloc(struct bpf_elf_ctx *ctx)
 {
 	const size_t log_max = UINT_MAX >> 8;
@@ -1526,6 +1545,9 @@ retry:
 		bpf_prog_report(fd, section, prog, ctx);
 	}
 
+	if (ctx->code)
+		bpf_dump_code(section, prog->insns, prog->size / sizeof(struct bpf_insn));
+
 	return fd;
 }
 
@@ -2439,7 +2461,7 @@ static void bpf_get_cfg(struct bpf_elf_ctx *ctx)
 
 static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
 			    enum bpf_prog_type type, __u32 ifindex,
-			    bool verbose)
+			    bool verbose, bool code)
 {
 	int ret = -EINVAL;
 
@@ -2450,6 +2472,7 @@ static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname,
 	memset(ctx, 0, sizeof(*ctx));
 	bpf_get_cfg(ctx);
 	ctx->verbose = verbose;
+	ctx->code    = code;
 	ctx->type    = type;
 	ctx->ifindex = ifindex;
 
@@ -2543,12 +2566,12 @@ static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure)
 static struct bpf_elf_ctx __ctx;
 
 static int bpf_obj_open(const char *pathname, enum bpf_prog_type type,
-			const char *section, __u32 ifindex, bool verbose)
+			const char *section, __u32 ifindex, bool verbose, bool code)
 {
 	struct bpf_elf_ctx *ctx = &__ctx;
 	int fd = 0, ret;
 
-	ret = bpf_elf_ctx_init(ctx, pathname, type, ifindex, verbose);
+	ret = bpf_elf_ctx_init(ctx, pathname, type, ifindex, verbose, code);
 	if (ret < 0) {
 		fprintf(stderr, "Cannot initialize ELF context!\n");
 		return ret;
diff --git a/tc/m_bpf.c b/tc/m_bpf.c
index 1c1f71c..9947113 100644
--- a/tc/m_bpf.c
+++ b/tc/m_bpf.c
@@ -33,7 +33,8 @@ static void explain(void)
 	fprintf(stderr, "\n");
 	fprintf(stderr, "eBPF use case:\n");
 	fprintf(stderr, " object-file FILE [ section ACT_NAME ] [ export UDS_FILE ]");
-	fprintf(stderr, " [ verbose ]\n");
+	fprintf(stderr, " [ verbose ]");
+	fprintf(stderr, " [ code ]\n");
 	fprintf(stderr, " object-pinned FILE\n");
 	fprintf(stderr, "\n");
 	fprintf(stderr, "Where BPF_BYTECODE := \'s,c t f k,c t f k,c t f k,...\'\n");
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] tc, bpf: add option to dump bpf verifier as C program fragment
  2018-06-17  8:48 [PATCH] tc, bpf: add option to dump bpf verifier as C program fragment Ophir Munk
@ 2018-06-18 20:18 ` Jakub Kicinski
  2018-06-18 21:44   ` David Ahern
  0 siblings, 1 reply; 5+ messages in thread
From: Jakub Kicinski @ 2018-06-18 20:18 UTC (permalink / raw)
  To: Ophir Munk
  Cc: netdev, Stephen Hemminger, David Ahern, Thomas Monjalon, Olga Shern

On Sun, 17 Jun 2018 08:48:41 +0000, Ophir Munk wrote:
> Similar to cbpf used within tcpdump utility with a "-d" option to dump
> the compiled packet-matching code in a human readable form - tc has the
> "verbose" option to dump ebpf verifier output.
> Another useful option of cbpf using tcpdump "-dd" option is to dump
> packet-matching code a C program fragment. Similar to this - this commit
> adds a new tc ebpf option named "code" to dump ebpf verifier as C program
> fragment.
> 
> Existing "verbose" option sample output:
> 
> Verifier analysis:
> 0: (61) r2 = *(u32 *)(r1 +52)
> 1: (18) r3 = 0xdeadbeef
> 3: (63) *(u32 *)(r10 -4) = r3
> .
> .
> 11: (63) *(u32 *)(r1 +52) = r2
> 12: (18) r0 = 0xffffffff
> 14: (95) exit
> 
> New "code" option sample output:
> 
> /* struct bpf_insn cls_q_code[] = { */
> {0x61,    2,    1,       52, 0x00000000},
> {0x18,    3,    0,        0, 0xdeadbeef},
> {0x00,    0,    0,        0, 0x00000000},
> .
> .
> {0x63,    1,    2,       52, 0x00000000},
> {0x18,    0,    0,        0, 0xffffffff},
> {0x00,    0,    0,        0, 0x00000000},
> {0x95,    0,    0,        0, 0x00000000},
> 
> Signed-off-by: Ophir Munk <ophirmu@mellanox.com>

Hmm... printing C arrays looks like hacky integration with some C
code...  Would you not be better served by simply using libbpf in
whatever is consuming this output?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] tc, bpf: add option to dump bpf verifier as C program fragment
  2018-06-18 20:18 ` Jakub Kicinski
@ 2018-06-18 21:44   ` David Ahern
  2018-06-19 22:13     ` Daniel Borkmann
  0 siblings, 1 reply; 5+ messages in thread
From: David Ahern @ 2018-06-18 21:44 UTC (permalink / raw)
  To: Jakub Kicinski, Ophir Munk
  Cc: netdev, Stephen Hemminger, Thomas Monjalon, Olga Shern

[-- Attachment #1: Type: text/plain, Size: 1670 bytes --]

On 6/18/18 2:18 PM, Jakub Kicinski wrote:
> On Sun, 17 Jun 2018 08:48:41 +0000, Ophir Munk wrote:
>> Similar to cbpf used within tcpdump utility with a "-d" option to dump
>> the compiled packet-matching code in a human readable form - tc has the
>> "verbose" option to dump ebpf verifier output.
>> Another useful option of cbpf using tcpdump "-dd" option is to dump
>> packet-matching code a C program fragment. Similar to this - this commit
>> adds a new tc ebpf option named "code" to dump ebpf verifier as C program
>> fragment.
>>
>> Existing "verbose" option sample output:
>>
>> Verifier analysis:
>> 0: (61) r2 = *(u32 *)(r1 +52)
>> 1: (18) r3 = 0xdeadbeef
>> 3: (63) *(u32 *)(r10 -4) = r3
>> .
>> .
>> 11: (63) *(u32 *)(r1 +52) = r2
>> 12: (18) r0 = 0xffffffff
>> 14: (95) exit
>>
>> New "code" option sample output:
>>
>> /* struct bpf_insn cls_q_code[] = { */
>> {0x61,    2,    1,       52, 0x00000000},
>> {0x18,    3,    0,        0, 0xdeadbeef},
>> {0x00,    0,    0,        0, 0x00000000},
>> .
>> .
>> {0x63,    1,    2,       52, 0x00000000},
>> {0x18,    0,    0,        0, 0xffffffff},
>> {0x00,    0,    0,        0, 0x00000000},
>> {0x95,    0,    0,        0, 0x00000000},
>>
>> Signed-off-by: Ophir Munk <ophirmu@mellanox.com>
> 
> Hmm... printing C arrays looks like hacky integration with some C
> code...  Would you not be better served by simply using libbpf in
> whatever is consuming this output?
> 

I was thinking the same. bpftool would provide options too -- print the
above, print in macro encodings and verifier. I gave an example of this
side by side dump at netconf 2.1. Does not look like the slides made it
online; see attached.

[-- Attachment #2: netconf-2.1-bpf.pdf --]
[-- Type: application/pdf, Size: 38266 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] tc, bpf: add option to dump bpf verifier as C program fragment
  2018-06-18 21:44   ` David Ahern
@ 2018-06-19 22:13     ` Daniel Borkmann
  2018-06-20 16:40       ` Stephen Hemminger
  0 siblings, 1 reply; 5+ messages in thread
From: Daniel Borkmann @ 2018-06-19 22:13 UTC (permalink / raw)
  To: David Ahern, Jakub Kicinski, Ophir Munk
  Cc: netdev, Stephen Hemminger, Thomas Monjalon, Olga Shern, ast

On 06/18/2018 11:44 PM, David Ahern wrote:
> On 6/18/18 2:18 PM, Jakub Kicinski wrote:
>> On Sun, 17 Jun 2018 08:48:41 +0000, Ophir Munk wrote:
>>> Similar to cbpf used within tcpdump utility with a "-d" option to dump
>>> the compiled packet-matching code in a human readable form - tc has the
>>> "verbose" option to dump ebpf verifier output.
>>> Another useful option of cbpf using tcpdump "-dd" option is to dump
>>> packet-matching code a C program fragment. Similar to this - this commit
>>> adds a new tc ebpf option named "code" to dump ebpf verifier as C program
>>> fragment.
>>>
>>> Existing "verbose" option sample output:
>>>
>>> Verifier analysis:
>>> 0: (61) r2 = *(u32 *)(r1 +52)
>>> 1: (18) r3 = 0xdeadbeef
>>> 3: (63) *(u32 *)(r10 -4) = r3
>>> .
>>> .
>>> 11: (63) *(u32 *)(r1 +52) = r2
>>> 12: (18) r0 = 0xffffffff
>>> 14: (95) exit
>>>
>>> New "code" option sample output:
>>>
>>> /* struct bpf_insn cls_q_code[] = { */
>>> {0x61,    2,    1,       52, 0x00000000},
>>> {0x18,    3,    0,        0, 0xdeadbeef},
>>> {0x00,    0,    0,        0, 0x00000000},
>>> .
>>> .
>>> {0x63,    1,    2,       52, 0x00000000},
>>> {0x18,    0,    0,        0, 0xffffffff},
>>> {0x00,    0,    0,        0, 0x00000000},
>>> {0x95,    0,    0,        0, 0x00000000},
>>>
>>> Signed-off-by: Ophir Munk <ophirmu@mellanox.com>
>>
>> Hmm... printing C arrays looks like hacky integration with some C
>> code...  Would you not be better served by simply using libbpf in
>> whatever is consuming this output?
> 
> I was thinking the same. bpftool would provide options too -- print the
> above, print in macro encodings and verifier. I gave an example of this
> side by side dump at netconf 2.1. Does not look like the slides made it
> online; see attached.

+1, I would also doubt that this adds a lot in terms of debuggability
when you're trying to load an object file with thousands of insns. Better
way would be to use llvm-objdump on the obj file to get to the annotated
disassembly, see also example in [0]. A .o to .c converter is wip for
libbpf/bpftool as presented in [1], which should provide the flexibility
to embedd an obj file.

Cheers,
Daniel

  [0] http://cilium.readthedocs.io/en/latest/bpf/#llvm
  [1] http://vger.kernel.org/netconf2018_files/AlexeiStarovoitov_netconf2018.pdf page 22

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] tc, bpf: add option to dump bpf verifier as C program fragment
  2018-06-19 22:13     ` Daniel Borkmann
@ 2018-06-20 16:40       ` Stephen Hemminger
  0 siblings, 0 replies; 5+ messages in thread
From: Stephen Hemminger @ 2018-06-20 16:40 UTC (permalink / raw)
  To: Daniel Borkmann
  Cc: David Ahern, Jakub Kicinski, Ophir Munk, netdev, Thomas Monjalon,
	Olga Shern, ast

On Wed, 20 Jun 2018 00:13:52 +0200
Daniel Borkmann <daniel@iogearbox.net> wrote:

> On 06/18/2018 11:44 PM, David Ahern wrote:
> > On 6/18/18 2:18 PM, Jakub Kicinski wrote:  
> >> On Sun, 17 Jun 2018 08:48:41 +0000, Ophir Munk wrote:  
> >>> Similar to cbpf used within tcpdump utility with a "-d" option to dump
> >>> the compiled packet-matching code in a human readable form - tc has the
> >>> "verbose" option to dump ebpf verifier output.
> >>> Another useful option of cbpf using tcpdump "-dd" option is to dump
> >>> packet-matching code a C program fragment. Similar to this - this commit
> >>> adds a new tc ebpf option named "code" to dump ebpf verifier as C program
> >>> fragment.
> >>>
> >>> Existing "verbose" option sample output:
> >>>
> >>> Verifier analysis:
> >>> 0: (61) r2 = *(u32 *)(r1 +52)
> >>> 1: (18) r3 = 0xdeadbeef
> >>> 3: (63) *(u32 *)(r10 -4) = r3
> >>> .
> >>> .
> >>> 11: (63) *(u32 *)(r1 +52) = r2
> >>> 12: (18) r0 = 0xffffffff
> >>> 14: (95) exit
> >>>
> >>> New "code" option sample output:
> >>>
> >>> /* struct bpf_insn cls_q_code[] = { */
> >>> {0x61,    2,    1,       52, 0x00000000},
> >>> {0x18,    3,    0,        0, 0xdeadbeef},
> >>> {0x00,    0,    0,        0, 0x00000000},
> >>> .
> >>> .
> >>> {0x63,    1,    2,       52, 0x00000000},
> >>> {0x18,    0,    0,        0, 0xffffffff},
> >>> {0x00,    0,    0,        0, 0x00000000},
> >>> {0x95,    0,    0,        0, 0x00000000},
> >>>
> >>> Signed-off-by: Ophir Munk <ophirmu@mellanox.com>  
> >>
> >> Hmm... printing C arrays looks like hacky integration with some C
> >> code...  Would you not be better served by simply using libbpf in
> >> whatever is consuming this output?  
> > 
> > I was thinking the same. bpftool would provide options too -- print the
> > above, print in macro encodings and verifier. I gave an example of this
> > side by side dump at netconf 2.1. Does not look like the slides made it
> > online; see attached.  
> 
> +1, I would also doubt that this adds a lot in terms of debuggability
> when you're trying to load an object file with thousands of insns. Better
> way would be to use llvm-objdump on the obj file to get to the annotated
> disassembly, see also example in [0]. A .o to .c converter is wip for
> libbpf/bpftool as presented in [1], which should provide the flexibility
> to embedd an obj file.
> 
> Cheers,
> Daniel
> 
>   [0] http://cilium.readthedocs.io/en/latest/bpf/#llvm
>   [1] http://vger.kernel.org/netconf2018_files/AlexeiStarovoitov_netconf2018.pdf page 22

I am going to not accept this for now. Please respin for iproute2 next if
you think bpftool won't be able to handle this.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-06-20 16:40 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-17  8:48 [PATCH] tc, bpf: add option to dump bpf verifier as C program fragment Ophir Munk
2018-06-18 20:18 ` Jakub Kicinski
2018-06-18 21:44   ` David Ahern
2018-06-19 22:13     ` Daniel Borkmann
2018-06-20 16:40       ` Stephen Hemminger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.