netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH iproute2-next] tc: full JSON support for 'bpf' actions
@ 2019-01-31 17:58 Davide Caratti
  2019-02-03 17:11 ` David Ahern
  2019-02-05 22:53 ` Stephen Hemminger
  0 siblings, 2 replies; 5+ messages in thread
From: Davide Caratti @ 2019-01-31 17:58 UTC (permalink / raw)
  To: David Ahern, Stephen Hemminger; +Cc: netdev

Add full JSON output support in the dump of 'act_bpf'.

Example using eBPF:

 # tc actions flush action bpf
 # tc action add action bpf object bpf/action.o section 'action-ok'
 # tc -j action list action bpf | jq
 [
   {
     "total acts": 1
   },
   {
     "actions": [
       {
         "order": 0,
         "kind": "bpf",
         "bpf_name": "action.o:[action-ok]",
         "prog": {
           "id": 33,
           "tag": "a04f5eef06a7f555",
           "jited": 1
         },
         "control_action": {
           "type": "pipe"
         },
         "index": 1,
         "ref": 1,
         "bind": 0
       }
     ]
   }
 ]

Example using cBPF:

 # tc actions flush action bpf
 # a=$(mktemp)
 # tcpdump -ddd not ether proto 0x888e >$a
 # tc action add action bpf bytecode-file $a index 42
 # rm $a
 # tc -j action list action bpf | jq
 [
   {
     "total acts": 1
   },
   {
     "actions": [
       {
         "order": 0,
         "kind": "bpf",
         "bytecode": {
           "length": 4,
           "insns": [
             {
               "code": 40,
               "jt": 0,
               "jf": 0,
               "k": 12
             },
             {
               "code": 21,
               "jt": 0,
               "jf": 1,
               "k": 34958
             },
             {
               "code": 6,
               "jt": 0,
               "jf": 0,
               "k": 0
             },
             {
               "code": 6,
               "jt": 0,
               "jf": 0,
               "k": 262144
             }
           ]
         },
         "control_action": {
           "type": "pipe"
         },
         "index": 42,
         "ref": 1,
         "bind": 0
       }
     ]
   }
 ]

Tested with:
 # ./tdc.py -c bpf

Cc: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
---
 include/bpf_util.h |  2 +-
 lib/bpf.c          | 26 ++++++++++++++++++--------
 tc/f_bpf.c         |  2 +-
 tc/m_bpf.c         | 32 +++++++++++++++++---------------
 4 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/include/bpf_util.h b/include/bpf_util.h
index 63837a04e56f..63db07ca49ae 100644
--- a/include/bpf_util.h
+++ b/include/bpf_util.h
@@ -272,7 +272,7 @@ const char *bpf_prog_to_default_section(enum bpf_prog_type type);
 int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv);
 int bpf_trace_pipe(void);
 
-void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len);
+void bpf_print_ops(struct rtattr *bpf_ops, __u16 len);
 
 int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
 		  size_t size_insns, const char *license, char *log,
diff --git a/lib/bpf.c b/lib/bpf.c
index 5e85cfc0bdd5..dfc4f4f522c3 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -339,7 +339,7 @@ out:
 	return ret;
 }
 
-void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
+void bpf_print_ops(struct rtattr *bpf_ops, __u16 len)
 {
 	struct sock_filter *ops = RTA_DATA(bpf_ops);
 	int i;
@@ -347,14 +347,24 @@ void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
 	if (len == 0)
 		return;
 
-	fprintf(f, "bytecode \'%u,", len);
-
-	for (i = 0; i < len - 1; i++)
-		fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt,
-			ops[i].jf, ops[i].k);
+	open_json_object("bytecode");
+	print_uint(PRINT_ANY, "length", "bytecode \'%u,", len);
+	open_json_array(PRINT_JSON, "insns");
+
+	for (i = 0; i < len; i++) {
+		open_json_object(NULL);
+		print_uint(PRINT_ANY, "code", "%hu ", ops[i].code);
+		print_uint(PRINT_ANY, "jt", "%hhu ", ops[i].jt);
+		print_uint(PRINT_ANY, "jf", "%hhu ", ops[i].jf);
+		if (i == len - 1)
+			print_uint(PRINT_ANY, "k", "%u\'", ops[i].k);
+		else
+			print_uint(PRINT_ANY, "k", "%u,", ops[i].k);
+		close_json_object();
+	}
 
