950-add-cake-to-tc.patch 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. --- a/include/linux/pkt_sched.h
  2. +++ b/include/linux/pkt_sched.h
  3. @@ -877,4 +877,60 @@ struct tc_pie_xstats {
  4. __u32 maxq; /* maximum queue size */
  5. __u32 ecn_mark; /* packets marked with ecn*/
  6. };
  7. +
  8. +/* CAKE */
  9. +enum {
  10. + TCA_CAKE_UNSPEC,
  11. + TCA_CAKE_BASE_RATE,
  12. + TCA_CAKE_DIFFSERV_MODE,
  13. + TCA_CAKE_ATM,
  14. + TCA_CAKE_FLOW_MODE,
  15. + TCA_CAKE_OVERHEAD,
  16. + TCA_CAKE_MPU,
  17. + TCA_CAKE_RTT,
  18. + TCA_CAKE_TARGET,
  19. + TCA_CAKE_AUTORATE,
  20. + TCA_CAKE_MEMORY,
  21. + TCA_CAKE_NAT,
  22. + TCA_CAKE_ETHERNET,
  23. + TCA_CAKE_WASH,
  24. + __TCA_CAKE_MAX
  25. +};
  26. +#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1)
  27. +
  28. +struct tc_cake_traffic_stats {
  29. + __u32 packets;
  30. + __u32 link_ms;
  31. + __u64 bytes;
  32. +};
  33. +
  34. +#define TC_CAKE_MAX_TINS (8)
  35. +struct tc_cake_xstats {
  36. + __u16 version; /* == 4, increments when struct extended */
  37. + __u8 max_tins; /* == TC_CAKE_MAX_TINS */
  38. + __u8 tin_cnt; /* <= TC_CAKE_MAX_TINS */
  39. +
  40. + __u32 threshold_rate [TC_CAKE_MAX_TINS];
  41. + __u32 target_us [TC_CAKE_MAX_TINS];
  42. + struct tc_cake_traffic_stats sent [TC_CAKE_MAX_TINS];
  43. + struct tc_cake_traffic_stats dropped [TC_CAKE_MAX_TINS];
  44. + struct tc_cake_traffic_stats ecn_marked[TC_CAKE_MAX_TINS];
  45. + struct tc_cake_traffic_stats backlog [TC_CAKE_MAX_TINS];
  46. + __u32 interval_us [TC_CAKE_MAX_TINS];
  47. + __u32 way_indirect_hits[TC_CAKE_MAX_TINS];
  48. + __u32 way_misses [TC_CAKE_MAX_TINS];
  49. + __u32 way_collisions [TC_CAKE_MAX_TINS];
  50. + __u32 peak_delay_us [TC_CAKE_MAX_TINS]; /* ~= delay to bulk flows */
  51. + __u32 avge_delay_us [TC_CAKE_MAX_TINS];
  52. + __u32 base_delay_us [TC_CAKE_MAX_TINS]; /* ~= delay to sparse flows */
  53. + __u16 sparse_flows [TC_CAKE_MAX_TINS];
  54. + __u16 bulk_flows [TC_CAKE_MAX_TINS];
  55. + __u16 unresponse_flows [TC_CAKE_MAX_TINS]; /* v4 - was u32 last_len */
  56. + __u16 spare [TC_CAKE_MAX_TINS]; /* v4 - split last_len */
  57. + __u32 max_skblen [TC_CAKE_MAX_TINS];
  58. + __u32 capacity_estimate; /* version 2 */
  59. + __u32 memory_limit; /* version 3 */
  60. + __u32 memory_used; /* version 3 */
  61. +};
  62. +
  63. #endif
  64. --- a/tc/Makefile
  65. +++ b/tc/Makefile
  66. @@ -64,6 +64,7 @@ TCMODULES += q_codel.o
  67. TCMODULES += q_fq_codel.o
  68. TCMODULES += q_fq.o
  69. TCMODULES += q_pie.o
  70. +TCMODULES += q_cake.o
  71. TCMODULES += q_hhf.o
  72. TCMODULES += e_bpf.o
  73. --- /dev/null
  74. +++ b/tc/q_cake.c
  75. @@ -0,0 +1,686 @@
  76. +/*
  77. + * Common Applications Kept Enhanced -- CAKE
  78. + *
  79. + * Copyright (C) 2014-2015 Jonathan Morton <chromatix99@gmail.com>
  80. + *
  81. + * Redistribution and use in source and binary forms, with or without
  82. + * modification, are permitted provided that the following conditions
  83. + * are met:
  84. + * 1. Redistributions of source code must retain the above copyright
  85. + * notice, this list of conditions, and the following disclaimer,
  86. + * without modification.
  87. + * 2. Redistributions in binary form must reproduce the above copyright
  88. + * notice, this list of conditions and the following disclaimer in the
  89. + * documentation and/or other materials provided with the distribution.
  90. + * 3. The names of the authors may not be used to endorse or promote products
  91. + * derived from this software without specific prior written permission.
  92. + *
  93. + * Alternatively, provided that this notice is retained in full, this
  94. + * software may be distributed under the terms of the GNU General
  95. + * Public License ("GPL") version 2, in which case the provisions of the
  96. + * GPL apply INSTEAD OF those given above.
  97. + *
  98. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  99. + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  100. + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  101. + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  102. + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  103. + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  104. + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  105. + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  106. + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  107. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  108. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
  109. + * DAMAGE.
  110. + *
  111. + */
  112. +
  113. +#include <stddef.h>
  114. +#include <stdio.h>
  115. +#include <stdlib.h>
  116. +#include <unistd.h>
  117. +#include <syslog.h>
  118. +#include <fcntl.h>
  119. +#include <sys/socket.h>
  120. +#include <netinet/in.h>
  121. +#include <arpa/inet.h>
  122. +#include <string.h>
  123. +
  124. +#include "utils.h"
  125. +#include "tc_util.h"
  126. +
  127. +static void explain(void)
  128. +{
  129. + fprintf(stderr, "Usage: ... cake [ bandwidth RATE | unlimited* | autorate_ingress ]\n"
  130. + " [ rtt TIME | datacentre | lan | metro | regional | internet* | oceanic | satellite | interplanetary ]\n"
  131. + " [ besteffort | precedence | diffserv8 | diffserv4 | diffserv-llt | diffserv3* ]\n"
  132. + " [ flowblind | srchost | dsthost | hosts | flows | dual-srchost | dual-dsthost | triple-isolate* ] [ nat | nonat* ]\n"
  133. + " [ ptm | atm | noatm* ] [ overhead N | conservative | raw* ] [ mpu N ]\n"
  134. + " [ wash | nowash* ]\n"
  135. + " [ memlimit LIMIT ]\n"
  136. + " (* marks defaults)\n");
  137. +}
  138. +
  139. +static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
  140. + struct nlmsghdr *n)
  141. +{
  142. + int unlimited = 0;
  143. + unsigned bandwidth = 0;
  144. + unsigned interval = 0;
  145. + unsigned target = 0;
  146. + unsigned diffserv = 0;
  147. + unsigned memlimit = 0;
  148. + int overhead = 0;
  149. + bool overhead_set = false;
  150. + bool overhead_override = false;
  151. + int wash = -1;
  152. + int mpu = 0;
  153. + int flowmode = -1;
  154. + int nat = -1;
  155. + int atm = -1;
  156. + int autorate = -1;
  157. + struct rtattr *tail;
  158. +
  159. + while (argc > 0) {
  160. + if (strcmp(*argv, "bandwidth") == 0) {
  161. + NEXT_ARG();
  162. + if (get_rate(&bandwidth, *argv)) {
  163. + fprintf(stderr, "Illegal \"bandwidth\"\n");
  164. + return -1;
  165. + }
  166. + unlimited = 0;
  167. + autorate = 0;
  168. + } else if (strcmp(*argv, "unlimited") == 0) {
  169. + bandwidth = 0;
  170. + unlimited = 1;
  171. + autorate = 0;
  172. + } else if (strcmp(*argv, "autorate_ingress") == 0) {
  173. + autorate = 1;
  174. +
  175. + } else if (strcmp(*argv, "rtt") == 0) {
  176. + NEXT_ARG();
  177. + if (get_time(&interval, *argv)) {
  178. + fprintf(stderr, "Illegal \"rtt\"\n");
  179. + return -1;
  180. + }
  181. + target = interval / 20;
  182. + if(!target)
  183. + target = 1;
  184. + } else if (strcmp(*argv, "datacentre") == 0) {
  185. + interval = 100;
  186. + target = 5;
  187. + } else if (strcmp(*argv, "lan") == 0) {
  188. + interval = 1000;
  189. + target = 50;
  190. + } else if (strcmp(*argv, "metro") == 0) {
  191. + interval = 10000;
  192. + target = 500;
  193. + } else if (strcmp(*argv, "regional") == 0) {
  194. + interval = 30000;
  195. + target = 1500;
  196. + } else if (strcmp(*argv, "internet") == 0) {
  197. + interval = 100000;
  198. + target = 5000;
  199. + } else if (strcmp(*argv, "oceanic") == 0) {
  200. + interval = 300000;
  201. + target = 15000;
  202. + } else if (strcmp(*argv, "satellite") == 0) {
  203. + interval = 1000000;
  204. + target = 50000;
  205. + } else if (strcmp(*argv, "interplanetary") == 0) {
  206. + interval = 3600000000U;
  207. + target = 5000;
  208. +
  209. + } else if (strcmp(*argv, "besteffort") == 0) {
  210. + diffserv = 1;
  211. + } else if (strcmp(*argv, "precedence") == 0) {
  212. + diffserv = 2;
  213. + } else if (strcmp(*argv, "diffserv8") == 0) {
  214. + diffserv = 3;
  215. + } else if (strcmp(*argv, "diffserv4") == 0) {
  216. + diffserv = 4;
  217. + } else if (strcmp(*argv, "diffserv") == 0) {
  218. + diffserv = 4;
  219. + } else if (strcmp(*argv, "diffserv-llt") == 0) {
  220. + diffserv = 5;
  221. + } else if (strcmp(*argv, "diffserv3") == 0) {
  222. + diffserv = 6;
  223. +
  224. + } else if (strcmp(*argv, "nowash") == 0) {
  225. + wash = 0;
  226. + } else if (strcmp(*argv, "wash") == 0) {
  227. + wash = 1;
  228. +
  229. + } else if (strcmp(*argv, "flowblind") == 0) {
  230. + flowmode = 0;
  231. + } else if (strcmp(*argv, "srchost") == 0) {
  232. + flowmode = 1;
  233. + } else if (strcmp(*argv, "dsthost") == 0) {
  234. + flowmode = 2;
  235. + } else if (strcmp(*argv, "hosts") == 0) {
  236. + flowmode = 3;
  237. + } else if (strcmp(*argv, "flows") == 0) {
  238. + flowmode = 4;
  239. + } else if (strcmp(*argv, "dual-srchost") == 0) {
  240. + flowmode = 5;
  241. + } else if (strcmp(*argv, "dual-dsthost") == 0) {
  242. + flowmode = 6;
  243. + } else if (strcmp(*argv, "triple-isolate") == 0) {
  244. + flowmode = 7;
  245. +
  246. + } else if (strcmp(*argv, "nat") == 0) {
  247. + nat = 1;
  248. + } else if (strcmp(*argv, "nonat") == 0) {
  249. + nat = 0;
  250. +
  251. + } else if (strcmp(*argv, "ptm") == 0) {
  252. + atm = 2;
  253. + } else if (strcmp(*argv, "atm") == 0) {
  254. + atm = 1;
  255. + } else if (strcmp(*argv, "noatm") == 0) {
  256. + atm = 0;
  257. +
  258. + } else if (strcmp(*argv, "raw") == 0) {
  259. + atm = 0;
  260. + overhead = 0;
  261. + overhead_set = true;
  262. + overhead_override = true;
  263. + } else if (strcmp(*argv, "conservative") == 0) {
  264. + /*
  265. + * Deliberately over-estimate overhead:
  266. + * one whole ATM cell plus ATM framing.
  267. + * A safe choice if the actual overhead is unknown.
  268. + */
  269. + atm = 1;
  270. + overhead = 48;
  271. + overhead_set = true;
  272. +
  273. + /* Various ADSL framing schemes, all over ATM cells */
  274. + } else if (strcmp(*argv, "ipoa-vcmux") == 0) {
  275. + atm = 1;
  276. + overhead += 8;
  277. + overhead_set = true;
  278. + } else if (strcmp(*argv, "ipoa-llcsnap") == 0) {
  279. + atm = 1;
  280. + overhead += 16;
  281. + overhead_set = true;
  282. + } else if (strcmp(*argv, "bridged-vcmux") == 0) {
  283. + atm = 1;
  284. + overhead += 24;
  285. + overhead_set = true;
  286. + } else if (strcmp(*argv, "bridged-llcsnap") == 0) {
  287. + atm = 1;
  288. + overhead += 32;
  289. + overhead_set = true;
  290. + } else if (strcmp(*argv, "pppoa-vcmux") == 0) {
  291. + atm = 1;
  292. + overhead += 10;
  293. + overhead_set = true;
  294. + } else if (strcmp(*argv, "pppoa-llc") == 0) {
  295. + atm = 1;
  296. + overhead += 14;
  297. + overhead_set = true;
  298. + } else if (strcmp(*argv, "pppoe-vcmux") == 0) {
  299. + atm = 1;
  300. + overhead += 32;
  301. + overhead_set = true;
  302. + } else if (strcmp(*argv, "pppoe-llcsnap") == 0) {
  303. + atm = 1;
  304. + overhead += 40;
  305. + overhead_set = true;
  306. +
  307. + /* Typical VDSL2 framing schemes, both over PTM */
  308. + /* PTM has 64b/65b coding which absorbs some bandwidth */
  309. + } else if (strcmp(*argv, "pppoe-ptm") == 0) {
  310. + atm = 2;
  311. + overhead += 27;
  312. + overhead_set = true;
  313. + } else if (strcmp(*argv, "bridged-ptm") == 0) {
  314. + atm = 2;
  315. + overhead += 19;
  316. + overhead_set = true;
  317. +
  318. + } else if (strcmp(*argv, "via-ethernet") == 0) {
  319. + /*
  320. + * We used to use this flag to manually compensate for
  321. + * Linux including the Ethernet header on Ethernet-type
  322. + * interfaces, but not on IP-type interfaces.
  323. + *
  324. + * It is no longer needed, because Cake now adjusts for
  325. + * that automatically, and is thus ignored.
  326. + *
  327. + * It would be deleted entirely, but it appears in the
  328. + * stats output when the automatic compensation is active.
  329. + */
  330. +
  331. + } else if (strcmp(*argv, "ethernet") == 0) {
  332. + /* ethernet pre-amble & interframe gap & FCS
  333. + * you may need to add vlan tag */
  334. + overhead += 38;
  335. + overhead_set = true;
  336. + mpu = 84;
  337. +
  338. + /* Additional Ethernet-related overhead used by some ISPs */
  339. + } else if (strcmp(*argv, "ether-vlan") == 0) {
  340. + /* 802.1q VLAN tag - may be repeated */
  341. + overhead += 4;
  342. + overhead_set = true;
  343. +
  344. + /*
  345. + * DOCSIS cable shapers account for Ethernet frame with FCS,
  346. + * but not interframe gap nor preamble.
  347. + */
  348. + } else if (strcmp(*argv, "docsis") == 0) {
  349. + atm = 0;
  350. + overhead += 18;
  351. + overhead_set = true;
  352. + mpu = 64;
  353. +
  354. + } else if (strcmp(*argv, "overhead") == 0) {
  355. + char* p = NULL;
  356. + NEXT_ARG();
  357. + overhead = strtol(*argv, &p, 10);
  358. + if(!p || *p || !*argv || overhead < -64 || overhead > 256) {
  359. + fprintf(stderr, "Illegal \"overhead\", valid range is -64 to 256\\n");
  360. + return -1;
  361. + }
  362. + overhead_set = true;
  363. +
  364. + } else if (strcmp(*argv, "mpu") == 0) {
  365. + char* p = NULL;
  366. + NEXT_ARG();
  367. + mpu = strtol(*argv, &p, 10);
  368. + if(!p || *p || !*argv || mpu < 0 || mpu > 256) {
  369. + fprintf(stderr, "Illegal \"mpu\", valid range is 0 to 256\\n");
  370. + return -1;
  371. + }
  372. +
  373. + } else if (strcmp(*argv, "memlimit") == 0) {
  374. + NEXT_ARG();
  375. + if(get_size(&memlimit, *argv)) {
  376. + fprintf(stderr, "Illegal value for \"memlimit\": \"%s\"\n", *argv);
  377. + return -1;
  378. + }
  379. +
  380. + } else if (strcmp(*argv, "help") == 0) {
  381. + explain();
  382. + return -1;
  383. + } else {
  384. + fprintf(stderr, "What is \"%s\"?\n", *argv);
  385. + explain();
  386. + return -1;
  387. + }
  388. + argc--; argv++;
  389. + }
  390. +
  391. + tail = NLMSG_TAIL(n);
  392. + addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
  393. + if (bandwidth || unlimited)
  394. + addattr_l(n, 1024, TCA_CAKE_BASE_RATE, &bandwidth, sizeof(bandwidth));
  395. + if (diffserv)
  396. + addattr_l(n, 1024, TCA_CAKE_DIFFSERV_MODE, &diffserv, sizeof(diffserv));
  397. + if (atm != -1)
  398. + addattr_l(n, 1024, TCA_CAKE_ATM, &atm, sizeof(atm));
  399. + if (flowmode != -1)
  400. + addattr_l(n, 1024, TCA_CAKE_FLOW_MODE, &flowmode, sizeof(flowmode));
  401. + if (overhead_set)
  402. + addattr_l(n, 1024, TCA_CAKE_OVERHEAD, &overhead, sizeof(overhead));
  403. + if (overhead_override) {
  404. + unsigned zero = 0;
  405. + addattr_l(n, 1024, TCA_CAKE_ETHERNET, &zero, sizeof(zero));
  406. + }
  407. + if (mpu > 0)
  408. + addattr_l(n, 1024, TCA_CAKE_MPU, &mpu, sizeof(mpu));
  409. + if (interval)
  410. + addattr_l(n, 1024, TCA_CAKE_RTT, &interval, sizeof(interval));
  411. + if (target)
  412. + addattr_l(n, 1024, TCA_CAKE_TARGET, &target, sizeof(target));
  413. + if (autorate != -1)
  414. + addattr_l(n, 1024, TCA_CAKE_AUTORATE, &autorate, sizeof(autorate));
  415. + if (memlimit)
  416. + addattr_l(n, 1024, TCA_CAKE_MEMORY, &memlimit, sizeof(memlimit));
  417. + if (nat != -1)
  418. + addattr_l(n, 1024, TCA_CAKE_NAT, &nat, sizeof(nat));
  419. + if (wash != -1)
  420. + addattr_l(n, 1024, TCA_CAKE_WASH, &wash, sizeof(wash));
  421. +
  422. + tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
  423. + return 0;
  424. +}
  425. +
  426. +
  427. +static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
  428. +{
  429. + struct rtattr *tb[TCA_CAKE_MAX + 1];
  430. + unsigned bandwidth = 0;
  431. + unsigned diffserv = 0;
  432. + unsigned flowmode = 0;
  433. + unsigned interval = 0;
  434. + unsigned memlimit = 0;
  435. + int overhead = 0;
  436. + int ethernet = 0;
  437. + int mpu = 0;
  438. + int atm = 0;
  439. + int nat = 0;
  440. + int autorate = 0;
  441. + int wash = 0;
  442. + SPRINT_BUF(b1);
  443. + SPRINT_BUF(b2);
  444. +
  445. + if (opt == NULL)
  446. + return 0;
  447. +
  448. + parse_rtattr_nested(tb, TCA_CAKE_MAX, opt);
  449. +
  450. + if (tb[TCA_CAKE_BASE_RATE] &&
  451. + RTA_PAYLOAD(tb[TCA_CAKE_BASE_RATE]) >= sizeof(__u32)) {
  452. + bandwidth = rta_getattr_u32(tb[TCA_CAKE_BASE_RATE]);
  453. + if(bandwidth)
  454. + fprintf(f, "bandwidth %s ", sprint_rate(bandwidth, b1));
  455. + else
  456. + fprintf(f, "unlimited ");
  457. + }
  458. + if (tb[TCA_CAKE_AUTORATE] &&
  459. + RTA_PAYLOAD(tb[TCA_CAKE_AUTORATE]) >= sizeof(__u32)) {
  460. + autorate = rta_getattr_u32(tb[TCA_CAKE_AUTORATE]);
  461. + if(autorate == 1)
  462. + fprintf(f, "autorate_ingress ");
  463. + else if(autorate)
  464. + fprintf(f, "(?autorate?) ");
  465. + }
  466. + if (tb[TCA_CAKE_DIFFSERV_MODE] &&
  467. + RTA_PAYLOAD(tb[TCA_CAKE_DIFFSERV_MODE]) >= sizeof(__u32)) {
  468. + diffserv = rta_getattr_u32(tb[TCA_CAKE_DIFFSERV_MODE]);
  469. + switch(diffserv) {
  470. + case 1:
  471. + fprintf(f, "besteffort ");
  472. + break;
  473. + case 2:
  474. + fprintf(f, "precedence ");
  475. + break;
  476. + case 3:
  477. + fprintf(f, "diffserv8 ");
  478. + break;
  479. + case 4:
  480. + fprintf(f, "diffserv4 ");
  481. + break;
  482. + case 5:
  483. + fprintf(f, "diffserv-llt ");
  484. + break;
  485. + case 6:
  486. + fprintf(f, "diffserv3 ");
  487. + break;
  488. + default:
  489. + fprintf(f, "(?diffserv?) ");
  490. + break;
  491. + };
  492. + }
  493. + if (tb[TCA_CAKE_FLOW_MODE] &&
  494. + RTA_PAYLOAD(tb[TCA_CAKE_FLOW_MODE]) >= sizeof(__u32)) {
  495. + flowmode = rta_getattr_u32(tb[TCA_CAKE_FLOW_MODE]);
  496. + nat = !!(flowmode & 64);
  497. + flowmode &= ~64;
  498. + switch(flowmode) {
  499. + case 0:
  500. + fprintf(f, "flowblind ");
  501. + break;
  502. + case 1:
  503. + fprintf(f, "srchost ");
  504. + break;
  505. + case 2:
  506. + fprintf(f, "dsthost ");
  507. + break;
  508. + case 3:
  509. + fprintf(f, "hosts ");
  510. + break;
  511. + case 4:
  512. + fprintf(f, "flows ");
  513. + break;
  514. + case 5:
  515. + fprintf(f, "dual-srchost ");
  516. + break;
  517. + case 6:
  518. + fprintf(f, "dual-dsthost ");
  519. + break;
  520. + case 7:
  521. + fprintf(f, "triple-isolate ");
  522. + break;
  523. + default:
  524. + fprintf(f, "(?flowmode?) ");
  525. + break;
  526. + };
  527. +
  528. + if(nat)
  529. + fprintf(f, "nat ");
  530. + }
  531. + if (tb[TCA_CAKE_WASH] &&
  532. + RTA_PAYLOAD(tb[TCA_CAKE_WASH]) >= sizeof(__u32)) {
  533. + wash = rta_getattr_u32(tb[TCA_CAKE_WASH]);
  534. + }
  535. + if (tb[TCA_CAKE_ATM] &&
  536. + RTA_PAYLOAD(tb[TCA_CAKE_ATM]) >= sizeof(__u32)) {
  537. + atm = rta_getattr_u32(tb[TCA_CAKE_ATM]);
  538. + }
  539. + if (tb[TCA_CAKE_OVERHEAD] &&
  540. + RTA_PAYLOAD(tb[TCA_CAKE_OVERHEAD]) >= sizeof(__u32)) {
  541. + overhead = rta_getattr_u32(tb[TCA_CAKE_OVERHEAD]);
  542. + }
  543. + if (tb[TCA_CAKE_MPU] &&
  544. + RTA_PAYLOAD(tb[TCA_CAKE_MPU]) >= sizeof(__u32)) {
  545. + mpu = rta_getattr_u32(tb[TCA_CAKE_MPU]);
  546. + }
  547. + if (tb[TCA_CAKE_ETHERNET] &&
  548. + RTA_PAYLOAD(tb[TCA_CAKE_ETHERNET]) >= sizeof(__u32)) {
  549. + ethernet = rta_getattr_u32(tb[TCA_CAKE_ETHERNET]);
  550. + }
  551. + if (tb[TCA_CAKE_RTT] &&
  552. + RTA_PAYLOAD(tb[TCA_CAKE_RTT]) >= sizeof(__u32)) {
  553. + interval = rta_getattr_u32(tb[TCA_CAKE_RTT]);
  554. + }
  555. +
  556. + if (wash)
  557. + fprintf(f,"wash ");
  558. +
  559. + if (interval)
  560. + fprintf(f, "rtt %s ", sprint_time(interval, b2));
  561. +
  562. + if (!atm && overhead == ethernet) {
  563. + fprintf(f, "raw ");
  564. + } else {
  565. + if (atm == 1)
  566. + fprintf(f, "atm ");
  567. + else if (atm == 2)
  568. + fprintf(f, "ptm ");
  569. + else
  570. + fprintf(f, "noatm ");
  571. +
  572. + fprintf(f, "overhead %d ", overhead);
  573. +
  574. + // This is actually the *amount* of automatic compensation, but we only report
  575. + // its presence as a boolean for now.
  576. + if (ethernet)
  577. + fprintf(f, "via-ethernet ");
  578. + }
  579. +
  580. + if (mpu) {
  581. + fprintf(f, "mpu %d ", mpu);
  582. + }
  583. +
  584. + if (memlimit)
  585. + fprintf(f, "memlimit %s", sprint_size(memlimit, b1));
  586. +
  587. + return 0;
  588. +}
  589. +
  590. +static int cake_print_xstats(struct qdisc_util *qu, FILE *f,
  591. + struct rtattr *xstats)
  592. +{
  593. + /* fq_codel stats format borrowed */
  594. + struct tc_fq_codel_xstats *st;
  595. + struct tc_cake_xstats *stnc;
  596. + SPRINT_BUF(b1);
  597. + SPRINT_BUF(b2);
  598. +
  599. + if (xstats == NULL)
  600. + return 0;
  601. +
  602. + if (RTA_PAYLOAD(xstats) < sizeof(st->type))
  603. + return -1;
  604. +
  605. + st = RTA_DATA(xstats);
  606. + stnc = RTA_DATA(xstats);
  607. +
  608. + if (st->type == TCA_FQ_CODEL_XSTATS_QDISC && RTA_PAYLOAD(xstats) >= sizeof(*st)) {
  609. + fprintf(f, " maxpacket %u drop_overlimit %u new_flow_count %u ecn_mark %u",
  610. + st->qdisc_stats.maxpacket,
  611. + st->qdisc_stats.drop_overlimit,
  612. + st->qdisc_stats.new_flow_count,
  613. + st->qdisc_stats.ecn_mark);
  614. + fprintf(f, "\n new_flows_len %u old_flows_len %u",
  615. + st->qdisc_stats.new_flows_len,
  616. + st->qdisc_stats.old_flows_len);
  617. + } else if (st->type == TCA_FQ_CODEL_XSTATS_CLASS && RTA_PAYLOAD(xstats) >= sizeof(*st)) {
  618. + fprintf(f, " deficit %d count %u lastcount %u ldelay %s",
  619. + st->class_stats.deficit,
  620. + st->class_stats.count,
  621. + st->class_stats.lastcount,
  622. + sprint_time(st->class_stats.ldelay, b1));
  623. + if (st->class_stats.dropping) {
  624. + fprintf(f, " dropping");
  625. + if (st->class_stats.drop_next < 0)
  626. + fprintf(f, " drop_next -%s",
  627. + sprint_time(-st->class_stats.drop_next, b1));
  628. + else
  629. + fprintf(f, " drop_next %s",
  630. + sprint_time(st->class_stats.drop_next, b1));
  631. + }
  632. + } else if (stnc->version >= 1 && stnc->version < 0xFF
  633. + && stnc->max_tins == TC_CAKE_MAX_TINS
  634. + && RTA_PAYLOAD(xstats) >= offsetof(struct tc_cake_xstats, capacity_estimate))
  635. + {
  636. + int i;
  637. +
  638. + if(stnc->version >= 3)
  639. + fprintf(f, " memory used: %s of %s\n", sprint_size(stnc->memory_used, b1), sprint_size(stnc->memory_limit, b2));
  640. +
  641. + if(stnc->version >= 2)
  642. + fprintf(f, " capacity estimate: %s\n", sprint_rate(stnc->capacity_estimate, b1));
  643. +
  644. + switch(stnc->tin_cnt) {
  645. + case 3:
  646. + fprintf(f, " Bulk Best Effort Voice\n");
  647. + break;
  648. +
  649. + case 4:
  650. + fprintf(f, " Bulk Best Effort Video Voice\n");
  651. + break;
  652. +
  653. + case 5:
  654. + fprintf(f, " Low Loss Best Effort Low Delay Bulk Net Control\n");
  655. + break;
  656. +
  657. + default:
  658. + fprintf(f, " ");
  659. + for(i=0; i < stnc->tin_cnt; i++)
  660. + fprintf(f, " Tin %u", i);
  661. + fprintf(f, "\n");
  662. + };
  663. +
  664. + fprintf(f, " thresh ");
  665. + for(i=0; i < stnc->tin_cnt; i++)
  666. + fprintf(f, "%12s", sprint_rate(stnc->threshold_rate[i], b1));
  667. + fprintf(f, "\n");
  668. +
  669. + fprintf(f, " target ");
  670. + for(i=0; i < stnc->tin_cnt; i++)
  671. + fprintf(f, "%12s", sprint_time(stnc->target_us[i], b1));
  672. + fprintf(f, "\n");
  673. +
  674. + fprintf(f, " interval");
  675. + for(i=0; i < stnc->tin_cnt; i++)
  676. + fprintf(f, "%12s", sprint_time(stnc->interval_us[i], b1));
  677. + fprintf(f, "\n");
  678. +
  679. + fprintf(f, " pk_delay");
  680. + for(i=0; i < stnc->tin_cnt; i++)
  681. + fprintf(f, "%12s", sprint_time(stnc->peak_delay_us[i], b1));
  682. + fprintf(f, "\n");
  683. +
  684. + fprintf(f, " av_delay");
  685. + for(i=0; i < stnc->tin_cnt; i++)
  686. + fprintf(f, "%12s", sprint_time(stnc->avge_delay_us[i], b1));
  687. + fprintf(f, "\n");
  688. +
  689. + fprintf(f, " sp_delay");
  690. + for(i=0; i < stnc->tin_cnt; i++)
  691. + fprintf(f, "%12s", sprint_time(stnc->base_delay_us[i], b1));
  692. + fprintf(f, "\n");
  693. +
  694. + fprintf(f, " pkts ");
  695. + for(i=0; i < stnc->tin_cnt; i++)
  696. + fprintf(f, "%12u", stnc->sent[i].packets);
  697. + fprintf(f, "\n");
  698. +
  699. + fprintf(f, " bytes ");
  700. + for(i=0; i < stnc->tin_cnt; i++)
  701. + fprintf(f, "%12llu", stnc->sent[i].bytes);
  702. + fprintf(f, "\n");
  703. +
  704. + fprintf(f, " way_inds");
  705. + for(i=0; i < stnc->tin_cnt; i++)
  706. + fprintf(f, "%12u", stnc->way_indirect_hits[i]);
  707. + fprintf(f, "\n");
  708. +
  709. + fprintf(f, " way_miss");
  710. + for(i=0; i < stnc->tin_cnt; i++)
  711. + fprintf(f, "%12u", stnc->way_misses[i]);
  712. + fprintf(f, "\n");
  713. +
  714. + fprintf(f, " way_cols");
  715. + for(i=0; i < stnc->tin_cnt; i++)
  716. + fprintf(f, "%12u", stnc->way_collisions[i]);
  717. + fprintf(f, "\n");
  718. +
  719. + fprintf(f, " drops ");
  720. + for(i=0; i < stnc->tin_cnt; i++)
  721. + fprintf(f, "%12u", stnc->dropped[i].packets);
  722. + fprintf(f, "\n");
  723. +
  724. + fprintf(f, " marks ");
  725. + for(i=0; i < stnc->tin_cnt; i++)
  726. + fprintf(f, "%12u", stnc->ecn_marked[i].packets);
  727. + fprintf(f, "\n");
  728. +
  729. + fprintf(f, " sp_flows");
  730. + for(i=0; i < stnc->tin_cnt; i++)
  731. + fprintf(f, "%12u", stnc->sparse_flows[i]);
  732. + fprintf(f, "\n");
  733. +
  734. + fprintf(f, " bk_flows");
  735. + for(i=0; i < stnc->tin_cnt; i++)
  736. + fprintf(f, "%12u", stnc->bulk_flows[i]);
  737. + fprintf(f, "\n");
  738. +
  739. + if(stnc->version >= 4) {
  740. + fprintf(f, " un_flows");
  741. + for(i=0; i < stnc->tin_cnt; i++)
  742. + fprintf(f, "%12u", stnc->unresponse_flows[i]);
  743. + fprintf(f, "\n");
  744. + }
  745. +
  746. + fprintf(f, " max_len ");
  747. + for(i=0; i < stnc->tin_cnt; i++)
  748. + fprintf(f, "%12u", stnc->max_skblen[i]);
  749. + fprintf(f, "\n");
  750. + } else {
  751. + return -1;
  752. + }
  753. + return 0;
  754. +}
  755. +
  756. +struct qdisc_util cake_qdisc_util = {
  757. + .id = "cake",
  758. + .parse_qopt = cake_parse_opt,
  759. + .print_qopt = cake_print_opt,
  760. + .print_xstats = cake_print_xstats,
  761. +};