iproute2: tc: backport canonical cake support

iproute2's tc was updated to support the recently upstreamed cake qdisc.
Backport this canonical support from upstream into iproute2 v4.17

There is no kernel kmod/userspace tc ABI change in this release from the
previous package bump, so everyone can breath a sigh of relief.

This is largely a code style change, the exception to prove the rule:
option 'autorate_ingress' has been changed to 'autorate-ingress' to fit
in with upstream option naming expectations.

No openwrt package (e.g. sqm-scripts) has knowledge of
'autorate_ingress' thus only users who made their own scripts or used
it within the 'dangerous configuration' options of sqm-scripts will be
affected.

Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
This commit is contained in:
Kevin Darbyshire-Bryant 2018-07-20 12:47:35 +01:00
parent 7c306ae640
commit 03fce62c09
2 changed files with 155 additions and 151 deletions

View File

@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=iproute2
PKG_VERSION:=4.17.0
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2

View File

@ -122,7 +122,7 @@
--- /dev/null
+++ b/man/man8/tc-cake.8
@@ -0,0 +1,632 @@
+.TH CAKE 8 "23 November 2017" "iproute2" "Linux"
+.TH CAKE 8 "19 July 2018" "iproute2" "Linux"
+.SH NAME
+CAKE \- Common Applications Kept Enhanced (CAKE)
+.SH SYNOPSIS
@ -133,7 +133,7 @@
+RATE |
+.BR unlimited*
+|
+.BR autorate_ingress
+.BR autorate-ingress
+]
+.br
+[
@ -273,7 +273,7 @@
+.BR tc(8)
+or examples below for details of the RATE value.
+.PP
+.B autorate_ingress
+.B autorate-ingress
+.br
+ Automatic capacity estimation based on traffic arriving at this qdisc.
+This is most likely to be useful with cellular links, which tend to change
@ -522,7 +522,7 @@
+.br
+ So named because Jupiter is about 1 light-hour from Earth. Use this to
+(almost) completely disable AQM actions. Equivalent to
+.B rtt 1000s.
+.B rtt 3600s.
+
+.SH FLOW ISOLATION PARAMETERS
+With flow isolation enabled, CAKE places packets from different flows into
@ -677,14 +677,14 @@
+.br
+# tc -s qdisc show dev eth0
+.br
+qdisc cake 1: dev eth0 root refcnt 2 bandwidth 100Mbit diffserv3 triple-isolate rtt 100.0ms noatm overhead 38 mpu 84
+ Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
+qdisc cake 1: root refcnt 2 bandwidth 100Mbit diffserv3 triple-isolate rtt 100.0ms noatm overhead 38 mpu 84
+ Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
+ backlog 0b 0p requeues 0
+ memory used: 0b of 5000000b
+ capacity estimate: 100Mbit
+ min/max network layer size: 65535 / 0
+ min/max overhead-adjusted size: 65535 / 0
+ average network hdr offset: 0
+ average network hdr offset: 0
+
+ Bulk Best Effort Voice
+ thresh 6250Kbit 100Mbit 25Mbit
@ -711,14 +711,14 @@
+.br
+# tc -s qdisc show dev eth0
+
+qdisc cake 1: root refcnt 2 bandwidth 100Mbit diffserv3 triple-isolate rtt 100.0ms noatm overhead 38 mpu 84
+ Sent 44709231 bytes 31931 pkt (dropped 45, overlimits 93782 requeues 0)
+qdisc cake 1: root refcnt 2 bandwidth 100Mbit diffserv3 triple-isolate rtt 100.0ms noatm overhead 38 mpu 84
+ Sent 44709231 bytes 31931 pkt (dropped 45, overlimits 93782 requeues 0)
+ backlog 33308b 22p requeues 0
+ memory used: 292352b of 5000000b
+ capacity estimate: 100Mbit
+ min/max network layer size: 28 / 1500
+ min/max overhead-adjusted size: 84 / 1538
+ average network hdr offset: 14
+ average network hdr offset: 14
+
+ Bulk Best Effort Voice
+ thresh 6250Kbit 100Mbit 25Mbit
@ -745,7 +745,7 @@
+.BR tc (8),
+.BR tc-codel (8),
+.BR tc-fq_codel (8),
+.BR tc-red (8)
+.BR tc-htb (8)
+
+.SH AUTHORS
+Cake's principal author is Jonathan Morton, with contributions from
@ -754,20 +754,31 @@
+
+This manual page was written by Loganaden Velvindron. Please report corrections
+to the Linux Networking mailing list <netdev@vger.kernel.org>.
--- a/man/man8/tc.8
+++ b/man/man8/tc.8
@@ -795,6 +795,7 @@ was written by Alexey N. Kuznetsov and a
.BR tc-basic (8),
.BR tc-bfifo (8),
.BR tc-bpf (8),
+.BR tc-cake (8),
.BR tc-cbq (8),
.BR tc-cgroup (8),
.BR tc-choke (8),
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -64,6 +64,7 @@ TCMODULES += em_meta.o
TCMODULES += q_mqprio.o
TCMODULES += q_codel.o
@@ -66,6 +66,7 @@ TCMODULES += q_codel.o
TCMODULES += q_fq_codel.o
+TCMODULES += q_cake.o
TCMODULES += q_fq.o
TCMODULES += q_pie.o
+TCMODULES += q_cake.o
TCMODULES += q_hhf.o
TCMODULES += q_clsact.o
TCMODULES += e_bpf.o
--- /dev/null
+++ b/tc/q_cake.c
@@ -0,0 +1,796 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
@@ -0,0 +1,790 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+/*
+ * Common Applications Kept Enhanced -- CAKE
+ *
@ -785,6 +796,7 @@
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <inttypes.h>
+
+#include "utils.h"
+#include "tc_util.h"
@ -806,6 +818,24 @@
+ {"interplanetary", 50000000, 1000000000},
+};
+
+static const char * diffserv_names[CAKE_DIFFSERV_MAX] = {
+ [CAKE_DIFFSERV_DIFFSERV3] = "diffserv3",
+ [CAKE_DIFFSERV_DIFFSERV4] = "diffserv4",
+ [CAKE_DIFFSERV_DIFFSERV8] = "diffserv8",
+ [CAKE_DIFFSERV_BESTEFFORT] = "besteffort",
+ [CAKE_DIFFSERV_PRECEDENCE] = "precedence",
+};
+
+static const char * flowmode_names[CAKE_FLOW_MAX] = {
+ [CAKE_FLOW_NONE] = "flowblind",
+ [CAKE_FLOW_SRC_IP] = "srchost",
+ [CAKE_FLOW_DST_IP] = "dsthost",
+ [CAKE_FLOW_HOSTS] = "hosts",
+ [CAKE_FLOW_FLOWS] = "flows",
+ [CAKE_FLOW_DUAL_SRC] = "dual-srchost",
+ [CAKE_FLOW_DUAL_DST] = "dual-dsthost",
+ [CAKE_FLOW_TRIPLE] = "triple-isolate",
+};
+
+static struct cake_preset *find_preset(char *argv)
+{
@ -820,7 +850,7 @@
+static void explain(void)
+{
+ fprintf(stderr,
+"Usage: ... cake [ bandwidth RATE | unlimited* | autorate_ingress ]\n"
+"Usage: ... cake [ bandwidth RATE | unlimited* | autorate-ingress ]\n"
+" [ rtt TIME | datacentre | lan | metro | regional |\n"
+" internet* | oceanic | satellite | interplanetary ]\n"
+" [ besteffort | diffserv8 | diffserv4 | diffserv3* ]\n"
@ -838,25 +868,25 @@
+static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
+ struct nlmsghdr *n, const char *dev)
+{
+ int unlimited = 0;
+ __u64 bandwidth = 0;
+ unsigned interval = 0;
+ unsigned target = 0;
+ unsigned diffserv = 0;
+ unsigned memlimit = 0;
+ int overhead = 0;
+ bool overhead_set = false;
+ struct cake_preset *preset, *preset_set = NULL;
+ bool overhead_override = false;
+ int mpu = 0;
+ int flowmode = -1;
+ int nat = -1;
+ int atm = -1;
+ int autorate = -1;
+ int wash = -1;
+ int ingress = -1;
+ bool overhead_set = false;
+ unsigned int interval = 0;
+ unsigned int diffserv = 0;
+ unsigned int memlimit = 0;
+ unsigned int target = 0;
+ __u64 bandwidth = 0;
+ int ack_filter = -1;
+ struct rtattr *tail;
+ struct cake_preset *preset, *preset_set = NULL;
+ int unlimited = 0;
+ int flowmode = -1;
+ int autorate = -1;
+ int ingress = -1;
+ int overhead = 0;
+ int wash = -1;
+ int nat = -1;
+ int atm = -1;
+ int mpu = 0;
+
+ while (argc > 0) {
+ if (strcmp(*argv, "bandwidth") == 0) {
@ -871,9 +901,8 @@
+ bandwidth = 0;
+ unlimited = 1;
+ autorate = 0;
+ } else if (strcmp(*argv, "autorate_ingress") == 0) {
+ } else if (strcmp(*argv, "autorate-ingress") == 0) {
+ autorate = 1;
+
+ } else if (strcmp(*argv, "rtt") == 0) {
+ NEXT_ARG();
+ if (get_time(&interval, *argv)) {
@ -881,7 +910,7 @@
+ return -1;
+ }
+ target = interval / 20;
+ if(!target)
+ if (!target)
+ target = 1;
+ } else if ((preset = find_preset(*argv))) {
+ if (preset_set)
@ -889,7 +918,6 @@
+ preset_set = preset;
+ target = preset->target;
+ interval = preset->interval;
+
+ } else if (strcmp(*argv, "besteffort") == 0) {
+ diffserv = CAKE_DIFFSERV_BESTEFFORT;
+ } else if (strcmp(*argv, "precedence") == 0) {
@ -902,12 +930,10 @@
+ diffserv = CAKE_DIFFSERV_DIFFSERV4;
+ } else if (strcmp(*argv, "diffserv3") == 0) {
+ diffserv = CAKE_DIFFSERV_DIFFSERV3;
+
+ } else if (strcmp(*argv, "nowash") == 0) {
+ wash = 0;
+ } else if (strcmp(*argv, "wash") == 0) {
+ wash = 1;
+
+ } else if (strcmp(*argv, "flowblind") == 0) {
+ flowmode = CAKE_FLOW_NONE;
+ } else if (strcmp(*argv, "srchost") == 0) {
@ -924,19 +950,16 @@
+ flowmode = CAKE_FLOW_DUAL_DST;
+ } else if (strcmp(*argv, "triple-isolate") == 0) {
+ flowmode = CAKE_FLOW_TRIPLE;
+
+ } else if (strcmp(*argv, "nat") == 0) {
+ nat = 1;
+ } else if (strcmp(*argv, "nonat") == 0) {
+ nat = 0;
+
+ } else if (strcmp(*argv, "ptm") == 0) {
+ atm = CAKE_ATM_PTM;
+ } else if (strcmp(*argv, "atm") == 0) {
+ atm = CAKE_ATM_ATM;
+ } else if (strcmp(*argv, "noatm") == 0) {
+ atm = CAKE_ATM_NONE;
+
+ } else if (strcmp(*argv, "raw") == 0) {
+ atm = CAKE_ATM_NONE;
+ overhead = 0;
@ -1006,7 +1029,6 @@
+ atm = CAKE_ATM_PTM;
+ overhead += 22;
+ overhead_set = true;
+
+ } else if (strcmp(*argv, "via-ethernet") == 0) {
+ /*
+ * We used to use this flag to manually compensate for
@ -1020,10 +1042,10 @@
+ * stats output when the automatic compensation is
+ * active.
+ */
+
+ } else if (strcmp(*argv, "ethernet") == 0) {
+ /* ethernet pre-amble & interframe gap & FCS
+ * you may need to add vlan tag */
+ * you may need to add vlan tag
+ */
+ overhead += 38;
+ overhead_set = true;
+ mpu = 84;
@ -1043,45 +1065,46 @@
+ overhead += 18;
+ overhead_set = true;
+ mpu = 64;
+
+ } else if (strcmp(*argv, "overhead") == 0) {
+ char* p = NULL;
+ char *p = NULL;
+
+ NEXT_ARG();
+ overhead = strtol(*argv, &p, 10);
+ if(!p || *p || !*argv || overhead < -64 || overhead > 256) {
+ fprintf(stderr, "Illegal \"overhead\", valid range is -64 to 256\\n");
+ if (!p || *p || !*argv ||
+ overhead < -64 || overhead > 256) {
+ fprintf(stderr,
+ "Illegal \"overhead\", valid range is -64 to 256\\n");
+ return -1;
+ }
+ overhead_set = true;
+
+ } else if (strcmp(*argv, "mpu") == 0) {
+ char* p = NULL;
+ char *p = NULL;
+
+ NEXT_ARG();
+ mpu = strtol(*argv, &p, 10);
+ if(!p || *p || !*argv || mpu < 0 || mpu > 256) {
+ fprintf(stderr, "Illegal \"mpu\", valid range is 0 to 256\\n");
+ if (!p || *p || !*argv || mpu < 0 || mpu > 256) {
+ fprintf(stderr,
+ "Illegal \"mpu\", valid range is 0 to 256\\n");
+ return -1;
+ }
+
+ } else if (strcmp(*argv, "ingress") == 0) {
+ ingress = 1;
+ } else if (strcmp(*argv, "egress") == 0) {
+ ingress = 0;
+
+ } else if (strcmp(*argv, "no-ack-filter") == 0) {
+ ack_filter = CAKE_ACK_NONE;
+ } else if (strcmp(*argv, "ack-filter") == 0) {
+ ack_filter = CAKE_ACK_FILTER;
+ } else if (strcmp(*argv, "ack-filter-aggressive") == 0) {
+ ack_filter = CAKE_ACK_AGGRESSIVE;
+
+ } else if (strcmp(*argv, "memlimit") == 0) {
+ NEXT_ARG();
+ if(get_size(&memlimit, *argv)) {
+ fprintf(stderr, "Illegal value for \"memlimit\": \"%s\"\n", *argv);
+ if (get_size(&memlimit, *argv)) {
+ fprintf(stderr,
+ "Illegal value for \"memlimit\": \"%s\"\n", *argv);
+ return -1;
+ }
+
+ } else if (strcmp(*argv, "help") == 0) {
+ explain();
+ return -1;
@ -1096,17 +1119,22 @@
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
+ if (bandwidth || unlimited)
+ addattr_l(n, 1024, TCA_CAKE_BASE_RATE64, &bandwidth, sizeof(bandwidth));
+ addattr_l(n, 1024, TCA_CAKE_BASE_RATE64, &bandwidth,
+ sizeof(bandwidth));
+ if (diffserv)
+ addattr_l(n, 1024, TCA_CAKE_DIFFSERV_MODE, &diffserv, sizeof(diffserv));
+ addattr_l(n, 1024, TCA_CAKE_DIFFSERV_MODE, &diffserv,
+ sizeof(diffserv));
+ if (atm != -1)
+ addattr_l(n, 1024, TCA_CAKE_ATM, &atm, sizeof(atm));
+ if (flowmode != -1)
+ addattr_l(n, 1024, TCA_CAKE_FLOW_MODE, &flowmode, sizeof(flowmode));
+ addattr_l(n, 1024, TCA_CAKE_FLOW_MODE, &flowmode,
+ sizeof(flowmode));
+ if (overhead_set)
+ addattr_l(n, 1024, TCA_CAKE_OVERHEAD, &overhead, sizeof(overhead));
+ addattr_l(n, 1024, TCA_CAKE_OVERHEAD, &overhead,
+ sizeof(overhead));
+ if (overhead_override) {
+ unsigned zero = 0;
+ unsigned int zero = 0;
+
+ addattr_l(n, 1024, TCA_CAKE_RAW, &zero, sizeof(zero));
+ }
+ if (mpu > 0)
@ -1116,9 +1144,11 @@
+ if (target)
+ addattr_l(n, 1024, TCA_CAKE_TARGET, &target, sizeof(target));
+ if (autorate != -1)
+ addattr_l(n, 1024, TCA_CAKE_AUTORATE, &autorate, sizeof(autorate));
+ addattr_l(n, 1024, TCA_CAKE_AUTORATE, &autorate,
+ sizeof(autorate));
+ if (memlimit)
+ addattr_l(n, 1024, TCA_CAKE_MEMORY, &memlimit, sizeof(memlimit));
+ addattr_l(n, 1024, TCA_CAKE_MEMORY, &memlimit,
+ sizeof(memlimit));
+ if (nat != -1)
+ addattr_l(n, 1024, TCA_CAKE_NAT, &nat, sizeof(nat));
+ if (wash != -1)
@ -1126,31 +1156,41 @@
+ if (ingress != -1)
+ addattr_l(n, 1024, TCA_CAKE_INGRESS, &ingress, sizeof(ingress));
+ if (ack_filter != -1)
+ addattr_l(n, 1024, TCA_CAKE_ACK_FILTER, &ack_filter, sizeof(ack_filter));
+ addattr_l(n, 1024, TCA_CAKE_ACK_FILTER, &ack_filter,
+ sizeof(ack_filter));
+
+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ return 0;
+}
+
+static void cake_print_mode(unsigned int value, unsigned int max,
+ const char *key, const char **table)
+{
+ if (value < max && table[value]) {
+ print_string(PRINT_ANY, key, "%s ", table[value]);
+ } else {
+ print_string(PRINT_JSON, key, NULL, "unknown");
+ print_string(PRINT_FP, NULL, "(?%s?)", key);
+ }
+}
+
+static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
+{
+ struct rtattr *tb[TCA_CAKE_MAX + 1];
+ unsigned int interval = 0;
+ unsigned int memlimit = 0;
+ __u64 bandwidth = 0;
+ unsigned diffserv = 0;
+ unsigned flowmode = 0;
+ unsigned interval = 0;
+ unsigned memlimit = 0;
+ int ack_filter = 0;
+ int split_gso = 0;
+ int overhead = 0;
+ int autorate = 0;
+ int ingress = 0;
+ int wash = 0;
+ int raw = 0;
+ int mpu = 0;
+ int atm = 0;
+ int nat = 0;
+ int autorate = 0;
+ int wash = 0;
+ int ingress = 0;
+ int ack_filter = 0;
+ int split_gso = 0;
+
+ SPRINT_BUF(b1);
+ SPRINT_BUF(b2);
+
@ -1162,85 +1202,41 @@
+ if (tb[TCA_CAKE_BASE_RATE64] &&
+ RTA_PAYLOAD(tb[TCA_CAKE_BASE_RATE64]) >= sizeof(bandwidth)) {
+ bandwidth = rta_getattr_u64(tb[TCA_CAKE_BASE_RATE64]);
+ if(bandwidth) {
+ if (bandwidth) {
+ print_uint(PRINT_JSON, "bandwidth", NULL, bandwidth);
+ print_string(PRINT_FP, NULL, "bandwidth %s ", sprint_rate(bandwidth, b1));
+ print_string(PRINT_FP, NULL, "bandwidth %s ",
+ sprint_rate(bandwidth, b1));
+ } else
+ print_string(PRINT_ANY, "bandwidth", "bandwidth %s ", "unlimited");
+ print_string(PRINT_ANY, "bandwidth", "bandwidth %s ",
+ "unlimited");
+ }
+ if (tb[TCA_CAKE_AUTORATE] &&
+ RTA_PAYLOAD(tb[TCA_CAKE_AUTORATE]) >= sizeof(__u32)) {
+ autorate = rta_getattr_u32(tb[TCA_CAKE_AUTORATE]);
+ if(autorate == 1)
+ print_string(PRINT_ANY, "autorate", "autorate_%s ", "ingress");
+ else if(autorate)
+ print_string(PRINT_ANY, "autorate", "(?autorate?) ", "unknown");
+ if (autorate == 1)
+ print_string(PRINT_ANY, "autorate", "%s ",
+ "autorate-ingress");
+ else if (autorate)
+ print_string(PRINT_ANY, "autorate", "(?autorate?) ",
+ "unknown");
+ }
+ if (tb[TCA_CAKE_DIFFSERV_MODE] &&
+ RTA_PAYLOAD(tb[TCA_CAKE_DIFFSERV_MODE]) >= sizeof(__u32)) {
+ diffserv = rta_getattr_u32(tb[TCA_CAKE_DIFFSERV_MODE]);
+ switch(diffserv) {
+ case CAKE_DIFFSERV_DIFFSERV3:
+ print_string(PRINT_ANY, "diffserv", "%s ", "diffserv3");
+ break;
+ case CAKE_DIFFSERV_DIFFSERV4:
+ print_string(PRINT_ANY, "diffserv", "%s ", "diffserv4");
+ break;
+ case CAKE_DIFFSERV_DIFFSERV8:
+ print_string(PRINT_ANY, "diffserv", "%s ", "diffserv8");
+ break;
+ case CAKE_DIFFSERV_BESTEFFORT:
+ print_string(PRINT_ANY, "diffserv", "%s ", "besteffort");
+ break;
+ case CAKE_DIFFSERV_PRECEDENCE:
+ print_string(PRINT_ANY, "diffserv", "%s ", "precedence");
+ break;
+ default:
+ print_string(PRINT_ANY, "diffserv", "(?diffserv?) ", "unknown");
+ break;
+ };
+ cake_print_mode(rta_getattr_u32(tb[TCA_CAKE_DIFFSERV_MODE]),
+ CAKE_DIFFSERV_MAX, "diffserv", diffserv_names);
+ }
+ if (tb[TCA_CAKE_FLOW_MODE] &&
+ RTA_PAYLOAD(tb[TCA_CAKE_FLOW_MODE]) >= sizeof(__u32)) {
+ flowmode = rta_getattr_u32(tb[TCA_CAKE_FLOW_MODE]);
+ switch(flowmode) {
+ case CAKE_FLOW_NONE:
+ print_string(PRINT_ANY, "flowmode", "%s ", "flowblind");
+ break;
+ case CAKE_FLOW_SRC_IP:
+ print_string(PRINT_ANY, "flowmode", "%s ", "srchost");
+ break;
+ case CAKE_FLOW_DST_IP:
+ print_string(PRINT_ANY, "flowmode", "%s ", "dsthost");
+ break;
+ case CAKE_FLOW_HOSTS:
+ print_string(PRINT_ANY, "flowmode", "%s ", "hosts");
+ break;
+ case CAKE_FLOW_FLOWS:
+ print_string(PRINT_ANY, "flowmode", "%s ", "flows");
+ break;
+ case CAKE_FLOW_DUAL_SRC:
+ print_string(PRINT_ANY, "flowmode", "%s ", "dual-srchost");
+ break;
+ case CAKE_FLOW_DUAL_DST:
+ print_string(PRINT_ANY, "flowmode", "%s ", "dual-dsthost");
+ break;
+ case CAKE_FLOW_TRIPLE:
+ print_string(PRINT_ANY, "flowmode", "%s ", "triple-isolate");
+ break;
+ default:
+ print_string(PRINT_ANY, "flowmode", "(?flowmode?) ", "unknown");
+ break;
+ };
+
+ cake_print_mode(rta_getattr_u32(tb[TCA_CAKE_FLOW_MODE]),
+ CAKE_FLOW_MAX, "flowmode", flowmode_names);
+ }
+
+ if (tb[TCA_CAKE_NAT] &&
+ RTA_PAYLOAD(tb[TCA_CAKE_NAT]) >= sizeof(__u32)) {
+ nat = rta_getattr_u32(tb[TCA_CAKE_NAT]);
+ nat = rta_getattr_u32(tb[TCA_CAKE_NAT]);
+ }
+
+ if(nat)
+ if (nat)
+ print_string(PRINT_FP, NULL, "nat ", NULL);
+ print_bool(PRINT_JSON, "nat", NULL, nat);
+
@ -1289,7 +1285,8 @@
+ print_bool(PRINT_JSON, "ingress", NULL, ingress);
+
+ if (ack_filter == CAKE_ACK_AGGRESSIVE)
+ print_string(PRINT_ANY, "ack-filter", "ack-filter-%s ", "aggressive");
+ print_string(PRINT_ANY, "ack-filter", "ack-filter-%s ",
+ "aggressive");
+ else if (ack_filter == CAKE_ACK_FILTER)
+ print_string(PRINT_ANY, "ack-filter", "ack-filter ", "enabled");
+ else
@ -1300,7 +1297,8 @@
+ print_bool(PRINT_JSON, "split_gso", NULL, split_gso);
+
+ if (interval)
+ print_string(PRINT_FP, NULL, "rtt %s ", sprint_time(interval, b2));
+ print_string(PRINT_FP, NULL, "rtt %s ",
+ sprint_time(interval, b2));
+ print_uint(PRINT_JSON, "rtt", NULL, interval);
+
+ if (raw)
@ -1321,7 +1319,8 @@
+
+ if (memlimit) {
+ print_uint(PRINT_JSON, "memlimit", NULL, memlimit);
+ print_string(PRINT_FP, NULL, "memlimit %s", sprint_size(memlimit, b1));
+ print_string(PRINT_FP, NULL, "memlimit %s",
+ sprint_size(memlimit, b1));
+ }
+
+ return 0;
@ -1331,7 +1330,8 @@
+{
+#define PRINT_TSTAT_JSON(type, name, attr) if (tstat[TCA_CAKE_TIN_STATS_ ## attr]) \
+ print_u64(PRINT_JSON, name, NULL, \
+ rta_getattr_ ## type((struct rtattr *)tstat[TCA_CAKE_TIN_STATS_ ## attr]))
+ rta_getattr_ ## type((struct rtattr *) \
+ tstat[TCA_CAKE_TIN_STATS_ ## attr]))
+
+ open_json_object(NULL);
+ PRINT_TSTAT_JSON(u64, "threshold_rate", THRESHOLD_RATE64);
@ -1362,15 +1362,15 @@
+static int cake_print_xstats(struct qdisc_util *qu, FILE *f,
+ struct rtattr *xstats)
+{
+ SPRINT_BUF(b1);
+ struct rtattr *st[TCA_CAKE_STATS_MAX + 1];
+ SPRINT_BUF(b1);
+ int i;
+
+ if (xstats == NULL)
+ return 0;
+
+#define GET_STAT_U32(attr) rta_getattr_u32(st[TCA_CAKE_STATS_ ## attr])
+#define GET_STAT_S32(attr) (*(__s32*)RTA_DATA(st[TCA_CAKE_STATS_ ## attr]))
+#define GET_STAT_S32(attr) (*(__s32 *)RTA_DATA(st[TCA_CAKE_STATS_ ## attr]))
+#define GET_STAT_U64(attr) rta_getattr_u64(st[TCA_CAKE_STATS_ ## attr])
+
+ parse_rtattr_nested(st, TCA_CAKE_STATS_MAX, xstats);
@ -1399,7 +1399,7 @@
+ if (st[TCA_CAKE_STATS_MIN_NETLEN] &&
+ st[TCA_CAKE_STATS_MAX_NETLEN]) {
+ print_uint(PRINT_ANY, "min_network_size",
+ " min/max network layer size: %8u",
+ " min/max network layer size: %12u",
+ GET_STAT_U32(MIN_NETLEN));
+ print_uint(PRINT_ANY, "max_network_size",
+ " /%8u\n", GET_STAT_U32(MAX_NETLEN));
@ -1416,7 +1416,7 @@
+
+ if (st[TCA_CAKE_STATS_AVG_NETOFF])
+ print_uint(PRINT_ANY, "avg_hdr_offset",
+ " average network hdr offset: %8u\n\n",
+ " average network hdr offset: %12u\n\n",
+ GET_STAT_U32(AVG_NETOFF));
+
+ /* class stats */
@ -1431,6 +1431,7 @@
+ print_bool(PRINT_ANY, "dropping", " dropping", true);
+ if (st[TCA_CAKE_STATS_DROP_NEXT_US]) {
+ int drop_next = GET_STAT_S32(DROP_NEXT_US);
+
+ if (drop_next < 0) {
+ print_string(PRINT_FP, NULL, " drop_next -%s",
+ sprint_time(drop_next, b1));
@ -1448,6 +1449,7 @@
+ GET_STAT_U32(P_DROP));
+ if (st[TCA_CAKE_STATS_BLUE_TIMER_US]) {
+ int blue_timer = GET_STAT_S32(BLUE_TIMER_US);
+
+ if (blue_timer < 0) {
+ print_string(PRINT_FP, NULL, " blue_timer -%s",
+ sprint_time(blue_timer, b1));
@ -1465,14 +1467,16 @@
+#undef GET_STAT_U64
+
+ if (st[TCA_CAKE_STATS_TIN_STATS]) {
+ struct rtattr *tins[TC_CAKE_MAX_TINS + 1];
+ struct rtattr *tstat[TC_CAKE_MAX_TINS][TCA_CAKE_TIN_STATS_MAX + 1];
+ struct rtattr *tins[TC_CAKE_MAX_TINS + 1];
+ int num_tins = 0;
+
+ parse_rtattr_nested(tins, TC_CAKE_MAX_TINS, st[TCA_CAKE_STATS_TIN_STATS]);
+ parse_rtattr_nested(tins, TC_CAKE_MAX_TINS,
+ st[TCA_CAKE_STATS_TIN_STATS]);
+
+ for (i = 1; i <= TC_CAKE_MAX_TINS && tins[i]; i++) {
+ parse_rtattr_nested(tstat[i-1], TCA_CAKE_TIN_STATS_MAX, tins[i]);
+ parse_rtattr_nested(tstat[i-1], TCA_CAKE_TIN_STATS_MAX,
+ tins[i]);
+ num_tins++;
+ }
+
@ -1489,7 +1493,7 @@
+ }
+
+
+ switch(num_tins) {
+ switch (num_tins) {
+ case 3:
+ fprintf(f, " Bulk Best Effort Voice\n");
+ break;
@ -1500,7 +1504,7 @@
+
+ default:
+ fprintf(f, " ");
+ for(i=0; i < num_tins; i++)
+ for (i = 0; i < num_tins; i++)
+ fprintf(f, " Tin %u", i);
+ fprintf(f, "\n");
+ };