-	fprintf(f, "%hu %hhu %hhu %u\'", ops[i].code, ops[i].jt,
-		ops[i].jf, ops[i].k);
+	close_json_array(PRINT_JSON, NULL);
+	close_json_object();
 }
 
 static void bpf_map_pin_report(const struct bpf_elf_map *pin,
diff --git a/tc/f_bpf.c b/tc/f_bpf.c
index 5906f8bb969d..948d9051b9a5 100644
--- a/tc/f_bpf.c
+++ b/tc/f_bpf.c
@@ -235,7 +235,7 @@ static int bpf_print_opt(struct filter_util *qu, FILE *f,
 	}
 
 	if (tb[TCA_BPF_OPS] && tb[TCA_BPF_OPS_LEN])
-		bpf_print_ops(f, tb[TCA_BPF_OPS],
+		bpf_print_ops(tb[TCA_BPF_OPS],
 			      rta_getattr_u16(tb[TCA_BPF_OPS_LEN]));
 
 	if (tb[TCA_BPF_ID])
diff --git a/tc/m_bpf.c b/tc/m_bpf.c
index 7c6f8c298abd..3e8468c68324 100644
--- a/tc/m_bpf.c
+++ b/tc/m_bpf.c
@@ -157,7 +157,7 @@ static int bpf_print_opt(struct action_util *au, FILE *f, struct rtattr *arg)
 {
 	struct rtattr *tb[TCA_ACT_BPF_MAX + 1];
 	struct tc_act_bpf *parm;
-	int dump_ok = 0;
+	int d_ok = 0;
 
 	if (arg == NULL)
 		return -1;
@@ -170,31 +170,33 @@ static int bpf_print_opt(struct action_util *au, FILE *f, struct rtattr *arg)
 	}
 
 	parm = RTA_DATA(tb[TCA_ACT_BPF_PARMS]);
-	fprintf(f, "bpf ");
+	print_string(PRINT_ANY, "kind", "%s ", "bpf");
 
 	if (tb[TCA_ACT_BPF_NAME])
-		fprintf(f, "%s ", rta_getattr_str(tb[TCA_ACT_BPF_NAME]));
-
+		print_string(PRINT_ANY, "bpf_name", "%s ",
+			     rta_getattr_str(tb[TCA_ACT_BPF_NAME]));
 	if (tb[TCA_ACT_BPF_OPS] && tb[TCA_ACT_BPF_OPS_LEN]) {
-		bpf_print_ops(f, tb[TCA_ACT_BPF_OPS],
+		bpf_print_ops(tb[TCA_ACT_BPF_OPS],
 			      rta_getattr_u16(tb[TCA_ACT_BPF_OPS_LEN]));
-		fprintf(f, " ");
+		print_string(PRINT_FP, NULL, "%s", " ");
 	}
 
 	if (tb[TCA_ACT_BPF_ID])
-		dump_ok = bpf_dump_prog_info(f, rta_getattr_u32(tb[TCA_ACT_BPF_ID]));
-	if (!dump_ok && tb[TCA_ACT_BPF_TAG]) {
+		d_ok = bpf_dump_prog_info(f,
+					  rta_getattr_u32(tb[TCA_ACT_BPF_ID]));
+	if (!d_ok && tb[TCA_ACT_BPF_TAG]) {
 		SPRINT_BUF(b);
 
-		fprintf(f, "tag %s ",
-			hexstring_n2a(RTA_DATA(tb[TCA_ACT_BPF_TAG]),
-				      RTA_PAYLOAD(tb[TCA_ACT_BPF_TAG]),
-				      b, sizeof(b)));
+		print_string(PRINT_ANY, "tag", "tag %s ",
+			     hexstring_n2a(RTA_DATA(tb[TCA_ACT_BPF_TAG]),
+			     RTA_PAYLOAD(tb[TCA_ACT_BPF_TAG]),
+			     b, sizeof(b)));
 	}
 
-	print_action_control(f, "default-action ", parm->action, "\n");
-	fprintf(f, "\tindex %u ref %d bind %d", parm->index, parm->refcnt,
-		parm->bindcnt);
+	print_action_control(f, "default-action ", parm->action, _SL_);
+	print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
+	print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
+	print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
 
 	if (show_stats) {
 		if (tb[TCA_ACT_BPF_TM]) {
-- 
2.20.1


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

* Re: [PATCH iproute2-next] tc: full JSON support for 'bpf' actions
  2019-01-31 17:58 [PATCH iproute2-next] tc: full JSON support for 'bpf' actions Davide Caratti
@ 2019-02-03 17:11 ` David Ahern
  2019-02-05 22:53 ` Stephen Hemminger
  1 sibling, 0 replies; 5+ messages in thread
From: David Ahern @ 2019-02-03 17:11 UTC (permalink / raw)
  To: Davide Caratti, David Ahern, Stephen Hemminger; +Cc: netdev

On 1/31/19 10:58 AM, Davide Caratti wrote:
> Add full JSON output support in the dump of 'act_bpf'.
> 
> Example using eBPF:
> 
>  # tc actions flush action bpf
>  # tc action add action bpf object bpf/action.o section 'action-ok'
>  # tc -j action list action bpf | jq
>  [
>    {
>      "total acts": 1
>    },
>    {
>      "actions": [
>        {
>          "order": 0,
>          "kind": "bpf",
>          "bpf_name": "action.o:[action-ok]",
>          "prog": {
>            "id": 33,
>            "tag": "a04f5eef06a7f555",
>            "jited": 1
>          },
>          "control_action": {
>            "type": "pipe"
>          },
>          "index": 1,
>          "ref": 1,
>          "bind": 0
>        }
>      ]
>    }
>  ]
> 
> Example using cBPF:
> 
>  # tc actions flush action bpf
>  # a=$(mktemp)
>  # tcpdump -ddd not ether proto 0x888e >$a
>  # tc action add action bpf bytecode-file $a index 42
>  # rm $a
>  # tc -j action list action bpf | jq
>  [
>    {
>      "total acts": 1
>    },
>    {
>      "actions": [
>        {
>          "order": 0,
>          "kind": "bpf",
>          "bytecode": {
>            "length": 4,
>            "insns": [
>              {
>                "code": 40,
>                "jt": 0,
>                "jf": 0,
>                "k": 12
>              },
>              {
>                "code": 21,
>                "jt": 0,
>                "jf": 1,
>                "k": 34958
>              },
>              {
>                "code": 6,
>                "jt": 0,
>                "jf": 0,
>                "k": 0
>              },
>              {
>                "code": 6,
>                "jt": 0,
>                "jf": 0,
>                "k": 262144
>              }
>            ]
>          },
>          "control_action": {
>            "type": "pipe"
>          },
>          "index": 42,
>          "ref": 1,
>          "bind": 0
>        }
>      ]
>    }
>  ]
> 
> Tested with:
>  # ./tdc.py -c bpf
> 
> Cc: Andrea Claudi <aclaudi@redhat.com>
> Signed-off-by: Davide Caratti <dcaratti@redhat.com>
> ---
>  include/bpf_util.h |  2 +-
>  lib/bpf.c          | 26 ++++++++++++++++++--------
>  tc/f_bpf.c         |  2 +-
>  tc/m_bpf.c         | 32 +++++++++++++++++---------------
>  4 files changed, 37 insertions(+), 25 deletions(-)
> 

applied to iproute2-next. Thanks



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

* Re: [PATCH iproute2-next] tc: full JSON support for 'bpf' actions
  2019-01-31 17:58 [PATCH iproute2-next] tc: full JSON support for 'bpf' actions Davide Caratti
  2019-02-03 17:11 ` David Ahern
@ 2019-02-05 22:53 ` Stephen Hemminger
  2019-02-05 22:59   ` David Ahern
  1 sibling, 1 reply; 5+ messages in thread
From: Stephen Hemminger @ 2019-02-05 22:53 UTC (permalink / raw)
  To: Davide Caratti; +Cc: David Ahern, netdev

On Thu, 31 Jan 2019 18:58:09 +0100
Davide Caratti <dcaratti@redhat.com> wrote:

> +		print_uint(PRINT_ANY, "code", "%hu ", ops[i].code);
> +		print_uint(PRINT_ANY, "jt", "%hhu ", ops[i].jt);
> +		print_uint(PRINT_ANY, "jf", "%hhu ", ops[i].jf);

Did you know that print_uint promotes the argument to unsigned int
then you are printing it with %hhu which expects only a u8.

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

* Re: [PATCH iproute2-next] tc: full JSON support for 'bpf' actions
  2019-02-05 22:53 ` Stephen Hemminger
@ 2019-02-05 22:59   ` David Ahern
  2019-02-06  9:14     ` Davide Caratti
  0 siblings, 1 reply; 5+ messages in thread
From: David Ahern @ 2019-02-05 22:59 UTC (permalink / raw)
  To: Stephen Hemminger, Davide Caratti; +Cc: netdev

On 2/5/19 2:53 PM, Stephen Hemminger wrote:
> On Thu, 31 Jan 2019 18:58:09 +0100
> Davide Caratti <dcaratti@redhat.com> wrote:
> 
>> +		print_uint(PRINT_ANY, "code", "%hu ", ops[i].code);
>> +		print_uint(PRINT_ANY, "jt", "%hhu ", ops[i].jt);
>> +		print_uint(PRINT_ANY, "jf", "%hhu ", ops[i].jf);
> 
> Did you know that print_uint promotes the argument to unsigned int
> then you are printing it with %hhu which expects only a u8.
> 

I did look at the print_hhu option and it seems really weird that you
use "print_hhu(..., "%hhu", ...)" which is why I took the patch as is.
There are existing examples of print_uint with '%hu' too.

The print_ functions really should be renamed (print_uchar,
print_ushort, etc).

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

* Re: [PATCH iproute2-next] tc: full JSON support for 'bpf' actions
  2019-02-05 22:59   ` David Ahern
@ 2019-02-06  9:14     ` Davide Caratti
  0 siblings, 0 replies; 5+ messages in thread
From: Davide Caratti @ 2019-02-06  9:14 UTC (permalink / raw)
  To: David Ahern, Stephen Hemminger; +Cc: netdev

On Tue, 2019-02-05 at 14:59 -0800, David Ahern wrote:
> On 2/5/19 2:53 PM, Stephen Hemminger wrote:
> > On Thu, 31 Jan 2019 18:58:09 +0100
> > Davide Caratti <dcaratti@redhat.com> wrote:
> > 
> > > +		print_uint(PRINT_ANY, "code", "%hu ", ops[i].code);
> > > +		print_uint(PRINT_ANY, "jt", "%hhu ", ops[i].jt);
> > > +		print_uint(PRINT_ANY, "jf", "%hhu ", ops[i].jf);
> > 
> > Did you know that print_uint promotes the argument to unsigned int

this happens frequently in iproute2 code,

> > then you are printing it with %hhu which expects only a u8.

but indeed, %hu and %hhu made the former cast just useless: thanks for
noticing.

> I did look at the print_hhu option and it seems really weird that you
> use "print_hhu(..., "%hhu", ...)" which is why I took the patch as is.
> There are existing examples of print_uint with '%hu' too.
> The print_ functions really should be renamed (print_uchar,
> print_ushort, etc).

maybe this can be done more reliably with an automatic tool, like
coccinelle. There are only 5 lines with the print_uint(...
"%hu" ...) pattern, so this can be uniformed easily with a small patch.

-- 
davide 


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

end of thread, other threads:[~2019-02-06  9:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-01-31 17:58 [PATCH iproute2-next] tc: full JSON support for 'bpf' actions Davide Caratti
2019-02-03 17:11 ` David Ahern
2019-02-05 22:53 ` Stephen Hemminger
2019-02-05 22:59   ` David Ahern
2019-02-06  9:14     ` Davide Caratti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).