[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <c1bb8538298d24e302ef0e84ead3bfb97f2438dc.1548957196.git.dcaratti@redhat.com>
Date: Thu, 31 Jan 2019 18:58:09 +0100
From: Davide Caratti <dcaratti@...hat.com>
To: David Ahern <dsahern@...il.com>,
Stephen Hemminger <stephen@...workplumber.org>
Cc: netdev@...r.kernel.org
Subject: [PATCH iproute2-next] tc: full JSON support for 'bpf' actions
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@...hat.com>
Signed-off-by: Davide Caratti <dcaratti@...hat.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
Powered by blists - more mailing lists