]>
Commit | Line | Data |
---|---|---|
80dd880d VS |
1 | /* Copyright (C) 2013 Cisco Systems, Inc, 2013. |
2 | * | |
3 | * This program is free software; you can redistribute it and/or | |
4 | * modify it under the terms of the GNU General Public License | |
5 | * as published by the Free Software Foundation; either version 2 | |
6 | * of the License. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * Author: Vijay Subramanian <vijaynsu@cisco.com> | |
14 | * Author: Mythili Prabhu <mysuryan@cisco.com> | |
15 | * | |
16 | */ | |
17 | ||
18 | #include <stdio.h> | |
19 | #include <stdlib.h> | |
20 | #include <unistd.h> | |
80dd880d VS |
21 | #include <fcntl.h> |
22 | #include <sys/socket.h> | |
23 | #include <netinet/in.h> | |
24 | #include <arpa/inet.h> | |
25 | #include <string.h> | |
26 | #include <math.h> | |
27 | ||
28 | #include "utils.h" | |
29 | #include "tc_util.h" | |
30 | ||
31 | static void explain(void) | |
32 | { | |
8589eb4e | 33 | fprintf(stderr, |
920700a4 GR |
34 | "Usage: ... pie [ limit PACKETS ] [ target TIME ]\n" |
35 | " [ tupdate TIME ] [ alpha ALPHA ] [ beta BETA ]\n" | |
36 | " [ bytemode | nobytemode ] [ ecn | noecn ]\n" | |
37 | " [ dq_rate_estimator | no_dq_rate_estimator ]\n"); | |
80dd880d VS |
38 | } |
39 | ||
40 | #define ALPHA_MAX 32 | |
80dd880d | 41 | #define BETA_MAX 32 |
80dd880d VS |
42 | |
43 | static int pie_parse_opt(struct qdisc_util *qu, int argc, char **argv, | |
927e3cfb | 44 | struct nlmsghdr *n, const char *dev) |
80dd880d VS |
45 | { |
46 | unsigned int limit = 0; | |
47 | unsigned int target = 0; | |
48 | unsigned int tupdate = 0; | |
49 | unsigned int alpha = 0; | |
50 | unsigned int beta = 0; | |
51 | int ecn = -1; | |
52 | int bytemode = -1; | |
920700a4 | 53 | int dq_rate_estimator = -1; |
80dd880d VS |
54 | struct rtattr *tail; |
55 | ||
56 | while (argc > 0) { | |
57 | if (strcmp(*argv, "limit") == 0) { | |
58 | NEXT_ARG(); | |
59 | if (get_unsigned(&limit, *argv, 0)) { | |
60 | fprintf(stderr, "Illegal \"limit\"\n"); | |
61 | return -1; | |
62 | } | |
63 | } else if (strcmp(*argv, "target") == 0) { | |
64 | NEXT_ARG(); | |
65 | if (get_time(&target, *argv)) { | |
66 | fprintf(stderr, "Illegal \"target\"\n"); | |
67 | return -1; | |
68 | } | |
69 | } else if (strcmp(*argv, "tupdate") == 0) { | |
70 | NEXT_ARG(); | |
71 | if (get_time(&tupdate, *argv)) { | |
72 | fprintf(stderr, "Illegal \"tupdate\"\n"); | |
73 | return -1; | |
74 | } | |
75 | } else if (strcmp(*argv, "alpha") == 0) { | |
76 | NEXT_ARG(); | |
77 | if (get_unsigned(&alpha, *argv, 0) || | |
60ccfcd7 | 78 | (alpha > ALPHA_MAX)) { |
80dd880d VS |
79 | fprintf(stderr, "Illegal \"alpha\"\n"); |
80 | return -1; | |
81 | } | |
82 | } else if (strcmp(*argv, "beta") == 0) { | |
83 | NEXT_ARG(); | |
84 | if (get_unsigned(&beta, *argv, 0) || | |
60ccfcd7 | 85 | (beta > BETA_MAX)) { |
80dd880d VS |
86 | fprintf(stderr, "Illegal \"beta\"\n"); |
87 | return -1; | |
88 | } | |
89 | } else if (strcmp(*argv, "ecn") == 0) { | |
90 | ecn = 1; | |
91 | } else if (strcmp(*argv, "noecn") == 0) { | |
92 | ecn = 0; | |
93 | } else if (strcmp(*argv, "bytemode") == 0) { | |
94 | bytemode = 1; | |
95 | } else if (strcmp(*argv, "nobytemode") == 0) { | |
96 | bytemode = 0; | |
920700a4 GR |
97 | } else if (strcmp(*argv, "dq_rate_estimator") == 0) { |
98 | dq_rate_estimator = 1; | |
99 | } else if (strcmp(*argv, "no_dq_rate_estimator") == 0) { | |
100 | dq_rate_estimator = 0; | |
80dd880d VS |
101 | } else if (strcmp(*argv, "help") == 0) { |
102 | explain(); | |
103 | return -1; | |
104 | } else { | |
105 | fprintf(stderr, "What is \"%s\"?\n", *argv); | |
106 | explain(); | |
107 | return -1; | |
108 | } | |
109 | argc--; | |
110 | argv++; | |
111 | } | |
112 | ||
c14f9d92 | 113 | tail = addattr_nest(n, 1024, TCA_OPTIONS); |
80dd880d VS |
114 | if (limit) |
115 | addattr_l(n, 1024, TCA_PIE_LIMIT, &limit, sizeof(limit)); | |
116 | if (tupdate) | |
117 | addattr_l(n, 1024, TCA_PIE_TUPDATE, &tupdate, sizeof(tupdate)); | |
118 | if (target) | |
119 | addattr_l(n, 1024, TCA_PIE_TARGET, &target, sizeof(target)); | |
120 | if (alpha) | |
121 | addattr_l(n, 1024, TCA_PIE_ALPHA, &alpha, sizeof(alpha)); | |
122 | if (beta) | |
123 | addattr_l(n, 1024, TCA_PIE_BETA, &beta, sizeof(beta)); | |
124 | if (ecn != -1) | |
125 | addattr_l(n, 1024, TCA_PIE_ECN, &ecn, sizeof(ecn)); | |
126 | if (bytemode != -1) | |
127 | addattr_l(n, 1024, TCA_PIE_BYTEMODE, &bytemode, | |
128 | sizeof(bytemode)); | |
920700a4 GR |
129 | if (dq_rate_estimator != -1) |
130 | addattr_l(n, 1024, TCA_PIE_DQ_RATE_ESTIMATOR, | |
131 | &dq_rate_estimator, sizeof(dq_rate_estimator)); | |
80dd880d | 132 | |
c14f9d92 | 133 | addattr_nest_end(n, tail); |
80dd880d VS |
134 | return 0; |
135 | } | |
136 | ||
137 | static int pie_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) | |
138 | { | |
139 | struct rtattr *tb[TCA_PIE_MAX + 1]; | |
140 | unsigned int limit; | |
141 | unsigned int tupdate; | |
142 | unsigned int target; | |
143 | unsigned int alpha; | |
144 | unsigned int beta; | |
32a121cb SH |
145 | unsigned int ecn; |
146 | unsigned int bytemode; | |
920700a4 | 147 | unsigned int dq_rate_estimator; |
32a121cb | 148 | |
80dd880d VS |
149 | SPRINT_BUF(b1); |
150 | ||
151 | if (opt == NULL) | |
152 | return 0; | |
153 | ||
154 | parse_rtattr_nested(tb, TCA_PIE_MAX, opt); | |
155 | ||
156 | if (tb[TCA_PIE_LIMIT] && | |
157 | RTA_PAYLOAD(tb[TCA_PIE_LIMIT]) >= sizeof(__u32)) { | |
158 | limit = rta_getattr_u32(tb[TCA_PIE_LIMIT]); | |
0154d096 | 159 | print_uint(PRINT_ANY, "limit", "limit %up ", limit); |
80dd880d VS |
160 | } |
161 | if (tb[TCA_PIE_TARGET] && | |
162 | RTA_PAYLOAD(tb[TCA_PIE_TARGET]) >= sizeof(__u32)) { | |
163 | target = rta_getattr_u32(tb[TCA_PIE_TARGET]); | |
0154d096 LM |
164 | print_uint(PRINT_JSON, "target", NULL, target); |
165 | print_string(PRINT_FP, NULL, "target %s ", | |
166 | sprint_time(target, b1)); | |
80dd880d VS |
167 | } |
168 | if (tb[TCA_PIE_TUPDATE] && | |
169 | RTA_PAYLOAD(tb[TCA_PIE_TUPDATE]) >= sizeof(__u32)) { | |
170 | tupdate = rta_getattr_u32(tb[TCA_PIE_TUPDATE]); | |
0154d096 LM |
171 | print_uint(PRINT_JSON, "tupdate", NULL, tupdate); |
172 | print_string(PRINT_FP, NULL, "tupdate %s ", | |
173 | sprint_time(tupdate, b1)); | |
80dd880d VS |
174 | } |
175 | if (tb[TCA_PIE_ALPHA] && | |
176 | RTA_PAYLOAD(tb[TCA_PIE_ALPHA]) >= sizeof(__u32)) { | |
177 | alpha = rta_getattr_u32(tb[TCA_PIE_ALPHA]); | |
0154d096 | 178 | print_uint(PRINT_ANY, "alpha", "alpha %u ", alpha); |
80dd880d VS |
179 | } |
180 | if (tb[TCA_PIE_BETA] && | |
181 | RTA_PAYLOAD(tb[TCA_PIE_BETA]) >= sizeof(__u32)) { | |
182 | beta = rta_getattr_u32(tb[TCA_PIE_BETA]); | |
0154d096 | 183 | print_uint(PRINT_ANY, "beta", "beta %u ", beta); |
80dd880d VS |
184 | } |
185 | ||
186 | if (tb[TCA_PIE_ECN] && RTA_PAYLOAD(tb[TCA_PIE_ECN]) >= sizeof(__u32)) { | |
187 | ecn = rta_getattr_u32(tb[TCA_PIE_ECN]); | |
188 | if (ecn) | |
0154d096 | 189 | print_bool(PRINT_ANY, "ecn", "ecn ", true); |
80dd880d VS |
190 | } |
191 | ||
192 | if (tb[TCA_PIE_BYTEMODE] && | |
193 | RTA_PAYLOAD(tb[TCA_PIE_BYTEMODE]) >= sizeof(__u32)) { | |
194 | bytemode = rta_getattr_u32(tb[TCA_PIE_BYTEMODE]); | |
195 | if (bytemode) | |
0154d096 | 196 | print_bool(PRINT_ANY, "bytemode", "bytemode ", true); |
80dd880d VS |
197 | } |
198 | ||
920700a4 GR |
199 | if (tb[TCA_PIE_DQ_RATE_ESTIMATOR] && |
200 | RTA_PAYLOAD(tb[TCA_PIE_DQ_RATE_ESTIMATOR]) >= sizeof(__u32)) { | |
201 | dq_rate_estimator = | |
202 | rta_getattr_u32(tb[TCA_PIE_DQ_RATE_ESTIMATOR]); | |
203 | if (dq_rate_estimator) | |
0154d096 LM |
204 | print_bool(PRINT_ANY, "dq_rate_estimator", |
205 | "dq_rate_estimator ", true); | |
920700a4 GR |
206 | } |
207 | ||
80dd880d VS |
208 | return 0; |
209 | } | |
210 | ||
211 | static int pie_print_xstats(struct qdisc_util *qu, FILE *f, | |
212 | struct rtattr *xstats) | |
213 | { | |
214 | struct tc_pie_xstats *st; | |
215 | ||
0154d096 LM |
216 | SPRINT_BUF(b1); |
217 | ||
80dd880d VS |
218 | if (xstats == NULL) |
219 | return 0; | |
220 | ||
221 | if (RTA_PAYLOAD(xstats) < sizeof(*st)) | |
222 | return -1; | |
223 | ||
224 | st = RTA_DATA(xstats); | |
0154d096 | 225 | |
94c4ce82 | 226 | /* prob is returned as a fracion of maximum integer value */ |
0154d096 | 227 | print_float(PRINT_ANY, "prob", " prob %lg", |
94c4ce82 | 228 | (double)st->prob / (double)UINT64_MAX); |
0154d096 LM |
229 | print_uint(PRINT_JSON, "delay", NULL, st->delay); |
230 | print_string(PRINT_FP, NULL, " delay %s", sprint_time(st->delay, b1)); | |
920700a4 GR |
231 | |
232 | if (st->dq_rate_estimating) | |
0154d096 LM |
233 | print_uint(PRINT_ANY, "avg_dq_rate", " avg_dq_rate %u", |
234 | st->avg_dq_rate); | |
235 | ||
236 | print_nl(); | |
237 | print_uint(PRINT_ANY, "pkts_in", " pkts_in %u", st->packets_in); | |
238 | print_uint(PRINT_ANY, "overlimit", " overlimit %u", st->overlimit); | |
239 | print_uint(PRINT_ANY, "dropped", " dropped %u", st->dropped); | |
240 | print_uint(PRINT_ANY, "maxq", " maxq %u", st->maxq); | |
241 | print_uint(PRINT_ANY, "ecn_mark", " ecn_mark %u", st->ecn_mark); | |
920700a4 | 242 | |
80dd880d VS |
243 | return 0; |
244 | ||
245 | } | |
246 | ||
247 | struct qdisc_util pie_qdisc_util = { | |
248 | .id = "pie", | |
249 | .parse_qopt = pie_parse_opt, | |
250 | .print_qopt = pie_print_opt, | |
251 | .print_xstats = pie_print_xstats, | |
252 | }; |