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_NAME:=iproute2
PKG_VERSION:=4.17.0 PKG_VERSION:=4.17.0
PKG_RELEASE:=1 PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2 PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2

View File

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