]>
Commit | Line | Data |
---|---|---|
aba5acdf SH |
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 <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 | #include <math.h> | |
23 | ||
24 | #include "utils.h" | |
25 | #include "tc_util.h" | |
26 | ||
dbd90dc2 | 27 | int get_qdisc_handle(__u32 *h, const char *str) |
aba5acdf SH |
28 | { |
29 | __u32 maj; | |
30 | char *p; | |
31 | ||
32 | maj = TC_H_UNSPEC; | |
33 | if (strcmp(str, "none") == 0) | |
34 | goto ok; | |
35 | maj = strtoul(str, &p, 16); | |
36 | if (p == str) | |
37 | return -1; | |
38 | maj <<= 16; | |
39 | if (*p != ':' && *p!=0) | |
40 | return -1; | |
41 | ok: | |
42 | *h = maj; | |
43 | return 0; | |
44 | } | |
45 | ||
dbd90dc2 | 46 | int get_tc_classid(__u32 *h, const char *str) |
aba5acdf SH |
47 | { |
48 | __u32 maj, min; | |
49 | char *p; | |
50 | ||
51 | maj = TC_H_ROOT; | |
52 | if (strcmp(str, "root") == 0) | |
53 | goto ok; | |
54 | maj = TC_H_UNSPEC; | |
55 | if (strcmp(str, "none") == 0) | |
56 | goto ok; | |
57 | maj = strtoul(str, &p, 16); | |
58 | if (p == str) { | |
59 | maj = 0; | |
60 | if (*p != ':') | |
61 | return -1; | |
62 | } | |
63 | if (*p == ':') { | |
64 | maj <<= 16; | |
65 | str = p+1; | |
66 | min = strtoul(str, &p, 16); | |
67 | if (*p != 0) | |
68 | return -1; | |
69 | maj |= min; | |
70 | } else if (*p != 0) | |
71 | return -1; | |
72 | ||
73 | ok: | |
74 | *h = maj; | |
75 | return 0; | |
76 | } | |
77 | ||
78 | int print_tc_classid(char *buf, int len, __u32 h) | |
79 | { | |
80 | if (h == TC_H_ROOT) | |
81 | sprintf(buf, "root"); | |
82 | else if (h == TC_H_UNSPEC) | |
83 | snprintf(buf, len, "none"); | |
84 | else if (TC_H_MAJ(h) == 0) | |
85 | snprintf(buf, len, ":%x", TC_H_MIN(h)); | |
86 | else if (TC_H_MIN(h) == 0) | |
87 | snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16); | |
88 | else | |
89 | snprintf(buf, len, "%x:%x", TC_H_MAJ(h)>>16, TC_H_MIN(h)); | |
90 | return 0; | |
91 | } | |
92 | ||
93 | char * sprint_tc_classid(__u32 h, char *buf) | |
94 | { | |
95 | if (print_tc_classid(buf, SPRINT_BSIZE-1, h)) | |
96 | strcpy(buf, "???"); | |
97 | return buf; | |
98 | } | |
99 | ||
4703e08a | 100 | /* |
72fc2040 SH |
101 | * NB: rates are scaled differently depending on bits or bytes. |
102 | * if bits are requested then k == 1000 | |
103 | * for bytes k = 1024 | |
4703e08a | 104 | */ |
dbd90dc2 | 105 | int get_rate(unsigned *rate, const char *str) |
aba5acdf SH |
106 | { |
107 | char *p; | |
108 | double bps = strtod(str, &p); | |
109 | ||
110 | if (p == str) | |
111 | return -1; | |
112 | ||
72fc2040 | 113 | if (*p == 0 || strcasecmp(p, "bit") == 0) |
aba5acdf | 114 | bps /= 8; |
72fc2040 SH |
115 | else if (strcasecmp(p, "kbit") == 0) |
116 | bps = (bps * 1000.) / 8; | |
117 | else if (strcasecmp(p, "mbit") == 0) | |
118 | bps = (bps * 1000000.)/8; | |
119 | else if (strcasecmp(p, "gbit") == 0) | |
120 | bps = (bps * 1000000000.)/8; | |
121 | else if (strcasecmp(p, "kibit") == 0) | |
122 | bps *= 1024 / 8; | |
123 | else if (strcasecmp(p, "mibit") == 0) | |
124 | bps *= 1024*1024/8; | |
125 | else if (strcasecmp(p, "gibit") == 0) | |
126 | bps *= 1024*1024*1024/8; | |
127 | else if (strcasecmp(p, "kbps") == 0) | |
128 | bps *= 1024; | |
129 | else if (strcasecmp(p, "mbps") == 0) | |
130 | bps *= 1024*1024; | |
131 | else if (strcasecmp(p, "gbps") == 0) | |
132 | bps *= 1024*1024*1024; | |
133 | else if (strcasecmp(p, "bps") != 0) | |
134 | return -1; | |
aba5acdf SH |
135 | |
136 | *rate = bps; | |
137 | return 0; | |
138 | } | |
139 | ||
140 | int get_rate_and_cell(unsigned *rate, int *cell_log, char *str) | |
141 | { | |
142 | char * slash = strchr(str, '/'); | |
143 | ||
144 | if (slash) | |
145 | *slash = 0; | |
146 | ||
147 | if (get_rate(rate, str)) | |
148 | return -1; | |
149 | ||
150 | if (slash) { | |
151 | int cell; | |
152 | int i; | |
153 | ||
154 | if (get_integer(&cell, slash+1, 0)) | |
155 | return -1; | |
156 | *slash = '/'; | |
157 | ||
158 | for (i=0; i<32; i++) { | |
159 | if ((1<<i) == cell) { | |
160 | *cell_log = i; | |
161 | return 0; | |
162 | } | |
163 | } | |
164 | return -1; | |
165 | } | |
166 | return 0; | |
167 | } | |
168 | ||
169 | ||
170 | int print_rate(char *buf, int len, __u32 rate) | |
171 | { | |
172 | double tmp = (double)rate*8; | |
173 | ||
4703e08a | 174 | if (tmp >= 999999 && fabs(1000000.*rint(tmp/1000000.) - tmp) < 1000) |
72fc2040 | 175 | snprintf(buf, len, "%gmbit", rint(tmp/1000000.)); |
4703e08a | 176 | else if (tmp >= 990 && fabs(1000.*rint(tmp/1000.) - tmp) < 10) |
72fc2040 | 177 | snprintf(buf, len, "%gkbit", rint(tmp/1000.)); |
aba5acdf | 178 | else |
72fc2040 | 179 | snprintf(buf, len, "%ubit", rate); |
aba5acdf SH |
180 | return 0; |
181 | } | |
182 | ||
183 | char * sprint_rate(__u32 rate, char *buf) | |
184 | { | |
185 | if (print_rate(buf, SPRINT_BSIZE-1, rate)) | |
186 | strcpy(buf, "???"); | |
187 | return buf; | |
188 | } | |
189 | ||
dbd90dc2 | 190 | int get_usecs(unsigned *usecs, const char *str) |
aba5acdf SH |
191 | { |
192 | double t; | |
193 | char *p; | |
194 | ||
195 | t = strtod(str, &p); | |
196 | if (p == str) | |
197 | return -1; | |
198 | ||
199 | if (*p) { | |
200 | if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 || | |
201 | strcasecmp(p, "secs")==0) | |
202 | t *= 1000000; | |
203 | else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 || | |
204 | strcasecmp(p, "msecs") == 0) | |
205 | t *= 1000; | |
206 | else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 || | |
207 | strcasecmp(p, "usecs") == 0) | |
208 | t *= 1; | |
209 | else | |
210 | return -1; | |
211 | } | |
212 | ||
213 | *usecs = t; | |
214 | return 0; | |
215 | } | |
216 | ||
217 | ||
218 | int print_usecs(char *buf, int len, __u32 usec) | |
219 | { | |
220 | double tmp = usec; | |
221 | ||
222 | if (tmp >= 1000000) | |
223 | snprintf(buf, len, "%.1fs", tmp/1000000); | |
224 | else if (tmp >= 1000) | |
225 | snprintf(buf, len, "%.1fms", tmp/1000); | |
226 | else | |
227 | snprintf(buf, len, "%uus", usec); | |
228 | return 0; | |
229 | } | |
230 | ||
231 | char * sprint_usecs(__u32 usecs, char *buf) | |
232 | { | |
233 | if (print_usecs(buf, SPRINT_BSIZE-1, usecs)) | |
234 | strcpy(buf, "???"); | |
235 | return buf; | |
236 | } | |
237 | ||
dbd90dc2 | 238 | int get_size(unsigned *size, const char *str) |
aba5acdf SH |
239 | { |
240 | double sz; | |
241 | char *p; | |
242 | ||
243 | sz = strtod(str, &p); | |
244 | if (p == str) | |
245 | return -1; | |
246 | ||
247 | if (*p) { | |
248 | if (strcasecmp(p, "kb") == 0 || strcasecmp(p, "k")==0) | |
249 | sz *= 1024; | |
dbd90dc2 SH |
250 | else if (strcasecmp(p, "gb") == 0 || strcasecmp(p, "g")==0) |
251 | sz *= 1024*1024*1024; | |
252 | else if (strcasecmp(p, "gbit") == 0) | |
253 | sz *= 1024*1024*1024/8; | |
aba5acdf SH |
254 | else if (strcasecmp(p, "mb") == 0 || strcasecmp(p, "m")==0) |
255 | sz *= 1024*1024; | |
256 | else if (strcasecmp(p, "mbit") == 0) | |
257 | sz *= 1024*1024/8; | |
258 | else if (strcasecmp(p, "kbit") == 0) | |
259 | sz *= 1024/8; | |
260 | else if (strcasecmp(p, "b") != 0) | |
261 | return -1; | |
262 | } | |
263 | ||
264 | *size = sz; | |
265 | return 0; | |
266 | } | |
267 | ||
268 | int get_size_and_cell(unsigned *size, int *cell_log, char *str) | |
269 | { | |
270 | char * slash = strchr(str, '/'); | |
271 | ||
272 | if (slash) | |
273 | *slash = 0; | |
274 | ||
275 | if (get_size(size, str)) | |
276 | return -1; | |
277 | ||
278 | if (slash) { | |
279 | int cell; | |
280 | int i; | |
281 | ||
282 | if (get_integer(&cell, slash+1, 0)) | |
283 | return -1; | |
284 | *slash = '/'; | |
285 | ||
286 | for (i=0; i<32; i++) { | |
287 | if ((1<<i) == cell) { | |
288 | *cell_log = i; | |
289 | return 0; | |
290 | } | |
291 | } | |
292 | return -1; | |
293 | } | |
294 | return 0; | |
295 | } | |
296 | ||
297 | int print_size(char *buf, int len, __u32 sz) | |
298 | { | |
299 | double tmp = sz; | |
300 | ||
301 | if (sz >= 1024*1024 && fabs(1024*1024*rint(tmp/(1024*1024)) - sz) < 1024) | |
302 | snprintf(buf, len, "%gMb", rint(tmp/(1024*1024))); | |
303 | else if (sz >= 1024 && fabs(1024*rint(tmp/1024) - sz) < 16) | |
304 | snprintf(buf, len, "%gKb", rint(tmp/1024)); | |
305 | else | |
306 | snprintf(buf, len, "%ub", sz); | |
307 | return 0; | |
308 | } | |
309 | ||
310 | char * sprint_size(__u32 size, char *buf) | |
311 | { | |
312 | if (print_size(buf, SPRINT_BSIZE-1, size)) | |
313 | strcpy(buf, "???"); | |
314 | return buf; | |
315 | } | |
316 | ||
63e989f5 SH |
317 | static double percent_scale = (double)(1ull << 32) / 100.; |
318 | ||
319 | int get_percent(__u32 *percent, const char *str) | |
320 | { | |
321 | char *p; | |
322 | double per = strtod(str, &p); | |
323 | ||
324 | if (per > 100.) | |
325 | return -1; | |
326 | if (*p && strcmp(p, "%")) | |
327 | return -1; | |
328 | ||
329 | *percent = per * percent_scale; | |
330 | return 0; | |
331 | } | |
332 | ||
333 | int print_percent(char *buf, int len, __u32 per) | |
334 | { | |
335 | snprintf(buf, len, "%g%%", (double) per / percent_scale); | |
336 | return 0; | |
337 | } | |
338 | ||
339 | char * sprint_percent(__u32 per, char *buf) | |
340 | { | |
341 | if (print_percent(buf, SPRINT_BSIZE-1, per)) | |
342 | strcpy(buf, "???"); | |
343 | return buf; | |
344 | } | |
345 | ||
aba5acdf SH |
346 | int print_qdisc_handle(char *buf, int len, __u32 h) |
347 | { | |
348 | snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16); | |
349 | return 0; | |
350 | } | |
351 | ||
352 | char * sprint_qdisc_handle(__u32 h, char *buf) | |
353 | { | |
354 | if (print_qdisc_handle(buf, SPRINT_BSIZE-1, h)) | |
355 | strcpy(buf, "???"); | |
356 | return buf; | |
357 | } | |
358 | ||
359 |