[openwrt/openwrt] iproute2: import latest cake

LEDE Commits lede-commits at lists.infradead.org
Sun May 6 23:09:35 PDT 2018


blogic pushed a commit to openwrt/openwrt.git, branch master:
https://git.lede-project.org/080fb7a3fbb63e78bb5ae75012f352c5e2a5473d

commit 080fb7a3fbb63e78bb5ae75012f352c5e2a5473d
Author: Kevin Darbyshire-Bryant <ldir at darbyshire-bryant.me.uk>
AuthorDate: Sun May 6 18:12:48 2018 +0000

    iproute2: import latest cake
    
    The sender domain has a DMARC Reject/Quarantine policy which disallows
    sending mailing list messages using the original "From" header.
    
    To mitigate this problem, the original message has been wrapped
    automatically by the mailing list software.
    Bearing fruits of the latest upstreaming efforts on cake.
    
    Changes: diffserv-llt dropped.  The paper describing this DSCP
    allocation has gone stale and doesn't appear used.
    
    The userspace to kernel netlink messages for cake have been reworked in
    a backwards incompatible way, so tc & cake must be bumped together this
    once.
    
    Signed-off-by: Kevin Darbyshire-Bryant <ldir at darbyshire-bryant.me.uk>
---
 package/network/utils/iproute2/Makefile            |   2 +-
 .../iproute2/patches/950-add-cake-to-tc.patch      | 869 ++++++++++-----------
 2 files changed, 425 insertions(+), 446 deletions(-)

diff --git a/package/network/utils/iproute2/Makefile b/package/network/utils/iproute2/Makefile
index f5a9db3..88a4851 100644
--- a/package/network/utils/iproute2/Makefile
+++ b/package/network/utils/iproute2/Makefile
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=iproute2
 PKG_VERSION:=4.16.0
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
 PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2
diff --git a/package/network/utils/iproute2/patches/950-add-cake-to-tc.patch b/package/network/utils/iproute2/patches/950-add-cake-to-tc.patch
index c8f70da..3c2cdaa 100644
--- a/package/network/utils/iproute2/patches/950-add-cake-to-tc.patch
+++ b/package/network/utils/iproute2/patches/950-add-cake-to-tc.patch
@@ -1,6 +1,6 @@
 --- a/include/uapi/linux/pkt_sched.h
 +++ b/include/uapi/linux/pkt_sched.h
