Fix build break in 64bit architectures
[platform/upstream/iproute2.git] / tc / tc_util.c
1 /*
2  * tc_util.c            Misc TC utility functions.
3  *
4  *              This program is free software; you can redistribute it and/or
5  *              modify it under the terms of the GNU General Public License
6  *              as published by the Free Software Foundation; either version
7  *              2 of the License, or (at your option) any later version.
8  *
9  * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10  *
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <sys/socket.h>
18 #include <sys/param.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <string.h>
22 #include <math.h>
23 #include <errno.h>
24
25 #include "utils.h"
26 #include "names.h"
27 #include "tc_util.h"
28 #include "tc_common.h"
29
30 #ifndef LIBDIR
31 #define LIBDIR "/usr/lib"
32 #endif
33
34 static struct db_names *cls_names;
35
36 #define NAMES_DB "/etc/iproute2/tc_cls"
37
38 int cls_names_init(char *path)
39 {
40         int ret;
41
42         cls_names = db_names_alloc();
43         if (!cls_names)
44                 return -1;
45
46         ret = db_names_load(cls_names, path ?: NAMES_DB);
47         if (ret == -ENOENT && path) {
48                 fprintf(stderr, "Can't open class names file: %s\n", path);
49                 return -1;
50         }
51         if (ret) {
52                 db_names_free(cls_names);
53                 cls_names = NULL;
54         }
55
56         return 0;
57 }
58
59 void cls_names_uninit(void)
60 {
61         db_names_free(cls_names);
62 }
63
64 const char *get_tc_lib(void)
65 {
66         const char *lib_dir;
67
68         lib_dir = getenv("TC_LIB_DIR");
69         if (!lib_dir)
70                 lib_dir = LIBDIR "/tc/";
71
72         return lib_dir;
73 }
74
75 int get_qdisc_handle(__u32 *h, const char *str)
76 {
77         __u32 maj;
78         char *p;
79
80         maj = TC_H_UNSPEC;
81         if (strcmp(str, "none") == 0)
82                 goto ok;
83         maj = strtoul(str, &p, 16);
84         if (p == str || maj >= (1 << 16))
85                 return -1;
86         maj <<= 16;
87         if (*p != ':' && *p != 0)
88                 return -1;
89 ok:
90         *h = maj;
91         return 0;
92 }
93
94 int get_tc_classid(__u32 *h, const char *str)
95 {
96         __u32 maj, min;
97         char *p;
98
99         maj = TC_H_ROOT;
100         if (strcmp(str, "root") == 0)
101                 goto ok;
102         maj = TC_H_UNSPEC;
103         if (strcmp(str, "none") == 0)
104                 goto ok;
105         maj = strtoul(str, &p, 16);
106         if (p == str) {
107                 maj = 0;
108                 if (*p != ':')
109                         return -1;
110         }
111         if (*p == ':') {
112                 if (maj >= (1<<16))
113                         return -1;
114                 maj <<= 16;
115                 str = p+1;
116                 min = strtoul(str, &p, 16);
117                 if (*p != 0)
118                         return -1;
119                 if (min >= (1<<16))
120                         return -1;
121                 maj |= min;
122         } else if (*p != 0)
123                 return -1;
124
125 ok:
126         *h = maj;
127         return 0;
128 }
129
130 int print_tc_classid(char *buf, int blen, __u32 h)
131 {
132         SPRINT_BUF(handle) = {};
133         int hlen = SPRINT_BSIZE - 1;
134
135         if (h == TC_H_ROOT)
136                 sprintf(handle, "root");
137         else if (h == TC_H_UNSPEC)
138                 snprintf(handle, hlen, "none");
139         else if (TC_H_MAJ(h) == 0)
140                 snprintf(handle, hlen, ":%x", TC_H_MIN(h));
141         else if (TC_H_MIN(h) == 0)
142                 snprintf(handle, hlen, "%x:", TC_H_MAJ(h) >> 16);
143         else
144                 snprintf(handle, hlen, "%x:%x", TC_H_MAJ(h) >> 16, TC_H_MIN(h));
145
146         if (use_names) {
147                 char clname[IDNAME_MAX] = {};
148
149                 if (id_to_name(cls_names, h, clname))
150                         snprintf(buf, blen, "%s#%s", clname, handle);
151                 else
152                         snprintf(buf, blen, "%s", handle);
153         } else {
154                 snprintf(buf, blen, "%s", handle);
155         }
156
157         return 0;
158 }
159
160 char *sprint_tc_classid(__u32 h, char *buf)
161 {
162         if (print_tc_classid(buf, SPRINT_BSIZE-1, h))
163                 strcpy(buf, "???");
164         return buf;
165 }
166
167 /* See http://physics.nist.gov/cuu/Units/binary.html */
168 static const struct rate_suffix {
169         const char *name;
170         double scale;
171 } suffixes[] = {
172         { "bit",        1. },
173         { "Kibit",      1024. },
174         { "kbit",       1000. },
175         { "mibit",      1024.*1024. },
176         { "mbit",       1000000. },
177         { "gibit",      1024.*1024.*1024. },
178         { "gbit",       1000000000. },
179         { "tibit",      1024.*1024.*1024.*1024. },
180         { "tbit",       1000000000000. },
181         { "Bps",        8. },
182         { "KiBps",      8.*1024. },
183         { "KBps",       8000. },
184         { "MiBps",      8.*1024*1024. },
185         { "MBps",       8000000. },
186         { "GiBps",      8.*1024.*1024.*1024. },
187         { "GBps",       8000000000. },
188         { "TiBps",      8.*1024.*1024.*1024.*1024. },
189         { "TBps",       8000000000000. },
190         { NULL }
191 };
192
193 /* Parse a percent e.g: '30%'
194  * return: 0 = ok, -1 = error, 1 = out of range
195  */
196 int parse_percent(double *val, const char *str)
197 {
198         char *p;
199
200         *val = strtod(str, &p) / 100.;
201         if (*val > 1.0 || *val < 0.0)
202                 return 1;
203         if (*p && strcmp(p, "%"))
204                 return -1;
205
206         return 0;
207 }
208
209 static int parse_percent_rate(char *rate, size_t len,
210                               const char *str, const char *dev)
211 {
212         long dev_mbit;
213         int ret;
214         double perc, rate_bit;
215         char *str_perc = NULL;
216
217         if (!dev[0]) {
218                 fprintf(stderr, "No device specified; specify device to rate limit by percentage\n");
219                 return -1;
220         }
221
222         if (read_prop(dev, "speed", &dev_mbit))
223                 return -1;
224
225         ret = sscanf(str, "%m[0-9.%]", &str_perc);
226         if (ret != 1)
227                 goto malf;
228
229         ret = parse_percent(&perc, str_perc);
230         if (ret == 1) {
231                 fprintf(stderr, "Invalid rate specified; should be between [0,100]%% but is %s\n", str);
232                 goto err;
233         } else if (ret == -1) {
234                 goto malf;
235         }
236
237         free(str_perc);
238
239         rate_bit = perc * dev_mbit * 1000 * 1000;
240
241         ret = snprintf(rate, len, "%lf", rate_bit);
242         if (ret <= 0 || ret >= len) {
243                 fprintf(stderr, "Unable to parse calculated rate\n");
244                 return -1;
245         }
246
247         return 0;
248
249 malf:
250         fprintf(stderr, "Specified rate value could not be read or is malformed\n");
251 err:
252         free(str_perc);
253         return -1;
254 }
255
256 int get_percent_rate(unsigned int *rate, const char *str, const char *dev)
257 {
258         char r_str[20];
259
260         if (parse_percent_rate(r_str, sizeof(r_str), str, dev))
261                 return -1;
262
263         return get_rate(rate, r_str);
264 }
265
266 int get_percent_rate64(__u64 *rate, const char *str, const char *dev)
267 {
268         char r_str[20];
269
270         if (parse_percent_rate(r_str, sizeof(r_str), str, dev))
271                 return -1;
272
273         return get_rate64(rate, r_str);
274 }
275
276 int get_rate(unsigned int *rate, const char *str)
277 {
278         char *p;
279         double bps = strtod(str, &p);
280         const struct rate_suffix *s;
281
282         if (p == str)
283                 return -1;
284
285         for (s = suffixes; s->name; ++s) {
286                 if (strcasecmp(s->name, p) == 0) {
287                         bps *= s->scale;
288                         p += strlen(p);
289                         break;
290                 }
291         }
292
293         if (*p)
294                 return -1; /* unknown suffix */
295
296         bps /= 8; /* -> bytes per second */
297         *rate = bps;
298         /* detect if an overflow happened */
299         if (*rate != floor(bps))
300                 return -1;
301         return 0;
302 }
303
304 int get_rate64(__u64 *rate, const char *str)
305 {
306         char *p;
307         double bps = strtod(str, &p);
308         const struct rate_suffix *s;
309
310         if (p == str)
311                 return -1;
312
313         for (s = suffixes; s->name; ++s) {
314                 if (strcasecmp(s->name, p) == 0) {
315                         bps *= s->scale;
316                         p += strlen(p);
317                         break;
318                 }
319         }
320
321         if (*p)
322                 return -1; /* unknown suffix */
323
324         bps /= 8; /* -> bytes per second */
325         *rate = bps;
326         return 0;
327 }
328
329 void print_rate(char *buf, int len, __u64 rate)
330 {
331         extern int use_iec;
332         unsigned long kilo = use_iec ? 1024 : 1000;
333         const char *str = use_iec ? "i" : "";
334         static char *units[5] = {"", "K", "M", "G", "T"};
335         int i;
336
337         rate <<= 3; /* bytes/sec -> bits/sec */
338
339         for (i = 0; i < ARRAY_SIZE(units) - 1; i++)  {
340                 if (rate < kilo)
341                         break;
342                 if (((rate % kilo) != 0) && rate < 1000*kilo)
343                         break;
344                 rate /= kilo;
345         }
346
347         snprintf(buf, len, "%.0f%s%sbit", (double)rate, units[i], str);
348 }
349
350 char *sprint_rate(__u64 rate, char *buf)
351 {
352         print_rate(buf, SPRINT_BSIZE-1, rate);
353         return buf;
354 }
355
356 char *sprint_ticks(__u32 ticks, char *buf)
357 {
358         return sprint_time(tc_core_tick2time(ticks), buf);
359 }
360
361 int get_size(unsigned int *size, const char *str)
362 {
363         double sz;
364         char *p;
365
366         sz = strtod(str, &p);
367         if (p == str)
368                 return -1;
369
370         if (*p) {
371                 if (strcasecmp(p, "kb") == 0 || strcasecmp(p, "k") == 0)
372                         sz *= 1024;
373                 else if (strcasecmp(p, "gb") == 0 || strcasecmp(p, "g") == 0)
374                         sz *= 1024*1024*1024;
375                 else if (strcasecmp(p, "gbit") == 0)
376                         sz *= 1024*1024*1024/8;
377                 else if (strcasecmp(p, "mb") == 0 || strcasecmp(p, "m") == 0)
378                         sz *= 1024*1024;
379                 else if (strcasecmp(p, "mbit") == 0)
380                         sz *= 1024*1024/8;
381                 else if (strcasecmp(p, "kbit") == 0)
382                         sz *= 1024/8;
383                 else if (strcasecmp(p, "b") != 0)
384                         return -1;
385         }
386
387         *size = sz;
388         return 0;
389 }
390
391 int get_size_and_cell(unsigned int *size, int *cell_log, char *str)
392 {
393         char *slash = strchr(str, '/');
394
395         if (slash)
396                 *slash = 0;
397
398         if (get_size(size, str))
399                 return -1;
400
401         if (slash) {
402                 int cell;
403                 int i;
404
405                 if (get_integer(&cell, slash+1, 0))
406                         return -1;
407                 *slash = '/';
408
409                 for (i = 0; i < 32; i++) {
410                         if ((1<<i) == cell) {
411                                 *cell_log = i;
412                                 return 0;
413                         }
414                 }
415                 return -1;
416         }
417         return 0;
418 }
419
420 void print_devname(enum output_type type, int ifindex)
421 {
422         const char *ifname = ll_index_to_name(ifindex);
423
424         if (!is_json_context())
425                 printf("dev ");
426
427         print_color_string(type, COLOR_IFNAME,
428                            "dev", "%s ", ifname);
429 }
430
431 static void print_size(char *buf, int len, __u32 sz)
432 {
433         double tmp = sz;
434
435         if (sz >= 1024*1024 && fabs(1024*1024*rint(tmp/(1024*1024)) - sz) < 1024)
436                 snprintf(buf, len, "%gMb", rint(tmp/(1024*1024)));
437         else if (sz >= 1024 && fabs(1024*rint(tmp/1024) - sz) < 16)
438                 snprintf(buf, len, "%gKb", rint(tmp/1024));
439         else
440                 snprintf(buf, len, "%ub", sz);
441 }
442
443 char *sprint_size(__u32 size, char *buf)
444 {
445         print_size(buf, SPRINT_BSIZE-1, size);
446         return buf;
447 }
448
449 static const char *action_n2a(int action)
450 {
451         static char buf[64];
452
453         if (TC_ACT_EXT_CMP(action, TC_ACT_GOTO_CHAIN))
454                 return "goto";
455         if (TC_ACT_EXT_CMP(action, TC_ACT_JUMP))
456                 return "jump";
457         switch (action) {
458         case TC_ACT_UNSPEC:
459                 return "continue";
460         case TC_ACT_OK:
461                 return "pass";
462         case TC_ACT_SHOT:
463                 return "drop";
464         case TC_ACT_RECLASSIFY:
465                 return "reclassify";
466         case TC_ACT_PIPE:
467                 return "pipe";
468         case TC_ACT_STOLEN:
469                 return "stolen";
470         case TC_ACT_TRAP:
471                 return "trap";
472         default:
473                 snprintf(buf, 64, "%d", action);
474                 return buf;
475         }
476 }
477
478 /* Convert action branch name into numeric format.
479  *
480  * Parameters:
481  * @arg - string to parse
482  * @result - pointer to output variable
483  * @allow_num - whether @arg may be in numeric format already
484  *
485  * In error case, returns -1 and does not touch @result. Otherwise returns 0.
486  */
487 int action_a2n(char *arg, int *result, bool allow_num)
488 {
489         int n;
490         char dummy;
491         struct {
492                 const char *a;
493                 int n;
494         } a2n[] = {
495                 {"continue", TC_ACT_UNSPEC},
496                 {"drop", TC_ACT_SHOT},
497                 {"shot", TC_ACT_SHOT},
498                 {"pass", TC_ACT_OK},
499                 {"ok", TC_ACT_OK},
500                 {"reclassify", TC_ACT_RECLASSIFY},
501                 {"pipe", TC_ACT_PIPE},
502                 {"goto", TC_ACT_GOTO_CHAIN},
503                 {"jump", TC_ACT_JUMP},
504                 {"trap", TC_ACT_TRAP},
505                 { NULL },
506         }, *iter;
507
508         for (iter = a2n; iter->a; iter++) {
509                 if (matches(arg, iter->a) != 0)
510                         continue;
511                 n = iter->n;
512                 goto out_ok;
513         }
514         if (!allow_num || sscanf(arg, "%d%c", &n, &dummy) != 1)
515                 return -1;
516
517 out_ok:
518         if (result)
519                 *result = n;
520         return 0;
521 }
522
523 static int __parse_action_control(int *argc_p, char ***argv_p, int *result_p,
524                                   bool allow_num, bool ignore_a2n_miss)
525 {
526         int argc = *argc_p;
527         char **argv = *argv_p;
528         int result;
529
530         if (!argc)
531                 return -1;
532         if (action_a2n(*argv, &result, allow_num) == -1) {
533                 if (!ignore_a2n_miss)
534                         fprintf(stderr, "Bad action type %s\n", *argv);
535                 return -1;
536         }
537         if (result == TC_ACT_GOTO_CHAIN) {
538                 __u32 chain_index;
539
540                 NEXT_ARG();
541                 if (matches(*argv, "chain") != 0) {
542                         fprintf(stderr, "\"chain index\" expected\n");
543                         return -1;
544                 }
545                 NEXT_ARG();
546                 if (get_u32(&chain_index, *argv, 10) ||
547                     chain_index > TC_ACT_EXT_VAL_MASK) {
548                         fprintf(stderr, "Illegal \"chain index\"\n");
549                         return -1;
550                 }
551                 result |= chain_index;
552         }
553         if (result == TC_ACT_JUMP) {
554                 __u32 jump_cnt = 0;
555
556                 NEXT_ARG();
557                 if (get_u32(&jump_cnt, *argv, 10) ||
558                     jump_cnt > TC_ACT_EXT_VAL_MASK) {
559                         fprintf(stderr, "Invalid \"jump count\" (%s)\n", *argv);
560                         return -1;
561                 }
562                 result |= jump_cnt;
563         }
564         NEXT_ARG_FWD();
565         *argc_p = argc;
566         *argv_p = argv;
567         *result_p = result;
568         return 0;
569 }
570
571 /* Parse action control including possible options.
572  *
573  * Parameters:
574  * @argc_p - pointer to argc to parse
575  * @argv_p - pointer to argv to parse
576  * @result_p - pointer to output variable
577  * @allow_num - whether action may be in numeric format already
578  *
579  * In error case, returns -1 and does not touch @result_1p. Otherwise returns 0.
580  */
581 int parse_action_control(int *argc_p, char ***argv_p,
582                          int *result_p, bool allow_num)
583 {
584         return __parse_action_control(argc_p, argv_p, result_p,
585                                       allow_num, false);
586 }
587
588 /* Parse action control including possible options.
589  *
590  * Parameters:
591  * @argc_p - pointer to argc to parse
592  * @argv_p - pointer to argv to parse
593  * @result_p - pointer to output variable
594  * @allow_num - whether action may be in numeric format already
595  * @default_result - set as a result in case of parsing error
596  *
597  * In case there is an error during parsing, the default result is used.
598  */
599 void parse_action_control_dflt(int *argc_p, char ***argv_p,
600                                int *result_p, bool allow_num,
601                                int default_result)
602 {
603         if (__parse_action_control(argc_p, argv_p, result_p, allow_num, true))
604                 *result_p = default_result;
605 }
606
607 static int parse_action_control_slash_spaces(int *argc_p, char ***argv_p,
608                                              int *result1_p, int *result2_p,
609                                              bool allow_num)
610 {
611         int argc = *argc_p;
612         char **argv = *argv_p;
613         int result1 = -1, result2;
614         int *result_p = &result1;
615         int ok = 0;
616         int ret;
617
618         while (argc > 0) {
619                 switch (ok) {
620                 case 1:
621                         if (strcmp(*argv, "/") != 0)
622                                 goto out;
623                         result_p = &result2;
624                         NEXT_ARG();
625                         /* fall-through */
626                 case 0: /* fall-through */
627                 case 2:
628                         ret = parse_action_control(&argc, &argv,
629                                                    result_p, allow_num);
630                         if (ret)
631                                 return ret;
632                         ok++;
633                         break;
634                 default:
635                         goto out;
636                 }
637         }
638 out:
639         *result1_p = result1;
640         if (ok == 2)
641                 *result2_p = result2;
642         *argc_p = argc;
643         *argv_p = argv;
644         return 0;
645 }
646
647 /* Parse action control with slash including possible options.
648  *
649  * Parameters:
650  * @argc_p - pointer to argc to parse
651  * @argv_p - pointer to argv to parse
652  * @result1_p - pointer to the first (before slash) output variable
653  * @result2_p - pointer to the second (after slash) output variable
654  * @allow_num - whether action may be in numeric format already
655  *
656  * In error case, returns -1 and does not touch @result*. Otherwise returns 0.
657  */
658 int parse_action_control_slash(int *argc_p, char ***argv_p,
659                                int *result1_p, int *result2_p, bool allow_num)
660 {
661         int result1, result2, argc = *argc_p;
662         char **argv = *argv_p;
663         char *p = strchr(*argv, '/');
664
665         if (!p)
666                 return parse_action_control_slash_spaces(argc_p, argv_p,
667                                                          result1_p, result2_p,
668                                                          allow_num);
669         *p = 0;
670         if (action_a2n(*argv, &result1, allow_num)) {
671                 *p = '/';
672                 return -1;
673         }
674
675         *p = '/';
676         if (action_a2n(p + 1, &result2, allow_num))
677                 return -1;
678
679         *result1_p = result1;
680         *result2_p = result2;
681         NEXT_ARG_FWD();
682         *argc_p = argc;
683         *argv_p = argv;
684         return 0;
685 }
686
687 void print_action_control(FILE *f, const char *prefix,
688                           int action, const char *suffix)
689 {
690         print_string(PRINT_FP, NULL, "%s", prefix);
691         open_json_object("control_action");
692         print_string(PRINT_ANY, "type", "%s", action_n2a(action));
693         if (TC_ACT_EXT_CMP(action, TC_ACT_GOTO_CHAIN))
694                 print_uint(PRINT_ANY, "chain", " chain %u",
695                            action & TC_ACT_EXT_VAL_MASK);
696         if (TC_ACT_EXT_CMP(action, TC_ACT_JUMP))
697                 print_uint(PRINT_ANY, "jump", " %u",
698                            action & TC_ACT_EXT_VAL_MASK);
699         close_json_object();
700         print_string(PRINT_FP, NULL, "%s", suffix);
701 }
702
703 int get_linklayer(unsigned int *val, const char *arg)
704 {
705         int res;
706
707         if (matches(arg, "ethernet") == 0)
708                 res = LINKLAYER_ETHERNET;
709         else if (matches(arg, "atm") == 0)
710                 res = LINKLAYER_ATM;
711         else if (matches(arg, "adsl") == 0)
712                 res = LINKLAYER_ATM;
713         else
714                 return -1; /* Indicate error */
715
716         *val = res;
717         return 0;
718 }
719
720 static void print_linklayer(char *buf, int len, unsigned int linklayer)
721 {
722         switch (linklayer) {
723         case LINKLAYER_UNSPEC:
724                 snprintf(buf, len, "%s", "unspec");
725                 return;
726         case LINKLAYER_ETHERNET:
727                 snprintf(buf, len, "%s", "ethernet");
728                 return;
729         case LINKLAYER_ATM:
730                 snprintf(buf, len, "%s", "atm");
731                 return;
732         default:
733                 snprintf(buf, len, "%s", "unknown");
734                 return;
735         }
736 }
737
738 char *sprint_linklayer(unsigned int linklayer, char *buf)
739 {
740         print_linklayer(buf, SPRINT_BSIZE-1, linklayer);
741         return buf;
742 }
743
744 void print_tm(FILE *f, const struct tcf_t *tm)
745 {
746         int hz = get_user_hz();
747
748         if (tm->install != 0) {
749                 print_uint(PRINT_JSON, "installed", NULL, tm->install);
750                 print_uint(PRINT_FP, NULL, " installed %u sec",
751                            (unsigned int)(tm->install/hz));
752         }
753         if (tm->lastuse != 0) {
754                 print_uint(PRINT_JSON, "last_used", NULL, tm->lastuse);
755                 print_uint(PRINT_FP, NULL, " used %u sec",
756                            (unsigned int)(tm->lastuse/hz));
757         }
758         if (tm->expires != 0) {
759                 print_uint(PRINT_JSON, "expires", NULL, tm->expires);
760                 print_uint(PRINT_FP, NULL, " expires %u sec",
761                            (unsigned int)(tm->expires/hz));
762         }
763 }
764
765 static void print_tcstats_basic_hw(struct rtattr **tbs, char *prefix)
766 {
767         struct gnet_stats_basic bs_hw;
768
769         if (!tbs[TCA_STATS_BASIC_HW])
770                 return;
771
772         memcpy(&bs_hw, RTA_DATA(tbs[TCA_STATS_BASIC_HW]),
773                MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC_HW]), sizeof(bs_hw)));
774
775         if (bs_hw.bytes == 0 && bs_hw.packets == 0)
776                 return;
777
778         if (tbs[TCA_STATS_BASIC]) {
779                 struct gnet_stats_basic bs;
780
781                 memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]),
782                        MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]),
783                            sizeof(bs)));
784
785                 if (bs.bytes >= bs_hw.bytes && bs.packets >= bs_hw.packets) {
786                         print_string(PRINT_FP, NULL, "%s", _SL_);
787                         print_string(PRINT_FP, NULL, "%s", prefix);
788                         print_lluint(PRINT_ANY, "sw_bytes",
789                                      "Sent software %llu bytes",
790                                      bs.bytes - bs_hw.bytes);
791                         print_uint(PRINT_ANY, "sw_packets", " %u pkt",
792                                    bs.packets - bs_hw.packets);
793                 }
794         }
795
796         print_string(PRINT_FP, NULL, "%s", _SL_);
797         print_string(PRINT_FP, NULL, "%s", prefix);
798         print_lluint(PRINT_ANY, "hw_bytes", "Sent hardware %llu bytes",
799                      bs_hw.bytes);
800         print_uint(PRINT_ANY, "hw_packets", " %u pkt", bs_hw.packets);
801 }
802
803 void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtattr **xstats)
804 {
805         SPRINT_BUF(b1);
806         struct rtattr *tbs[TCA_STATS_MAX + 1];
807
808         parse_rtattr_nested(tbs, TCA_STATS_MAX, rta);
809
810         if (tbs[TCA_STATS_BASIC]) {
811                 struct gnet_stats_basic bs = {0};
812                 __u64 packets64 = 0;
813
814                 if (tbs[TCA_STATS_PKT64])
815                         packets64 = rta_getattr_u64(tbs[TCA_STATS_PKT64]);
816
817                 memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]),
818                        MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]), sizeof(bs)));
819                 print_string(PRINT_FP, NULL, "%s", prefix);
820                 print_lluint(PRINT_ANY, "bytes", "Sent %llu bytes", bs.bytes);
821                 if (packets64)
822                         print_lluint(PRINT_ANY, "packets",
823                                      " %llu pkt", packets64);
824                 else
825                         print_uint(PRINT_ANY, "packets",
826                                    " %u pkt", bs.packets);
827         }
828
829         if (tbs[TCA_STATS_QUEUE]) {
830                 struct gnet_stats_queue q = {0};
831
832                 memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]),
833                        MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
834                 print_uint(PRINT_ANY, "drops", " (dropped %u", q.drops);
835                 print_uint(PRINT_ANY, "overlimits", ", overlimits %u",
836                            q.overlimits);
837                 print_uint(PRINT_ANY, "requeues", " requeues %u) ", q.requeues);
838         }
839
840         if (tbs[TCA_STATS_BASIC_HW])
841                 print_tcstats_basic_hw(tbs, prefix);
842
843         if (tbs[TCA_STATS_RATE_EST64]) {
844                 struct gnet_stats_rate_est64 re = {0};
845
846                 memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST64]),
847                        MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST64]),
848                            sizeof(re)));
849                 print_string(PRINT_FP, NULL, "\n%s", prefix);
850                 print_lluint(PRINT_JSON, "rate", NULL, re.bps);
851                 print_string(PRINT_FP, NULL, "rate %s",
852                              sprint_rate(re.bps, b1));
853                 print_lluint(PRINT_ANY, "pps", " %llupps", re.pps);
854         } else if (tbs[TCA_STATS_RATE_EST]) {
855                 struct gnet_stats_rate_est re = {0};
856
857                 memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST]),
858                        MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));
859                 print_string(PRINT_FP, NULL, "\n%s", prefix);
860                 print_uint(PRINT_JSON, "rate", NULL, re.bps);
861                 print_string(PRINT_FP, NULL, "rate %s",
862                              sprint_rate(re.bps, b1));
863                 print_uint(PRINT_ANY, "pps", " %upps", re.pps);
864         }
865
866         if (tbs[TCA_STATS_QUEUE]) {
867                 struct gnet_stats_queue q = {0};
868
869                 memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]),
870                        MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
871                 if (!tbs[TCA_STATS_RATE_EST])
872                         print_string(PRINT_FP, NULL, "\n", "");
873                 print_uint(PRINT_JSON, "backlog", NULL, q.backlog);
874                 print_string(PRINT_FP, NULL, "%s", prefix);
875                 print_string(PRINT_FP, NULL, "backlog %s",
876                              sprint_size(q.backlog, b1));
877                 print_uint(PRINT_ANY, "qlen", " %up", q.qlen);
878                 print_uint(PRINT_FP, NULL, " requeues %u", q.requeues);
879         }
880
881         if (xstats)
882                 *xstats = tbs[TCA_STATS_APP] ? : NULL;
883 }
884
885 void print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix,
886                         struct rtattr **xstats)
887 {
888         SPRINT_BUF(b1);
889
890         if (tb[TCA_STATS2]) {
891                 print_tcstats2_attr(fp, tb[TCA_STATS2], prefix, xstats);
892                 if (xstats && !*xstats)
893                         goto compat_xstats;
894                 return;
895         }
896         /* backward compatibility */
897         if (tb[TCA_STATS]) {
898                 struct tc_stats st = {};
899
900                 /* handle case where kernel returns more/less than we know about */
901                 memcpy(&st, RTA_DATA(tb[TCA_STATS]),
902                        MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st)));
903
904                 fprintf(fp,
905                         "%sSent %llu bytes %u pkts (dropped %u, overlimits %u) ",
906                         prefix, (unsigned long long)st.bytes,
907                         st.packets, st.drops, st.overlimits);
908
909                 if (st.bps || st.pps || st.qlen || st.backlog) {
910                         fprintf(fp, "\n%s", prefix);
911                         if (st.bps || st.pps) {
912                                 fprintf(fp, "rate ");
913                                 if (st.bps)
914                                         fprintf(fp, "%s ",
915                                                 sprint_rate(st.bps, b1));
916                                 if (st.pps)
917                                         fprintf(fp, "%upps ", st.pps);
918                         }
919                         if (st.qlen || st.backlog) {
920                                 fprintf(fp, "backlog ");
921                                 if (st.backlog)
922                                         fprintf(fp, "%s ",
923                                                 sprint_size(st.backlog, b1));
924                                 if (st.qlen)
925                                         fprintf(fp, "%up ", st.qlen);
926                         }
927                 }
928         }
929
930 compat_xstats:
931         if (tb[TCA_XSTATS] && xstats)
932                 *xstats = tb[TCA_XSTATS];
933 }
934
935 static void print_masked_type(__u32 type_max,
936                               __u32 (*rta_getattr_type)(const struct rtattr *),
937                               const char *name, struct rtattr *attr,
938                               struct rtattr *mask_attr, bool newline)
939 {
940         SPRINT_BUF(namefrm);
941         __u32 value, mask;
942         SPRINT_BUF(out);
943         size_t done;
944
945         if (!attr)
946                 return;
947
948         value = rta_getattr_type(attr);
949         mask = mask_attr ? rta_getattr_type(mask_attr) : type_max;
950
951         if (is_json_context()) {
952                 sprintf(namefrm, "\n  %s %%u", name);
953                 print_hu(PRINT_ANY, name, namefrm,
954                          rta_getattr_type(attr));
955                 if (mask != type_max) {
956                         char mask_name[SPRINT_BSIZE-6];
957
958                         sprintf(mask_name, "%s_mask", name);
959                         if (newline)
960                                 print_string(PRINT_FP, NULL, "%s ", _SL_);
961                         sprintf(namefrm, " %s %%u", mask_name);
962                         print_hu(PRINT_ANY, mask_name, namefrm, mask);
963                 }
964         } else {
965                 done = sprintf(out, "%u", value);
966                 if (mask != type_max)
967                         sprintf(out + done, "/0x%x", mask);
968                 if (newline)
969                         print_string(PRINT_FP, NULL, "%s ", _SL_);
970                 sprintf(namefrm, " %s %%s", name);
971                 print_string(PRINT_ANY, name, namefrm, out);
972         }
973 }
974
975 void print_masked_u32(const char *name, struct rtattr *attr,
976                       struct rtattr *mask_attr, bool newline)
977 {
978         print_masked_type(UINT32_MAX, rta_getattr_u32, name, attr, mask_attr,
979                           newline);
980 }
981
982 static __u32 __rta_getattr_u16_u32(const struct rtattr *attr)
983 {
984         return rta_getattr_u16(attr);
985 }
986
987 void print_masked_u16(const char *name, struct rtattr *attr,
988                       struct rtattr *mask_attr, bool newline)
989 {
990         print_masked_type(UINT16_MAX, __rta_getattr_u16_u32, name, attr,
991                           mask_attr, newline);
992 }
993
994 static __u32 __rta_getattr_u8_u32(const struct rtattr *attr)
995 {
996         return rta_getattr_u8(attr);
997 }
998
999 void print_masked_u8(const char *name, struct rtattr *attr,
1000                      struct rtattr *mask_attr, bool newline)
1001 {
1002         print_masked_type(UINT8_MAX,  __rta_getattr_u8_u32, name, attr,
1003                           mask_attr, newline);
1004 }
1005
1006 static __u32 __rta_getattr_be16_u32(const struct rtattr *attr)
1007 {
1008         return rta_getattr_be16(attr);
1009 }
1010
1011 void print_masked_be16(const char *name, struct rtattr *attr,
1012                        struct rtattr *mask_attr, bool newline)
1013 {
1014         print_masked_type(UINT16_MAX, __rta_getattr_be16_u32, name, attr,
1015                           mask_attr, newline);
1016 }