]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blob - tc/q_netem.c
Fix netem display of rate and limit.
[lisovros/iproute2_canprio.git] / tc / q_netem.c
1 /*
2  * q_netem.c            NETEM.
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:     Stephen Hemminger <shemminger@osdl.org>
10  *
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <syslog.h>
17 #include <fcntl.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
21 #include <string.h>
22
23 #include "utils.h"
24 #include "tc_util.h"
25
26 static void explain(void)
27 {
28         fprintf(stderr, 
29 "Usage: ... netem latency TIME [ gap PACKETS] \n" \
30 "                 [ loss PERCENT ] [ duplicate PERCENT ]\n" \
31 "                 [ rate KBPS ] [ limit BYTES]\n");
32 }
33
34 static void explain1(const char *arg)
35 {
36         fprintf(stderr, "Illegal \"%s\"\n", arg);
37 }
38
39 #define usage() return(-1)
40
41 static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, 
42                            struct nlmsghdr *n)
43 {
44         struct tc_netem_qopt opt;
45         int ok = 0;
46
47         memset(&opt, 0, sizeof(opt));
48         opt.limit = 1000;
49
50         while (argc > 0) {
51                 if (matches(*argv, "limit") == 0) {
52                         NEXT_ARG();
53                         if (get_size(&opt.limit, *argv)) {
54                                 explain1("limit");
55                                 return -1;
56                         }
57                         ok++;
58                 } else if (matches(*argv, "latency") == 0) {
59                         NEXT_ARG();
60                         if (get_usecs(&opt.latency, *argv)) {
61                                 explain1("latency");
62                                 return -1;
63                         }
64                         ok++;
65                 } else if (matches(*argv, "loss") == 0) {
66                         NEXT_ARG();
67                         if (get_percent(&opt.loss, *argv)) {
68                                 explain1("loss");
69                                 return -1;
70                         }
71                         ok++;
72                 } else if (matches(*argv, "gap") == 0) {
73                         char *p;
74                         NEXT_ARG();
75                         opt.gap = strtoul(*argv, &p, 0);
76                         if (p == *argv || *p) {
77                                 explain1("gap");
78                                 return -1;
79                         }
80                         ok++;
81                 } else if (matches(*argv, "duplicate") == 0) {
82                         NEXT_ARG();
83                         if (get_percent(&opt.duplicate, *argv)) {
84                                 explain1("duplicate");
85                                 return -1;
86                         }
87                         ok++;
88                 } else if (matches(*argv, "rate") == 0) {
89                         NEXT_ARG();
90                         if (get_rate(&opt.rate, *argv)) {
91                                 explain1("rate");
92                                 return -1;
93                         }
94                         ok++;
95                 } else if (strcmp(*argv, "help") == 0) {
96                         explain();
97                         return -1;
98                 } else {
99                         fprintf(stderr, "What is \"%s\"?\n", *argv);
100                         explain();
101                         return -1;
102                 }
103                 argc--; argv++;
104         }
105
106         if (ok)
107                 addattr_l(n, 1024, TCA_OPTIONS, &opt, sizeof(opt));
108         return 0;
109 }
110
111 static int netem_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
112 {
113         struct tc_netem_qopt *qopt;
114         SPRINT_BUF(b1);
115         SPRINT_BUF(b2);
116
117         if (opt == NULL)
118                 return 0;
119
120         if (RTA_PAYLOAD(opt)  < sizeof(*qopt))
121                 return -1;
122
123         qopt = RTA_DATA(opt);
124
125         fprintf(f, "limit %d", qopt->limit);
126         if (qopt->latency)
127                 fprintf(f, " latency %s", 
128                         sprint_usecs(qopt->latency, b2));
129         if (qopt->loss)
130                 fprintf(f, " loss %s",
131                         sprint_percent(qopt->loss, b1));
132         if (qopt->gap)
133                 fprintf(f, " gap %lu", (unsigned long)qopt->gap);
134
135         if (qopt->rate)
136                 fprintf(f, " rate %s", sprint_rate(qopt->rate, b1));
137
138         return 0;
139 }
140
141 static int netem_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
142 {
143         return 0;
144 }
145
146 struct qdisc_util netem_util = {
147         NULL,
148         "netem",
149         netem_parse_opt,
150         netem_print_opt,
151         netem_print_xstats,
152 };