iproute2: tc: backport canonical cake support
authorKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Fri, 20 Jul 2018 11:47:35 +0000 (12:47 +0100)
committerKevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Sat, 21 Jul 2018 07:47:40 +0000 (08:47 +0100)
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>
package/network/utils/iproute2/Makefile
package/network/utils/iproute2/patches/190-add-cake-to-tc.patch

index c5e9c5a66ecebe0a0d444d53f31d273d75e05e76..b1e4518b2355a70d2369259a8254cdc893f24249 100644 (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
index fa238c53504a4e5f1d6b5403e577f7a144660abb..76594cca498c4d6bb347bff463a4fab6e787c920 100644 (file)
 --- /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
 +RATE |
 +.BR unlimited*
 +|
-+.BR autorate_ingress
++.BR autorate-ingress
 +]
 +.br
 +[
 +.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
 +.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
 +.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
 +.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
 +.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
 +
 +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
 + *
 +#include <netinet/in.h>
 +#include <arpa/inet.h>
 +#include <string.h>
++#include <inttypes.h>
 +
 +#include "utils.h"
 +#include "tc_util.h"
 +      {"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 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"
 +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;
++      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;
++      int unlimited = 0;
 +      int flowmode = -1;
-+      int nat = -1;
-+      int atm = -1;
 +      int autorate = -1;
-+      int wash = -1;
 +      int ingress = -1;
-+      int ack_filter = -1;
-+      struct rtattr *tail;
-+      struct cake_preset *preset, *preset_set = NULL;
++      int overhead = 0;
++      int wash = -1;
++      int nat = -1;
++      int atm = -1;
++      int mpu = 0;
 +
 +      while (argc > 0) {
 +              if (strcmp(*argv, "bandwidth") == 0) {
 +                      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)) {
 +                              return -1;
 +                      }
 +                      target = interval / 20;
-+                      if(!target)
++                      if (!target)
 +                              target = 1;
 +              } else if ((preset = find_preset(*argv))) {
 +                      if (preset_set)
 +                      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) {
 +                      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) {
 +                      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;
 +                      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
 +                       * 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;
 +                      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;
 +      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)
 +      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)
 +      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);
 +
 +      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);
 +
 +      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
 +      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)
 +
 +      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;
 +{
 +#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);
 +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);
 +      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));
 +
 +      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 */
 +              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));
 +                         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));
 +#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++;
 +              }
 +
 +              }
 +
 +
-+              switch(num_tins) {
++              switch (num_tins) {
 +              case 3:
 +                      fprintf(f, "                   Bulk  Best Effort        Voice\n");
 +                      break;
 +
 +              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");
 +              };