190-add-cake-to-tc.patch 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578
  1. --- a/include/uapi/linux/pkt_sched.h
  2. +++ b/include/uapi/linux/pkt_sched.h
  3. @@ -934,4 +934,118 @@ enum {
  4. #define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
  5. +/* CAKE */
  6. +enum {
  7. + TCA_CAKE_UNSPEC,
  8. + TCA_CAKE_PAD,
  9. + TCA_CAKE_BASE_RATE64,
  10. + TCA_CAKE_DIFFSERV_MODE,
  11. + TCA_CAKE_ATM,
  12. + TCA_CAKE_FLOW_MODE,
  13. + TCA_CAKE_OVERHEAD,
  14. + TCA_CAKE_RTT,
  15. + TCA_CAKE_TARGET,
  16. + TCA_CAKE_AUTORATE,
  17. + TCA_CAKE_MEMORY,
  18. + TCA_CAKE_NAT,
  19. + TCA_CAKE_RAW, // was _ETHERNET
  20. + TCA_CAKE_WASH,
  21. + TCA_CAKE_MPU,
  22. + TCA_CAKE_INGRESS,
  23. + TCA_CAKE_ACK_FILTER,
  24. + TCA_CAKE_SPLIT_GSO,
  25. + __TCA_CAKE_MAX
  26. +};
  27. +#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1)
  28. +
  29. +enum {
  30. + __TCA_CAKE_STATS_INVALID,
  31. + TCA_CAKE_STATS_PAD,
  32. + TCA_CAKE_STATS_CAPACITY_ESTIMATE64,
  33. + TCA_CAKE_STATS_MEMORY_LIMIT,
  34. + TCA_CAKE_STATS_MEMORY_USED,
  35. + TCA_CAKE_STATS_AVG_NETOFF,
  36. + TCA_CAKE_STATS_MIN_NETLEN,
  37. + TCA_CAKE_STATS_MAX_NETLEN,
  38. + TCA_CAKE_STATS_MIN_ADJLEN,
  39. + TCA_CAKE_STATS_MAX_ADJLEN,
  40. + TCA_CAKE_STATS_TIN_STATS,
  41. + TCA_CAKE_STATS_DEFICIT,
  42. + TCA_CAKE_STATS_COBALT_COUNT,
  43. + TCA_CAKE_STATS_DROPPING,
  44. + TCA_CAKE_STATS_DROP_NEXT_US,
  45. + TCA_CAKE_STATS_P_DROP,
  46. + TCA_CAKE_STATS_BLUE_TIMER_US,
  47. + __TCA_CAKE_STATS_MAX
  48. +};
  49. +#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1)
  50. +
  51. +enum {
  52. + __TCA_CAKE_TIN_STATS_INVALID,
  53. + TCA_CAKE_TIN_STATS_PAD,
  54. + TCA_CAKE_TIN_STATS_SENT_PACKETS,
  55. + TCA_CAKE_TIN_STATS_SENT_BYTES64,
  56. + TCA_CAKE_TIN_STATS_DROPPED_PACKETS,
  57. + TCA_CAKE_TIN_STATS_DROPPED_BYTES64,
  58. + TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS,
  59. + TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64,
  60. + TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS,
  61. + TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64,
  62. + TCA_CAKE_TIN_STATS_BACKLOG_PACKETS,
  63. + TCA_CAKE_TIN_STATS_BACKLOG_BYTES,
  64. + TCA_CAKE_TIN_STATS_THRESHOLD_RATE64,
  65. + TCA_CAKE_TIN_STATS_TARGET_US,
  66. + TCA_CAKE_TIN_STATS_INTERVAL_US,
  67. + TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS,
  68. + TCA_CAKE_TIN_STATS_WAY_MISSES,
  69. + TCA_CAKE_TIN_STATS_WAY_COLLISIONS,
  70. + TCA_CAKE_TIN_STATS_PEAK_DELAY_US,
  71. + TCA_CAKE_TIN_STATS_AVG_DELAY_US,
  72. + TCA_CAKE_TIN_STATS_BASE_DELAY_US,
  73. + TCA_CAKE_TIN_STATS_SPARSE_FLOWS,
  74. + TCA_CAKE_TIN_STATS_BULK_FLOWS,
  75. + TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS,
  76. + TCA_CAKE_TIN_STATS_MAX_SKBLEN,
  77. + TCA_CAKE_TIN_STATS_FLOW_QUANTUM,
  78. + __TCA_CAKE_TIN_STATS_MAX
  79. +};
  80. +#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1)
  81. +#define TC_CAKE_MAX_TINS (8)
  82. +
  83. +enum {
  84. + CAKE_FLOW_NONE = 0,
  85. + CAKE_FLOW_SRC_IP,
  86. + CAKE_FLOW_DST_IP,
  87. + CAKE_FLOW_HOSTS, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_DST_IP */
  88. + CAKE_FLOW_FLOWS,
  89. + CAKE_FLOW_DUAL_SRC, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_FLOWS */
  90. + CAKE_FLOW_DUAL_DST, /* = CAKE_FLOW_DST_IP | CAKE_FLOW_FLOWS */
  91. + CAKE_FLOW_TRIPLE, /* = CAKE_FLOW_HOSTS | CAKE_FLOW_FLOWS */
  92. + CAKE_FLOW_MAX,
  93. +};
  94. +
  95. +enum {
  96. + CAKE_DIFFSERV_DIFFSERV3 = 0,
  97. + CAKE_DIFFSERV_DIFFSERV4,
  98. + CAKE_DIFFSERV_DIFFSERV8,
  99. + CAKE_DIFFSERV_BESTEFFORT,
  100. + CAKE_DIFFSERV_PRECEDENCE,
  101. + CAKE_DIFFSERV_MAX
  102. +};
  103. +
  104. +enum {
  105. + CAKE_ACK_NONE = 0,
  106. + CAKE_ACK_FILTER,
  107. + CAKE_ACK_AGGRESSIVE,
  108. + CAKE_ACK_MAX
  109. +};
  110. +
  111. +enum {
  112. + CAKE_ATM_NONE = 0,
  113. + CAKE_ATM_ATM,
  114. + CAKE_ATM_PTM,
  115. + CAKE_ATM_MAX
  116. +};
  117. +
  118. +
  119. #endif
  120. --- /dev/null
  121. +++ b/man/man8/tc-cake.8
  122. @@ -0,0 +1,632 @@
  123. +.TH CAKE 8 "19 July 2018" "iproute2" "Linux"
  124. +.SH NAME
  125. +CAKE \- Common Applications Kept Enhanced (CAKE)
  126. +.SH SYNOPSIS
  127. +.B tc qdisc ... cake
  128. +.br
  129. +[
  130. +.BR bandwidth
  131. +RATE |
  132. +.BR unlimited*
  133. +|
  134. +.BR autorate-ingress
  135. +]
  136. +.br
  137. +[
  138. +.BR rtt
  139. +TIME |
  140. +.BR datacentre
  141. +|
  142. +.BR lan
  143. +|
  144. +.BR metro
  145. +|
  146. +.BR regional
  147. +|
  148. +.BR internet*
  149. +|
  150. +.BR oceanic
  151. +|
  152. +.BR satellite
  153. +|
  154. +.BR interplanetary
  155. +]
  156. +.br
  157. +[
  158. +.BR besteffort
  159. +|
  160. +.BR diffserv8
  161. +|
  162. +.BR diffserv4
  163. +|
  164. +.BR diffserv3*
  165. +]
  166. +.br
  167. +[
  168. +.BR flowblind
  169. +|
  170. +.BR srchost
  171. +|
  172. +.BR dsthost
  173. +|
  174. +.BR hosts
  175. +|
  176. +.BR flows
  177. +|
  178. +.BR dual-srchost
  179. +|
  180. +.BR dual-dsthost
  181. +|
  182. +.BR triple-isolate*
  183. +]
  184. +.br
  185. +[
  186. +.BR nat
  187. +|
  188. +.BR nonat*
  189. +]
  190. +.br
  191. +[
  192. +.BR wash
  193. +|
  194. +.BR nowash*
  195. +]
  196. +.br
  197. +[
  198. +.BR ack-filter
  199. +|
  200. +.BR ack-filter-aggressive
  201. +|
  202. +.BR no-ack-filter*
  203. +]
  204. +.br
  205. +[
  206. +.BR memlimit
  207. +LIMIT ]
  208. +.br
  209. +[
  210. +.BR ptm
  211. +|
  212. +.BR atm
  213. +|
  214. +.BR noatm*
  215. +]
  216. +.br
  217. +[
  218. +.BR overhead
  219. +N |
  220. +.BR conservative
  221. +|
  222. +.BR raw*
  223. +]
  224. +.br
  225. +[
  226. +.BR mpu
  227. +N ]
  228. +.br
  229. +[
  230. +.BR ingress
  231. +|
  232. +.BR egress*
  233. +]
  234. +.br
  235. +(* marks defaults)
  236. +
  237. +
  238. +.SH DESCRIPTION
  239. +CAKE (Common Applications Kept Enhanced) is a shaping-capable queue discipline
  240. +which uses both AQM and FQ. It combines COBALT, which is an AQM algorithm
  241. +combining Codel and BLUE, a shaper which operates in deficit mode, and a variant
  242. +of DRR++ for flow isolation. 8-way set-associative hashing is used to virtually
  243. +eliminate hash collisions. Priority queuing is available through a simplified
  244. +diffserv implementation. Overhead compensation for various encapsulation
  245. +schemes is tightly integrated.
  246. +
  247. +All settings are optional; the default settings are chosen to be sensible in
  248. +most common deployments. Most people will only need to set the
  249. +.B bandwidth
  250. +parameter to get useful results, but reading the
  251. +.B Overhead Compensation
  252. +and
  253. +.B Round Trip Time
  254. +sections is strongly encouraged.
  255. +
  256. +.SH SHAPER PARAMETERS
  257. +CAKE uses a deficit-mode shaper, which does not exhibit the initial burst
  258. +typical of token-bucket shapers. It will automatically burst precisely as much
  259. +as required to maintain the configured throughput. As such, it is very
  260. +straightforward to configure.
  261. +.PP
  262. +.B unlimited
  263. +(default)
  264. +.br
  265. + No limit on the bandwidth.
  266. +.PP
  267. +.B bandwidth
  268. +RATE
  269. +.br
  270. + Set the shaper bandwidth. See
  271. +.BR tc(8)
  272. +or examples below for details of the RATE value.
  273. +.PP
  274. +.B autorate-ingress
  275. +.br
  276. + Automatic capacity estimation based on traffic arriving at this qdisc.
  277. +This is most likely to be useful with cellular links, which tend to change
  278. +quality randomly. A
  279. +.B bandwidth
  280. +parameter can be used in conjunction to specify an initial estimate. The shaper
  281. +will periodically be set to a bandwidth slightly below the estimated rate. This
  282. +estimator cannot estimate the bandwidth of links downstream of itself.
  283. +
  284. +.SH OVERHEAD COMPENSATION PARAMETERS
  285. +The size of each packet on the wire may differ from that seen by Linux. The
  286. +following parameters allow CAKE to compensate for this difference by internally
  287. +considering each packet to be bigger than Linux informs it. To assist users who
  288. +are not expert network engineers, keywords have been provided to represent a
  289. +number of common link technologies.
  290. +
  291. +.SS Manual Overhead Specification
  292. +.B overhead
  293. +BYTES
  294. +.br
  295. + Adds BYTES to the size of each packet. BYTES may be negative; values
  296. +between -64 and 256 (inclusive) are accepted.
  297. +.PP
  298. +.B mpu
  299. +BYTES
  300. +.br
  301. + Rounds each packet (including overhead) up to a minimum length
  302. +BYTES. BYTES may not be negative; values between 0 and 256 (inclusive)
  303. +are accepted.
  304. +.PP
  305. +.B atm
  306. +.br
  307. + Compensates for ATM cell framing, which is normally found on ADSL links.
  308. +This is performed after the
  309. +.B overhead
  310. +parameter above. ATM uses fixed 53-byte cells, each of which can carry 48 bytes
  311. +payload.
  312. +.PP
  313. +.B ptm
  314. +.br
  315. + Compensates for PTM encoding, which is normally found on VDSL2 links and
  316. +uses a 64b/65b encoding scheme. It is even more efficient to simply
  317. +derate the specified shaper bandwidth by a factor of 64/65 or 0.984. See
  318. +ITU G.992.3 Annex N and IEEE 802.3 Section 61.3 for details.
  319. +.PP
  320. +.B noatm
  321. +.br
  322. + Disables ATM and PTM compensation.
  323. +
  324. +.SS Failsafe Overhead Keywords
  325. +These two keywords are provided for quick-and-dirty setup. Use them if you
  326. +can't be bothered to read the rest of this section.
  327. +.PP
  328. +.B raw
  329. +(default)
  330. +.br
  331. + Turns off all overhead compensation in CAKE. The packet size reported
  332. +by Linux will be used directly.
  333. +.PP
  334. + Other overhead keywords may be added after "raw". The effect of this is
  335. +to make the overhead compensation operate relative to the reported packet size,
  336. +not the underlying IP packet size.
  337. +.PP
  338. +.B conservative
  339. +.br
  340. + Compensates for more overhead than is likely to occur on any
  341. +widely-deployed link technology.
  342. +.br
  343. + Equivalent to
  344. +.B overhead 48 atm.
  345. +
  346. +.SS ADSL Overhead Keywords
  347. +Most ADSL modems have a way to check which framing scheme is in use. Often this
  348. +is also specified in the settings document provided by the ISP. The keywords in
  349. +this section are intended to correspond with these sources of information. All
  350. +of them implicitly set the
  351. +.B atm
  352. +flag.
  353. +.PP
  354. +.B pppoa-vcmux
  355. +.br
  356. + Equivalent to
  357. +.B overhead 10 atm
  358. +.PP
  359. +.B pppoa-llc
  360. +.br
  361. + Equivalent to
  362. +.B overhead 14 atm
  363. +.PP
  364. +.B pppoe-vcmux
  365. +.br
  366. + Equivalent to
  367. +.B overhead 32 atm
  368. +.PP
  369. +.B pppoe-llcsnap
  370. +.br
  371. + Equivalent to
  372. +.B overhead 40 atm
  373. +.PP
  374. +.B bridged-vcmux
  375. +.br
  376. + Equivalent to
  377. +.B overhead 24 atm
  378. +.PP
  379. +.B bridged-llcsnap
  380. +.br
  381. + Equivalent to
  382. +.B overhead 32 atm
  383. +.PP
  384. +.B ipoa-vcmux
  385. +.br
  386. + Equivalent to
  387. +.B overhead 8 atm
  388. +.PP
  389. +.B ipoa-llcsnap
  390. +.br
  391. + Equivalent to
  392. +.B overhead 16 atm
  393. +.PP
  394. +See also the Ethernet Correction Factors section below.
  395. +
  396. +.SS VDSL2 Overhead Keywords
  397. +ATM was dropped from VDSL2 in favour of PTM, which is a much more
  398. +straightforward framing scheme. Some ISPs retained PPPoE for compatibility with
  399. +their existing back-end systems.
  400. +.PP
  401. +.B pppoe-ptm
  402. +.br
  403. + Equivalent to
  404. +.B overhead 30 ptm
  405. +
  406. +.br
  407. + PPPoE: 2B PPP + 6B PPPoE +
  408. +.br
  409. + ETHERNET: 6B dest MAC + 6B src MAC + 2B ethertype + 4B Frame Check Sequence +
  410. +.br
  411. + PTM: 1B Start of Frame (S) + 1B End of Frame (Ck) + 2B TC-CRC (PTM-FCS)
  412. +.br
  413. +.PP
  414. +.B bridged-ptm
  415. +.br
  416. + Equivalent to
  417. +.B overhead 22 ptm
  418. +.br
  419. + ETHERNET: 6B dest MAC + 6B src MAC + 2B ethertype + 4B Frame Check Sequence +
  420. +.br
  421. + PTM: 1B Start of Frame (S) + 1B End of Frame (Ck) + 2B TC-CRC (PTM-FCS)
  422. +.br
  423. +.PP
  424. +See also the Ethernet Correction Factors section below.
  425. +
  426. +.SS DOCSIS Cable Overhead Keyword
  427. +DOCSIS is the universal standard for providing Internet service over cable-TV
  428. +infrastructure.
  429. +
  430. +In this case, the actual on-wire overhead is less important than the packet size
  431. +the head-end equipment uses for shaping and metering. This is specified to be
  432. +an Ethernet frame including the CRC (aka FCS).
  433. +.PP
  434. +.B docsis
  435. +.br
  436. + Equivalent to
  437. +.B overhead 18 mpu 64 noatm
  438. +
  439. +.SS Ethernet Overhead Keywords
  440. +.PP
  441. +.B ethernet
  442. +.br
  443. + Accounts for Ethernet's preamble, inter-frame gap, and Frame Check
  444. +Sequence. Use this keyword when the bottleneck being shaped for is an
  445. +actual Ethernet cable.
  446. +.br
  447. + Equivalent to
  448. +.B overhead 38 mpu 84 noatm
  449. +.PP
  450. +.B ether-vlan
  451. +.br
  452. + Adds 4 bytes to the overhead compensation, accounting for an IEEE 802.1Q
  453. +VLAN header appended to the Ethernet frame header. NB: Some ISPs use one or
  454. +even two of these within PPPoE; this keyword may be repeated as necessary to
  455. +express this.
  456. +
  457. +.SH ROUND TRIP TIME PARAMETERS
  458. +Active Queue Management (AQM) consists of embedding congestion signals in the
  459. +packet flow, which receivers use to instruct senders to slow down when the queue
  460. +is persistently occupied. CAKE uses ECN signalling when available, and packet
  461. +drops otherwise, according to a combination of the Codel and BLUE AQM algorithms
  462. +called COBALT.
  463. +
  464. +Very short latencies require a very rapid AQM response to adequately control
  465. +latency. However, such a rapid response tends to impair throughput when the
  466. +actual RTT is relatively long. CAKE allows specifying the RTT it assumes for
  467. +tuning various parameters. Actual RTTs within an order of magnitude of this
  468. +will generally work well for both throughput and latency management.
  469. +
  470. +At the 'lan' setting and below, the time constants are similar in magnitude to
  471. +the jitter in the Linux kernel itself, so congestion might be signalled
  472. +prematurely. The flows will then become sparse and total throughput reduced,
  473. +leaving little or no back-pressure for the fairness logic to work against. Use
  474. +the "metro" setting for local lans unless you have a custom kernel.
  475. +.PP
  476. +.B rtt
  477. +TIME
  478. +.br
  479. + Manually specify an RTT.
  480. +.PP
  481. +.B datacentre
  482. +.br
  483. + For extremely high-performance 10GigE+ networks only. Equivalent to
  484. +.B rtt 100us.
  485. +.PP
  486. +.B lan
  487. +.br
  488. + For pure Ethernet (not Wi-Fi) networks, at home or in the office. Don't
  489. +use this when shaping for an Internet access link. Equivalent to
  490. +.B rtt 1ms.
  491. +.PP
  492. +.B metro
  493. +.br
  494. + For traffic mostly within a single city. Equivalent to
  495. +.B rtt 10ms.
  496. +.PP
  497. +.B regional
  498. +.br
  499. + For traffic mostly within a European-sized country. Equivalent to
  500. +.B rtt 30ms.
  501. +.PP
  502. +.B internet
  503. +(default)
  504. +.br
  505. + This is suitable for most Internet traffic. Equivalent to
  506. +.B rtt 100ms.
  507. +.PP
  508. +.B oceanic
  509. +.br
  510. + For Internet traffic with generally above-average latency, such as that
  511. +suffered by Australasian residents. Equivalent to
  512. +.B rtt 300ms.
  513. +.PP
  514. +.B satellite
  515. +.br
  516. + For traffic via geostationary satellites. Equivalent to
  517. +.B rtt 1000ms.
  518. +.PP
  519. +.B interplanetary
  520. +.br
  521. + So named because Jupiter is about 1 light-hour from Earth. Use this to
  522. +(almost) completely disable AQM actions. Equivalent to
  523. +.B rtt 3600s.
  524. +
  525. +.SH FLOW ISOLATION PARAMETERS
  526. +With flow isolation enabled, CAKE places packets from different flows into
  527. +different queues, each of which carries its own AQM state. Packets from each
  528. +queue are then delivered fairly, according to a DRR++ algorithm which minimises
  529. +latency for "sparse" flows. CAKE uses a set-associative hashing algorithm to
  530. +minimise flow collisions.
  531. +
  532. +These keywords specify whether fairness based on source address, destination
  533. +address, individual flows, or any combination of those is desired.
  534. +.PP
  535. +.B flowblind
  536. +.br
  537. + Disables flow isolation; all traffic passes through a single queue for
  538. +each tin.
  539. +.PP
  540. +.B srchost
  541. +.br
  542. + Flows are defined only by source address. Could be useful on the egress
  543. +path of an ISP backhaul.
  544. +.PP
  545. +.B dsthost
  546. +.br
  547. + Flows are defined only by destination address. Could be useful on the
  548. +ingress path of an ISP backhaul.
  549. +.PP
  550. +.B hosts
  551. +.br
  552. + Flows are defined by source-destination host pairs. This is host
  553. +isolation, rather than flow isolation.
  554. +.PP
  555. +.B flows
  556. +.br
  557. + Flows are defined by the entire 5-tuple of source address, destination
  558. +address, transport protocol, source port and destination port. This is the type
  559. +of flow isolation performed by SFQ and fq_codel.
  560. +.PP
  561. +.B dual-srchost
  562. +.br
  563. + Flows are defined by the 5-tuple, and fairness is applied first over
  564. +source addresses, then over individual flows. Good for use on egress traffic
  565. +from a LAN to the internet, where it'll prevent any one LAN host from
  566. +monopolising the uplink, regardless of the number of flows they use.
  567. +.PP
  568. +.B dual-dsthost
  569. +.br
  570. + Flows are defined by the 5-tuple, and fairness is applied first over
  571. +destination addresses, then over individual flows. Good for use on ingress
  572. +traffic to a LAN from the internet, where it'll prevent any one LAN host from
  573. +monopolising the downlink, regardless of the number of flows they use.
  574. +.PP
  575. +.B triple-isolate
  576. +(default)
  577. +.br
  578. + Flows are defined by the 5-tuple, and fairness is applied over source
  579. +*and* destination addresses intelligently (ie. not merely by host-pairs), and
  580. +also over individual flows. Use this if you're not certain whether to use
  581. +dual-srchost or dual-dsthost; it'll do both jobs at once, preventing any one
  582. +host on *either* side of the link from monopolising it with a large number of
  583. +flows.
  584. +.PP
  585. +.B nat
  586. +.br
  587. + Instructs Cake to perform a NAT lookup before applying flow-isolation
  588. +rules, to determine the true addresses and port numbers of the packet, to
  589. +improve fairness between hosts "inside" the NAT. This has no practical effect
  590. +in "flowblind" or "flows" modes, or if NAT is performed on a different host.
  591. +.PP
  592. +.B nonat
  593. +(default)
  594. +.br
  595. + Cake will not perform a NAT lookup. Flow isolation will be performed
  596. +using the addresses and port numbers directly visible to the interface Cake is
  597. +attached to.
  598. +
  599. +.SH PRIORITY QUEUE PARAMETERS
  600. +CAKE can divide traffic into "tins" based on the Diffserv field. Each tin has
  601. +its own independent set of flow-isolation queues, and is serviced based on a WRR
  602. +algorithm. To avoid perverse Diffserv marking incentives, tin weights have a
  603. +"priority sharing" value when bandwidth used by that tin is below a threshold,
  604. +and a lower "bandwidth sharing" value when above. Bandwidth is compared against
  605. +the threshold using the same algorithm as the deficit-mode shaper.
  606. +
  607. +Detailed customisation of tin parameters is not provided. The following presets
  608. +perform all necessary tuning, relative to the current shaper bandwidth and RTT
  609. +settings.
  610. +.PP
  611. +.B besteffort
  612. +.br
  613. + Disables priority queuing by placing all traffic in one tin.
  614. +.PP
  615. +.B precedence
  616. +.br
  617. + Enables legacy interpretation of TOS "Precedence" field. Use of this
  618. +preset on the modern Internet is firmly discouraged.
  619. +.PP
  620. +.B diffserv4
  621. +.br
  622. + Provides a general-purpose Diffserv implementation with four tins:
  623. +.br
  624. + Bulk (CS1), 6.25% threshold, generally low priority.
  625. +.br
  626. + Best Effort (general), 100% threshold.
  627. +.br
  628. + Video (AF4x, AF3x, CS3, AF2x, CS2, TOS4, TOS1), 50% threshold.
  629. +.br
  630. + Voice (CS7, CS6, EF, VA, CS5, CS4), 25% threshold.
  631. +.PP
  632. +.B diffserv3
  633. +(default)
  634. +.br
  635. + Provides a simple, general-purpose Diffserv implementation with three tins:
  636. +.br
  637. + Bulk (CS1), 6.25% threshold, generally low priority.
  638. +.br
  639. + Best Effort (general), 100% threshold.
  640. +.br
  641. + Voice (CS7, CS6, EF, VA, TOS4), 25% threshold, reduced Codel interval.
  642. +
  643. +.SH OTHER PARAMETERS
  644. +.B memlimit
  645. +LIMIT
  646. +.br
  647. + Limit the memory consumed by Cake to LIMIT bytes. Note that this does
  648. +not translate directly to queue size (so do not size this based on bandwidth
  649. +delay product considerations, but rather on worst case acceptable memory
  650. +consumption), as there is some overhead in the data structures containing the
  651. +packets, especially for small packets.
  652. +
  653. + By default, the limit is calculated based on the bandwidth and RTT
  654. +settings.
  655. +
  656. +.PP
  657. +.B wash
  658. +
  659. +.br
  660. + Traffic entering your diffserv domain is frequently mis-marked in
  661. +transit from the perspective of your network, and traffic exiting yours may be
  662. +mis-marked from the perspective of the transiting provider.
  663. +
  664. +Apply the wash option to clear all extra diffserv (but not ECN bits), after
  665. +priority queuing has taken place.
  666. +
  667. +If you are shaping inbound, and cannot trust the diffserv markings (as is the
  668. +case for Comcast Cable, among others), it is best to use a single queue
  669. +"besteffort" mode with wash.
  670. +
  671. +.SH EXAMPLES
  672. +# tc qdisc delete root dev eth0
  673. +.br
  674. +# tc qdisc add root dev eth0 cake bandwidth 100Mbit ethernet
  675. +.br
  676. +# tc -s qdisc show dev eth0
  677. +.br
  678. +qdisc cake 1: root refcnt 2 bandwidth 100Mbit diffserv3 triple-isolate rtt 100.0ms noatm overhead 38 mpu 84
  679. + Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
  680. + backlog 0b 0p requeues 0
  681. + memory used: 0b of 5000000b
  682. + capacity estimate: 100Mbit
  683. + min/max network layer size: 65535 / 0
  684. + min/max overhead-adjusted size: 65535 / 0
  685. + average network hdr offset: 0
  686. +
  687. + Bulk Best Effort Voice
  688. + thresh 6250Kbit 100Mbit 25Mbit
  689. + target 5.0ms 5.0ms 5.0ms
  690. + interval 100.0ms 100.0ms 100.0ms
  691. + pk_delay 0us 0us 0us
  692. + av_delay 0us 0us 0us
  693. + sp_delay 0us 0us 0us
  694. + pkts 0 0 0
  695. + bytes 0 0 0
  696. + way_inds 0 0 0
  697. + way_miss 0 0 0
  698. + way_cols 0 0 0
  699. + drops 0 0 0
  700. + marks 0 0 0
  701. + ack_drop 0 0 0
  702. + sp_flows 0 0 0
  703. + bk_flows 0 0 0
  704. + un_flows 0 0 0
  705. + max_len 0 0 0
  706. + quantum 300 1514 762
  707. +
  708. +After some use:
  709. +.br
  710. +# tc -s qdisc show dev eth0
  711. +
  712. +qdisc cake 1: root refcnt 2 bandwidth 100Mbit diffserv3 triple-isolate rtt 100.0ms noatm overhead 38 mpu 84
  713. + Sent 44709231 bytes 31931 pkt (dropped 45, overlimits 93782 requeues 0)
  714. + backlog 33308b 22p requeues 0
  715. + memory used: 292352b of 5000000b
  716. + capacity estimate: 100Mbit
  717. + min/max network layer size: 28 / 1500
  718. + min/max overhead-adjusted size: 84 / 1538
  719. + average network hdr offset: 14
  720. +
  721. + Bulk Best Effort Voice
  722. + thresh 6250Kbit 100Mbit 25Mbit
  723. + target 5.0ms 5.0ms 5.0ms
  724. + interval 100.0ms 100.0ms 100.0ms
  725. + pk_delay 8.7ms 6.9ms 5.0ms
  726. + av_delay 4.9ms 5.3ms 3.8ms
  727. + sp_delay 727us 1.4ms 511us
  728. + pkts 2590 21271 8137
  729. + bytes 3081804 30302659 11426206
  730. + way_inds 0 46 0
  731. + way_miss 3 17 4
  732. + way_cols 0 0 0
  733. + drops 20 15 10
  734. + marks 0 0 0
  735. + ack_drop 0 0 0
  736. + sp_flows 2 4 1
  737. + bk_flows 1 2 1
  738. + un_flows 0 0 0
  739. + max_len 1514 1514 1514
  740. + quantum 300 1514 762
  741. +
  742. +.SH SEE ALSO
  743. +.BR tc (8),
  744. +.BR tc-codel (8),
  745. +.BR tc-fq_codel (8),
  746. +.BR tc-htb (8)
  747. +
  748. +.SH AUTHORS
  749. +Cake's principal author is Jonathan Morton, with contributions from
  750. +Tony Ambardar, Kevin Darbyshire-Bryant, Toke Høiland-Jørgensen,
  751. +Sebastian Moeller, Ryan Mounce, Dean Scarff, Nils Andreas Svee, and Dave Täht.
  752. +
  753. +This manual page was written by Loganaden Velvindron. Please report corrections
  754. +to the Linux Networking mailing list <[email protected]>.
  755. --- a/man/man8/tc.8
  756. +++ b/man/man8/tc.8
  757. @@ -795,6 +795,7 @@ was written by Alexey N. Kuznetsov and a
  758. .BR tc-basic (8),
  759. .BR tc-bfifo (8),
  760. .BR tc-bpf (8),
  761. +.BR tc-cake (8),
  762. .BR tc-cbq (8),
  763. .BR tc-cgroup (8),
  764. .BR tc-choke (8),
  765. --- a/tc/Makefile
  766. +++ b/tc/Makefile
  767. @@ -66,6 +66,7 @@ TCMODULES += q_codel.o
  768. TCMODULES += q_fq_codel.o
  769. TCMODULES += q_fq.o
  770. TCMODULES += q_pie.o
  771. +TCMODULES += q_cake.o
  772. TCMODULES += q_hhf.o
  773. TCMODULES += q_clsact.o
  774. TCMODULES += e_bpf.o
  775. --- /dev/null
  776. +++ b/tc/q_cake.c
  777. @@ -0,0 +1,799 @@
  778. +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  779. +
  780. +/*
  781. + * Common Applications Kept Enhanced -- CAKE
  782. + *
  783. + * Copyright (C) 2014-2018 Jonathan Morton <[email protected]>
  784. + * Copyright (C) 2017-2018 Toke Høiland-Jørgensen <[email protected]>
  785. + */
  786. +
  787. +#include <stddef.h>
  788. +#include <stdio.h>
  789. +#include <stdlib.h>
  790. +#include <unistd.h>
  791. +#include <syslog.h>
  792. +#include <fcntl.h>
  793. +#include <sys/socket.h>
  794. +#include <netinet/in.h>
  795. +#include <arpa/inet.h>
  796. +#include <string.h>
  797. +#include <inttypes.h>
  798. +
  799. +#include "utils.h"
  800. +#include "tc_util.h"
  801. +
  802. +struct cake_preset {
  803. + char *name;
  804. + unsigned int target;
  805. + unsigned int interval;
  806. +};
  807. +
  808. +static struct cake_preset presets[] = {
  809. + {"datacentre", 5, 100},
  810. + {"lan", 50, 1000},
  811. + {"metro", 500, 10000},
  812. + {"regional", 1500, 30000},
  813. + {"internet", 5000, 100000},
  814. + {"oceanic", 15000, 300000},
  815. + {"satellite", 50000, 1000000},
  816. + {"interplanetary", 50000000, 1000000000},
  817. +};
  818. +
  819. +static const char * diffserv_names[CAKE_DIFFSERV_MAX] = {
  820. + [CAKE_DIFFSERV_DIFFSERV3] = "diffserv3",
  821. + [CAKE_DIFFSERV_DIFFSERV4] = "diffserv4",
  822. + [CAKE_DIFFSERV_DIFFSERV8] = "diffserv8",
  823. + [CAKE_DIFFSERV_BESTEFFORT] = "besteffort",
  824. + [CAKE_DIFFSERV_PRECEDENCE] = "precedence",
  825. +};
  826. +
  827. +static const char * flowmode_names[CAKE_FLOW_MAX] = {
  828. + [CAKE_FLOW_NONE] = "flowblind",
  829. + [CAKE_FLOW_SRC_IP] = "srchost",
  830. + [CAKE_FLOW_DST_IP] = "dsthost",
  831. + [CAKE_FLOW_HOSTS] = "hosts",
  832. + [CAKE_FLOW_FLOWS] = "flows",
  833. + [CAKE_FLOW_DUAL_SRC] = "dual-srchost",
  834. + [CAKE_FLOW_DUAL_DST] = "dual-dsthost",
  835. + [CAKE_FLOW_TRIPLE] = "triple-isolate",
  836. +};
  837. +
  838. +static struct cake_preset *find_preset(char *argv)
  839. +{
  840. + int i;
  841. +
  842. + for (i = 0; i < ARRAY_SIZE(presets); i++)
  843. + if (!strcmp(argv, presets[i].name))
  844. + return &presets[i];
  845. + return NULL;
  846. +}
  847. +
  848. +static void explain(void)
  849. +{
  850. + fprintf(stderr,
  851. +"Usage: ... cake [ bandwidth RATE | unlimited* | autorate-ingress ]\n"
  852. +" [ rtt TIME | datacentre | lan | metro | regional |\n"
  853. +" internet* | oceanic | satellite | interplanetary ]\n"
  854. +" [ besteffort | diffserv8 | diffserv4 | diffserv3* ]\n"
  855. +" [ flowblind | srchost | dsthost | hosts | flows |\n"
  856. +" dual-srchost | dual-dsthost | triple-isolate* ]\n"
  857. +" [ nat | nonat* ]\n"
  858. +" [ wash | nowash* ]\n"
  859. +" [ split-gso* | no-split-gso ]\n"
  860. +" [ ack-filter | ack-filter-aggressive | no-ack-filter* ]\n"
  861. +" [ memlimit LIMIT ]\n"
  862. +" [ ptm | atm | noatm* ] [ overhead N | conservative | raw* ]\n"
  863. +" [ mpu N ] [ ingress | egress* ]\n"
  864. +" (* marks defaults)\n");
  865. +}
  866. +
  867. +static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
  868. + struct nlmsghdr *n, const char *dev)
  869. +{
  870. + struct cake_preset *preset, *preset_set = NULL;
  871. + bool overhead_override = false;
  872. + bool overhead_set = false;
  873. + unsigned int interval = 0;
  874. + unsigned int diffserv = 0;
  875. + unsigned int memlimit = 0;
  876. + unsigned int target = 0;
  877. + __u64 bandwidth = 0;
  878. + int ack_filter = -1;
  879. + struct rtattr *tail;
  880. + int unlimited = 0;
  881. + int flowmode = -1;
  882. + int autorate = -1;
  883. + int ingress = -1;
  884. + int overhead = 0;
  885. + int wash = -1;
  886. + int nat = -1;
  887. + int atm = -1;
  888. + int mpu = 0;
  889. + int split_gso = -1;
  890. +
  891. + while (argc > 0) {
  892. + if (strcmp(*argv, "bandwidth") == 0) {
  893. + NEXT_ARG();
  894. + if (get_rate64(&bandwidth, *argv)) {
  895. + fprintf(stderr, "Illegal \"bandwidth\"\n");
  896. + return -1;
  897. + }
  898. + unlimited = 0;
  899. + autorate = 0;
  900. + } else if (strcmp(*argv, "unlimited") == 0) {
  901. + bandwidth = 0;
  902. + unlimited = 1;
  903. + autorate = 0;
  904. + } else if (strcmp(*argv, "autorate-ingress") == 0) {
  905. + autorate = 1;
  906. + } else if (strcmp(*argv, "rtt") == 0) {
  907. + NEXT_ARG();
  908. + if (get_time(&interval, *argv)) {
  909. + fprintf(stderr, "Illegal \"rtt\"\n");
  910. + return -1;
  911. + }
  912. + target = interval / 20;
  913. + if (!target)
  914. + target = 1;
  915. + } else if ((preset = find_preset(*argv))) {
  916. + if (preset_set)
  917. + duparg(*argv, preset_set->name);
  918. + preset_set = preset;
  919. + target = preset->target;
  920. + interval = preset->interval;
  921. + } else if (strcmp(*argv, "besteffort") == 0) {
  922. + diffserv = CAKE_DIFFSERV_BESTEFFORT;
  923. + } else if (strcmp(*argv, "precedence") == 0) {
  924. + diffserv = CAKE_DIFFSERV_PRECEDENCE;
  925. + } else if (strcmp(*argv, "diffserv8") == 0) {
  926. + diffserv = CAKE_DIFFSERV_DIFFSERV8;
  927. + } else if (strcmp(*argv, "diffserv4") == 0) {
  928. + diffserv = CAKE_DIFFSERV_DIFFSERV4;
  929. + } else if (strcmp(*argv, "diffserv") == 0) {
  930. + diffserv = CAKE_DIFFSERV_DIFFSERV4;
  931. + } else if (strcmp(*argv, "diffserv3") == 0) {
  932. + diffserv = CAKE_DIFFSERV_DIFFSERV3;
  933. + } else if (strcmp(*argv, "nowash") == 0) {
  934. + wash = 0;
  935. + } else if (strcmp(*argv, "wash") == 0) {
  936. + wash = 1;
  937. + } else if (strcmp(*argv, "split-gso") == 0) {
  938. + split_gso = 1;
  939. + } else if (strcmp(*argv, "no-split-gso") == 0) {
  940. + split_gso = 0;
  941. + } else if (strcmp(*argv, "flowblind") == 0) {
  942. + flowmode = CAKE_FLOW_NONE;
  943. + } else if (strcmp(*argv, "srchost") == 0) {
  944. + flowmode = CAKE_FLOW_SRC_IP;
  945. + } else if (strcmp(*argv, "dsthost") == 0) {
  946. + flowmode = CAKE_FLOW_DST_IP;
  947. + } else if (strcmp(*argv, "hosts") == 0) {
  948. + flowmode = CAKE_FLOW_HOSTS;
  949. + } else if (strcmp(*argv, "flows") == 0) {
  950. + flowmode = CAKE_FLOW_FLOWS;
  951. + } else if (strcmp(*argv, "dual-srchost") == 0) {
  952. + flowmode = CAKE_FLOW_DUAL_SRC;
  953. + } else if (strcmp(*argv, "dual-dsthost") == 0) {
  954. + flowmode = CAKE_FLOW_DUAL_DST;
  955. + } else if (strcmp(*argv, "triple-isolate") == 0) {
  956. + flowmode = CAKE_FLOW_TRIPLE;
  957. + } else if (strcmp(*argv, "nat") == 0) {
  958. + nat = 1;
  959. + } else if (strcmp(*argv, "nonat") == 0) {
  960. + nat = 0;
  961. + } else if (strcmp(*argv, "ptm") == 0) {
  962. + atm = CAKE_ATM_PTM;
  963. + } else if (strcmp(*argv, "atm") == 0) {
  964. + atm = CAKE_ATM_ATM;
  965. + } else if (strcmp(*argv, "noatm") == 0) {
  966. + atm = CAKE_ATM_NONE;
  967. + } else if (strcmp(*argv, "raw") == 0) {
  968. + atm = CAKE_ATM_NONE;
  969. + overhead = 0;
  970. + overhead_set = true;
  971. + overhead_override = true;
  972. + } else if (strcmp(*argv, "conservative") == 0) {
  973. + /*
  974. + * Deliberately over-estimate overhead:
  975. + * one whole ATM cell plus ATM framing.
  976. + * A safe choice if the actual overhead is unknown.
  977. + */
  978. + atm = CAKE_ATM_ATM;
  979. + overhead = 48;
  980. + overhead_set = true;
  981. +
  982. + /* Various ADSL framing schemes, all over ATM cells */
  983. + } else if (strcmp(*argv, "ipoa-vcmux") == 0) {
  984. + atm = CAKE_ATM_ATM;
  985. + overhead += 8;
  986. + overhead_set = true;
  987. + } else if (strcmp(*argv, "ipoa-llcsnap") == 0) {
  988. + atm = CAKE_ATM_ATM;
  989. + overhead += 16;
  990. + overhead_set = true;
  991. + } else if (strcmp(*argv, "bridged-vcmux") == 0) {
  992. + atm = CAKE_ATM_ATM;
  993. + overhead += 24;
  994. + overhead_set = true;
  995. + } else if (strcmp(*argv, "bridged-llcsnap") == 0) {
  996. + atm = CAKE_ATM_ATM;
  997. + overhead += 32;
  998. + overhead_set = true;
  999. + } else if (strcmp(*argv, "pppoa-vcmux") == 0) {
  1000. + atm = CAKE_ATM_ATM;
  1001. + overhead += 10;
  1002. + overhead_set = true;
  1003. + } else if (strcmp(*argv, "pppoa-llc") == 0) {
  1004. + atm = CAKE_ATM_ATM;
  1005. + overhead += 14;
  1006. + overhead_set = true;
  1007. + } else if (strcmp(*argv, "pppoe-vcmux") == 0) {
  1008. + atm = CAKE_ATM_ATM;
  1009. + overhead += 32;
  1010. + overhead_set = true;
  1011. + } else if (strcmp(*argv, "pppoe-llcsnap") == 0) {
  1012. + atm = CAKE_ATM_ATM;
  1013. + overhead += 40;
  1014. + overhead_set = true;
  1015. +
  1016. + /* Typical VDSL2 framing schemes, both over PTM */
  1017. + /* PTM has 64b/65b coding which absorbs some bandwidth */
  1018. + } else if (strcmp(*argv, "pppoe-ptm") == 0) {
  1019. + /* 2B PPP + 6B PPPoE + 6B dest MAC + 6B src MAC
  1020. + * + 2B ethertype + 4B Frame Check Sequence
  1021. + * + 1B Start of Frame (S) + 1B End of Frame (Ck)
  1022. + * + 2B TC-CRC (PTM-FCS) = 30B
  1023. + */
  1024. + atm = CAKE_ATM_PTM;
  1025. + overhead += 30;
  1026. + overhead_set = true;
  1027. + } else if (strcmp(*argv, "bridged-ptm") == 0) {
  1028. + /* 6B dest MAC + 6B src MAC + 2B ethertype
  1029. + * + 4B Frame Check Sequence
  1030. + * + 1B Start of Frame (S) + 1B End of Frame (Ck)
  1031. + * + 2B TC-CRC (PTM-FCS) = 22B
  1032. + */
  1033. + atm = CAKE_ATM_PTM;
  1034. + overhead += 22;
  1035. + overhead_set = true;
  1036. + } else if (strcmp(*argv, "via-ethernet") == 0) {
  1037. + /*
  1038. + * We used to use this flag to manually compensate for
  1039. + * Linux including the Ethernet header on Ethernet-type
  1040. + * interfaces, but not on IP-type interfaces.
  1041. + *
  1042. + * It is no longer needed, because Cake now adjusts for
  1043. + * that automatically, and is thus ignored.
  1044. + *
  1045. + * It would be deleted entirely, but it appears in the
  1046. + * stats output when the automatic compensation is
  1047. + * active.
  1048. + */
  1049. + } else if (strcmp(*argv, "ethernet") == 0) {
  1050. + /* ethernet pre-amble & interframe gap & FCS
  1051. + * you may need to add vlan tag
  1052. + */
  1053. + overhead += 38;
  1054. + overhead_set = true;
  1055. + mpu = 84;
  1056. +
  1057. + /* Additional Ethernet-related overhead used by some ISPs */
  1058. + } else if (strcmp(*argv, "ether-vlan") == 0) {
  1059. + /* 802.1q VLAN tag - may be repeated */
  1060. + overhead += 4;
  1061. + overhead_set = true;
  1062. +
  1063. + /*
  1064. + * DOCSIS cable shapers account for Ethernet frame with FCS,
  1065. + * but not interframe gap or preamble.
  1066. + */
  1067. + } else if (strcmp(*argv, "docsis") == 0) {
  1068. + atm = CAKE_ATM_NONE;
  1069. + overhead += 18;
  1070. + overhead_set = true;
  1071. + mpu = 64;
  1072. + } else if (strcmp(*argv, "overhead") == 0) {
  1073. + char *p = NULL;
  1074. +
  1075. + NEXT_ARG();
  1076. + overhead = strtol(*argv, &p, 10);
  1077. + if (!p || *p || !*argv ||
  1078. + overhead < -64 || overhead > 256) {
  1079. + fprintf(stderr,
  1080. + "Illegal \"overhead\", valid range is -64 to 256\\n");
  1081. + return -1;
  1082. + }
  1083. + overhead_set = true;
  1084. +
  1085. + } else if (strcmp(*argv, "mpu") == 0) {
  1086. + char *p = NULL;
  1087. +
  1088. + NEXT_ARG();
  1089. + mpu = strtol(*argv, &p, 10);
  1090. + if (!p || *p || !*argv || mpu < 0 || mpu > 256) {
  1091. + fprintf(stderr,
  1092. + "Illegal \"mpu\", valid range is 0 to 256\\n");
  1093. + return -1;
  1094. + }
  1095. + } else if (strcmp(*argv, "ingress") == 0) {
  1096. + ingress = 1;
  1097. + } else if (strcmp(*argv, "egress") == 0) {
  1098. + ingress = 0;
  1099. + } else if (strcmp(*argv, "no-ack-filter") == 0) {
  1100. + ack_filter = CAKE_ACK_NONE;
  1101. + } else if (strcmp(*argv, "ack-filter") == 0) {
  1102. + ack_filter = CAKE_ACK_FILTER;
  1103. + } else if (strcmp(*argv, "ack-filter-aggressive") == 0) {
  1104. + ack_filter = CAKE_ACK_AGGRESSIVE;
  1105. + } else if (strcmp(*argv, "memlimit") == 0) {
  1106. + NEXT_ARG();
  1107. + if (get_size(&memlimit, *argv)) {
  1108. + fprintf(stderr,
  1109. + "Illegal value for \"memlimit\": \"%s\"\n", *argv);
  1110. + return -1;
  1111. + }
  1112. + } else if (strcmp(*argv, "help") == 0) {
  1113. + explain();
  1114. + return -1;
  1115. + } else {
  1116. + fprintf(stderr, "What is \"%s\"?\n", *argv);
  1117. + explain();
  1118. + return -1;
  1119. + }
  1120. + argc--; argv++;
  1121. + }
  1122. +
  1123. + tail = NLMSG_TAIL(n);
  1124. + addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
  1125. + if (bandwidth || unlimited)
  1126. + addattr_l(n, 1024, TCA_CAKE_BASE_RATE64, &bandwidth,
  1127. + sizeof(bandwidth));
  1128. + if (diffserv)
  1129. + addattr_l(n, 1024, TCA_CAKE_DIFFSERV_MODE, &diffserv,
  1130. + sizeof(diffserv));
  1131. + if (atm != -1)
  1132. + addattr_l(n, 1024, TCA_CAKE_ATM, &atm, sizeof(atm));
  1133. + if (flowmode != -1)
  1134. + addattr_l(n, 1024, TCA_CAKE_FLOW_MODE, &flowmode,
  1135. + sizeof(flowmode));
  1136. + if (overhead_set)
  1137. + addattr_l(n, 1024, TCA_CAKE_OVERHEAD, &overhead,
  1138. + sizeof(overhead));
  1139. + if (overhead_override) {
  1140. + unsigned int zero = 0;
  1141. +
  1142. + addattr_l(n, 1024, TCA_CAKE_RAW, &zero, sizeof(zero));
  1143. + }
  1144. + if (mpu > 0)
  1145. + addattr_l(n, 1024, TCA_CAKE_MPU, &mpu, sizeof(mpu));
  1146. + if (interval)
  1147. + addattr_l(n, 1024, TCA_CAKE_RTT, &interval, sizeof(interval));
  1148. + if (target)
  1149. + addattr_l(n, 1024, TCA_CAKE_TARGET, &target, sizeof(target));
  1150. + if (autorate != -1)
  1151. + addattr_l(n, 1024, TCA_CAKE_AUTORATE, &autorate,
  1152. + sizeof(autorate));
  1153. + if (memlimit)
  1154. + addattr_l(n, 1024, TCA_CAKE_MEMORY, &memlimit,
  1155. + sizeof(memlimit));
  1156. + if (nat != -1)
  1157. + addattr_l(n, 1024, TCA_CAKE_NAT, &nat, sizeof(nat));
  1158. + if (wash != -1)
  1159. + addattr_l(n, 1024, TCA_CAKE_WASH, &wash, sizeof(wash));
  1160. + if (split_gso != -1)
  1161. + addattr_l(n, 1024, TCA_CAKE_SPLIT_GSO, &split_gso,
  1162. + sizeof(split_gso));
  1163. + if (ingress != -1)
  1164. + addattr_l(n, 1024, TCA_CAKE_INGRESS, &ingress, sizeof(ingress));
  1165. + if (ack_filter != -1)
  1166. + addattr_l(n, 1024, TCA_CAKE_ACK_FILTER, &ack_filter,
  1167. + sizeof(ack_filter));
  1168. +
  1169. + tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
  1170. + return 0;
  1171. +}
  1172. +
  1173. +static void cake_print_mode(unsigned int value, unsigned int max,
  1174. + const char *key, const char **table)
  1175. +{
  1176. + if (value < max && table[value]) {
  1177. + print_string(PRINT_ANY, key, "%s ", table[value]);
  1178. + } else {
  1179. + print_string(PRINT_JSON, key, NULL, "unknown");
  1180. + print_string(PRINT_FP, NULL, "(?%s?)", key);
  1181. + }
  1182. +}
  1183. +
  1184. +static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
  1185. +{
  1186. + struct rtattr *tb[TCA_CAKE_MAX + 1];
  1187. + unsigned int interval = 0;
  1188. + unsigned int memlimit = 0;
  1189. + __u64 bandwidth = 0;
  1190. + int ack_filter = 0;
  1191. + int split_gso = 0;
  1192. + int overhead = 0;
  1193. + int autorate = 0;
  1194. + int ingress = 0;
  1195. + int wash = 0;
  1196. + int raw = 0;
  1197. + int mpu = 0;
  1198. + int atm = 0;
  1199. + int nat = 0;
  1200. +
  1201. + SPRINT_BUF(b1);
  1202. + SPRINT_BUF(b2);
  1203. +
  1204. + if (opt == NULL)
  1205. + return 0;
  1206. +
  1207. + parse_rtattr_nested(tb, TCA_CAKE_MAX, opt);
  1208. +
  1209. + if (tb[TCA_CAKE_BASE_RATE64] &&
  1210. + RTA_PAYLOAD(tb[TCA_CAKE_BASE_RATE64]) >= sizeof(bandwidth)) {
  1211. + bandwidth = rta_getattr_u64(tb[TCA_CAKE_BASE_RATE64]);
  1212. + if (bandwidth) {
  1213. + print_uint(PRINT_JSON, "bandwidth", NULL, bandwidth);
  1214. + print_string(PRINT_FP, NULL, "bandwidth %s ",
  1215. + sprint_rate(bandwidth, b1));
  1216. + } else
  1217. + print_string(PRINT_ANY, "bandwidth", "bandwidth %s ",
  1218. + "unlimited");
  1219. + }
  1220. + if (tb[TCA_CAKE_AUTORATE] &&
  1221. + RTA_PAYLOAD(tb[TCA_CAKE_AUTORATE]) >= sizeof(__u32)) {
  1222. + autorate = rta_getattr_u32(tb[TCA_CAKE_AUTORATE]);
  1223. + if (autorate == 1)
  1224. + print_string(PRINT_ANY, "autorate", "%s ",
  1225. + "autorate-ingress");
  1226. + else if (autorate)
  1227. + print_string(PRINT_ANY, "autorate", "(?autorate?) ",
  1228. + "unknown");
  1229. + }
  1230. + if (tb[TCA_CAKE_DIFFSERV_MODE] &&
  1231. + RTA_PAYLOAD(tb[TCA_CAKE_DIFFSERV_MODE]) >= sizeof(__u32)) {
  1232. + cake_print_mode(rta_getattr_u32(tb[TCA_CAKE_DIFFSERV_MODE]),
  1233. + CAKE_DIFFSERV_MAX, "diffserv", diffserv_names);
  1234. + }
  1235. + if (tb[TCA_CAKE_FLOW_MODE] &&
  1236. + RTA_PAYLOAD(tb[TCA_CAKE_FLOW_MODE]) >= sizeof(__u32)) {
  1237. + cake_print_mode(rta_getattr_u32(tb[TCA_CAKE_FLOW_MODE]),
  1238. + CAKE_FLOW_MAX, "flowmode", flowmode_names);
  1239. + }
  1240. +
  1241. + if (tb[TCA_CAKE_NAT] &&
  1242. + RTA_PAYLOAD(tb[TCA_CAKE_NAT]) >= sizeof(__u32)) {
  1243. + nat = rta_getattr_u32(tb[TCA_CAKE_NAT]);
  1244. + }
  1245. +
  1246. + if (nat)
  1247. + print_string(PRINT_FP, NULL, "nat ", NULL);
  1248. + print_bool(PRINT_JSON, "nat", NULL, nat);
  1249. +
  1250. + if (tb[TCA_CAKE_WASH] &&
  1251. + RTA_PAYLOAD(tb[TCA_CAKE_WASH]) >= sizeof(__u32)) {
  1252. + wash = rta_getattr_u32(tb[TCA_CAKE_WASH]);
  1253. + }
  1254. + if (tb[TCA_CAKE_ATM] &&
  1255. + RTA_PAYLOAD(tb[TCA_CAKE_ATM]) >= sizeof(__u32)) {
  1256. + atm = rta_getattr_u32(tb[TCA_CAKE_ATM]);
  1257. + }
  1258. + if (tb[TCA_CAKE_OVERHEAD] &&
  1259. + RTA_PAYLOAD(tb[TCA_CAKE_OVERHEAD]) >= sizeof(__s32)) {
  1260. + overhead = *(__s32 *) RTA_DATA(tb[TCA_CAKE_OVERHEAD]);
  1261. + }
  1262. + if (tb[TCA_CAKE_MPU] &&
  1263. + RTA_PAYLOAD(tb[TCA_CAKE_MPU]) >= sizeof(__u32)) {
  1264. + mpu = rta_getattr_u32(tb[TCA_CAKE_MPU]);
  1265. + }
  1266. + if (tb[TCA_CAKE_INGRESS] &&
  1267. + RTA_PAYLOAD(tb[TCA_CAKE_INGRESS]) >= sizeof(__u32)) {
  1268. + ingress = rta_getattr_u32(tb[TCA_CAKE_INGRESS]);
  1269. + }
  1270. + if (tb[TCA_CAKE_ACK_FILTER] &&
  1271. + RTA_PAYLOAD(tb[TCA_CAKE_ACK_FILTER]) >= sizeof(__u32)) {
  1272. + ack_filter = rta_getattr_u32(tb[TCA_CAKE_ACK_FILTER]);
  1273. + }
  1274. + if (tb[TCA_CAKE_SPLIT_GSO] &&
  1275. + RTA_PAYLOAD(tb[TCA_CAKE_SPLIT_GSO]) >= sizeof(__u32)) {
  1276. + split_gso = rta_getattr_u32(tb[TCA_CAKE_SPLIT_GSO]);
  1277. + }
  1278. + if (tb[TCA_CAKE_RAW]) {
  1279. + raw = 1;
  1280. + }
  1281. + if (tb[TCA_CAKE_RTT] &&
  1282. + RTA_PAYLOAD(tb[TCA_CAKE_RTT]) >= sizeof(__u32)) {
  1283. + interval = rta_getattr_u32(tb[TCA_CAKE_RTT]);
  1284. + }
  1285. +
  1286. + if (wash)
  1287. + print_string(PRINT_FP, NULL, "wash ", NULL);
  1288. + print_bool(PRINT_JSON, "wash", NULL, wash);
  1289. +
  1290. + if (ingress)
  1291. + print_string(PRINT_FP, NULL, "ingress ", NULL);
  1292. + print_bool(PRINT_JSON, "ingress", NULL, ingress);
  1293. +
  1294. + if (ack_filter == CAKE_ACK_AGGRESSIVE)
  1295. + print_string(PRINT_ANY, "ack-filter", "ack-filter-%s ",
  1296. + "aggressive");
  1297. + else if (ack_filter == CAKE_ACK_FILTER)
  1298. + print_string(PRINT_ANY, "ack-filter", "ack-filter ", "enabled");
  1299. + else
  1300. + print_string(PRINT_JSON, "ack-filter", NULL, "disabled");
  1301. +
  1302. + if (split_gso)
  1303. + print_string(PRINT_FP, NULL, "split-gso ", NULL);
  1304. + print_bool(PRINT_JSON, "split_gso", NULL, split_gso);
  1305. +
  1306. + if (interval)
  1307. + print_string(PRINT_FP, NULL, "rtt %s ",
  1308. + sprint_time(interval, b2));
  1309. + print_uint(PRINT_JSON, "rtt", NULL, interval);
  1310. +
  1311. + if (raw)
  1312. + print_string(PRINT_FP, NULL, "raw ", NULL);
  1313. + print_bool(PRINT_JSON, "raw", NULL, raw);
  1314. +
  1315. + if (atm == CAKE_ATM_ATM)
  1316. + print_string(PRINT_ANY, "atm", "%s ", "atm");
  1317. + else if (atm == CAKE_ATM_PTM)
  1318. + print_string(PRINT_ANY, "atm", "%s ", "ptm");
  1319. + else if (!raw)
  1320. + print_string(PRINT_ANY, "atm", "%s ", "noatm");
  1321. +
  1322. + print_int(PRINT_ANY, "overhead", "overhead %d ", overhead);
  1323. +
  1324. + if (mpu)
  1325. + print_uint(PRINT_ANY, "mpu", "mpu %u ", mpu);
  1326. +
  1327. + if (memlimit) {
  1328. + print_uint(PRINT_JSON, "memlimit", NULL, memlimit);
  1329. + print_string(PRINT_FP, NULL, "memlimit %s",
  1330. + sprint_size(memlimit, b1));
  1331. + }
  1332. +
  1333. + return 0;
  1334. +}
  1335. +
  1336. +static void cake_print_json_tin(struct rtattr **tstat)
  1337. +{
  1338. +#define PRINT_TSTAT_JSON(type, name, attr) if (tstat[TCA_CAKE_TIN_STATS_ ## attr]) \
  1339. + print_u64(PRINT_JSON, name, NULL, \
  1340. + rta_getattr_ ## type((struct rtattr *) \
  1341. + tstat[TCA_CAKE_TIN_STATS_ ## attr]))
  1342. +
  1343. + open_json_object(NULL);
  1344. + PRINT_TSTAT_JSON(u64, "threshold_rate", THRESHOLD_RATE64);
  1345. + PRINT_TSTAT_JSON(u64, "sent_bytes", SENT_BYTES64);
  1346. + PRINT_TSTAT_JSON(u32, "backlog_bytes", BACKLOG_BYTES);
  1347. + PRINT_TSTAT_JSON(u32, "target_us", TARGET_US);
  1348. + PRINT_TSTAT_JSON(u32, "interval_us", INTERVAL_US);
  1349. + PRINT_TSTAT_JSON(u32, "peak_delay_us", PEAK_DELAY_US);
  1350. + PRINT_TSTAT_JSON(u32, "avg_delay_us", AVG_DELAY_US);
  1351. + PRINT_TSTAT_JSON(u32, "base_delay_us", BASE_DELAY_US);
  1352. + PRINT_TSTAT_JSON(u32, "sent_packets", SENT_PACKETS);
  1353. + PRINT_TSTAT_JSON(u32, "way_indirect_hits", WAY_INDIRECT_HITS);
  1354. + PRINT_TSTAT_JSON(u32, "way_misses", WAY_MISSES);
  1355. + PRINT_TSTAT_JSON(u32, "way_collisions", WAY_COLLISIONS);
  1356. + PRINT_TSTAT_JSON(u32, "drops", DROPPED_PACKETS);
  1357. + PRINT_TSTAT_JSON(u32, "ecn_mark", ECN_MARKED_PACKETS);
  1358. + PRINT_TSTAT_JSON(u32, "ack_drops", ACKS_DROPPED_PACKETS);
  1359. + PRINT_TSTAT_JSON(u32, "sparse_flows", SPARSE_FLOWS);
  1360. + PRINT_TSTAT_JSON(u32, "bulk_flows", BULK_FLOWS);
  1361. + PRINT_TSTAT_JSON(u32, "unresponsive_flows", UNRESPONSIVE_FLOWS);
  1362. + PRINT_TSTAT_JSON(u32, "max_pkt_len", MAX_SKBLEN);
  1363. + PRINT_TSTAT_JSON(u32, "flow_quantum", FLOW_QUANTUM);
  1364. + close_json_object();
  1365. +
  1366. +#undef PRINT_TSTAT_JSON
  1367. +}
  1368. +
  1369. +static int cake_print_xstats(struct qdisc_util *qu, FILE *f,
  1370. + struct rtattr *xstats)
  1371. +{
  1372. + struct rtattr *st[TCA_CAKE_STATS_MAX + 1];
  1373. + SPRINT_BUF(b1);
  1374. + int i;
  1375. +
  1376. + if (xstats == NULL)
  1377. + return 0;
  1378. +
  1379. +#define GET_STAT_U32(attr) rta_getattr_u32(st[TCA_CAKE_STATS_ ## attr])
  1380. +#define GET_STAT_S32(attr) (*(__s32 *)RTA_DATA(st[TCA_CAKE_STATS_ ## attr]))
  1381. +#define GET_STAT_U64(attr) rta_getattr_u64(st[TCA_CAKE_STATS_ ## attr])
  1382. +
  1383. + parse_rtattr_nested(st, TCA_CAKE_STATS_MAX, xstats);
  1384. +
  1385. + if (st[TCA_CAKE_STATS_MEMORY_USED] &&
  1386. + st[TCA_CAKE_STATS_MEMORY_LIMIT]) {
  1387. + print_string(PRINT_FP, NULL, " memory used: %s",
  1388. + sprint_size(GET_STAT_U32(MEMORY_USED), b1));
  1389. +
  1390. + print_string(PRINT_FP, NULL, " of %s\n",
  1391. + sprint_size(GET_STAT_U32(MEMORY_LIMIT), b1));
  1392. +
  1393. + print_uint(PRINT_JSON, "memory_used", NULL,
  1394. + GET_STAT_U32(MEMORY_USED));
  1395. + print_uint(PRINT_JSON, "memory_limit", NULL,
  1396. + GET_STAT_U32(MEMORY_LIMIT));
  1397. + }
  1398. +
  1399. + if (st[TCA_CAKE_STATS_CAPACITY_ESTIMATE64]) {
  1400. + print_string(PRINT_FP, NULL, " capacity estimate: %s\n",
  1401. + sprint_rate(GET_STAT_U64(CAPACITY_ESTIMATE64), b1));
  1402. + print_uint(PRINT_JSON, "capacity_estimate", NULL,
  1403. + GET_STAT_U64(CAPACITY_ESTIMATE64));
  1404. + }
  1405. +
  1406. + if (st[TCA_CAKE_STATS_MIN_NETLEN] &&
  1407. + st[TCA_CAKE_STATS_MAX_NETLEN]) {
  1408. + print_uint(PRINT_ANY, "min_network_size",
  1409. + " min/max network layer size: %12u",
  1410. + GET_STAT_U32(MIN_NETLEN));
  1411. + print_uint(PRINT_ANY, "max_network_size",
  1412. + " /%8u\n", GET_STAT_U32(MAX_NETLEN));
  1413. + }
  1414. +
  1415. + if (st[TCA_CAKE_STATS_MIN_ADJLEN] &&
  1416. + st[TCA_CAKE_STATS_MAX_ADJLEN]) {
  1417. + print_uint(PRINT_ANY, "min_adj_size",
  1418. + " min/max overhead-adjusted size: %8u",
  1419. + GET_STAT_U32(MIN_ADJLEN));
  1420. + print_uint(PRINT_ANY, "max_adj_size",
  1421. + " /%8u\n", GET_STAT_U32(MAX_ADJLEN));
  1422. + }
  1423. +
  1424. + if (st[TCA_CAKE_STATS_AVG_NETOFF])
  1425. + print_uint(PRINT_ANY, "avg_hdr_offset",
  1426. + " average network hdr offset: %12u\n\n",
  1427. + GET_STAT_U32(AVG_NETOFF));
  1428. +
  1429. + /* class stats */
  1430. + if (st[TCA_CAKE_STATS_DEFICIT])
  1431. + print_int(PRINT_ANY, "deficit", " deficit %u",
  1432. + GET_STAT_S32(DEFICIT));
  1433. + if (st[TCA_CAKE_STATS_COBALT_COUNT])
  1434. + print_uint(PRINT_ANY, "count", " count %u",
  1435. + GET_STAT_U32(COBALT_COUNT));
  1436. +
  1437. + if (st[TCA_CAKE_STATS_DROPPING] && GET_STAT_U32(DROPPING)) {
  1438. + print_bool(PRINT_ANY, "dropping", " dropping", true);
  1439. + if (st[TCA_CAKE_STATS_DROP_NEXT_US]) {
  1440. + int drop_next = GET_STAT_S32(DROP_NEXT_US);
  1441. +
  1442. + if (drop_next < 0) {
  1443. + print_string(PRINT_FP, NULL, " drop_next -%s",
  1444. + sprint_time(drop_next, b1));
  1445. + } else {
  1446. + print_uint(PRINT_JSON, "drop_next", NULL,
  1447. + drop_next);
  1448. + print_string(PRINT_FP, NULL, " drop_next %s",
  1449. + sprint_time(drop_next, b1));
  1450. + }
  1451. + }
  1452. + }
  1453. +
  1454. + if (st[TCA_CAKE_STATS_P_DROP]) {
  1455. + print_uint(PRINT_ANY, "blue_prob", " blue_prob %u",
  1456. + GET_STAT_U32(P_DROP));
  1457. + if (st[TCA_CAKE_STATS_BLUE_TIMER_US]) {
  1458. + int blue_timer = GET_STAT_S32(BLUE_TIMER_US);
  1459. +
  1460. + if (blue_timer < 0) {
  1461. + print_string(PRINT_FP, NULL, " blue_timer -%s",
  1462. + sprint_time(blue_timer, b1));
  1463. + } else {
  1464. + print_uint(PRINT_JSON, "blue_timer", NULL,
  1465. + blue_timer);
  1466. + print_string(PRINT_FP, NULL, " blue_timer %s",
  1467. + sprint_time(blue_timer, b1));
  1468. + }
  1469. + }
  1470. + }
  1471. +
  1472. +#undef GET_STAT_U32
  1473. +#undef GET_STAT_S32
  1474. +#undef GET_STAT_U64
  1475. +
  1476. + if (st[TCA_CAKE_STATS_TIN_STATS]) {
  1477. + struct rtattr *tstat[TC_CAKE_MAX_TINS][TCA_CAKE_TIN_STATS_MAX + 1];
  1478. + struct rtattr *tins[TC_CAKE_MAX_TINS + 1];
  1479. + int num_tins = 0;
  1480. +
  1481. + parse_rtattr_nested(tins, TC_CAKE_MAX_TINS,
  1482. + st[TCA_CAKE_STATS_TIN_STATS]);
  1483. +
  1484. + for (i = 1; i <= TC_CAKE_MAX_TINS && tins[i]; i++) {
  1485. + parse_rtattr_nested(tstat[i-1], TCA_CAKE_TIN_STATS_MAX,
  1486. + tins[i]);
  1487. + num_tins++;
  1488. + }
  1489. +
  1490. + if (!num_tins)
  1491. + return 0;
  1492. +
  1493. + if (is_json_context()) {
  1494. + open_json_array(PRINT_JSON, "tins");
  1495. + for (i = 0; i < num_tins; i++)
  1496. + cake_print_json_tin(tstat[i]);
  1497. + close_json_array(PRINT_JSON, NULL);
  1498. +
  1499. + return 0;
  1500. + }
  1501. +
  1502. +
  1503. + switch (num_tins) {
  1504. + case 3:
  1505. + fprintf(f, " Bulk Best Effort Voice\n");
  1506. + break;
  1507. +
  1508. + case 4:
  1509. + fprintf(f, " Bulk Best Effort Video Voice\n");
  1510. + break;
  1511. +
  1512. + default:
  1513. + fprintf(f, " ");
  1514. + for (i = 0; i < num_tins; i++)
  1515. + fprintf(f, " Tin %u", i);
  1516. + fprintf(f, "\n");
  1517. + };
  1518. +
  1519. +#define GET_TSTAT(i, attr) (tstat[i][TCA_CAKE_TIN_STATS_ ## attr])
  1520. +#define PRINT_TSTAT(name, attr, fmts, val) do { \
  1521. + if (GET_TSTAT(0, attr)) { \
  1522. + fprintf(f, name); \
  1523. + for (i = 0; i < num_tins; i++) \
  1524. + fprintf(f, " %12" fmts, val); \
  1525. + fprintf(f, "\n"); \
  1526. + } \
  1527. + } while (0)
  1528. +
  1529. +#define SPRINT_TSTAT(pfunc, type, name, attr) PRINT_TSTAT( \
  1530. + name, attr, "s", sprint_ ## pfunc( \
  1531. + rta_getattr_ ## type(GET_TSTAT(i, attr)), b1))
  1532. +
  1533. +#define PRINT_TSTAT_U32(name, attr) PRINT_TSTAT( \
  1534. + name, attr, "u", rta_getattr_u32(GET_TSTAT(i, attr)))
  1535. +
  1536. +#define PRINT_TSTAT_U64(name, attr) PRINT_TSTAT( \
  1537. + name, attr, "llu", rta_getattr_u64(GET_TSTAT(i, attr)))
  1538. +
  1539. + SPRINT_TSTAT(rate, u64, " thresh ", THRESHOLD_RATE64);
  1540. + SPRINT_TSTAT(time, u32, " target ", TARGET_US);
  1541. + SPRINT_TSTAT(time, u32, " interval", INTERVAL_US);
  1542. + SPRINT_TSTAT(time, u32, " pk_delay", PEAK_DELAY_US);
  1543. + SPRINT_TSTAT(time, u32, " av_delay", AVG_DELAY_US);
  1544. + SPRINT_TSTAT(time, u32, " sp_delay", BASE_DELAY_US);
  1545. + SPRINT_TSTAT(size, u32, " backlog ", BACKLOG_BYTES);
  1546. +
  1547. + PRINT_TSTAT_U32(" pkts ", SENT_PACKETS);
  1548. + PRINT_TSTAT_U64(" bytes ", SENT_BYTES64);
  1549. +
  1550. + PRINT_TSTAT_U32(" way_inds", WAY_INDIRECT_HITS);
  1551. + PRINT_TSTAT_U32(" way_miss", WAY_MISSES);
  1552. + PRINT_TSTAT_U32(" way_cols", WAY_COLLISIONS);
  1553. + PRINT_TSTAT_U32(" drops ", DROPPED_PACKETS);
  1554. + PRINT_TSTAT_U32(" marks ", ECN_MARKED_PACKETS);
  1555. + PRINT_TSTAT_U32(" ack_drop", ACKS_DROPPED_PACKETS);
  1556. + PRINT_TSTAT_U32(" sp_flows", SPARSE_FLOWS);
  1557. + PRINT_TSTAT_U32(" bk_flows", BULK_FLOWS);
  1558. + PRINT_TSTAT_U32(" un_flows", UNRESPONSIVE_FLOWS);
  1559. + PRINT_TSTAT_U32(" max_len ", MAX_SKBLEN);
  1560. + PRINT_TSTAT_U32(" quantum ", FLOW_QUANTUM);
  1561. +
  1562. +#undef GET_STAT
  1563. +#undef PRINT_TSTAT
  1564. +#undef SPRINT_TSTAT
  1565. +#undef PRINT_TSTAT_U32
  1566. +#undef PRINT_TSTAT_U64
  1567. + }
  1568. + return 0;
  1569. +}
  1570. +
  1571. +struct qdisc_util cake_qdisc_util = {
  1572. + .id = "cake",
  1573. + .parse_qopt = cake_parse_opt,
  1574. + .print_qopt = cake_print_opt,
  1575. + .print_xstats = cake_print_xstats,
  1576. +};