diff --git a/SOURCES/0012-tc-u32-add-support-for-json-output.patch b/SOURCES/0012-tc-u32-add-support-for-json-output.patch new file mode 100644 index 0000000..0e6efe0 --- /dev/null +++ b/SOURCES/0012-tc-u32-add-support-for-json-output.patch @@ -0,0 +1,206 @@ +From 0a250b280fbaf8e4d6ad173cf6d9e082658954b4 Mon Sep 17 00:00:00 2001 +Message-Id: <0a250b280fbaf8e4d6ad173cf6d9e082658954b4.1644243783.git.aclaudi@redhat.com> +In-Reply-To: +References: +From: Andrea Claudi +Date: Mon, 7 Feb 2022 15:16:36 +0100 +Subject: [PATCH] tc: u32: add support for json output + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1989591 +Upstream Status: unknown commit c733722b + +commit c733722b993cb82832722b1490cbc5002035fd20 +Author: Wen Liang +Date: Wed Jan 26 14:44:47 2022 -0500 + + tc: u32: add support for json output + + Currently u32 filter output does not support json. This commit uses + proper json functions to add support for it. + + `sprint_u32_handle` adds an extra space after the raw check, remove the + extra space. + + Signed-off-by: Wen Liang + Tested-by: Victor Nogueira + Signed-off-by: David Ahern +--- + tc/f_u32.c | 83 ++++++++++++++++++++++++++++++------------------------ + 1 file changed, 46 insertions(+), 37 deletions(-) + +diff --git a/tc/f_u32.c b/tc/f_u32.c +index a5747f67..11da202e 100644 +--- a/tc/f_u32.c ++++ b/tc/f_u32.c +@@ -109,7 +109,7 @@ static char *sprint_u32_handle(__u32 handle, char *buf) + } + } + if (show_raw) +- snprintf(b, bsize, "[%08x] ", handle); ++ snprintf(b, bsize, "[%08x]", handle); + return buf; + } + +@@ -1213,11 +1213,11 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, + + if (handle) { + SPRINT_BUF(b1); +- fprintf(f, "fh %s ", sprint_u32_handle(handle, b1)); ++ print_string(PRINT_ANY, "fh", "fh %s ", sprint_u32_handle(handle, b1)); + } + + if (TC_U32_NODE(handle)) +- fprintf(f, "order %d ", TC_U32_NODE(handle)); ++ print_int(PRINT_ANY, "order", "order %d ", TC_U32_NODE(handle)); + + if (tb[TCA_U32_SEL]) { + if (RTA_PAYLOAD(tb[TCA_U32_SEL]) < sizeof(*sel)) +@@ -1227,15 +1227,15 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, + } + + if (tb[TCA_U32_DIVISOR]) { +- fprintf(f, "ht divisor %d ", +- rta_getattr_u32(tb[TCA_U32_DIVISOR])); ++ __u32 htdivisor = rta_getattr_u32(tb[TCA_U32_DIVISOR]); ++ ++ print_int(PRINT_ANY, "ht_divisor", "ht divisor %d ", htdivisor); + } else if (tb[TCA_U32_HASH]) { + __u32 htid = rta_getattr_u32(tb[TCA_U32_HASH]); +- +- fprintf(f, "key ht %x bkt %x ", TC_U32_USERHTID(htid), +- TC_U32_HASH(htid)); ++ print_hex(PRINT_ANY, "key_ht", "key ht %x ", TC_U32_USERHTID(htid)); ++ print_hex(PRINT_ANY, "bkt", "bkt %x ", TC_U32_HASH(htid)); + } else { +- fprintf(f, "??? "); ++ fprintf(stderr, "divisor and hash missing "); + } + if (tb[TCA_U32_CLASSID]) { + SPRINT_BUF(b1); +@@ -1244,27 +1244,27 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, + sprint_tc_classid(rta_getattr_u32(tb[TCA_U32_CLASSID]), + b1)); + } else if (sel && sel->flags & TC_U32_TERMINAL) { +- fprintf(f, "terminal flowid ??? "); ++ print_string(PRINT_FP, NULL, "terminal flowid ", NULL); + } + if (tb[TCA_U32_LINK]) { + SPRINT_BUF(b1); +- fprintf(f, "link %s ", +- sprint_u32_handle(rta_getattr_u32(tb[TCA_U32_LINK]), +- b1)); ++ char *link = sprint_u32_handle(rta_getattr_u32(tb[TCA_U32_LINK]), b1); ++ ++ print_string(PRINT_ANY, "link", "link %s ", link); + } + + if (tb[TCA_U32_FLAGS]) { + __u32 flags = rta_getattr_u32(tb[TCA_U32_FLAGS]); + + if (flags & TCA_CLS_FLAGS_SKIP_HW) +- fprintf(f, "skip_hw "); ++ print_bool(PRINT_ANY, "skip_hw", "skip_hw ", true); + if (flags & TCA_CLS_FLAGS_SKIP_SW) +- fprintf(f, "skip_sw "); ++ print_bool(PRINT_ANY, "skip_sw", "skip_sw ", true); + + if (flags & TCA_CLS_FLAGS_IN_HW) +- fprintf(f, "in_hw "); ++ print_bool(PRINT_ANY, "in_hw", "in_hw ", true); + else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) +- fprintf(f, "not_in_hw "); ++ print_bool(PRINT_ANY, "not_in_hw", "not_in_hw ", true); + } + + if (tb[TCA_U32_PCNT]) { +@@ -1275,10 +1275,10 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, + pf = RTA_DATA(tb[TCA_U32_PCNT]); + } + +- if (sel && show_stats && NULL != pf) +- fprintf(f, " (rule hit %llu success %llu)", +- (unsigned long long) pf->rcnt, +- (unsigned long long) pf->rhit); ++ if (sel && show_stats && NULL != pf) { ++ print_u64(PRINT_ANY, "rule_hit", "(rule hit %llu ", pf->rcnt); ++ print_u64(PRINT_ANY, "success", "success %llu)", pf->rhit); ++ } + + if (tb[TCA_U32_MARK]) { + struct tc_u32_mark *mark = RTA_DATA(tb[TCA_U32_MARK]); +@@ -1286,8 +1286,10 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, + if (RTA_PAYLOAD(tb[TCA_U32_MARK]) < sizeof(*mark)) { + fprintf(f, "\n Invalid mark (kernel&iproute2 mismatch)\n"); + } else { +- fprintf(f, "\n mark 0x%04x 0x%04x (success %d)", +- mark->val, mark->mask, mark->success); ++ print_nl(); ++ print_0xhex(PRINT_ANY, "fwmark_value", " mark 0x%04x ", mark->val); ++ print_0xhex(PRINT_ANY, "fwmark_mask", "0x%04x ", mark->mask); ++ print_int(PRINT_ANY, "fwmark_success", "(success %d)", mark->success); + } + } + +@@ -1298,38 +1300,45 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, + for (i = 0; i < sel->nkeys; i++) { + show_keys(f, sel->keys + i); + if (show_stats && NULL != pf) +- fprintf(f, " (success %llu ) ", +- (unsigned long long) pf->kcnts[i]); ++ print_u64(PRINT_ANY, "success", " (success %llu ) ", ++ pf->kcnts[i]); + } + } + + if (sel->flags & (TC_U32_VAROFFSET | TC_U32_OFFSET)) { +- fprintf(f, "\n offset "); +- if (sel->flags & TC_U32_VAROFFSET) +- fprintf(f, "%04x>>%d at %d ", +- ntohs(sel->offmask), +- sel->offshift, sel->offoff); ++ print_nl(); ++ print_string(PRINT_ANY, NULL, "%s", " offset "); ++ if (sel->flags & TC_U32_VAROFFSET) { ++ print_hex(PRINT_ANY, "offset_mask", "%04x", ntohs(sel->offmask)); ++ print_int(PRINT_ANY, "offset_shift", ">>%d ", sel->offshift); ++ print_int(PRINT_ANY, "offset_off", "at %d ", sel->offoff); ++ } + if (sel->off) +- fprintf(f, "plus %d ", sel->off); ++ print_int(PRINT_ANY, "plus", "plus %d ", sel->off); + } + if (sel->flags & TC_U32_EAT) +- fprintf(f, " eat "); ++ print_string(PRINT_ANY, NULL, "%s", " eat "); + + if (sel->hmask) { +- fprintf(f, "\n hash mask %08x at %d ", +- (unsigned int)htonl(sel->hmask), sel->hoff); ++ print_nl(); ++ unsigned int hmask = (unsigned int)htonl(sel->hmask); ++ ++ print_hex(PRINT_ANY, "hash_mask", " hash mask %08x ", hmask); ++ print_int(PRINT_ANY, "hash_off", "at %d ", sel->hoff); + } + } + + if (tb[TCA_U32_POLICE]) { +- fprintf(f, "\n"); ++ print_nl(); + tc_print_police(f, tb[TCA_U32_POLICE]); + } + + if (tb[TCA_U32_INDEV]) { + struct rtattr *idev = tb[TCA_U32_INDEV]; +- +- fprintf(f, "\n input dev %s\n", rta_getattr_str(idev)); ++ print_nl(); ++ print_string(PRINT_ANY, "input_dev", " input dev %s", ++ rta_getattr_str(idev)); ++ print_nl(); + } + + if (tb[TCA_U32_ACT]) +-- +2.34.1 + diff --git a/SOURCES/0013-tc-u32-add-json-support-in-print_raw-print_ipv4-prin.patch b/SOURCES/0013-tc-u32-add-json-support-in-print_raw-print_ipv4-prin.patch new file mode 100644 index 0000000..c5d48b1 --- /dev/null +++ b/SOURCES/0013-tc-u32-add-json-support-in-print_raw-print_ipv4-prin.patch @@ -0,0 +1,240 @@ +From 66efa0a6dc179f814614fbd2f47c37d7e20e4405 Mon Sep 17 00:00:00 2001 +Message-Id: <66efa0a6dc179f814614fbd2f47c37d7e20e4405.1644243783.git.aclaudi@redhat.com> +In-Reply-To: +References: +From: Andrea Claudi +Date: Mon, 7 Feb 2022 15:16:36 +0100 +Subject: [PATCH] tc: u32: add json support in `print_raw`, `print_ipv4`, + `print_ipv6` + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1989591 +Upstream Status: unknown commit 721435dc + +commit 721435dcfd9274277af2fb6a4cec81d4a9bcc6b4 +Author: Wen Liang +Date: Wed Jan 26 14:44:48 2022 -0500 + + tc: u32: add json support in `print_raw`, `print_ipv4`, `print_ipv6` + + Currently the key struct of u32 filter does not support json. This + commit adds json support for showing key. + + Signed-off-by: Wen Liang + Tested-by: Victor Nogueira + Signed-off-by: David Ahern +--- + tc/f_u32.c | 121 ++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 79 insertions(+), 42 deletions(-) + +diff --git a/tc/f_u32.c b/tc/f_u32.c +index 11da202e..d787eb91 100644 +--- a/tc/f_u32.c ++++ b/tc/f_u32.c +@@ -824,23 +824,27 @@ static void print_ipv4(FILE *f, const struct tc_u32_key *key) + { + char abuf[256]; + ++ open_json_object("match"); + switch (key->off) { + case 0: + switch (ntohl(key->mask)) { + case 0x0f000000: +- fprintf(f, "\n match IP ihl %u", +- ntohl(key->val) >> 24); ++ print_nl(); ++ print_uint(PRINT_ANY, "ip_ihl", " match IP ihl %u", ++ ntohl(key->val) >> 24); + return; + case 0x00ff0000: +- fprintf(f, "\n match IP dsfield %#x", +- ntohl(key->val) >> 16); ++ print_nl(); ++ print_0xhex(PRINT_ANY, "ip_dsfield", " match IP dsfield %#x", ++ ntohl(key->val) >> 16); + return; + } + break; + case 8: + if (ntohl(key->mask) == 0x00ff0000) { +- fprintf(f, "\n match IP protocol %d", +- ntohl(key->val) >> 16); ++ print_nl(); ++ print_int(PRINT_ANY, "ip_protocol", " match IP protocol %d", ++ ntohl(key->val) >> 16); + return; + } + break; +@@ -849,11 +853,21 @@ static void print_ipv4(FILE *f, const struct tc_u32_key *key) + int bits = mask2bits(key->mask); + + if (bits >= 0) { +- fprintf(f, "\n %s %s/%d", +- key->off == 12 ? "match IP src" : "match IP dst", +- inet_ntop(AF_INET, &key->val, +- abuf, sizeof(abuf)), +- bits); ++ const char *addr; ++ ++ if (key->off == 12) { ++ print_nl(); ++ print_null(PRINT_FP, NULL, " match IP src ", NULL); ++ open_json_object("src"); ++ } else { ++ print_nl(); ++ print_null(PRINT_FP, NULL, " match IP dst ", NULL); ++ open_json_object("dst"); ++ } ++ addr = inet_ntop(AF_INET, &key->val, abuf, sizeof(abuf)); ++ print_string(PRINT_ANY, "address", "%s", addr); ++ print_int(PRINT_ANY, "prefixlen", "/%d", bits); ++ close_json_object(); + return; + } + } +@@ -862,45 +876,52 @@ static void print_ipv4(FILE *f, const struct tc_u32_key *key) + case 20: + switch (ntohl(key->mask)) { + case 0x0000ffff: +- fprintf(f, "\n match dport %u", +- ntohl(key->val) & 0xffff); ++ print_uint(PRINT_ANY, "dport", "match dport %u", ++ ntohl(key->val) & 0xffff); + return; + case 0xffff0000: +- fprintf(f, "\n match sport %u", +- ntohl(key->val) >> 16); ++ print_nl(); ++ print_uint(PRINT_ANY, "sport", " match sport %u", ++ ntohl(key->val) >> 16); + return; + case 0xffffffff: +- fprintf(f, "\n match dport %u, match sport %u", +- ntohl(key->val) & 0xffff, +- ntohl(key->val) >> 16); +- ++ print_nl(); ++ print_uint(PRINT_ANY, "dport", " match dport %u, ", ++ ntohl(key->val) & 0xffff); ++ print_uint(PRINT_ANY, "sport", "match sport %u", ++ ntohl(key->val) >> 16); + return; + } + /* XXX: Default print_raw */ + } ++ close_json_object(); + } + + static void print_ipv6(FILE *f, const struct tc_u32_key *key) + { + char abuf[256]; + ++ open_json_object("match"); + switch (key->off) { + case 0: + switch (ntohl(key->mask)) { + case 0x0f000000: +- fprintf(f, "\n match IP ihl %u", +- ntohl(key->val) >> 24); ++ print_nl(); ++ print_uint(PRINT_ANY, "ip_ihl", " match IP ihl %u", ++ ntohl(key->val) >> 24); + return; + case 0x00ff0000: +- fprintf(f, "\n match IP dsfield %#x", +- ntohl(key->val) >> 16); ++ print_nl(); ++ print_0xhex(PRINT_ANY, "ip_dsfield", " match IP dsfield %#x", ++ ntohl(key->val) >> 16); + return; + } + break; + case 8: + if (ntohl(key->mask) == 0x00ff0000) { +- fprintf(f, "\n match IP protocol %d", +- ntohl(key->val) >> 16); ++ print_nl(); ++ print_int(PRINT_ANY, "ip_protocol", " match IP protocol %d", ++ ntohl(key->val) >> 16); + return; + } + break; +@@ -909,11 +930,21 @@ static void print_ipv6(FILE *f, const struct tc_u32_key *key) + int bits = mask2bits(key->mask); + + if (bits >= 0) { +- fprintf(f, "\n %s %s/%d", +- key->off == 12 ? "match IP src" : "match IP dst", +- inet_ntop(AF_INET, &key->val, +- abuf, sizeof(abuf)), +- bits); ++ const char *addr; ++ ++ if (key->off == 12) { ++ print_nl(); ++ print_null(PRINT_FP, NULL, " match IP src ", NULL); ++ open_json_object("src"); ++ } else { ++ print_nl(); ++ print_null(PRINT_FP, NULL, " match IP dst ", NULL); ++ open_json_object("dst"); ++ } ++ addr = inet_ntop(AF_INET, &key->val, abuf, sizeof(abuf)); ++ print_string(PRINT_ANY, "address", "%s", addr); ++ print_int(PRINT_ANY, "prefixlen", "/%d", bits); ++ close_json_object(); + return; + } + } +@@ -922,31 +953,37 @@ static void print_ipv6(FILE *f, const struct tc_u32_key *key) + case 20: + switch (ntohl(key->mask)) { + case 0x0000ffff: +- fprintf(f, "\n match sport %u", +- ntohl(key->val) & 0xffff); ++ print_nl(); ++ print_uint(PRINT_ANY, "sport", " match sport %u", ++ ntohl(key->val) & 0xffff); + return; + case 0xffff0000: +- fprintf(f, "\n match dport %u", +- ntohl(key->val) >> 16); ++ print_uint(PRINT_ANY, "dport", "match dport %u", ++ ntohl(key->val) >> 16); + return; + case 0xffffffff: +- fprintf(f, "\n match sport %u, match dport %u", +- ntohl(key->val) & 0xffff, +- ntohl(key->val) >> 16); ++ print_nl(); ++ print_uint(PRINT_ANY, "sport", " match sport %u, ", ++ ntohl(key->val) & 0xffff); ++ print_uint(PRINT_ANY, "dport", "match dport %u", ++ ntohl(key->val) >> 16); + + return; + } + /* XXX: Default print_raw */ + } ++ close_json_object(); + } + + static void print_raw(FILE *f, const struct tc_u32_key *key) + { +- fprintf(f, "\n match %08x/%08x at %s%d", +- (unsigned int)ntohl(key->val), +- (unsigned int)ntohl(key->mask), +- key->offmask ? "nexthdr+" : "", +- key->off); ++ open_json_object("match"); ++ print_nl(); ++ print_hex(PRINT_ANY, "value", " match %08x", (unsigned int)ntohl(key->val)); ++ print_hex(PRINT_ANY, "mask", "/%08x ", (unsigned int)ntohl(key->mask)); ++ print_string(PRINT_ANY, "offmask", "at %s", key->offmask ? "nexthdr+" : ""); ++ print_int(PRINT_ANY, "off", "%d", key->off); ++ close_json_object(); + } + + static const struct { +-- +2.34.1 + diff --git a/SPECS/iproute.spec b/SPECS/iproute.spec index c309cd8..51002b0 100644 --- a/SPECS/iproute.spec +++ b/SPECS/iproute.spec @@ -1,8 +1,10 @@ Summary: Advanced IP routing and network device configuration tools Name: iproute Version: 5.15.0 -Release: 2%{?dist}%{?buildid} +Release: 3%{?dist}%{?buildid} +%if 0%{?rhel} Group: Applications/System +%endif URL: https://kernel.org/pub/linux/utils/net/%{name}2/ Source0: https://kernel.org/pub/linux/utils/net/%{name}2/%{name}2-%{version}.tar.xz Source1: rt_dsfield.deprecated @@ -17,6 +19,8 @@ Patch7: 0008-vdpa-align-uapi-headers.patch Patch8: 0009-vdpa-Enable-user-to-query-vdpa-device-config-layout.patch Patch9: 0010-vdpa-Enable-user-to-set-mac-address-of-vdpa-device.patch Patch10: 0011-vdpa-Enable-user-to-set-mtu-of-the-vdpa-device.patch +Patch11: 0012-tc-u32-add-support-for-json-output.patch +Patch12: 0013-tc-u32-add-json-support-in-print_raw-print_ipv4-prin.patch License: GPLv2+ and Public Domain BuildRequires: bison @@ -135,6 +139,10 @@ cat %{SOURCE1} >>%{buildroot}%{_sysconfdir}/iproute2/rt_dsfield %{_includedir}/iproute2/bpf_elf.h %changelog +* Mon Feb 07 2022 Andrea Claudi - 5.15.0-3.el8 +- tc: u32: add json support in `print_raw`, `print_ipv4`, `print_ipv6` (Andrea Claudi) [1989591] +- tc: u32: add support for json output (Andrea Claudi) [1989591] + * Wed Jan 26 2022 Andrea Claudi - 5.15.0-2.el8 - vdpa: Enable user to set mtu of the vdpa device (Andrea Claudi) [2036880] - vdpa: Enable user to set mac address of vdpa device (Andrea Claudi) [2036880]