aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Machata <petrm@mellanox.com>2020-04-28 14:44:33 +0300
committerDavid Ahern <dsahern@gmail.com>2020-04-30 02:43:23 +0000
commit081d6c310d3a6e0412431a9652f641dff3f72aee (patch)
tree76ae697312d68242181a24f2c807b20b37e9a989
parent846b6b2da8358d34aa4be8b310f90195e134b5b0 (diff)
downloadiproute2-081d6c310d3a6e0412431a9652f641dff3f72aee.tar.gz
tc: pedit: Support JSON dumping
The action pedit does not currently support dumping to JSON. Convert print_pedit() to the print_* family of functions so that dumping is correct both in plain and JSON mode. In plain mode, the output is character for character the same as it was before. In JSON mode, this is an example dump: $ tc filter add dev dummy0 ingress prio 125 flower \ action pedit ex munge udp dport set 12345 \ munge ip ttl add 1 \ munge offset 10 u8 clear $ tc -j filter show dev dummy0 ingress | jq [ { "protocol": "all", "pref": 125, "kind": "flower", "chain": 0 }, { "protocol": "all", "pref": 125, "kind": "flower", "chain": 0, "options": { "handle": 1, "keys": {}, "not_in_hw": true, "actions": [ { "order": 1, "kind": "pedit", "control_action": { "type": "pass" }, "nkeys": 3, "index": 1, "ref": 1, "bind": 1, "keys": [ { "htype": "udp", "offset": 0, "cmd": "set", "val": "3039", "mask": "ffff0000" }, { "htype": "ipv4", "offset": 8, "cmd": "add", "val": "1000000", "mask": "ffffff" }, { "htype": "network", "offset": 8, "cmd": "set", "val": "0", "mask": "ffff00ff" } ] } ] } } ] Signed-off-by: Petr Machata <petrm@mellanox.com> Signed-off-by: David Ahern <dsahern@gmail.com>
-rw-r--r--tc/m_pedit.c71
1 files changed, 46 insertions, 25 deletions
diff --git a/tc/m_pedit.c b/tc/m_pedit.c
index fccfd17ca..51dcf1093 100644
--- a/tc/m_pedit.c
+++ b/tc/m_pedit.c
@@ -714,20 +714,28 @@ static const char * const pedit_htype_str[] = {
[TCA_PEDIT_KEY_EX_HDR_TYPE_UDP] = "udp",
};
-static void print_pedit_location(FILE *f,
- enum pedit_header_type htype, __u32 off)
+static int print_pedit_location(FILE *f,
+ enum pedit_header_type htype, __u32 off)
{
- if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK) {
- fprintf(f, "%d", (unsigned int)off);
- return;
+ char *buf = NULL;
+ int rc;
+
+ if (htype != TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK) {
+ if (htype < ARRAY_SIZE(pedit_htype_str))
+ rc = asprintf(&buf, "%s", pedit_htype_str[htype]);
+ else
+ rc = asprintf(&buf, "unknown(%d)", htype);
+ if (rc < 0)
+ return rc;
+ print_string(PRINT_ANY, "htype", "%s", buf);
+ print_int(PRINT_ANY, "offset", "%+d", off);
+ } else {
+ print_string(PRINT_JSON, "htype", NULL, "network");
+ print_int(PRINT_ANY, "offset", "%d", off);
}
- if (htype < ARRAY_SIZE(pedit_htype_str))
- fprintf(f, "%s", pedit_htype_str[htype]);
- else
- fprintf(f, "unknown(%d)", htype);
-
- fprintf(f, "%c%d", (int)off >= 0 ? '+' : '-', abs((int)off));
+ free(buf);
+ return 0;
}
static int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
@@ -735,6 +743,7 @@ static int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
struct tc_pedit_sel *sel;
struct rtattr *tb[TCA_PEDIT_MAX + 1];
struct m_pedit_key_ex *keys_ex = NULL;
+ int err;
if (arg == NULL)
return -1;
@@ -774,11 +783,12 @@ static int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
}
}
- fprintf(f, " pedit ");
+ print_string(PRINT_ANY, "kind", " %s ", "pedit");
print_action_control(f, "action ", sel->action, " ");
- fprintf(f,"keys %d\n ", sel->nkeys);
- fprintf(f, "\t index %u ref %d bind %d", sel->index, sel->refcnt,
- sel->bindcnt);
+ print_uint(PRINT_ANY, "nkeys", "keys %d\n", sel->nkeys);
+ print_uint(PRINT_ANY, "index", " \t index %u", sel->index);
+ print_int(PRINT_ANY, "ref", " ref %d", sel->refcnt);
+ print_int(PRINT_ANY, "bind", " bind %d", sel->bindcnt);
if (show_stats) {
if (tb[TCA_PEDIT_TM]) {
@@ -787,6 +797,7 @@ static int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
print_tm(f, tm);
}
}
+ open_json_array(PRINT_JSON, "keys");
if (sel->nkeys) {
int i;
struct tc_pedit_key *key = sel->keys;
@@ -804,21 +815,31 @@ static int print_pedit(struct action_util *au, FILE *f, struct rtattr *arg)
key_ex++;
}
- fprintf(f, "\n\t key #%d", i);
-
- fprintf(f, " at ");
-
- print_pedit_location(f, htype, key->off);
-
- fprintf(f, ": %s %08x mask %08x",
- cmd ? "add" : "val",
- (unsigned int)ntohl(key->val),
- (unsigned int)ntohl(key->mask));
+ open_json_object(NULL);
+ print_uint(PRINT_FP, NULL, "\n\t key #%d at ", i);
+
+ err = print_pedit_location(f, htype, key->off);
+ if (err)
+ return err;
+
+ /* In FP, report the "set" command as "val" to keep
+ * backward compatibility. Report the true name in JSON.
+ */
+ print_string(PRINT_FP, NULL, ": %s",
+ cmd ? "add" : "val");
+ print_string(PRINT_JSON, "cmd", NULL,
+ cmd ? "add" : "set");
+ print_hex(PRINT_ANY, "val", " %08x",
+ (unsigned int)ntohl(key->val));
+ print_hex(PRINT_ANY, "mask", " mask %08x",
+ (unsigned int)ntohl(key->mask));
+ close_json_object();
}
} else {
fprintf(f, "\npedit %x keys %d is not LEGIT", sel->index,
sel->nkeys);
}
+ close_json_array(PRINT_JSON, " ");
print_nl();