tc_util.c revision 63e989f5e043a3a45857fe4ba083c49050eb3300
15f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes/*
25f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * tc_util.c		Misc TC utility functions.
35f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *
45f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *		This program is free software; you can redistribute it and/or
55f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *		modify it under the terms of the GNU General Public License
65f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *		as published by the Free Software Foundation; either version
75f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *		2 of the License, or (at your option) any later version.
85f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *
95f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
105f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes *
115f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes */
125f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
135f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <stdio.h>
145f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <stdlib.h>
155f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <unistd.h>
165f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <syslog.h>
175f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <fcntl.h>
185f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <sys/socket.h>
195f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <netinet/in.h>
205f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <arpa/inet.h>
215f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <string.h>
225f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include <math.h>
235f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
245f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include "utils.h"
255f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes#include "tc_util.h"
265f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
275f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesint get_qdisc_handle(__u32 *h, const char *str)
285f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes{
295f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	__u32 maj;
305f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	char *p;
315f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
325f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	maj = TC_H_UNSPEC;
335f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (strcmp(str, "none") == 0)
345f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		goto ok;
355f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	maj = strtoul(str, &p, 16);
365f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (p == str)
375f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		return -1;
385f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	maj <<= 16;
395f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (*p != ':' && *p!=0)
405f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		return -1;
415f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesok:
425f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	*h = maj;
435f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	return 0;
445f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes}
455f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
465f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesint get_tc_classid(__u32 *h, const char *str)
475f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes{
485f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	__u32 maj, min;
495f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	char *p;
505f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
515f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	maj = TC_H_ROOT;
525f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (strcmp(str, "root") == 0)
535f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		goto ok;
545f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	maj = TC_H_UNSPEC;
555f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (strcmp(str, "none") == 0)
565f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		goto ok;
575f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	maj = strtoul(str, &p, 16);
585f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (p == str) {
595f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		maj = 0;
605f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		if (*p != ':')
615f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes			return -1;
625f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	}
635f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (*p == ':') {
645f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		maj <<= 16;
655f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		str = p+1;
665f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		min = strtoul(str, &p, 16);
675f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		if (*p != 0)
685f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes			return -1;
695f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		maj |= min;
705f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	} else if (*p != 0)
715f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		return -1;
725f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
735f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesok:
745f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	*h = maj;
755f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	return 0;
765f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes}
775f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
785f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughesint print_tc_classid(char *buf, int len, __u32 h)
795f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes{
805f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (h == TC_H_ROOT)
815f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		sprintf(buf, "root");
825f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	else if (h == TC_H_UNSPEC)
835f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		snprintf(buf, len, "none");
845f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	else if (TC_H_MAJ(h) == 0)
855f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		snprintf(buf, len, ":%x", TC_H_MIN(h));
865f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	else if (TC_H_MIN(h) == 0)
875f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16);
885f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	else
895f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		snprintf(buf, len, "%x:%x", TC_H_MAJ(h)>>16, TC_H_MIN(h));
905f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	return 0;
915f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes}
925f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes
935f0a23683aa603d8c50b6dd071a565821b76067bElliott Hugheschar * sprint_tc_classid(__u32 h, char *buf)
945f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes{
955f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes	if (print_tc_classid(buf, SPRINT_BSIZE-1, h))
965f0a23683aa603d8c50b6dd071a565821b76067bElliott Hughes		strcpy(buf, "???");
97	return buf;
98}
99
100/*
101 * NB: rates are scaled differently depending on bits or bytes.
102 *     if bits are requested then k == 1000
103 *     for bytes k = 1024
104 */
105int get_rate(unsigned *rate, const char *str)
106{
107	char *p;
108	double bps = strtod(str, &p);
109
110	if (p == str)
111		return -1;
112
113	if (*p == 0 || strcasecmp(p, "bit") == 0)
114		bps /= 8;
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;
135
136	*rate = bps;
137	return 0;
138}
139
140int 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
170int print_rate(char *buf, int len, __u32 rate)
171{
172	double tmp = (double)rate*8;
173
174	if (tmp >= 999999 && fabs(1000000.*rint(tmp/1000000.) - tmp) < 1000)
175		snprintf(buf, len, "%gmbit", rint(tmp/1000000.));
176	else if (tmp >= 990 && fabs(1000.*rint(tmp/1000.) - tmp) < 10)
177		snprintf(buf, len, "%gkbit", rint(tmp/1000.));
178	else
179		snprintf(buf, len, "%ubit", rate);
180	return 0;
181}
182
183char * sprint_rate(__u32 rate, char *buf)
184{
185	if (print_rate(buf, SPRINT_BSIZE-1, rate))
186		strcpy(buf, "???");
187	return buf;
188}
189
190int get_usecs(unsigned *usecs, const char *str)
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
218int 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
231char * sprint_usecs(__u32 usecs, char *buf)
232{
233	if (print_usecs(buf, SPRINT_BSIZE-1, usecs))
234		strcpy(buf, "???");
235	return buf;
236}
237
238int get_size(unsigned *size, const char *str)
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;
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;
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
268int 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
297int 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
310char * sprint_size(__u32 size, char *buf)
311{
312	if (print_size(buf, SPRINT_BSIZE-1, size))
313		strcpy(buf, "???");
314	return buf;
315}
316
317static double percent_scale = (double)(1ull << 32) / 100.;
318
319int 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
333int print_percent(char *buf, int len, __u32 per)
334{
335	snprintf(buf, len, "%g%%", (double) per / percent_scale);
336	return 0;
337}
338
339char * sprint_percent(__u32 per, char *buf)
340{
341	if (print_percent(buf, SPRINT_BSIZE-1, per))
342		strcpy(buf, "???");
343	return buf;
344}
345
346int 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
352char * 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
360