1 /* $NetBSD: qop_wfq.c,v 1.5 2002/03/05 04:11:53 itojun Exp $ */
2 /* $KAME: qop_wfq.c,v 1.6 2001/12/03 08:20:56 kjc Exp $ */
4 * Copyright (C) 1999-2000
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>
30 #include <sys/socket.h>
31 #include <sys/sockio.h>
32 #include <sys/ioctl.h>
33 #include <sys/fcntl.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
48 #include <altq/altq.h>
49 #include <altq/altq_wfq.h>
53 static int wfq_attach(struct ifinfo
*);
54 static int wfq_detach(struct ifinfo
*);
55 static int wfq_enable(struct ifinfo
*);
56 static int wfq_disable(struct ifinfo
*);
58 #define WFQ_DEVICE "/dev/altq/wfq"
60 static int wfq_fd
= -1;
61 static int wfq_refcount
= 0;
63 static struct qdisc_ops wfq_qdisc
= {
72 NULL
, /* modify class */
73 NULL
, /* delete class */
74 NULL
, /* add filter */
75 NULL
/* delete filter */
81 #define EQUAL(s1, s2) (strcmp((s1), (s2)) == 0)
84 wfq_interface_parser(const char *ifname
, int argc
, char **argv
)
86 u_int bandwidth
= 100000000; /* 100Mbps */
88 int hash_policy
= 0; /* 0: use default */
89 int nqueues
= 0; /* 0: use default */
90 int qsize
= 0; /* 0: use default */
96 if (EQUAL(*argv
, "bandwidth")) {
99 bandwidth
= atobps(*argv
);
100 } else if (EQUAL(*argv
, "tbrsize")) {
103 tbrsize
= atobytes(*argv
);
104 } else if (EQUAL(*argv
, "nqueues")) {
107 nqueues
= (int)strtol(*argv
, NULL
, 0);
108 } else if (EQUAL(*argv
, "qsize")) {
111 qsize
= atobytes(*argv
);
112 } else if (EQUAL(*argv
, "hash")) {
115 if (EQUAL(*argv
, "dstaddr"))
116 hash_policy
= WFQ_HASH_DSTADDR
;
117 else if (EQUAL(*argv
, "full"))
118 hash_policy
= WFQ_HASH_FULL
;
119 else if (EQUAL(*argv
, "srcport"))
120 hash_policy
= WFQ_HASH_SRCPORT
;
121 else if (EQUAL(*argv
, "srcaddr"))
122 hash_policy
= WFQ_HASH_SRCADDR
;
125 "Unknown hash policy '%s'", *argv
);
129 } else if (EQUAL(*argv
, "wfq")) {
132 LOG(LOG_ERR
, 0, "Unknown keyword '%s'", *argv
);
138 if (qcmd_tbr_register(ifname
, bandwidth
, tbrsize
) != 0)
141 if (qsize
!= 0 && qsize
< 1500) {
142 LOG(LOG_ERR
, 0, "qsize too small: %d bytes", qsize
);
146 if (qcmd_wfq_add_if(ifname
, bandwidth
,
147 hash_policy
, nqueues
, qsize
) != 0)
156 qcmd_wfq_add_if(const char *ifname
, u_int bandwidth
, int hash_policy
,
157 int nqueues
, int qsize
)
161 error
= qop_wfq_add_if(NULL
, ifname
, bandwidth
,
162 hash_policy
, nqueues
, qsize
);
164 LOG(LOG_ERR
, errno
, "%s: can't add wfq on interface '%s'",
165 qoperror(error
), ifname
);
173 qop_wfq_add_if(struct ifinfo
**rp
, const char *ifname
, u_int bandwidth
,
174 int hash_policy
, int nqueues
, int qsize
)
176 struct ifinfo
*ifinfo
= NULL
;
177 struct wfq_ifinfo
*wfq_ifinfo
;
180 if ((wfq_ifinfo
= calloc(1, sizeof(*wfq_ifinfo
))) == NULL
)
181 return (QOPERR_NOMEM
);
182 wfq_ifinfo
->hash_policy
= hash_policy
;
183 wfq_ifinfo
->nqueues
= nqueues
;
184 wfq_ifinfo
->qsize
= qsize
;
186 error
= qop_add_if(&ifinfo
, ifname
, bandwidth
,
187 &wfq_qdisc
, wfq_ifinfo
);
199 * system call interfaces for qdisc_ops
202 wfq_attach(struct ifinfo
*ifinfo
)
204 struct wfq_interface iface
;
205 struct wfq_ifinfo
*wfq_ifinfo
;
206 struct wfq_conf conf
;
209 (wfq_fd
= open(WFQ_DEVICE
, O_RDWR
)) < 0 &&
210 (wfq_fd
= open_module(WFQ_DEVICE
, O_RDWR
)) < 0) {
211 LOG(LOG_ERR
, errno
, "WFQ open");
212 return (QOPERR_SYSCALL
);
216 memset(&iface
, 0, sizeof(iface
));
217 strncpy(iface
.wfq_ifacename
, ifinfo
->ifname
, IFNAMSIZ
);
219 if (ioctl(wfq_fd
, WFQ_IF_ATTACH
, &iface
) < 0)
220 return (QOPERR_SYSCALL
);
222 /* set wfq parameters */
223 wfq_ifinfo
= (struct wfq_ifinfo
*)ifinfo
->private;
224 if (wfq_ifinfo
->hash_policy
!= 0 || wfq_ifinfo
->nqueues
!= 0 ||
225 wfq_ifinfo
->qsize
!= 0) {
226 memset(&conf
, 0, sizeof(conf
));
227 strncpy(conf
.iface
.wfq_ifacename
, ifinfo
->ifname
, IFNAMSIZ
);
228 conf
.hash_policy
= wfq_ifinfo
->hash_policy
;
229 conf
.nqueues
= wfq_ifinfo
->nqueues
;
230 conf
.qlimit
= wfq_ifinfo
->qsize
;
231 if (ioctl(wfq_fd
, WFQ_CONFIG
, &conf
) < 0) {
232 LOG(LOG_ERR
, errno
, "WFQ_CONFIG");
233 return (QOPERR_SYSCALL
);
237 LOG(LOG_INFO
, 0, "wfq attached to %s", iface
.wfq_ifacename
);
243 wfq_detach(struct ifinfo
*ifinfo
)
245 struct wfq_interface iface
;
247 memset(&iface
, 0, sizeof(iface
));
248 strncpy(iface
.wfq_ifacename
, ifinfo
->ifname
, IFNAMSIZ
);
250 if (ioctl(wfq_fd
, WFQ_IF_DETACH
, &iface
) < 0)
251 return (QOPERR_SYSCALL
);
253 if (--wfq_refcount
== 0) {
261 wfq_enable(struct ifinfo
*ifinfo
)
263 struct wfq_interface iface
;
265 memset(&iface
, 0, sizeof(iface
));
266 strncpy(iface
.wfq_ifacename
, ifinfo
->ifname
, IFNAMSIZ
);
268 if (ioctl(wfq_fd
, WFQ_ENABLE
, &iface
) < 0)
269 return (QOPERR_SYSCALL
);
274 wfq_disable(struct ifinfo
*ifinfo
)
276 struct wfq_interface iface
;
278 memset(&iface
, 0, sizeof(iface
));
279 strncpy(iface
.wfq_ifacename
, ifinfo
->ifname
, IFNAMSIZ
);
281 if (ioctl(wfq_fd
, WFQ_DISABLE
, &iface
) < 0)
282 return (QOPERR_SYSCALL
);