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@redhat.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
Davide Caratti 2019-01-31 18:58:09 +01:00 committed by David Ahern
parent 2abc3d76e3
commit 52d57f6bbd
4 changed files with 36 additions and 24 deletions

View File

@ -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_graft_map(const char *map_path, uint32_t *key, int argc, char **argv);
int bpf_trace_pipe(void); 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, int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns,
size_t size_insns, const char *license, char *log, size_t size_insns, const char *license, char *log,

View File

@ -339,7 +339,7 @@ out:
return ret; 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); struct sock_filter *ops = RTA_DATA(bpf_ops);
int i; int i;
@ -347,14 +347,24 @@ void bpf_print_ops(FILE *f, struct rtattr *bpf_ops, __u16 len)
if (len == 0) if (len == 0)
return; return;
fprintf(f, "bytecode \'%u,", len); open_json_object("bytecode");
print_uint(PRINT_ANY, "length", "bytecode \'%u,", len);
open_json_array(PRINT_JSON, "insns");
for (i = 0; i < len - 1; i++) for (i = 0; i < len; i++) {
fprintf(f, "%hu %hhu %hhu %u,", ops[i].code, ops[i].jt, open_json_object(NULL);
ops[i].jf, ops[i].k); 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, close_json_array(PRINT_JSON, NULL);
ops[i].jf, ops[i].k); close_json_object();
} }
static void bpf_map_pin_report(const struct bpf_elf_map *pin, static void bpf_map_pin_report(const struct bpf_elf_map *pin,

View File

@ -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]) 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])); rta_getattr_u16(tb[TCA_BPF_OPS_LEN]));
if (tb[TCA_BPF_ID]) if (tb[TCA_BPF_ID])

View File

@ -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 rtattr *tb[TCA_ACT_BPF_MAX + 1];
struct tc_act_bpf *parm; struct tc_act_bpf *parm;
int dump_ok = 0; int d_ok = 0;
if (arg == NULL) if (arg == NULL)
return -1; 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]); parm = RTA_DATA(tb[TCA_ACT_BPF_PARMS]);
fprintf(f, "bpf "); print_string(PRINT_ANY, "kind", "%s ", "bpf");
if (tb[TCA_ACT_BPF_NAME]) 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]) { 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])); rta_getattr_u16(tb[TCA_ACT_BPF_OPS_LEN]));
fprintf(f, " "); print_string(PRINT_FP, NULL, "%s", " ");
} }
if (tb[TCA_ACT_BPF_ID]) if (tb[TCA_ACT_BPF_ID])
dump_ok = bpf_dump_prog_info(f, rta_getattr_u32(tb[TCA_ACT_BPF_ID])); d_ok = bpf_dump_prog_info(f,
if (!dump_ok && tb[TCA_ACT_BPF_TAG]) { rta_getattr_u32(tb[TCA_ACT_BPF_ID]));
if (!d_ok && tb[TCA_ACT_BPF_TAG]) {
SPRINT_BUF(b); SPRINT_BUF(b);
fprintf(f, "tag %s ", print_string(PRINT_ANY, "tag", "tag %s ",
hexstring_n2a(RTA_DATA(tb[TCA_ACT_BPF_TAG]), hexstring_n2a(RTA_DATA(tb[TCA_ACT_BPF_TAG]),
RTA_PAYLOAD(tb[TCA_ACT_BPF_TAG]), RTA_PAYLOAD(tb[TCA_ACT_BPF_TAG]),
b, sizeof(b))); b, sizeof(b)));
} }
print_action_control(f, "default-action ", parm->action, "\n"); print_action_control(f, "default-action ", parm->action, _SL_);
fprintf(f, "\tindex %u ref %d bind %d", parm->index, parm->refcnt, print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
parm->bindcnt); print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
if (show_stats) { if (show_stats) {
if (tb[TCA_ACT_BPF_TM]) { if (tb[TCA_ACT_BPF_TM]) {