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