Imported Upstream version 5.5.0
[platform/upstream/iproute2.git] / tc / q_fq.c
1 /*
2  * Fair Queue
3  *
4  *  Copyright (C) 2013-2015 Eric Dumazet <edumazet@google.com>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions, and the following disclaimer,
11  *    without modification.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The names of the authors may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * Alternatively, provided that this notice is retained in full, this
19  * software may be distributed under the terms of the GNU General
20  * Public License ("GPL") version 2, in which case the provisions of the
21  * GPL apply INSTEAD OF those given above.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
34  * DAMAGE.
35  *
36  */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <string.h>
46 #include <stdbool.h>
47
48 #include "utils.h"
49 #include "tc_util.h"
50
51 static void explain(void)
52 {
53         fprintf(stderr,
54                 "Usage: ... fq  [ limit PACKETS ] [ flow_limit PACKETS ]\n"
55                 "               [ quantum BYTES ] [ initial_quantum BYTES ]\n"
56                 "               [ maxrate RATE  ] [ buckets NUMBER ]\n"
57                 "               [ [no]pacing ] [ refill_delay TIME ]\n"
58                 "               [ low_rate_threshold RATE ]\n"
59                 "               [ orphan_mask MASK]\n"
60                 "               [ ce_threshold TIME ]\n");
61 }
62
63 static unsigned int ilog2(unsigned int val)
64 {
65         unsigned int res = 0;
66
67         val--;
68         while (val) {
69                 res++;
70                 val >>= 1;
71         }
72         return res;
73 }
74
75 static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv,
76                         struct nlmsghdr *n, const char *dev)
77 {
78         unsigned int plimit;
79         unsigned int flow_plimit;
80         unsigned int quantum;
81         unsigned int initial_quantum;
82         unsigned int buckets = 0;
83         unsigned int maxrate;
84         unsigned int low_rate_threshold;
85         unsigned int defrate;
86         unsigned int refill_delay;
87         unsigned int orphan_mask;
88         unsigned int ce_threshold;
89         bool set_plimit = false;
90         bool set_flow_plimit = false;
91         bool set_quantum = false;
92         bool set_initial_quantum = false;
93         bool set_maxrate = false;
94         bool set_defrate = false;
95         bool set_refill_delay = false;
96         bool set_orphan_mask = false;
97         bool set_low_rate_threshold = false;
98         bool set_ce_threshold = false;
99         int pacing = -1;
100         struct rtattr *tail;
101
102         while (argc > 0) {
103                 if (strcmp(*argv, "limit") == 0) {
104                         NEXT_ARG();
105                         if (get_unsigned(&plimit, *argv, 0)) {
106                                 fprintf(stderr, "Illegal \"limit\"\n");
107                                 return -1;
108                         }
109                         set_plimit = true;
110                 } else if (strcmp(*argv, "flow_limit") == 0) {
111                         NEXT_ARG();
112                         if (get_unsigned(&flow_plimit, *argv, 0)) {
113                                 fprintf(stderr, "Illegal \"flow_limit\"\n");
114                                 return -1;
115                         }
116                         set_flow_plimit = true;
117                 } else if (strcmp(*argv, "buckets") == 0) {
118                         NEXT_ARG();
119                         if (get_unsigned(&buckets, *argv, 0)) {
120                                 fprintf(stderr, "Illegal \"buckets\"\n");
121                                 return -1;
122                         }
123                 } else if (strcmp(*argv, "maxrate") == 0) {
124                         NEXT_ARG();
125                         if (strchr(*argv, '%')) {
126                                 if (get_percent_rate(&maxrate, *argv, dev)) {
127                                         fprintf(stderr, "Illegal \"maxrate\"\n");
128                                         return -1;
129                                 }
130                         } else if (get_rate(&maxrate, *argv)) {
131                                 fprintf(stderr, "Illegal \"maxrate\"\n");
132                                 return -1;
133                         }
134                         set_maxrate = true;
135                 } else if (strcmp(*argv, "low_rate_threshold") == 0) {
136                         NEXT_ARG();
137                         if (get_rate(&low_rate_threshold, *argv)) {
138                                 fprintf(stderr, "Illegal \"low_rate_threshold\"\n");
139                                 return -1;
140                         }
141                         set_low_rate_threshold = true;
142                 } else if (strcmp(*argv, "ce_threshold") == 0) {
143                         NEXT_ARG();
144                         if (get_time(&ce_threshold, *argv)) {
145                                 fprintf(stderr, "Illegal \"ce_threshold\"\n");
146                                 return -1;
147                         }
148                         set_ce_threshold = true;
149                 } else if (strcmp(*argv, "defrate") == 0) {
150                         NEXT_ARG();
151                         if (strchr(*argv, '%')) {
152                                 if (get_percent_rate(&defrate, *argv, dev)) {
153                                         fprintf(stderr, "Illegal \"defrate\"\n");
154                                         return -1;
155                                 }
156                         } else if (get_rate(&defrate, *argv)) {
157                                 fprintf(stderr, "Illegal \"defrate\"\n");
158                                 return -1;
159                         }
160                         set_defrate = true;
161                 } else if (strcmp(*argv, "quantum") == 0) {
162                         NEXT_ARG();
163                         if (get_unsigned(&quantum, *argv, 0)) {
164                                 fprintf(stderr, "Illegal \"quantum\"\n");
165                                 return -1;
166                         }
167                         set_quantum = true;
168                 } else if (strcmp(*argv, "initial_quantum") == 0) {
169                         NEXT_ARG();
170                         if (get_unsigned(&initial_quantum, *argv, 0)) {
171                                 fprintf(stderr, "Illegal \"initial_quantum\"\n");
172                                 return -1;
173                         }
174                         set_initial_quantum = true;
175                 } else if (strcmp(*argv, "orphan_mask") == 0) {
176                         NEXT_ARG();
177                         if (get_unsigned(&orphan_mask, *argv, 0)) {
178                                 fprintf(stderr, "Illegal \"initial_quantum\"\n");
179                                 return -1;
180                         }
181                         set_orphan_mask = true;
182                 } else if (strcmp(*argv, "refill_delay") == 0) {
183                         NEXT_ARG();
184                         if (get_time(&refill_delay, *argv)) {
185                                 fprintf(stderr, "Illegal \"refill_delay\"\n");
186                                 return -1;
187                         }
188                         set_refill_delay = true;
189                 } else if (strcmp(*argv, "pacing") == 0) {
190                         pacing = 1;
191                 } else if (strcmp(*argv, "nopacing") == 0) {
192                         pacing = 0;
193                 } else if (strcmp(*argv, "help") == 0) {
194                         explain();
195                         return -1;
196                 } else {
197                         fprintf(stderr, "What is \"%s\"?\n", *argv);
198                         explain();
199                         return -1;
200                 }
201                 argc--; argv++;
202         }
203
204         tail = addattr_nest(n, 1024, TCA_OPTIONS);
205         if (buckets) {
206                 unsigned int log = ilog2(buckets);
207
208                 addattr_l(n, 1024, TCA_FQ_BUCKETS_LOG,
209                           &log, sizeof(log));
210         }
211         if (set_plimit)
212                 addattr_l(n, 1024, TCA_FQ_PLIMIT,
213                           &plimit, sizeof(plimit));
214         if (set_flow_plimit)
215                 addattr_l(n, 1024, TCA_FQ_FLOW_PLIMIT,
216                           &flow_plimit, sizeof(flow_plimit));
217         if (set_quantum)
218                 addattr_l(n, 1024, TCA_FQ_QUANTUM, &quantum, sizeof(quantum));
219         if (set_initial_quantum)
220                 addattr_l(n, 1024, TCA_FQ_INITIAL_QUANTUM,
221                           &initial_quantum, sizeof(initial_quantum));
222         if (pacing != -1)
223                 addattr_l(n, 1024, TCA_FQ_RATE_ENABLE,
224                           &pacing, sizeof(pacing));
225         if (set_maxrate)
226                 addattr_l(n, 1024, TCA_FQ_FLOW_MAX_RATE,
227                           &maxrate, sizeof(maxrate));
228         if (set_low_rate_threshold)
229                 addattr_l(n, 1024, TCA_FQ_LOW_RATE_THRESHOLD,
230                           &low_rate_threshold, sizeof(low_rate_threshold));
231         if (set_defrate)
232                 addattr_l(n, 1024, TCA_FQ_FLOW_DEFAULT_RATE,
233                           &defrate, sizeof(defrate));
234         if (set_refill_delay)
235                 addattr_l(n, 1024, TCA_FQ_FLOW_REFILL_DELAY,
236                           &refill_delay, sizeof(refill_delay));
237         if (set_orphan_mask)
238                 addattr_l(n, 1024, TCA_FQ_ORPHAN_MASK,
239                           &orphan_mask, sizeof(refill_delay));
240         if (set_ce_threshold)
241                 addattr_l(n, 1024, TCA_FQ_CE_THRESHOLD,
242                           &ce_threshold, sizeof(ce_threshold));
243         addattr_nest_end(n, tail);
244         return 0;
245 }
246
247 static int fq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
248 {
249         struct rtattr *tb[TCA_FQ_MAX + 1];
250         unsigned int plimit, flow_plimit;
251         unsigned int buckets_log;
252         int pacing;
253         unsigned int rate, quantum;
254         unsigned int refill_delay;
255         unsigned int orphan_mask;
256         unsigned int ce_threshold;
257
258         SPRINT_BUF(b1);
259
260         if (opt == NULL)
261                 return 0;
262
263         parse_rtattr_nested(tb, TCA_FQ_MAX, opt);
264
265         if (tb[TCA_FQ_PLIMIT] &&
266             RTA_PAYLOAD(tb[TCA_FQ_PLIMIT]) >= sizeof(__u32)) {
267                 plimit = rta_getattr_u32(tb[TCA_FQ_PLIMIT]);
268                 print_uint(PRINT_ANY, "limit", "limit %up ", plimit);
269         }
270         if (tb[TCA_FQ_FLOW_PLIMIT] &&
271             RTA_PAYLOAD(tb[TCA_FQ_FLOW_PLIMIT]) >= sizeof(__u32)) {
272                 flow_plimit = rta_getattr_u32(tb[TCA_FQ_FLOW_PLIMIT]);
273                 print_uint(PRINT_ANY, "flow_limit", "flow_limit %up ",
274                            flow_plimit);
275         }
276         if (tb[TCA_FQ_BUCKETS_LOG] &&
277             RTA_PAYLOAD(tb[TCA_FQ_BUCKETS_LOG]) >= sizeof(__u32)) {
278                 buckets_log = rta_getattr_u32(tb[TCA_FQ_BUCKETS_LOG]);
279                 print_uint(PRINT_ANY, "buckets", "buckets %u ",
280                            1U << buckets_log);
281         }
282         if (tb[TCA_FQ_ORPHAN_MASK] &&
283             RTA_PAYLOAD(tb[TCA_FQ_ORPHAN_MASK]) >= sizeof(__u32)) {
284                 orphan_mask = rta_getattr_u32(tb[TCA_FQ_ORPHAN_MASK]);
285                 print_uint(PRINT_ANY, "orphan_mask", "orphan_mask %u ",
286                            orphan_mask);
287         }
288         if (tb[TCA_FQ_RATE_ENABLE] &&
289             RTA_PAYLOAD(tb[TCA_FQ_RATE_ENABLE]) >= sizeof(int)) {
290                 pacing = rta_getattr_u32(tb[TCA_FQ_RATE_ENABLE]);
291                 if (pacing == 0)
292                         print_bool(PRINT_ANY, "pacing", "nopacing ", false);
293         }
294         if (tb[TCA_FQ_QUANTUM] &&
295             RTA_PAYLOAD(tb[TCA_FQ_QUANTUM]) >= sizeof(__u32)) {
296                 quantum = rta_getattr_u32(tb[TCA_FQ_QUANTUM]);
297                 print_uint(PRINT_JSON, "quantum", NULL, quantum);
298                 print_string(PRINT_FP, NULL, "quantum %s ",
299                              sprint_size(quantum, b1));
300         }
301         if (tb[TCA_FQ_INITIAL_QUANTUM] &&
302             RTA_PAYLOAD(tb[TCA_FQ_INITIAL_QUANTUM]) >= sizeof(__u32)) {
303                 quantum = rta_getattr_u32(tb[TCA_FQ_INITIAL_QUANTUM]);
304                 print_uint(PRINT_JSON, "initial_quantum", NULL, quantum);
305                 print_string(PRINT_FP, NULL, "initial_quantum %s ",
306                              sprint_size(quantum, b1));
307         }
308         if (tb[TCA_FQ_FLOW_MAX_RATE] &&
309             RTA_PAYLOAD(tb[TCA_FQ_FLOW_MAX_RATE]) >= sizeof(__u32)) {
310                 rate = rta_getattr_u32(tb[TCA_FQ_FLOW_MAX_RATE]);
311
312                 if (rate != ~0U) {
313                         print_uint(PRINT_JSON, "maxrate", NULL, rate);
314                         print_string(PRINT_FP, NULL, "maxrate %s ",
315                                      sprint_rate(rate, b1));
316                 }
317         }
318         if (tb[TCA_FQ_FLOW_DEFAULT_RATE] &&
319             RTA_PAYLOAD(tb[TCA_FQ_FLOW_DEFAULT_RATE]) >= sizeof(__u32)) {
320                 rate = rta_getattr_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]);
321
322                 if (rate != 0) {
323                         print_uint(PRINT_JSON, "defrate", NULL, rate);
324                         print_string(PRINT_FP, NULL, "defrate %s ",
325                                      sprint_rate(rate, b1));
326                 }
327         }
328         if (tb[TCA_FQ_LOW_RATE_THRESHOLD] &&
329             RTA_PAYLOAD(tb[TCA_FQ_LOW_RATE_THRESHOLD]) >= sizeof(__u32)) {
330                 rate = rta_getattr_u32(tb[TCA_FQ_LOW_RATE_THRESHOLD]);
331
332                 if (rate != 0) {
333                         print_uint(PRINT_JSON, "low_rate_threshold", NULL,
334                                    rate);
335                         print_string(PRINT_FP, NULL, "low_rate_threshold %s ",
336                                      sprint_rate(rate, b1));
337                 }
338         }
339         if (tb[TCA_FQ_FLOW_REFILL_DELAY] &&
340             RTA_PAYLOAD(tb[TCA_FQ_FLOW_REFILL_DELAY]) >= sizeof(__u32)) {
341                 refill_delay = rta_getattr_u32(tb[TCA_FQ_FLOW_REFILL_DELAY]);
342                 print_uint(PRINT_JSON, "refill_delay", NULL, refill_delay);
343                 print_string(PRINT_FP, NULL, "refill_delay %s ",
344                              sprint_time(refill_delay, b1));
345         }
346
347         if (tb[TCA_FQ_CE_THRESHOLD] &&
348             RTA_PAYLOAD(tb[TCA_FQ_CE_THRESHOLD]) >= sizeof(__u32)) {
349                 ce_threshold = rta_getattr_u32(tb[TCA_FQ_CE_THRESHOLD]);
350                 if (ce_threshold != ~0U) {
351                         print_uint(PRINT_JSON, "ce_threshold", NULL,
352                                    ce_threshold);
353                         print_string(PRINT_FP, NULL, "ce_threshold %s ",
354                                      sprint_time(ce_threshold, b1));
355                 }
356         }
357
358         return 0;
359 }
360
361 static int fq_print_xstats(struct qdisc_util *qu, FILE *f,
362                            struct rtattr *xstats)
363 {
364         struct tc_fq_qd_stats *st, _st;
365
366         SPRINT_BUF(b1);
367
368         if (xstats == NULL)
369                 return 0;
370
371         memset(&_st, 0, sizeof(_st));
372         memcpy(&_st, RTA_DATA(xstats), min(RTA_PAYLOAD(xstats), sizeof(*st)));
373
374         st = &_st;
375
376         print_uint(PRINT_ANY, "flows", "  flows %u", st->flows);
377         print_uint(PRINT_ANY, "inactive", " (inactive %u", st->inactive_flows);
378         print_uint(PRINT_ANY, "throttled", " throttled %u)",
379                    st->throttled_flows);
380
381         if (st->time_next_delayed_flow > 0) {
382                 print_lluint(PRINT_JSON, "next_packet_delay", NULL,
383                              st->time_next_delayed_flow);
384                 print_string(PRINT_FP, NULL, " next_packet_delay %s",
385                              sprint_time64(st->time_next_delayed_flow, b1));
386         }
387
388         print_nl();
389         print_lluint(PRINT_ANY, "gc", "  gc %llu", st->gc_flows);
390         print_lluint(PRINT_ANY, "highprio", " highprio %llu",
391                      st->highprio_packets);
392
393         if (st->tcp_retrans)
394                 print_lluint(PRINT_ANY, "retrans", " retrans %llu",
395                              st->tcp_retrans);
396
397         print_lluint(PRINT_ANY, "throttled", " throttled %llu", st->throttled);
398
399         if (st->unthrottle_latency_ns) {
400                 print_uint(PRINT_JSON, "latency", NULL,
401                            st->unthrottle_latency_ns);
402                 print_string(PRINT_FP, NULL, " latency %s",
403                              sprint_time64(st->unthrottle_latency_ns, b1));
404         }
405
406         if (st->ce_mark)
407                 print_lluint(PRINT_ANY, "ce_mark", " ce_mark %llu",
408                              st->ce_mark);
409
410         if (st->flows_plimit)
411                 print_lluint(PRINT_ANY, "flows_plimit", " flows_plimit %llu",
412                              st->flows_plimit);
413
414         if (st->pkts_too_long || st->allocation_errors) {
415                 print_nl();
416                 print_lluint(PRINT_ANY, "pkts_too_long",
417                              "  pkts_too_long %llu", st->pkts_too_long);
418                 print_lluint(PRINT_ANY, "alloc_errors", " alloc_erros %llu",
419                              st->allocation_errors);
420         }
421
422         return 0;
423 }
424
425 struct qdisc_util fq_qdisc_util = {
426         .id             = "fq",
427         .parse_qopt     = fq_parse_opt,
428         .print_qopt     = fq_print_opt,
429         .print_xstats   = fq_print_xstats,
430 };