2 /* $KAME: tbrconfig.c,v 1.3 2001/05/08 04:36:39 itojun Exp $ */
5 * Sony Computer Science Laboratories Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/param.h>
31 #include <sys/socket.h>
32 #include <sys/ioctl.h>
33 #include <sys/fcntl.h>
34 #include <sys/sysctl.h>
43 #include <altq/altq.h>
45 #define ALTQ_DEVICE "/dev/altq/altq"
47 static void usage(void);
48 static u_long
atobps(const char *s
);
49 static u_long
atobytes(const char *s
);
50 static u_int
size_bucket(const char *ifname
, const u_int rate
);
51 static u_int
autosize_bucket(const char *ifname
, const u_int rate
);
52 static int get_clockfreq(void);
53 static int get_ifmtu(const char *ifname
);
54 static void list_all(void);
59 fprintf(stderr
, "usage: tbrconfig interface [tokenrate [bucketsize]\n");
60 fprintf(stderr
, " tbrconfig -d interface\n");
61 fprintf(stderr
, " tbrconfig -a\n");
66 main(int argc
, char **argv
)
76 while ((ch
= getopt(argc
, argv
, "ad")) != -1) {
92 req
.ifname
[IFNAMSIZ
-1] = '\0';
93 strncpy(req
.ifname
, argv
[0], IFNAMSIZ
-1);
95 rate
= (u_int
)atobps(argv
[1]);
97 if (strncmp(argv
[2], "auto", strlen("auto")) == 0)
98 depth
= autosize_bucket(req
.ifname
, rate
);
100 depth
= (u_int
)atobytes(argv
[2]);
105 if (delete || rate
> 0) {
106 /* set token bucket regulator */
110 depth
= size_bucket(req
.ifname
, rate
);
112 req
.tb_prof
.rate
= rate
;
113 req
.tb_prof
.depth
= depth
;
115 if ((fd
= open(ALTQ_DEVICE
, O_RDWR
)) < 0)
116 err(1, "can't open altq device");
118 if (ioctl(fd
, ALTQTBRSET
, &req
) < 0)
119 err(1, "ALTQTBRSET for interface %s", req
.ifname
);
124 printf("deleted token bucket regulator on %s\n",
130 /* get token bucket regulator */
131 if ((fd
= open(ALTQ_DEVICE
, O_RDONLY
)) < 0)
132 err(1, "can't open altq device");
133 if (ioctl(fd
, ALTQTBRGET
, &req
) < 0)
134 err(1, "ALTQTBRGET for interface %s", req
.ifname
);
135 if (req
.tb_prof
.rate
== 0)
136 printf("no token bucket regulater found on %s\n", req
.ifname
);
138 char rate_str
[64], size_str
[64];
140 if (req
.tb_prof
.rate
< 999999)
141 sprintf(rate_str
, "%.2fK",
142 (double)req
.tb_prof
.rate
/1000.0);
144 sprintf(rate_str
, "%.2fM",
145 (double)req
.tb_prof
.rate
/1000000.0);
146 if (req
.tb_prof
.depth
< 10240)
147 sprintf(size_str
, "%u", req
.tb_prof
.depth
);
149 sprintf(size_str
, "%.2fK",
150 (double)req
.tb_prof
.depth
/1024.0);
151 printf("%s: tokenrate %s(bps) bucketsize %s(bytes)\n",
152 req
.ifname
, rate_str
, size_str
);
161 struct if_nameindex
*ifn_list
, *ifnp
;
163 char rate_str
[64], size_str
[64];
166 if ((ifn_list
= if_nameindex()) == NULL
)
167 err(1, "if_nameindex failed");
169 if ((fd
= open(ALTQ_DEVICE
, O_RDONLY
)) < 0)
170 err(1, "can't open altq device");
173 for (ifnp
= ifn_list
; ifnp
->if_name
!= NULL
; ifnp
++) {
174 req
.ifname
[IFNAMSIZ
-1] = '\0';
175 strncpy(req
.ifname
, ifnp
->if_name
, IFNAMSIZ
-1);
176 if (ioctl(fd
, ALTQTBRGET
, &req
) < 0)
177 err(1, "ALTQTBRGET");
178 if (req
.tb_prof
.rate
== 0)
181 if (req
.tb_prof
.rate
< 999999)
182 sprintf(rate_str
, "%.2fK",
183 (double)req
.tb_prof
.rate
/1000.0);
185 sprintf(rate_str
, "%.2fM",
186 (double)req
.tb_prof
.rate
/1000000.0);
187 if (req
.tb_prof
.depth
< 10240)
188 sprintf(size_str
, "%u", req
.tb_prof
.depth
);
190 sprintf(size_str
, "%.2fK",
191 (double)req
.tb_prof
.depth
/1024.0);
192 printf("%s: tokenrate %s(bps) bucketsize %s(bytes)\n",
193 req
.ifname
, rate_str
, size_str
);
197 printf("no active token bucket regulator\n");
200 if_freenameindex(ifn_list
);
204 atobps(const char *s
)
209 bandwidth
= strtoul(s
, &cp
, 0);
211 if (*cp
== 'K' || *cp
== 'k')
213 else if (*cp
== 'M' || *cp
== 'm')
214 bandwidth
*= 1000000;
215 else if (*cp
== 'G' || *cp
== 'g')
216 bandwidth
*= 1000000000;
222 atobytes(const char *s
)
227 bytes
= strtoul(s
, &cp
, 0);
229 if (*cp
== 'K' || *cp
== 'k')
231 else if (*cp
== 'M' || *cp
== 'm')
232 bytes
*= 1024 * 1024;
233 else if (*cp
== 'G' || *cp
== 'g')
234 bytes
*= 1024 * 1024 * 1024;
240 * use heuristics to determin the bucket size
243 size_bucket(const char *ifname
, const u_int rate
)
247 mtu
= get_ifmtu(ifname
);
249 mtu
= 1500; /* assume that the path mtu is still 1500 */
251 if (rate
<= 1*1000*1000)
253 else if (rate
<= 10*1000*1000)
255 else if (rate
<= 200*1000*1000)
265 * compute the bucket size to be required to fill the rate
266 * even when the rate is controlled only by the kernel timer.
269 autosize_bucket(const char *ifname
, const u_int rate
)
271 u_int size
, freq
, mtu
;
273 mtu
= get_ifmtu(ifname
);
274 freq
= get_clockfreq();
275 size
= rate
/ 8 / freq
;
284 struct clockinfo clkinfo
;
288 clkinfo
.hz
= 100; /* default Hz */
291 mib
[1] = KERN_CLOCKRATE
;
292 len
= sizeof(struct clockinfo
);
293 if (sysctl(mib
, 2, &clkinfo
, &len
, NULL
, 0) == -1)
294 warnx("can't get clockrate via sysctl! use %dHz", clkinfo
.hz
);
299 get_ifmtu(const char *ifname
)
304 struct if_data ifdata
;
307 mtu
= 512; /* default MTU */
309 if ((s
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
311 strncpy(ifr
.ifr_name
, ifname
, sizeof ifr
.ifr_name
);
313 ifr
.ifr_data
= (caddr_t
)&ifdata
;
314 if (ioctl(s
, SIOCGIFDATA
, (caddr_t
)&ifr
) == 0)
315 mtu
= ifdata
.ifi_mtu
;
317 if (ioctl(s
, SIOCGIFMTU
, (caddr_t
)&ifr
) == 0)