-@@ -934,4 +934,75 @@ enum {
+@@ -934,4 +934,110 @@ enum {
  
  #define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
  
@@ -22,66 +22,101 @@
 +	TCA_CAKE_MPU,
 +	TCA_CAKE_INGRESS,
 +	TCA_CAKE_ACK_FILTER,
++	TCA_CAKE_SPLIT_GSO,
 +	__TCA_CAKE_MAX
 +};
 +#define TCA_CAKE_MAX	(__TCA_CAKE_MAX - 1)
 +
-+struct tc_cake_traffic_stats {
-+	__u32 packets;
-+	__u32 link_ms;
-+	__u64 bytes;
++enum {
++	__TCA_CAKE_STATS_INVALID,
++	TCA_CAKE_STATS_CAPACITY_ESTIMATE,
++	TCA_CAKE_STATS_MEMORY_LIMIT,
++	TCA_CAKE_STATS_MEMORY_USED,
++	TCA_CAKE_STATS_AVG_NETOFF,
++	TCA_CAKE_STATS_MIN_NETLEN,
++	TCA_CAKE_STATS_MAX_NETLEN,
++	TCA_CAKE_STATS_MIN_ADJLEN,
++	TCA_CAKE_STATS_MAX_ADJLEN,
++	TCA_CAKE_STATS_TIN_STATS,
++	__TCA_CAKE_STATS_MAX
 +};
++#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1)
 +
++enum {
++	__TCA_CAKE_TIN_STATS_INVALID,
++	TCA_CAKE_TIN_STATS_PAD,
++	TCA_CAKE_TIN_STATS_SENT_PACKETS,
++	TCA_CAKE_TIN_STATS_SENT_BYTES64,
++	TCA_CAKE_TIN_STATS_DROPPED_PACKETS,
++	TCA_CAKE_TIN_STATS_DROPPED_BYTES64,
++	TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS,
++	TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64,
++	TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS,
++	TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64,
++	TCA_CAKE_TIN_STATS_BACKLOG_PACKETS,
++	TCA_CAKE_TIN_STATS_BACKLOG_BYTES64,
++	TCA_CAKE_TIN_STATS_THRESHOLD_RATE,
++	TCA_CAKE_TIN_STATS_TARGET_US,
++	TCA_CAKE_TIN_STATS_INTERVAL_US,
++	TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS,
++	TCA_CAKE_TIN_STATS_WAY_MISSES,
++	TCA_CAKE_TIN_STATS_WAY_COLLISIONS,
++	TCA_CAKE_TIN_STATS_PEAK_DELAY_US,
++	TCA_CAKE_TIN_STATS_AVG_DELAY_US,
++	TCA_CAKE_TIN_STATS_BASE_DELAY_US,
++	TCA_CAKE_TIN_STATS_SPARSE_FLOWS,
++	TCA_CAKE_TIN_STATS_BULK_FLOWS,
++	TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS,
++	TCA_CAKE_TIN_STATS_MAX_SKBLEN,
++	TCA_CAKE_TIN_STATS_FLOW_QUANTUM,
++	__TCA_CAKE_TIN_STATS_MAX
++};
++#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1)
 +#define TC_CAKE_MAX_TINS (8)
-+struct tc_cake_tin_stats {
-+
-+	__u32 threshold_rate;
-+	__u32 target_us;
-+	struct tc_cake_traffic_stats sent;
-+	struct tc_cake_traffic_stats dropped;
-+	struct tc_cake_traffic_stats ecn_marked;
-+	struct tc_cake_traffic_stats backlog;
-+	__u32 interval_us;
-+	__u32 way_indirect_hits;
-+	__u32 way_misses;
-+	__u32 way_collisions;
-+	__u32 peak_delay_us; /* ~= bulk flow delay */
-+	__u32 avge_delay_us;
-+	__u32 base_delay_us; /* ~= sparse flows delay */
-+	__u16 sparse_flows;
-+	__u16 bulk_flows;
-+	__u16 unresponse_flows;
-+	__u16 spare;
-+	__u32 max_skblen;
-+	struct tc_cake_traffic_stats ack_drops;
++
++enum {
++	CAKE_FLOW_NONE = 0,
++	CAKE_FLOW_SRC_IP,
++	CAKE_FLOW_DST_IP,
++	CAKE_FLOW_HOSTS,    /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_DST_IP */
++	CAKE_FLOW_FLOWS,
++	CAKE_FLOW_DUAL_SRC, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_FLOWS */
++	CAKE_FLOW_DUAL_DST, /* = CAKE_FLOW_DST_IP | CAKE_FLOW_FLOWS */
++	CAKE_FLOW_TRIPLE,   /* = CAKE_FLOW_HOSTS  | CAKE_FLOW_FLOWS */
++	CAKE_FLOW_MAX,
 +};
 +
-+struct tc_cake_xstats {
-+	__u16 version;
-+	__u16 tin_stats_size; /* == sizeof(struct tc_cake_tin_stats) */
-+	__u32 capacity_estimate;
-+	__u32 memory_limit;
-+	__u32 memory_used;
-+	__u8  tin_cnt;
-+	__u8  avg_trnoff;
-+	__u16 max_trnlen;
-+	__u16 max_adjlen;
-+	__u16 min_trnlen;
-+	__u16 min_adjlen;
-+
-+	__u16 spare1;
-+	__u32 spare2;
-+
-+	struct tc_cake_tin_stats tin_stats[0]; /* keep last */
++enum {
++	CAKE_DIFFSERV_DIFFSERV3 = 0,
++	CAKE_DIFFSERV_DIFFSERV4,
++	CAKE_DIFFSERV_DIFFSERV8,
++	CAKE_DIFFSERV_BESTEFFORT,
++	CAKE_DIFFSERV_PRECEDENCE,
++	CAKE_DIFFSERV_MAX
++};
++
++enum {
++	CAKE_ACK_NONE = 0,
++	CAKE_ACK_FILTER,
++	CAKE_ACK_AGGRESSIVE,
++	CAKE_ACK_MAX
 +};
 +
++enum {
++	CAKE_ATM_NONE = 0,
++	CAKE_ATM_ATM,
++	CAKE_ATM_PTM,
++	CAKE_ATM_MAX
++};
++
++
  #endif
 --- /dev/null
 +++ b/man/man8/tc-cake.8
-@@ -0,0 +1,678 @@
+@@ -0,0 +1,632 @@
 +.TH CAKE 8 "23 November 2017" "iproute2" "Linux"
 +.SH NAME
-+CAKE \- COMMON Applications Kept Enhanced (CAKE)
++CAKE \- Common Applications Kept Enhanced (CAKE)
 +.SH SYNOPSIS
 +.B tc qdisc ... cake
 +.br
@@ -120,8 +155,6 @@
 +|
 +.BR diffserv4
 +|
-+.BR diffserv-llt
-+|
 +.BR diffserv3*
 +]
 +.br
@@ -578,20 +611,6 @@
 +	Enables legacy interpretation of TOS "Precedence" field.  Use of this
 +preset on the modern Internet is firmly discouraged.
 +.PP
-+.B diffserv-llt
-+.br
-+	Provides a "Latency-Loss Tradeoff" implementation with five tins:
-+.br
-+		Low Loss (TOS1, TOS2), 100% threshold, increased Codel target.
-+.br
-+		Best Effort (general), 100% threshold, normal Codel target & interval.
-+.br
-+		Low Latency (TOS4, TOS5, VA, EF), 100% threshold, reduced Codel interval.
-+.br
-+		Bulk (CS1), 6.25% threshold, normal Codel target & interval.
-+.br
-+		Net Control (CS6, CS7), 6.25% threshold, increased Codel target & interval.
-+.PP
 +.B diffserv4
 +.br
 +	Provides a general-purpose Diffserv implementation with four tins:
@@ -646,103 +665,73 @@
 +.SH EXAMPLES
 +# tc qdisc delete root dev eth0
 +.br
-+# tc qdisc add root dev eth0 cake bandwidth 9500Kbit pppoe-ptm ether-vlan
++# tc qdisc add root dev eth0 cake bandwidth 100Mbit ethernet
 +.br
 +# tc -s qdisc show dev eth0
 +.br
-+qdisc cake 8007: root refcnt 6 bandwidth 9500Kbit diffserv3 triple-isolate rtt 100.0ms ptm overhead 34 via-ethernet total_overhead 34 hard_header_len 14
-+ Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
++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) 
 + backlog 0b 0p requeues 0
-+ memory used: 0b of 4Mb
-+ capacity estimate: 9500Kbit
-+.br
-+                 Bulk   Best Effort      Voice
-+.br
-+  thresh     593744bit    9500Kbit    2375Kbit
-+.br
-+  target        30.6ms       5.0ms       7.6ms
-+.br
-+  interval     125.6ms     100.0ms     102.6ms
-+.br
-+  pk_delay         0us         0us         0us
-+.br
-+  av_delay         0us         0us         0us
-+.br
-+  sp_delay         0us         0us         0us
-+.br
-+  pkts               0           0           0
-+.br
-+  bytes              0           0           0
-+.br
-+  way_inds           0           0           0
-+.br
-+  way_miss           0           0           0
-+.br
-+  way_cols           0           0           0
-+.br
-+  drops              0           0           0
-+.br
-+  marks              0           0           0
-+.br
-+  ack_drop           0           0           0
-+.br
-+  sp_flows           0           0           0
-+.br
-+  bk_flows           0           0           0
-+.br
-+  un_flows           0           0           0
-+.br
-+  max_len            0           0           0
-+.br
++ 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
++
++                   Bulk  Best Effort        Voice
++  thresh       6250Kbit      100Mbit       25Mbit
++  target          5.0ms        5.0ms        5.0ms
++  interval      100.0ms      100.0ms      100.0ms
++  pk_delay          0us          0us          0us
++  av_delay          0us          0us          0us
++  sp_delay          0us          0us          0us
++  pkts                0            0            0
++  bytes               0            0            0
++  way_inds            0            0            0
++  way_miss            0            0            0
++  way_cols            0            0            0
++  drops               0            0            0
++  marks               0            0            0
++  ack_drop            0            0            0
++  sp_flows            0            0            0
++  bk_flows            0            0            0
++  un_flows            0            0            0
++  max_len             0            0            0
++  quantum           300         1514          762
 +
 +After some use:
 +.br
 +# tc -s qdisc show dev eth0
 +
-+qdisc cake 8007: root refcnt 6 bandwidth 9500Kbit diffserv3 triple-isolate rtt 100.0ms ptm overhead 34 via-ethernet total_overhead 34 hard_header_len 14
-+ Sent 110769306 bytes 313857 pkt (dropped 18, overlimits 741791 requeues 0)
-+ backlog 0b 0p requeues 0
-+ memory used: 110488b of 4Mb
-+ capacity estimate: 9500Kbit
-+.br
-+                 Bulk   Best Effort      Voice
-+.br
-+  thresh     593744bit    9500Kbit    2375Kbit
-+.br
-+  target        30.6ms       5.0ms       7.6ms
-+.br
-+  interval     125.6ms     100.0ms     102.6ms
-+.br
-+  pk_delay      16.0ms       545us        15us
-+.br
-+  av_delay       2.4ms       161us         3us
-+.br
-+  sp_delay        59us         1us         1us
-+.br
-+  pkts           32866      195815       85194
-+.br
-+  bytes        8132614    69517496    33122156
-+.br
-+  way_inds           0       29208           0
-+.br
-+  way_miss           7         173          17
-+.br
-+  way_cols           0           0           0
-+.br
-+  drops             10           7           1
-+.br
-+  marks            217         692         300
-+.br
-+  ack_drop           0           0           0
-+.br
-+  sp_flows           0           0           0
-+.br
-+  bk_flows           0           0           1
-+.br
-+  un_flows           0           0           0
-+.br
-+  max_len         3028        3012        3028
-+.br
++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
++
++                   Bulk  Best Effort        Voice
++  thresh       6250Kbit      100Mbit       25Mbit
++  target          5.0ms        5.0ms        5.0ms
++  interval      100.0ms      100.0ms      100.0ms
++  pk_delay        8.7ms        6.9ms        5.0ms
++  av_delay        4.9ms        5.3ms        3.8ms
++  sp_delay        727us        1.4ms        511us
++  pkts             2590        21271         8137
++  bytes         3081804     30302659     11426206
++  way_inds            0           46            0
++  way_miss            3           17            4
++  way_cols            0            0            0
++  drops              20           15           10
++  marks               0            0            0
++  ack_drop            0            0            0
++  sp_flows            2            4            1
++  bk_flows            1            2            1
++  un_flows            0            0            0
++  max_len          1514         1514         1514
++  quantum           300         1514          762
 +
 +.SH SEE ALSO
 +.BR tc (8),
@@ -769,44 +758,13 @@
  TCMODULES += q_hhf.o
 --- /dev/null
 +++ b/tc/q_cake.c
-@@ -0,0 +1,770 @@
+@@ -0,0 +1,749 @@
 +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
 +/*
 + * Common Applications Kept Enhanced  --  CAKE
 + *
 + *  Copyright (C) 2014-2018 Jonathan Morton <chromatix99 at gmail.com>
 + *  Copyright (C) 2017-2018 Toke Høiland-Jørgensen <toke at toke.dk>
-+ *
-+ * Redistribution and use in source and binary forms, with or without
-+ * modification, are permitted provided that the following conditions
-+ * are met:
-+ * 1. Redistributions of source code must retain the above copyright
-+ *    notice, this list of conditions, and the following disclaimer,
-+ *    without modification.
-+ * 2. Redistributions in binary form must reproduce the above copyright
-+ *    notice, this list of conditions and the following disclaimer in the
-+ *    documentation and/or other materials provided with the distribution.
-+ * 3. The names of the authors may not be used to endorse or promote products
-+ *    derived from this software without specific prior written permission.
-+ *
-+ * Alternatively, provided that this notice is retained in full, this
-+ * software may be distributed under the terms of the GNU General
-+ * Public License ("GPL") version 2, in which case the provisions of the
-+ * GPL apply INSTEAD OF those given above.
-+ *
-+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-+ * DAMAGE.
-+ *
 + */
 +
 +#include <stddef.h>
@@ -823,14 +781,41 @@
 +#include "utils.h"
 +#include "tc_util.h"
 +
++struct cake_preset {
++	char *name;
++	unsigned int target;
++	unsigned int interval;
++};
++
++static struct cake_preset presets[] = {
++	{"datacentre",		5,		100},
++	{"lan",			50,		1000},
++	{"metro",		500,		10000},
++	{"regional",		1500,		30000},
++	{"internet",		5000,		100000},
++	{"oceanic",		15000,		300000},
++	{"satellite",		50000,		1000000},
++	{"interplanetary",	50000000,	1000000000},
++};
++
++
++static struct cake_preset *find_preset(char *argv)
++{
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(presets); i++)
++		if (!strcmp(argv, presets[i].name))
++			return &presets[i];
++	return NULL;
++}
++
 +static void explain(void)
 +{
 +	fprintf(stderr,
 +"Usage: ... cake [ bandwidth RATE | unlimited* | autorate_ingress ]\n"
 +"                [ rtt TIME | datacentre | lan | metro | regional |\n"
 +"                  internet* | oceanic | satellite | interplanetary ]\n"
-+"                [ besteffort | diffserv8 | diffserv4 | diffserv-llt |\n"
-+"                  diffserv3* ]\n"
++"                [ besteffort | diffserv8 | diffserv4 | diffserv3* ]\n"
 +"                [ flowblind | srchost | dsthost | hosts | flows |\n"
 +"                  dual-srchost | dual-dsthost | triple-isolate* ]\n"
 +"                [ nat | nonat* ]\n"
@@ -863,6 +848,7 @@
 +	int ingress = -1;
 +	int ack_filter = -1;
 +	struct rtattr *tail;
++	struct cake_preset *preset, *preset_set = NULL;
 +
 +	while (argc > 0) {
 +		if (strcmp(*argv, "bandwidth") == 0) {
@@ -889,45 +875,25 @@
 +			target = interval / 20;
 +			if(!target)
 +				target = 1;
-+		} else if (strcmp(*argv, "datacentre") == 0) {
-+			interval = 100;
-+			target   =   5;
-+		} else if (strcmp(*argv, "lan") == 0) {
-+			interval = 1000;
-+			target   =   50;
-+		} else if (strcmp(*argv, "metro") == 0) {
-+			interval = 10000;
-+			target   =   500;
-+		} else if (strcmp(*argv, "regional") == 0) {
-+			interval = 30000;
-+			target    = 1500;
-+		} else if (strcmp(*argv, "internet") == 0) {
-+			interval = 100000;
-+			target   =   5000;
-+		} else if (strcmp(*argv, "oceanic") == 0) {
-+			interval = 300000;
-+			target   =  15000;
-+		} else if (strcmp(*argv, "satellite") == 0) {
-+			interval = 1000000;
-+			target   =   50000;
-+		} else if (strcmp(*argv, "interplanetary") == 0) {
-+			interval = 1000000000;
-+			target   =   50000000;
++		} else if ((preset = find_preset(*argv))) {
++			if (preset_set)
++				duparg(*argv, preset_set->name);
++			preset_set = preset;
++			target = preset->target;
++			interval = preset->interval;
 +
 +		} else if (strcmp(*argv, "besteffort") == 0) {
-+			diffserv = 1;
++			diffserv = CAKE_DIFFSERV_BESTEFFORT;
 +		} else if (strcmp(*argv, "precedence") == 0) {
-+			diffserv = 2;
++			diffserv = CAKE_DIFFSERV_PRECEDENCE;
 +		} else if (strcmp(*argv, "diffserv8") == 0) {
-+			diffserv = 3;
++			diffserv = CAKE_DIFFSERV_DIFFSERV8;
 +		} else if (strcmp(*argv, "diffserv4") == 0) {
-+			diffserv = 4;
++			diffserv = CAKE_DIFFSERV_DIFFSERV4;
 +		} else if (strcmp(*argv, "diffserv") == 0) {
-+			diffserv = 4;
-+		} else if (strcmp(*argv, "diffserv-llt") == 0) {
-+			diffserv = 5;
++			diffserv = CAKE_DIFFSERV_DIFFSERV4;
 +		} else if (strcmp(*argv, "diffserv3") == 0) {
-+			diffserv = 6;
++			diffserv = CAKE_DIFFSERV_DIFFSERV3;
 +
 +		} else if (strcmp(*argv, "nowash") == 0) {
 +			wash = 0;
@@ -935,21 +901,21 @@
 +			wash = 1;
 +
 +		} else if (strcmp(*argv, "flowblind") == 0) {
-+			flowmode = 0;
++			flowmode = CAKE_FLOW_NONE;
 +		} else if (strcmp(*argv, "srchost") == 0) {
-+			flowmode = 1;
++			flowmode = CAKE_FLOW_SRC_IP;
 +		} else if (strcmp(*argv, "dsthost") == 0) {
-+			flowmode = 2;
++			flowmode = CAKE_FLOW_DST_IP;
 +		} else if (strcmp(*argv, "hosts") == 0) {
-+			flowmode = 3;
++			flowmode = CAKE_FLOW_HOSTS;
 +		} else if (strcmp(*argv, "flows") == 0) {
-+			flowmode = 4;
++			flowmode = CAKE_FLOW_FLOWS;
 +		} else if (strcmp(*argv, "dual-srchost") == 0) {
-+			flowmode = 5;
++			flowmode = CAKE_FLOW_DUAL_SRC;
 +		} else if (strcmp(*argv, "dual-dsthost") == 0) {
-+			flowmode = 6;
++			flowmode = CAKE_FLOW_DUAL_DST;
 +		} else if (strcmp(*argv, "triple-isolate") == 0) {
-+			flowmode = 7;
++			flowmode = CAKE_FLOW_TRIPLE;
 +
 +		} else if (strcmp(*argv, "nat") == 0) {
 +			nat = 1;
@@ -957,14 +923,14 @@
 +			nat = 0;
 +
 +		} else if (strcmp(*argv, "ptm") == 0) {
-+			atm = 2;
++			atm = CAKE_ATM_PTM;
 +		} else if (strcmp(*argv, "atm") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +		} else if (strcmp(*argv, "noatm") == 0) {
-+			atm = 0;
++			atm = CAKE_ATM_NONE;
 +
 +		} else if (strcmp(*argv, "raw") == 0) {
-+			atm = 0;
++			atm = CAKE_ATM_NONE;
 +			overhead = 0;
 +			overhead_set = true;
 +			overhead_override = true;
@@ -974,41 +940,41 @@
 +			 * one whole ATM cell plus ATM framing.
 +			 * A safe choice if the actual overhead is unknown.
 +			 */
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead = 48;
 +			overhead_set = true;
 +
 +		/* Various ADSL framing schemes, all over ATM cells */
 +		} else if (strcmp(*argv, "ipoa-vcmux") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead += 8;
 +			overhead_set = true;
 +		} else if (strcmp(*argv, "ipoa-llcsnap") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead += 16;
 +			overhead_set = true;
 +		} else if (strcmp(*argv, "bridged-vcmux") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead += 24;
 +			overhead_set = true;
 +		} else if (strcmp(*argv, "bridged-llcsnap") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead += 32;
 +			overhead_set = true;
 +		} else if (strcmp(*argv, "pppoa-vcmux") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead += 10;
 +			overhead_set = true;
 +		} else if (strcmp(*argv, "pppoa-llc") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead += 14;
 +			overhead_set = true;
 +		} else if (strcmp(*argv, "pppoe-vcmux") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead += 32;
 +			overhead_set = true;
 +		} else if (strcmp(*argv, "pppoe-llcsnap") == 0) {
-+			atm = 1;
++			atm = CAKE_ATM_ATM;
 +			overhead += 40;
 +			overhead_set = true;
 +
@@ -1020,7 +986,7 @@
 +			 * + 1B Start of Frame (S) + 1B End of Frame (Ck)
 +			 * + 2B TC-CRC (PTM-FCS) = 30B
 +			 */
-+			atm = 2;
++			atm = CAKE_ATM_PTM;
 +			overhead += 30;
 +			overhead_set = true;
 +		} else if (strcmp(*argv, "bridged-ptm") == 0) {
@@ -1029,7 +995,7 @@
 +			 * + 1B Start of Frame (S) + 1B End of Frame (Ck)
 +			 * + 2B TC-CRC (PTM-FCS) = 22B
 +			 */
-+			atm = 2;
++			atm = CAKE_ATM_PTM;
 +			overhead += 22;
 +			overhead_set = true;
 +
@@ -1065,7 +1031,7 @@
 +		 * but not interframe gap or preamble.
 +		 */
 +		} else if (strcmp(*argv, "docsis") == 0) {
-+			atm = 0;
++			atm = CAKE_ATM_NONE;
 +			overhead += 18;
 +			overhead_set = true;
 +			mpu = 64;
@@ -1095,11 +1061,11 @@
 +			ingress = 0;
 +
 +		} else if (strcmp(*argv, "no-ack-filter") == 0) {
-+			ack_filter = 0;
++			ack_filter = CAKE_ACK_NONE;
 +		} else if (strcmp(*argv, "ack-filter") == 0) {
-+			ack_filter = 0x0200;
++			ack_filter = CAKE_ACK_FILTER;
 +		} else if (strcmp(*argv, "ack-filter-aggressive") == 0) {
-+			ack_filter = 0x0600;
++			ack_filter = CAKE_ACK_AGGRESSIVE;
 +
 +		} else if (strcmp(*argv, "memlimit") == 0) {
 +			NEXT_ARG();
@@ -1176,6 +1142,7 @@
 +	int wash = 0;
 +	int ingress = 0;
 +	int ack_filter = 0;
++	int split_gso = 0;
 +	SPRINT_BUF(b1);
 +	SPRINT_BUF(b2);
 +
@@ -1205,23 +1172,20 @@
 +	    RTA_PAYLOAD(tb[TCA_CAKE_DIFFSERV_MODE]) >= sizeof(__u32)) {
 +		diffserv = rta_getattr_u32(tb[TCA_CAKE_DIFFSERV_MODE]);
 +		switch(diffserv) {
-+		case 1:
-+			print_string(PRINT_ANY, "diffserv", "%s ", "besteffort");
++		case CAKE_DIFFSERV_DIFFSERV3:
++			print_string(PRINT_ANY, "diffserv", "%s ", "diffserv3");
 +			break;
-+		case 2:
-+			print_string(PRINT_ANY, "diffserv", "%s ", "precedence");
++		case CAKE_DIFFSERV_DIFFSERV4:
++			print_string(PRINT_ANY, "diffserv", "%s ", "diffserv4");
 +			break;
-+		case 3:
++		case CAKE_DIFFSERV_DIFFSERV8:
 +			print_string(PRINT_ANY, "diffserv", "%s ", "diffserv8");
 +			break;
-+		case 4:
-+			print_string(PRINT_ANY, "diffserv", "%s ", "diffserv4");
-+			break;
-+		case 5:
-+			print_string(PRINT_ANY, "diffserv", "%s ", "diffserv-llt");
++		case CAKE_DIFFSERV_BESTEFFORT:
++			print_string(PRINT_ANY, "diffserv", "%s ", "besteffort");
 +			break;
-+		case 6:
-+			print_string(PRINT_ANY, "diffserv", "%s ", "diffserv3");
++		case CAKE_DIFFSERV_PRECEDENCE:
++			print_string(PRINT_ANY, "diffserv", "%s ", "precedence");
 +			break;
 +		default:
 +			print_string(PRINT_ANY, "diffserv", "(?diffserv?) ", "unknown");
@@ -1231,31 +1195,29 @@
 +	if (tb[TCA_CAKE_FLOW_MODE] &&
 +	    RTA_PAYLOAD(tb[TCA_CAKE_FLOW_MODE]) >= sizeof(__u32)) {
 +		flowmode = rta_getattr_u32(tb[TCA_CAKE_FLOW_MODE]);
-+		nat = !!(flowmode & 64);
-+		flowmode &= ~64;
 +		switch(flowmode) {
-+		case 0:
++		case CAKE_FLOW_NONE:
 +			print_string(PRINT_ANY, "flowmode", "%s ", "flowblind");
 +			break;
-+		case 1:
++		case CAKE_FLOW_SRC_IP:
 +			print_string(PRINT_ANY, "flowmode", "%s ", "srchost");
 +			break;
-+		case 2:
++		case CAKE_FLOW_DST_IP:
 +			print_string(PRINT_ANY, "flowmode", "%s ", "dsthost");
 +			break;
-+		case 3:
++		case CAKE_FLOW_HOSTS:
 +			print_string(PRINT_ANY, "flowmode", "%s ", "hosts");
 +			break;
-+		case 4:
++		case CAKE_FLOW_FLOWS:
 +			print_string(PRINT_ANY, "flowmode", "%s ", "flows");
 +			break;
-+		case 5:
++		case CAKE_FLOW_DUAL_SRC:
 +			print_string(PRINT_ANY, "flowmode", "%s ", "dual-srchost");
 +			break;
-+		case 6:
++		case CAKE_FLOW_DUAL_DST:
 +			print_string(PRINT_ANY, "flowmode", "%s ", "dual-dsthost");
 +			break;
-+		case 7:
++		case CAKE_FLOW_TRIPLE:
 +			print_string(PRINT_ANY, "flowmode", "%s ", "triple-isolate");
 +			break;
 +		default:
@@ -1263,10 +1225,17 @@
 +			break;
 +		};
 +
-+		if(nat)
-+			print_string(PRINT_FP, NULL, "nat ", NULL);
-+		print_bool(PRINT_JSON, "nat", NULL, nat);
 +	}
++
++	if (tb[TCA_CAKE_NAT] &&
++	    RTA_PAYLOAD(tb[TCA_CAKE_NAT]) >= sizeof(__u32)) {
++	    nat = rta_getattr_u32(tb[TCA_CAKE_NAT]);
++	}
++
++	if(nat)
++		print_string(PRINT_FP, NULL, "nat ", NULL);
++	print_bool(PRINT_JSON, "nat", NULL, nat);
++
 +	if (tb[TCA_CAKE_WASH] &&
 +	    RTA_PAYLOAD(tb[TCA_CAKE_WASH]) >= sizeof(__u32)) {
 +		wash = rta_getattr_u32(tb[TCA_CAKE_WASH]);
@@ -1276,8 +1245,8 @@
 +		atm = rta_getattr_u32(tb[TCA_CAKE_ATM]);
 +	}
 +	if (tb[TCA_CAKE_OVERHEAD] &&
-+	    RTA_PAYLOAD(tb[TCA_CAKE_OVERHEAD]) >= sizeof(__u32)) {
-+		overhead = rta_getattr_u32(tb[TCA_CAKE_OVERHEAD]);
++	    RTA_PAYLOAD(tb[TCA_CAKE_OVERHEAD]) >= sizeof(__s32)) {
++		overhead = *(__s32 *) RTA_DATA(tb[TCA_CAKE_OVERHEAD]);
 +	}
 +	if (tb[TCA_CAKE_MPU] &&
 +	    RTA_PAYLOAD(tb[TCA_CAKE_MPU]) >= sizeof(__u32)) {
@@ -1291,6 +1260,10 @@
 +	    RTA_PAYLOAD(tb[TCA_CAKE_ACK_FILTER]) >= sizeof(__u32)) {
 +		ack_filter = rta_getattr_u32(tb[TCA_CAKE_ACK_FILTER]);
 +	}
++	if (tb[TCA_CAKE_SPLIT_GSO] &&
++	    RTA_PAYLOAD(tb[TCA_CAKE_SPLIT_GSO]) >= sizeof(__u32)) {
++		split_gso = rta_getattr_u32(tb[TCA_CAKE_SPLIT_GSO]);
++	}
 +	if (tb[TCA_CAKE_RAW]) {
 +		raw = 1;
 +	}
@@ -1307,13 +1280,17 @@
 +		print_string(PRINT_FP, NULL, "ingress ", NULL);
 +	print_bool(PRINT_JSON, "ingress", NULL, ingress);
 +
-+	if (ack_filter == 0x0600)
++	if (ack_filter == CAKE_ACK_AGGRESSIVE)
 +		print_string(PRINT_ANY, "ack-filter", "ack-filter-%s ", "aggressive");
-+	else if (ack_filter)
++	else if (ack_filter == CAKE_ACK_FILTER)
 +		print_string(PRINT_ANY, "ack-filter", "ack-filter ", "enabled");
 +	else
 +		print_string(PRINT_JSON, "ack-filter", NULL, "disabled");
 +
++	if (split_gso)
++		print_string(PRINT_FP, NULL, "split-gso ", NULL);
++	print_bool(PRINT_JSON, "split_gso", NULL, split_gso);
++
 +	if (interval)
 +		print_string(PRINT_FP, NULL, "rtt %s ", sprint_time(interval, b2));
 +	print_uint(PRINT_JSON, "rtt", NULL, interval);
@@ -1322,9 +1299,9 @@
 +		print_string(PRINT_FP, NULL, "raw ", NULL);
 +	print_bool(PRINT_JSON, "raw", NULL, raw);
 +
-+	if (atm == 1)
++	if (atm == CAKE_ATM_ATM)
 +		print_string(PRINT_ANY, "atm", "%s ", "atm");
-+	else if (atm == 2)
++	else if (atm == CAKE_ATM_PTM)
 +		print_string(PRINT_ANY, "atm", "%s ", "ptm");
 +	else if (!raw)
 +		print_string(PRINT_ANY, "atm", "%s ", "noatm");
@@ -1332,7 +1309,7 @@
 +	print_uint(PRINT_ANY, "overhead", "overhead %d ", overhead);
 +
 +	if (mpu)
-+		print_uint(PRINT_ANY, "mpu", "mpu %d ", mpu);
++		print_uint(PRINT_ANY, "mpu", "mpu %u ", mpu);
 +
 +	if (memlimit) {
 +		print_uint(PRINT_JSON, "memlimit", NULL, memlimit);
@@ -1342,195 +1319,186 @@
 +	return 0;
 +}
 +
-+#define FOR_EACH_TIN(xstats, tst, i)				\
-+	for(tst = xstats->tin_stats, i = 0;			\
-+	i < xstats->tin_cnt;						\
-+	    i++, tst = ((void *) xstats->tin_stats) + xstats->tin_stats_size * i)
-+
-+static void cake_print_json_tin(struct tc_cake_tin_stats *tst)
++static void cake_print_json_tin(struct rtattr **tstat)
 +{
++#define PRINT_TSTAT_JSON(type, name, attr) if (tstat[TCA_CAKE_TIN_STATS_ ## attr]) \
++		print_uint(PRINT_JSON, name, NULL,			\
++			rta_getattr_ ## type((struct rtattr *)tstat[TCA_CAKE_TIN_STATS_ ## attr]))
++
 +	open_json_object(NULL);
-+	print_uint(PRINT_JSON, "threshold_rate", NULL, tst->threshold_rate);
-+	print_uint(PRINT_JSON, "target", NULL, tst->target_us);
-+	print_uint(PRINT_JSON, "interval", NULL, tst->interval_us);
-+	print_uint(PRINT_JSON, "peak_delay", NULL, tst->peak_delay_us);
-+	print_uint(PRINT_JSON, "average_delay", NULL, tst->avge_delay_us);
-+	print_uint(PRINT_JSON, "base_delay", NULL, tst->base_delay_us);
-+	print_uint(PRINT_JSON, "sent_packets", NULL, tst->sent.packets);
-+	print_uint(PRINT_JSON, "sent_bytes", NULL, tst->sent.bytes);
-+	print_uint(PRINT_JSON, "way_indirect_hits", NULL, tst->way_indirect_hits);
-+	print_uint(PRINT_JSON, "way_misses", NULL, tst->way_misses);
-+	print_uint(PRINT_JSON, "way_collisions", NULL, tst->way_collisions);
-+	print_uint(PRINT_JSON, "drops", NULL, tst->dropped.packets);
-+	print_uint(PRINT_JSON, "ecn_mark", NULL, tst->ecn_marked.packets);
-+	print_uint(PRINT_JSON, "ack_drops", NULL, tst->ack_drops.packets);
-+	print_uint(PRINT_JSON, "sparse_flows", NULL, tst->sparse_flows);
-+	print_uint(PRINT_JSON, "bulk_flows", NULL, tst->bulk_flows);
-+	print_uint(PRINT_JSON, "unresponsive_flows", NULL, tst->unresponse_flows);
-+	print_uint(PRINT_JSON, "max_pkt_len", NULL, tst->max_skblen);
++	PRINT_TSTAT_JSON(u32, "threshold_rate", THRESHOLD_RATE);
++	PRINT_TSTAT_JSON(u32, "target_us", TARGET_US);
++	PRINT_TSTAT_JSON(u32, "interval_us", INTERVAL_US);
++	PRINT_TSTAT_JSON(u32, "peak_delay_us", PEAK_DELAY_US);
++	PRINT_TSTAT_JSON(u32, "avg_delay_us", AVG_DELAY_US);
++	PRINT_TSTAT_JSON(u32, "base_delay_us", BASE_DELAY_US);
++	PRINT_TSTAT_JSON(u32, "sent_packets", SENT_PACKETS);
++	PRINT_TSTAT_JSON(u64, "sent_bytes", SENT_BYTES64);
++	PRINT_TSTAT_JSON(u32, "way_indirect_hits", WAY_INDIRECT_HITS);
++	PRINT_TSTAT_JSON(u32, "way_misses", WAY_MISSES);
++	PRINT_TSTAT_JSON(u32, "way_collisions", WAY_COLLISIONS);
++	PRINT_TSTAT_JSON(u32, "drops", DROPPED_PACKETS);
++	PRINT_TSTAT_JSON(u32, "ecn_mark", ECN_MARKED_PACKETS);
++	PRINT_TSTAT_JSON(u32, "ack_drops", ACKS_DROPPED_PACKETS);
++	PRINT_TSTAT_JSON(u32, "sparse_flows", SPARSE_FLOWS);
++	PRINT_TSTAT_JSON(u32, "bulk_flows", BULK_FLOWS);
++	PRINT_TSTAT_JSON(u32, "unresponsive_flows", UNRESPONSIVE_FLOWS);
++	PRINT_TSTAT_JSON(u32, "max_pkt_len", MAX_SKBLEN);
++	PRINT_TSTAT_JSON(u32, "flow_quantum", FLOW_QUANTUM);
 +	close_json_object();
++
++#undef PRINT_TSTAT_JSON
 +}
 +
 +static int cake_print_xstats(struct qdisc_util *qu, FILE *f,
 +			     struct rtattr *xstats)
 +{
-+	struct tc_cake_xstats     *stnc;
-+	struct tc_cake_tin_stats  *tst;
 +	SPRINT_BUF(b1);
++	struct rtattr *st[TCA_CAKE_STATS_MAX + 1];
 +	int i;
 +
 +	if (xstats == NULL)
 +		return 0;
 +
-+	if (RTA_PAYLOAD(xstats) < sizeof(*stnc))
-+		return -1;
-+
-+	stnc = RTA_DATA(xstats);
-+
-+	if (stnc->version < 0x101 ||
-+	    RTA_PAYLOAD(xstats) < (sizeof(struct tc_cake_xstats) +
-+				    stnc->tin_stats_size * stnc->tin_cnt))
-+		return -1;
-+
-+	print_uint(PRINT_JSON, "memory_used", NULL, stnc->memory_used);
-+	print_uint(PRINT_JSON, "memory_limit", NULL, stnc->memory_limit);
-+	print_uint(PRINT_JSON, "capacity_estimate", NULL, stnc->capacity_estimate);
-+
-+	print_string(PRINT_FP, NULL, " memory used: %s",
-+		sprint_size(stnc->memory_used, b1));
-+	print_string(PRINT_FP, NULL, " of %s\n",
-+		sprint_size(stnc->memory_limit, b1));
-+	print_string(PRINT_FP, NULL, " capacity estimate: %s\n",
-+		sprint_rate(stnc->capacity_estimate, b1));
-+
-+	print_uint(PRINT_ANY, "min_transport_size", " min/max transport layer size: %10u",
-+		stnc->min_trnlen);
-+	print_uint(PRINT_ANY, "max_transport_size", " /%8u\n", stnc->max_trnlen);
-+	print_uint(PRINT_ANY, "min_adj_size", " min/max overhead-adjusted size: %8u",
-+		stnc->min_adjlen);
-+	print_uint(PRINT_ANY, "max_adj_size", " /%8u\n", stnc->max_adjlen);
-+	print_uint(PRINT_ANY, "avg_hdr_offset", " average transport hdr offset: %10u\n\n",
-+		stnc->avg_trnoff);
-+
-+	if (is_json_context()) {
-+		open_json_array(PRINT_JSON, "tins");
-+		FOR_EACH_TIN(stnc, tst, i)
-+			cake_print_json_tin(tst);
-+		close_json_array(PRINT_JSON, NULL);
-+		return 0;
++#define GET_STAT_U32(attr) rta_getattr_u32(st[TCA_CAKE_STATS_ ## attr])
++
++	parse_rtattr_nested(st, TCA_CAKE_STATS_MAX, xstats);
++
++	if (st[TCA_CAKE_STATS_MEMORY_USED] &&
++	    st[TCA_CAKE_STATS_MEMORY_LIMIT]) {
++		print_string(PRINT_FP, NULL, " memory used: %s",
++			sprint_size(GET_STAT_U32(MEMORY_USED), b1));
++
++		print_string(PRINT_FP, NULL, " of %s\n",
++			sprint_size(GET_STAT_U32(MEMORY_LIMIT), b1));
++
++		print_uint(PRINT_JSON, "memory_used", NULL,
++			GET_STAT_U32(MEMORY_USED));
++		print_uint(PRINT_JSON, "memory_limit", NULL,
++			GET_STAT_U32(MEMORY_LIMIT));
++	}
++
++	if (st[TCA_CAKE_STATS_CAPACITY_ESTIMATE]) {
++		print_string(PRINT_FP, NULL, " capacity estimate: %s\n",
++			sprint_rate(GET_STAT_U32(CAPACITY_ESTIMATE), b1));
++		print_uint(PRINT_JSON, "capacity_estimate", NULL,
++			GET_STAT_U32(CAPACITY_ESTIMATE));
 +	}
 +
++	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",
++			   GET_STAT_U32(MIN_NETLEN));
++		print_uint(PRINT_ANY, "max_network_size",
++			   " /%8u\n", GET_STAT_U32(MAX_NETLEN));
++	}
++
++	if (st[TCA_CAKE_STATS_MIN_ADJLEN] &&
++	    st[TCA_CAKE_STATS_MAX_ADJLEN]) {
++		print_uint(PRINT_ANY, "min_adj_size",
++			   " min/max overhead-adjusted size: %8u",
++			   GET_STAT_U32(MIN_ADJLEN));
++		print_uint(PRINT_ANY, "max_adj_size",
++			   " /%8u\n", GET_STAT_U32(MAX_ADJLEN));
++	}
++
++	if (st[TCA_CAKE_STATS_AVG_NETOFF])
++		print_uint(PRINT_ANY, "avg_hdr_offset",
++			   " average network hdr offset:     %8u\n\n",
++			   GET_STAT_U32(AVG_NETOFF));
++
++#undef GET_STAT_U32
++
++	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];
++		int num_tins = 0;
++
++		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]);
++			num_tins++;
++		}
++
++		if (!num_tins)
++			return 0;
++
++		if (is_json_context()) {
++			open_json_array(PRINT_JSON, "tins");
++			for (i = 0; i < num_tins; i++)
++				cake_print_json_tin(tstat[i]);
++			close_json_array(PRINT_JSON, NULL);
++
++			return 0;
++		}
++
++
++		switch(num_tins) {
++		case 3:
++			fprintf(f, "                   Bulk  Best Effort        Voice\n");
++			break;
++
++		case 4:
++			fprintf(f, "                   Bulk  Best Effort        Video        Voice\n");
++			break;
 +
-+	switch(stnc->tin_cnt) {
-+	case 3:
-+		fprintf(f, "                   Bulk  Best Effort        Voice\n");
-+		break;
-+
-+	case 4:
-+		fprintf(f, "                   Bulk  Best Effort        Video        Voice\n");
-+		break;
-+
-+	case 5:
-+		fprintf(f, "               Low Loss  Best Effort    Low Delay         Bulk  Net Control\n");
-+		break;
-+
-+	default:
-+		fprintf(f, "          ");
-+		for(i=0; i < stnc->tin_cnt; i++)
-+			fprintf(f, "        Tin %u", i);
-+		fprintf(f, "\n");
-+	};
-+
-+	fprintf(f, "  thresh  ");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12s", sprint_rate(tst->threshold_rate, b1));
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  target  ");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12s", sprint_time(tst->target_us, b1));
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  interval");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12s", sprint_time(tst->interval_us, b1));
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  pk_delay");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12s", sprint_time(tst->peak_delay_us, b1));
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  av_delay");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12s", sprint_time(tst->avge_delay_us, b1));
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  sp_delay");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12s", sprint_time(tst->base_delay_us, b1));
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  pkts    ");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->sent.packets);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  bytes   ");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12llu", tst->sent.bytes);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  way_inds");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->way_indirect_hits);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  way_miss");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->way_misses);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  way_cols");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->way_collisions);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  drops   ");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->dropped.packets);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  marks   ");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->ecn_marked.packets);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  ack_drop");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->ack_drops.packets);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  sp_flows");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->sparse_flows);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  bk_flows");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->bulk_flows);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  un_flows");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->unresponse_flows);
-+	fprintf(f, "\n");
-+
-+	fprintf(f, "  max_len ");
-+	FOR_EACH_TIN(stnc, tst, i)
-+		fprintf(f, " %12u", tst->max_skblen);
-+	fprintf(f, "\n");
++		default:
++			fprintf(f, "          ");
++			for(i=0; i < num_tins; i++)
++				fprintf(f, "        Tin %u", i);
++			fprintf(f, "\n");
++		};
 +
