From: Davide Caratti Date: Thu, 31 Jan 2019 17:58:09 +0000 (+0100) Subject: tc: full JSON support for 'bpf' actions X-Git-Tag: v5.1.0~27^2~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52d57f6bbdf799c2b54307a70c256e0c127e9663;p=thirdparty%2Fiproute2.git 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 Signed-off-by: Davide Caratti Signed-off-by: David Ahern --- diff --git a/include/bpf_util.h b/include/bpf_util.h index 63837a04e..63db07ca4 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 5e85cfc0b..dfc4f4f52 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 5906f8bb9..948d9051b 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 7c6f8c298..3e8468c68 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]) {