1dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/*
2dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * tc_util.c		Misc TC utility functions.
3dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
4dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		This program is free software; you can redistribute it and/or
5dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		modify it under the terms of the GNU General Public License
6dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		as published by the Free Software Foundation; either version
7dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *		2 of the License, or (at your option) any later version.
8dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
9dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat *
11dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat */
12dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
13dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdio.h>
14dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <stdlib.h>
15dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <unistd.h>
16dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <syslog.h>
17dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <fcntl.h>
18dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <sys/socket.h>
19dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <netinet/in.h>
20dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <arpa/inet.h>
21dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <string.h>
22dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include <math.h>
23dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
24dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "utils.h"
25dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#include "tc_util.h"
26dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
27dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#ifndef LIBDIR
28dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#define LIBDIR "/usr/lib/"
29dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat#endif
30dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
31dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatconst char *get_tc_lib(void)
32dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
33dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	const char *lib_dir;
34dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
35dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	lib_dir = getenv("TC_LIB_DIR");
36dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (!lib_dir)
37dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		lib_dir = LIBDIR "/tc/";
38dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
39dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return lib_dir;
40dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
41dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
42dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_qdisc_handle(__u32 *h, const char *str)
43dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
44dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	__u32 maj;
45dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *p;
46dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
47dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	maj = TC_H_UNSPEC;
48dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (strcmp(str, "none") == 0)
49dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		goto ok;
50dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	maj = strtoul(str, &p, 16);
51dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (p == str)
52dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
53dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	maj <<= 16;
54dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (*p != ':' && *p!=0)
55dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
56dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatok:
57dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*h = maj;
58dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
59dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
60dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
61dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_tc_classid(__u32 *h, const char *str)
62dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
63dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	__u32 maj, min;
64dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *p;
65dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
66dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	maj = TC_H_ROOT;
67dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (strcmp(str, "root") == 0)
68dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		goto ok;
69dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	maj = TC_H_UNSPEC;
70dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (strcmp(str, "none") == 0)
71dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		goto ok;
72dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	maj = strtoul(str, &p, 16);
73dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (p == str) {
74dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		maj = 0;
75dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (*p != ':')
76dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
77dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
78dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (*p == ':') {
79dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (maj >= (1<<16))
80dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
81dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		maj <<= 16;
82dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		str = p+1;
83dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		min = strtoul(str, &p, 16);
84dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (*p != 0)
85dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
86dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (min >= (1<<16))
87dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
88dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		maj |= min;
89dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else if (*p != 0)
90dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
91dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
92dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatok:
93dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*h = maj;
94dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
95dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
96dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
97dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint print_tc_classid(char *buf, int len, __u32 h)
98dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
99dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (h == TC_H_ROOT)
100dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		sprintf(buf, "root");
101dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (h == TC_H_UNSPEC)
102dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "none");
103dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (TC_H_MAJ(h) == 0)
104dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, ":%x", TC_H_MIN(h));
105dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (TC_H_MIN(h) == 0)
106dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16);
107dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
108dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%x:%x", TC_H_MAJ(h)>>16, TC_H_MIN(h));
109dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
110dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
111dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
112dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar * sprint_tc_classid(__u32 h, char *buf)
113dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
114dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (print_tc_classid(buf, SPRINT_BSIZE-1, h))
115dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		strcpy(buf, "???");
116dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return buf;
117dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
118dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
119dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat/* See http://physics.nist.gov/cuu/Units/binary.html */
120dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const struct rate_suffix {
121dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	const char *name;
122dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double scale;
123dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat} suffixes[] = {
124dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "bit",	1. },
125dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "Kibit",	1024. },
126dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "kbit",	1000. },
127dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "mibit",	1024.*1024. },
128dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "mbit",	1000000. },
129dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "gibit",	1024.*1024.*1024. },
130dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "gbit",	1000000000. },
131dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "tibit",	1024.*1024.*1024.*1024. },
132dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "tbit",	1000000000000. },
133dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "Bps",	8. },
134dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "KiBps",	8.*1024. },
135dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "KBps",	8000. },
136dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "MiBps",	8.*1024*1024. },
137dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "MBps",	8000000. },
138dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "GiBps",	8.*1024.*1024.*1024. },
139dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "GBps",	8000000000. },
140dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "TiBps",	8.*1024.*1024.*1024.*1024. },
141dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ "TBps",	8000000000000. },
142dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	{ NULL }
143dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat};
144dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
145dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
146dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_rate(unsigned *rate, const char *str)
147dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
148dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *p;
149dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double bps = strtod(str, &p);
150dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	const struct rate_suffix *s;
151dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
152dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (p == str)
153dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
154dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
155dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (*p == '\0') {
156dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*rate = bps / 8.;	/* assume bytes/sec */
157dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return 0;
158dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
159dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
160dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	for (s = suffixes; s->name; ++s) {
161dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (strcasecmp(s->name, p) == 0) {
162dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			*rate = (bps * s->scale) / 8.;
163dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return 0;
164dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
165dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
166dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
167dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return -1;
168dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
169dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
170dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_rate_and_cell(unsigned *rate, int *cell_log, char *str)
171dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
172dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char * slash = strchr(str, '/');
173dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
174dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (slash)
175dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*slash = 0;
176dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
177dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (get_rate(rate, str))
178dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
179dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
180dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (slash) {
181dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int cell;
182dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
183dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
184dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (get_integer(&cell, slash+1, 0))
185dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
186dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*slash = '/';
187dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
188dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (i=0; i<32; i++) {
189dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if ((1<<i) == cell) {
190dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				*cell_log = i;
191dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return 0;
192dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
193dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
194dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
195dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
196dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
197dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
198dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
199dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_rate(char *buf, int len, __u32 rate)
200dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
201dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double tmp = (double)rate*8;
202dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	extern int use_iec;
203dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
204dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (use_iec) {
205dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (tmp >= 1000.0*1024.0*1024.0)
206dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			snprintf(buf, len, "%.0fMibit", tmp/1024.0*1024.0);
207dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (tmp >= 1000.0*1024)
208dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			snprintf(buf, len, "%.0fKibit", tmp/1024);
209dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else
210dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			snprintf(buf, len, "%.0fbit", tmp);
211dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	} else {
212dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (tmp >= 1000.0*1000000.0)
213dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			snprintf(buf, len, "%.0fMbit", tmp/1000000.0);
214dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (tmp >= 1000.0 * 1000.0)
215dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			snprintf(buf, len, "%.0fKbit", tmp/1000.0);
216dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else
217dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			snprintf(buf, len, "%.0fbit",  tmp);
218dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
219dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
220dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
221dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar * sprint_rate(__u32 rate, char *buf)
222dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
223dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	print_rate(buf, SPRINT_BSIZE-1, rate);
224dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return buf;
225dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
226dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
227dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_time(unsigned *time, const char *str)
228dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
229dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double t;
230dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *p;
231dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
232dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	t = strtod(str, &p);
233dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (p == str)
234dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
235dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
236dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (*p) {
237dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 ||
238dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		    strcasecmp(p, "secs")==0)
239dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			t *= TIME_UNITS_PER_SEC;
240dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 ||
241dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			 strcasecmp(p, "msecs") == 0)
242dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			t *= TIME_UNITS_PER_SEC/1000;
243dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 ||
244dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			 strcasecmp(p, "usecs") == 0)
245dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			t *= TIME_UNITS_PER_SEC/1000000;
246dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else
247dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
248dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
249dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
250dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*time = t;
251dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
252dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
253dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
254dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
255dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_time(char *buf, int len, __u32 time)
256dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
257dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double tmp = time;
258dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
259dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tmp >= TIME_UNITS_PER_SEC)
260dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%.1fs", tmp/TIME_UNITS_PER_SEC);
261dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (tmp >= TIME_UNITS_PER_SEC/1000)
262dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%.1fms", tmp/(TIME_UNITS_PER_SEC/1000));
263dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
264dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%uus", time);
265dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
266dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
267dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar * sprint_time(__u32 time, char *buf)
268dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
269dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	print_time(buf, SPRINT_BSIZE-1, time);
270dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return buf;
271dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
272dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
273dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar * sprint_ticks(__u32 ticks, char *buf)
274dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
275dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return sprint_time(tc_core_tick2time(ticks), buf);
276dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
277dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
278dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_size(unsigned *size, const char *str)
279dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
280dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double sz;
281dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *p;
282dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
283dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	sz = strtod(str, &p);
284dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (p == str)
285dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
286dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
287dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (*p) {
288dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (strcasecmp(p, "kb") == 0 || strcasecmp(p, "k")==0)
289dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sz *= 1024;
290dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (strcasecmp(p, "gb") == 0 || strcasecmp(p, "g")==0)
291dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sz *= 1024*1024*1024;
292dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (strcasecmp(p, "gbit") == 0)
293dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sz *= 1024*1024*1024/8;
294dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (strcasecmp(p, "mb") == 0 || strcasecmp(p, "m")==0)
295dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sz *= 1024*1024;
296dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (strcasecmp(p, "mbit") == 0)
297dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sz *= 1024*1024/8;
298dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (strcasecmp(p, "kbit") == 0)
299dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sz *= 1024/8;
300dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		else if (strcasecmp(p, "b") != 0)
301dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
302dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
303dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
304dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*size = sz;
305dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
306dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
307dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
308dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_size_and_cell(unsigned *size, int *cell_log, char *str)
309dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
310dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char * slash = strchr(str, '/');
311dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
312dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (slash)
313dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*slash = 0;
314dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
315dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (get_size(size, str))
316dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
317dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
318dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (slash) {
319dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int cell;
320dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		int i;
321dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
322dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (get_integer(&cell, slash+1, 0))
323dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
324dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*slash = '/';
325dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
326dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		for (i=0; i<32; i++) {
327dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if ((1<<i) == cell) {
328dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				*cell_log = i;
329dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				return 0;
330dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
331dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
332dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
333dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
334dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
335dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
336dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
337dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_size(char *buf, int len, __u32 sz)
338dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
339dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double tmp = sz;
340dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
341dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (sz >= 1024*1024 && fabs(1024*1024*rint(tmp/(1024*1024)) - sz) < 1024)
342dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%gMb", rint(tmp/(1024*1024)));
343dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (sz >= 1024 && fabs(1024*rint(tmp/1024) - sz) < 16)
344dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%gKb", rint(tmp/1024));
345dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
346dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%ub", sz);
347dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
348dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
349dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar * sprint_size(__u32 size, char *buf)
350dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
351dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	print_size(buf, SPRINT_BSIZE-1, size);
352dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return buf;
353dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
354dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
355dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatstatic const double max_percent_value = 0xffffffff;
356dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
357dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_percent(__u32 *percent, const char *str)
358dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
359dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	char *p;
360dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	double per = strtod(str, &p) / 100.;
361dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
362dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (per > 1. || per < 0)
363dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
364dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (*p && strcmp(p, "%"))
365dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1;
366dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
367dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*percent = (unsigned) rint(per * max_percent_value);
368dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
369dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
370dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
371dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_percent(char *buf, int len, __u32 per)
372dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
373dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	snprintf(buf, len, "%g%%", 100. * (double) per / max_percent_value);
374dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
375dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
376dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar * sprint_percent(__u32 per, char *buf)
377dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
378dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	print_percent(buf, SPRINT_BSIZE-1, per);
379dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return buf;
380dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
381dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
382dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_qdisc_handle(char *buf, int len, __u32 h)
383dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
384dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	snprintf(buf, len, "%x:", TC_H_MAJ(h)>>16);
385dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
386dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
387dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar * sprint_qdisc_handle(__u32 h, char *buf)
388dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
389dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	print_qdisc_handle(buf, SPRINT_BSIZE-1, h);
390dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return buf;
391dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
392dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
393dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar * action_n2a(int action, char *buf, int len)
394dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
395dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	switch (action) {
396dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case -1:
397dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return "continue";
398dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		break;
399dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case TC_ACT_OK:
400dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return "pass";
401dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		break;
402dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case TC_ACT_SHOT:
403dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return "drop";
404dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		break;
405dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case TC_ACT_RECLASSIFY:
406dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return "reclassify";
407dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case TC_ACT_PIPE:
408dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return "pipe";
409dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case TC_ACT_STOLEN:
410dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return "stolen";
411dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	default:
412dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%d", action);
413dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return buf;
414dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
415dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
416dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
417dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint action_a2n(char *arg, int *result)
418dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
419dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int res;
420dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
421dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(arg, "continue") == 0)
422dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = -1;
423dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (matches(arg, "drop") == 0)
424dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = TC_ACT_SHOT;
425dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (matches(arg, "shot") == 0)
426dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = TC_ACT_SHOT;
427dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (matches(arg, "pass") == 0)
428dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = TC_ACT_OK;
429dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (strcmp(arg, "ok") == 0)
430dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = TC_ACT_OK;
431dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (matches(arg, "reclassify") == 0)
432dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = TC_ACT_RECLASSIFY;
433dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else {
434dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		char dummy;
435dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (sscanf(arg, "%d%c", &res, &dummy) != 1)
436dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			return -1;
437dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
438dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*result = res;
439dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
440dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
441dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
442dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatint get_linklayer(unsigned *val, const char *arg)
443dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
444dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int res;
445dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
446dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (matches(arg, "ethernet") == 0)
447dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = LINKLAYER_ETHERNET;
448dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (matches(arg, "atm") == 0)
449dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = LINKLAYER_ATM;
450dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else if (matches(arg, "adsl") == 0)
451dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		res = LINKLAYER_ATM;
452dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	else
453dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return -1; /* Indicate error */
454dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
455dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	*val = res;
456dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return 0;
457dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
458dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
459dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_linklayer(char *buf, int len, unsigned linklayer)
460dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
461dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	switch (linklayer) {
462dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case LINKLAYER_UNSPEC:
463dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%s", "unspec");
464dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return;
465dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case LINKLAYER_ETHERNET:
466dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%s", "ethernet");
467dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return;
468dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	case LINKLAYER_ATM:
469dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%s", "atm");
470dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return;
471dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	default:
472dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		snprintf(buf, len, "%s", "unknown");
473dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return;
474dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
475dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
476dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
477dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatchar *sprint_linklayer(unsigned linklayer, char *buf)
478dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
479dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	print_linklayer(buf, SPRINT_BSIZE-1, linklayer);
480dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	return buf;
481dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
482dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
483dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_tm(FILE * f, const struct tcf_t *tm)
484dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
485dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	int hz = get_user_hz();
486dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tm->install != 0)
487dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, " installed %u sec", (unsigned)(tm->install/hz));
488dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tm->lastuse != 0)
489dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, " used %u sec", (unsigned)(tm->lastuse/hz));
490dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tm->expires != 0)
491dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(f, " expires %u sec", (unsigned)(tm->expires/hz));
492dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
493dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
494dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtattr **xstats)
495dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
496dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	SPRINT_BUF(b1);
497dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	struct rtattr *tbs[TCA_STATS_MAX + 1];
498dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
499dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	parse_rtattr_nested(tbs, TCA_STATS_MAX, rta);
500dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
501dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tbs[TCA_STATS_BASIC]) {
502dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct gnet_stats_basic bs = {0};
503dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]), sizeof(bs)));
504dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%sSent %llu bytes %u pkt",
505dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			prefix, (unsigned long long) bs.bytes, bs.packets);
506dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
507dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
508dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tbs[TCA_STATS_QUEUE]) {
509dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct gnet_stats_queue q = {0};
510dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
511dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, " (dropped %u, overlimits %u requeues %u) ",
512dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			q.drops, q.overlimits, q.requeues);
513dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
514dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
515dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tbs[TCA_STATS_RATE_EST]) {
516dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct gnet_stats_rate_est re = {0};
517dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re)));
518dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "\n%srate %s %upps ",
519dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			prefix, sprint_rate(re.bps, b1), re.pps);
520dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
521dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
522dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tbs[TCA_STATS_QUEUE]) {
523dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct gnet_stats_queue q = {0};
524dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q)));
525dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (!tbs[TCA_STATS_RATE_EST])
526dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(fp, "\n%s", prefix);
527dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "backlog %s %up requeues %u ",
528dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			sprint_size(q.backlog, b1), q.qlen, q.requeues);
529dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
530dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
531dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (xstats)
532dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*xstats = tbs[TCA_STATS_APP] ? : NULL;
533dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
534dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
535dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatvoid print_tcstats_attr(FILE *fp, struct rtattr *tb[], char *prefix, struct rtattr **xstats)
536dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat{
537dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	SPRINT_BUF(b1);
538dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
539dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_STATS2]) {
540dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		print_tcstats2_attr(fp, tb[TCA_STATS2], prefix, xstats);
541dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (xstats && NULL == *xstats)
542dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			goto compat_xstats;
543dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		return;
544dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
545dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	/* backward compatibility */
546dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_STATS]) {
547dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		struct tc_stats st;
548dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
549dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		/* handle case where kernel returns more/less than we know about */
550dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memset(&st, 0, sizeof(st));
551dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		memcpy(&st, RTA_DATA(tb[TCA_STATS]), MIN(RTA_PAYLOAD(tb[TCA_STATS]), sizeof(st)));
552dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
553dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		fprintf(fp, "%sSent %llu bytes %u pkts (dropped %u, overlimits %u) ",
554dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			prefix, (unsigned long long)st.bytes, st.packets, st.drops,
555dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			st.overlimits);
556dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
557dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		if (st.bps || st.pps || st.qlen || st.backlog) {
558dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			fprintf(fp, "\n%s", prefix);
559dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (st.bps || st.pps) {
560dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(fp, "rate ");
561dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (st.bps)
562dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					fprintf(fp, "%s ", sprint_rate(st.bps, b1));
563dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (st.pps)
564dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					fprintf(fp, "%upps ", st.pps);
565dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
566dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			if (st.qlen || st.backlog) {
567dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				fprintf(fp, "backlog ");
568dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (st.backlog)
569dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					fprintf(fp, "%s ", sprint_size(st.backlog, b1));
570dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat				if (st.qlen)
571dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat					fprintf(fp, "%up ", st.qlen);
572dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat			}
573dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		}
574dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	}
575dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
576dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehatcompat_xstats:
577dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat	if (tb[TCA_XSTATS] && xstats)
578dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat		*xstats = tb[TCA_XSTATS];
579dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat}
580dcfb7a77f8709125e97c313cb8ab6ec4d87468f4San Mehat
581