Sync usage with man page.
[netbsd-mini2440.git] / usr.sbin / altq / libaltq / qop_priq.c
blob260cf81df5f07d148376c76cc8e83a899b9353a8
1 /* $NetBSD: qop_priq.c,v 1.4 2001/08/22 08:52:37 itojun Exp $ */
2 /* $KAME: qop_priq.c,v 1.4 2001/12/03 08:20:55 kjc Exp $ */
3 /*
4 * Copyright (C) 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
9 * are met:
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
26 * SUCH DAMAGE.
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>
34 #include <net/if.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <stddef.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <errno.h>
45 #include <syslog.h>
46 #include <netdb.h>
48 #include <altq/altq.h>
49 #include <altq/altq_priq.h>
50 #include "altq_qop.h"
51 #include "qop_priq.h"
53 static int qop_priq_enable_hook(struct ifinfo *);
55 static int priq_attach(struct ifinfo *);
56 static int priq_detach(struct ifinfo *);
57 static int priq_clear(struct ifinfo *);
58 static int priq_enable(struct ifinfo *);
59 static int priq_disable(struct ifinfo *);
60 static int priq_add_class(struct classinfo *);
61 static int priq_modify_class(struct classinfo *, void *);
62 static int priq_delete_class(struct classinfo *);
63 static int priq_add_filter(struct fltrinfo *);
64 static int priq_delete_filter(struct fltrinfo *);
66 #define PRIQ_DEVICE "/dev/altq/priq"
68 static int priq_fd = -1;
69 static int priq_refcount = 0;
71 static struct qdisc_ops priq_qdisc = {
72 ALTQT_PRIQ,
73 "priq",
74 priq_attach,
75 priq_detach,
76 priq_clear,
77 priq_enable,
78 priq_disable,
79 priq_add_class,
80 priq_modify_class,
81 priq_delete_class,
82 priq_add_filter,
83 priq_delete_filter,
86 #define EQUAL(s1, s2) (strcmp((s1), (s2)) == 0)
89 * parser interface
91 int
92 priq_interface_parser(const char *ifname, int argc, char **argv)
94 u_int bandwidth = 100000000; /* 100Mbps */
95 u_int tbrsize = 0;
96 int flags = 0;
99 * process options
101 while (argc > 0) {
102 if (EQUAL(*argv, "bandwidth")) {
103 argc--; argv++;
104 if (argc > 0)
105 bandwidth = atobps(*argv);
106 } else if (EQUAL(*argv, "tbrsize")) {
107 argc--; argv++;
108 if (argc > 0)
109 tbrsize = atobytes(*argv);
110 } else if (EQUAL(*argv, "priq")) {
111 /* just skip */
112 } else {
113 LOG(LOG_ERR, 0, "Unknown keyword '%s'", *argv);
114 return (0);
116 argc--; argv++;
119 if (qcmd_tbr_register(ifname, bandwidth, tbrsize) != 0)
120 return (0);
122 if (qcmd_priq_add_if(ifname, bandwidth, flags) != 0)
123 return (0);
124 return (1);
128 priq_class_parser(const char *ifname, const char *class_name,
129 const char *parent_name, int argc, char **argv)
131 int pri = 0, qlimit = 50;
132 int flags = 0, error;
134 while (argc > 0) {
135 if (EQUAL(*argv, "priority")) {
136 argc--; argv++;
137 if (argc > 0)
138 pri = strtoul(*argv, NULL, 0);
139 } else if (EQUAL(*argv, "qlimit")) {
140 argc--; argv++;
141 if (argc > 0)
142 qlimit = strtoul(*argv, NULL, 0);
143 } else if (EQUAL(*argv, "default")) {
144 flags |= PRCF_DEFAULTCLASS;
145 } else if (EQUAL(*argv, "red")) {
146 flags |= PRCF_RED;
147 } else if (EQUAL(*argv, "ecn")) {
148 flags |= PRCF_ECN;
149 } else if (EQUAL(*argv, "rio")) {
150 flags |= PRCF_RIO;
151 } else if (EQUAL(*argv, "cleardscp")) {
152 flags |= PRCF_CLEARDSCP;
153 } else {
154 LOG(LOG_ERR, 0,
155 "Unknown keyword '%s' in %s, line %d",
156 *argv, altqconfigfile, line_no);
157 return (0);
160 argc--; argv++;
163 if ((flags & PRCF_ECN) && (flags & (PRCF_RED|PRCF_RIO)) == 0)
164 flags |= PRCF_RED;
166 error = qcmd_priq_add_class(ifname, class_name, pri, qlimit, flags);
168 if (error) {
169 LOG(LOG_ERR, errno, "priq_class_parser: %s",
170 qoperror(error));
171 return (0);
173 return (1);
177 * qcmd api
180 qcmd_priq_add_if(const char *ifname, u_int bandwidth, int flags)
182 int error;
184 error = qop_priq_add_if(NULL, ifname, bandwidth, flags);
185 if (error != 0)
186 LOG(LOG_ERR, errno, "%s: can't add priq on interface '%s'",
187 qoperror(error), ifname);
188 return (error);
192 qcmd_priq_add_class(const char *ifname, const char *class_name,
193 int pri, int qlimit, int flags)
195 struct ifinfo *ifinfo;
196 int error = 0;
198 if ((ifinfo = ifname2ifinfo(ifname)) == NULL)
199 error = QOPERR_BADIF;
201 if (error == 0)
202 error = qop_priq_add_class(NULL, class_name, ifinfo,
203 pri, qlimit, flags);
204 if (error != 0)
205 LOG(LOG_ERR, errno,
206 "priq: %s: can't add class '%s' on interface '%s'",
207 qoperror(error), class_name, ifname);
208 return (error);
212 qcmd_priq_modify_class(const char *ifname, const char *class_name,
213 int pri, int qlimit, int flags)
215 struct ifinfo *ifinfo;
216 struct classinfo *clinfo;
218 if ((ifinfo = ifname2ifinfo(ifname)) == NULL)
219 return (QOPERR_BADIF);
221 if ((clinfo = clname2clinfo(ifinfo, class_name)) == NULL)
222 return (QOPERR_BADCLASS);
224 return qop_priq_modify_class(clinfo, pri, qlimit, flags);
228 * qop api
230 int
231 qop_priq_add_if(struct ifinfo **rp, const char *ifname,
232 u_int bandwidth, int flags)
234 struct ifinfo *ifinfo = NULL;
235 struct priq_ifinfo *priq_ifinfo = NULL;
236 int error;
238 if ((priq_ifinfo = calloc(1, sizeof(*priq_ifinfo))) == NULL)
239 return (QOPERR_NOMEM);
241 error = qop_add_if(&ifinfo, ifname, bandwidth,
242 &priq_qdisc, priq_ifinfo);
243 if (error != 0)
244 goto err_ret;
246 /* set enable hook */
247 ifinfo->enable_hook = qop_priq_enable_hook;
249 if (rp != NULL)
250 *rp = ifinfo;
251 return (0);
253 err_ret:
254 if (priq_ifinfo != NULL) {
255 free(priq_ifinfo);
256 if (ifinfo != NULL)
257 ifinfo->private = NULL;
259 return (error);
262 int
263 qop_priq_add_class(struct classinfo **rp, const char *class_name,
264 struct ifinfo *ifinfo, int pri, int qlimit, int flags)
266 struct classinfo *clinfo;
267 struct priq_ifinfo *priq_ifinfo;
268 struct priq_classinfo *priq_clinfo = NULL;
269 int error;
271 priq_ifinfo = ifinfo->private;
272 if ((flags & PRCF_DEFAULTCLASS) && priq_ifinfo->default_class != NULL)
273 return (QOPERR_CLASS_INVAL);
275 if ((priq_clinfo = calloc(1, sizeof(*priq_clinfo))) == NULL) {
276 error = QOPERR_NOMEM;
277 goto err_ret;
280 priq_clinfo->pri = pri;
281 priq_clinfo->qlimit = qlimit;
282 priq_clinfo->flags = flags;
284 if ((error = qop_add_class(&clinfo, class_name, ifinfo, NULL,
285 priq_clinfo)) != 0)
286 goto err_ret;
288 if (flags & PRCF_DEFAULTCLASS)
289 priq_ifinfo->default_class = clinfo;
291 if (rp != NULL)
292 *rp = clinfo;
293 return (0);
295 err_ret:
296 if (priq_clinfo != NULL) {
297 free(priq_clinfo);
298 clinfo->private = NULL;
301 return (error);
305 qop_priq_modify_class(struct classinfo *clinfo,
306 int pri, int qlimit, int flags)
308 struct priq_classinfo *priq_clinfo, *parent_clinfo;
309 int error;
311 priq_clinfo = clinfo->private;
312 if (clinfo->parent == NULL)
313 return (QOPERR_CLASS_INVAL);
314 parent_clinfo = clinfo->parent->private;
316 priq_clinfo->pri = pri;
317 priq_clinfo->qlimit = qlimit;
318 priq_clinfo->flags = flags;
320 error = qop_modify_class(clinfo, NULL);
321 if (error == 0)
322 return (0);
323 return (error);
327 * sanity check at enabling priq:
328 * 1. there must one default class for an interface
330 static int
331 qop_priq_enable_hook(struct ifinfo *ifinfo)
333 struct priq_ifinfo *priq_ifinfo;
335 priq_ifinfo = ifinfo->private;
336 if (priq_ifinfo->default_class == NULL) {
337 LOG(LOG_ERR, 0, "priq: no default class on interface %s!",
338 ifinfo->ifname);
339 return (QOPERR_CLASS);
341 return (0);
345 * system call interfaces for qdisc_ops
347 static int
348 priq_attach(struct ifinfo *ifinfo)
350 struct priq_interface iface;
352 memset(&iface, 0, sizeof(iface));
353 strncpy(iface.ifname, ifinfo->ifname, IFNAMSIZ);
355 if (priq_fd < 0 &&
356 (priq_fd = open(PRIQ_DEVICE, O_RDWR)) < 0 &&
357 (priq_fd = open_module(PRIQ_DEVICE, O_RDWR)) < 0) {
358 LOG(LOG_ERR, errno, "PRIQ open");
359 return (QOPERR_SYSCALL);
362 priq_refcount++;
363 memset(&iface, 0, sizeof(iface));
364 strncpy(iface.ifname, ifinfo->ifname, IFNAMSIZ);
365 iface.arg = ifinfo->bandwidth;
367 if (ioctl(priq_fd, PRIQ_IF_ATTACH, &iface) < 0)
368 return (QOPERR_SYSCALL);
369 return (0);
372 static int
373 priq_detach(struct ifinfo *ifinfo)
375 struct priq_interface iface;
377 memset(&iface, 0, sizeof(iface));
378 strncpy(iface.ifname, ifinfo->ifname, IFNAMSIZ);
380 if (ioctl(priq_fd, PRIQ_IF_DETACH, &iface) < 0)
381 return (QOPERR_SYSCALL);
383 if (--priq_refcount == 0) {
384 close(priq_fd);
385 priq_fd = -1;
387 return (0);
390 static int
391 priq_clear(struct ifinfo *ifinfo)
393 struct priq_interface iface;
395 memset(&iface, 0, sizeof(iface));
396 strncpy(iface.ifname, ifinfo->ifname, IFNAMSIZ);
398 if (ioctl(priq_fd, PRIQ_CLEAR, &iface) < 0)
399 return (QOPERR_SYSCALL);
400 return (0);
403 static int
404 priq_enable(struct ifinfo *ifinfo)
406 struct priq_interface iface;
408 memset(&iface, 0, sizeof(iface));
409 strncpy(iface.ifname, ifinfo->ifname, IFNAMSIZ);
411 if (ioctl(priq_fd, PRIQ_ENABLE, &iface) < 0)
412 return (QOPERR_SYSCALL);
413 return (0);
416 static int
417 priq_disable(struct ifinfo *ifinfo)
419 struct priq_interface iface;
421 memset(&iface, 0, sizeof(iface));
422 strncpy(iface.ifname, ifinfo->ifname, IFNAMSIZ);
424 if (ioctl(priq_fd, PRIQ_DISABLE, &iface) < 0)
425 return (QOPERR_SYSCALL);
426 return (0);
429 static int
430 priq_add_class(struct classinfo *clinfo)
432 struct priq_add_class class_add;
433 struct priq_classinfo *priq_clinfo;
434 struct priq_ifinfo *priq_ifinfo;
436 priq_ifinfo = clinfo->ifinfo->private;
437 priq_clinfo = clinfo->private;
439 memset(&class_add, 0, sizeof(class_add));
440 strncpy(class_add.iface.ifname, clinfo->ifinfo->ifname, IFNAMSIZ);
442 class_add.pri = priq_clinfo->pri;
443 class_add.qlimit = priq_clinfo->qlimit;
444 class_add.flags = priq_clinfo->flags;
445 if (ioctl(priq_fd, PRIQ_ADD_CLASS, &class_add) < 0) {
446 clinfo->handle = PRIQ_NULLCLASS_HANDLE;
447 return (QOPERR_SYSCALL);
449 clinfo->handle = class_add.class_handle;
450 return (0);
453 static int
454 priq_modify_class(struct classinfo *clinfo, void *arg)
456 struct priq_modify_class class_mod;
457 struct priq_classinfo *priq_clinfo;
459 priq_clinfo = clinfo->private;
461 memset(&class_mod, 0, sizeof(class_mod));
462 strncpy(class_mod.iface.ifname, clinfo->ifinfo->ifname, IFNAMSIZ);
463 class_mod.class_handle = clinfo->handle;
465 class_mod.pri = priq_clinfo->pri;
466 class_mod.qlimit = priq_clinfo->qlimit;
467 class_mod.flags = priq_clinfo->flags;
469 if (ioctl(priq_fd, PRIQ_MOD_CLASS, &class_mod) < 0)
470 return (QOPERR_SYSCALL);
471 return (0);
474 static int
475 priq_delete_class(struct classinfo *clinfo)
477 struct priq_delete_class class_delete;
479 if (clinfo->handle == PRIQ_NULLCLASS_HANDLE)
480 return (0);
482 memset(&class_delete, 0, sizeof(class_delete));
483 strncpy(class_delete.iface.ifname, clinfo->ifinfo->ifname,
484 IFNAMSIZ);
485 class_delete.class_handle = clinfo->handle;
487 if (ioctl(priq_fd, PRIQ_DEL_CLASS, &class_delete) < 0)
488 return (QOPERR_SYSCALL);
489 return (0);
492 static int
493 priq_add_filter(struct fltrinfo *fltrinfo)
495 struct priq_add_filter fltr_add;
497 memset(&fltr_add, 0, sizeof(fltr_add));
498 strncpy(fltr_add.iface.ifname, fltrinfo->clinfo->ifinfo->ifname,
499 IFNAMSIZ);
500 fltr_add.class_handle = fltrinfo->clinfo->handle;
501 fltr_add.filter = fltrinfo->fltr;
503 if (ioctl(priq_fd, PRIQ_ADD_FILTER, &fltr_add) < 0)
504 return (QOPERR_SYSCALL);
505 fltrinfo->handle = fltr_add.filter_handle;
506 return (0);
509 static int
510 priq_delete_filter(struct fltrinfo *fltrinfo)
512 struct priq_delete_filter fltr_del;
514 memset(&fltr_del, 0, sizeof(fltr_del));
515 strncpy(fltr_del.iface.ifname, fltrinfo->clinfo->ifinfo->ifname,
516 IFNAMSIZ);
517 fltr_del.filter_handle = fltrinfo->handle;
519 if (ioctl(priq_fd, PRIQ_DEL_FILTER, &fltr_del) < 0)
520 return (QOPERR_SYSCALL);
521 return (0);