++#define GET_TSTAT(i, attr) (tstat[i][TCA_CAKE_TIN_STATS_ ## attr])
++#define PRINT_TSTAT(name, attr, fmts, val)	do {		\
++			if (GET_TSTAT(0, attr)) {		\
++				fprintf(f, name);		\
++				for (i = 0; i < num_tins; i++)	\
++					fprintf(f, " %12" fmts,	val);	\
++				fprintf(f, "\n");			\
++			}						\
++		} while (0)
++
++#define SPRINT_TSTAT(pfunc, name, attr) PRINT_TSTAT(		\
++			name, attr, "s", sprint_ ## pfunc(		\
++				rta_getattr_u32(GET_TSTAT(i, attr)), b1))
++
++#define PRINT_TSTAT_U32(name, attr)	PRINT_TSTAT(			\
++			name, attr, "u", rta_getattr_u32(GET_TSTAT(i, attr)))
++
++#define PRINT_TSTAT_U64(name, attr)	PRINT_TSTAT(			\
++			name, attr, "llu", rta_getattr_u64(GET_TSTAT(i, attr)))
++
++		SPRINT_TSTAT(rate, "  thresh  ", THRESHOLD_RATE);
++		SPRINT_TSTAT(time, "  target  ", TARGET_US);
++		SPRINT_TSTAT(time, "  interval", INTERVAL_US);
++		SPRINT_TSTAT(time, "  pk_delay", PEAK_DELAY_US);
++		SPRINT_TSTAT(time, "  av_delay", AVG_DELAY_US);
++		SPRINT_TSTAT(time, "  sp_delay", BASE_DELAY_US);
++
++		PRINT_TSTAT_U32("  pkts    ", SENT_PACKETS);
++		PRINT_TSTAT_U64("  bytes   ", SENT_BYTES64);
++
++		PRINT_TSTAT_U32("  way_inds", WAY_INDIRECT_HITS);
++		PRINT_TSTAT_U32("  way_miss", WAY_MISSES);
++		PRINT_TSTAT_U32("  way_cols", WAY_COLLISIONS);
++		PRINT_TSTAT_U32("  drops   ", DROPPED_PACKETS);
++		PRINT_TSTAT_U32("  marks   ", ECN_MARKED_PACKETS);
++		PRINT_TSTAT_U32("  ack_drop", ACKS_DROPPED_PACKETS);
++		PRINT_TSTAT_U32("  sp_flows", SPARSE_FLOWS);
++		PRINT_TSTAT_U32("  bk_flows", BULK_FLOWS);
++		PRINT_TSTAT_U32("  un_flows", UNRESPONSIVE_FLOWS);
++		PRINT_TSTAT_U32("  max_len ", MAX_SKBLEN);
++		PRINT_TSTAT_U32("  quantum ", FLOW_QUANTUM);
++
++#undef GET_STAT
++#undef PRINT_TSTAT
++#undef SPRINT_TSTAT
++#undef PRINT_TSTAT_U32
++#undef PRINT_TSTAT_U64
++	}
 +	return 0;
 +}
 +
@@ -1540,3 +1508,14 @@
 +	.print_qopt	= cake_print_opt,
 +	.print_xstats	= cake_print_xstats,
 +};
+--- a/tc/q_ingress.c
++++ b/tc/q_ingress.c
+@@ -40,7 +40,7 @@ static int ingress_parse_opt(struct qdis
+ static int ingress_print_opt(struct qdisc_util *qu, FILE *f,
+ 			     struct rtattr *opt)
+ {
+-	fprintf(f, "---------------- ");
++	print_string(PRINT_FP, NULL, "---------------- ", NULL);
+ 	return 0;
+ }
+ 



More information about the lede-commits mailing list