qop_fifoq.c revision 1.1.1.1 1 /* $KAME: qop_fifoq.c,v 1.3 2000/10/18 09:15:19 kjc Exp $ */
2 /*
3 * Copyright (C) 1999-2000
4 * Sony Computer Science Laboratories, Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/param.h>
29 #include <sys/socket.h>
30 #include <sys/sockio.h>
31 #include <sys/ioctl.h>
32 #include <sys/fcntl.h>
33 #include <net/if.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <stddef.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <errno.h>
44 #include <syslog.h>
45 #include <netdb.h>
46
47 #include <altq/altq.h>
48 #include <altq/altq_fifoq.h>
49 #include "altq_qop.h"
50 #include "qop_fifoq.h"
51
52 static int fifoq_attach(struct ifinfo *ifinfo);
53 static int fifoq_detach(struct ifinfo *ifinfo);
54 static int fifoq_enable(struct ifinfo *ifinfo);
55 static int fifoq_disable(struct ifinfo *ifinfo);
56
57 #define FIFOQ_DEVICE "/dev/altq/fifoq"
58
59 static int fifoq_fd = -1;
60 static int fifoq_refcount = 0;
61
62 static struct qdisc_ops fifoq_qdisc = {
63 ALTQT_FIFOQ,
64 "fifoq",
65 fifoq_attach,
66 fifoq_detach,
67 NULL, /* clear */
68 fifoq_enable,
69 fifoq_disable,
70 NULL, /* add class */
71 NULL, /* modify class */
72 NULL, /* delete class */
73 NULL, /* add filter */
74 NULL /* delete filter */
75 };
76
77 /*
78 * parser interface
79 */
80 #define EQUAL(s1, s2) (strcmp((s1), (s2)) == 0)
81
82 int
83 fifoq_interface_parser(const char *ifname, int argc, char **argv)
84 {
85 u_int bandwidth = 100000000; /* 100Mbps */
86 u_int tbrsize = 0;
87 int qlimit = 50;
88
89 /*
90 * process options
91 */
92 while (argc > 0) {
93 if (EQUAL(*argv, "bandwidth")) {
94 argc--; argv++;
95 if (argc > 0)
96 bandwidth = atobps(*argv);
97 } else if (EQUAL(*argv, "tbrsize")) {
98 argc--; argv++;
99 if (argc > 0)
100 tbrsize = atobytes(*argv);
101 } else if (EQUAL(*argv, "qlimit")) {
102 argc--; argv++;
103 if (argc > 0)
104 qlimit = (int)strtol(*argv, NULL, 0);
105 } else if (EQUAL(*argv, "fifoq")) {
106 /* just skip */
107 } else {
108 LOG(LOG_ERR, 0, "Unknown keyword '%s'\n", argv);
109 return (0);
110 }
111 argc--; argv++;
112 }
113
114 if (qcmd_tbr_register(ifname, bandwidth, tbrsize) != 0)
115 return (0);
116
117 if (qcmd_fifoq_add_if(ifname, bandwidth, qlimit) != 0)
118 return (0);
119 return (1);
120 }
121
122 /*
123 * qcmd api
124 */
125 int
126 qcmd_fifoq_add_if(const char *ifname, u_int bandwidth, int qlimit)
127 {
128 int error;
129
130 error = qop_fifoq_add_if(NULL, ifname, bandwidth, qlimit);
131 if (error != 0)
132 LOG(LOG_ERR, errno, "%s: can't add fifoq on interface '%s'\n",
133 qoperror(error), ifname);
134 return (error);
135 }
136
137 /*
138 * qop api
139 */
140 int
141 qop_fifoq_add_if(struct ifinfo **rp, const char *ifname,
142 u_int bandwidth, int qlimit)
143 {
144 struct ifinfo *ifinfo = NULL;
145 struct fifoq_ifinfo *fifoq_ifinfo;
146 int error;
147
148 if ((fifoq_ifinfo = calloc(1, sizeof(*fifoq_ifinfo))) == NULL)
149 return (QOPERR_NOMEM);
150 fifoq_ifinfo->qlimit = qlimit;
151
152 error = qop_add_if(&ifinfo, ifname, bandwidth,
153 &fifoq_qdisc, fifoq_ifinfo);
154 if (error != 0) {
155 free(fifoq_ifinfo);
156 return (error);
157 }
158
159 if (rp != NULL)
160 *rp = ifinfo;
161 return (0);
162 }
163
164 /*
165 * system call interfaces for qdisc_ops
166 */
167 static int
168 fifoq_attach(struct ifinfo *ifinfo)
169 {
170 struct fifoq_interface iface;
171 struct fifoq_ifinfo *fifoq_ifinfo;
172 struct fifoq_conf conf;
173
174 if (fifoq_fd < 0 &&
175 (fifoq_fd = open(FIFOQ_DEVICE, O_RDWR)) < 0 &&
176 (fifoq_fd = open_module(FIFOQ_DEVICE, O_RDWR)) < 0) {
177 LOG(LOG_ERR, errno, "FIFOQ open\n");
178 return (QOPERR_SYSCALL);
179 }
180
181 fifoq_refcount++;
182 memset(&iface, 0, sizeof(iface));
183 strncpy(iface.fifoq_ifname, ifinfo->ifname, IFNAMSIZ);
184
185 if (ioctl(fifoq_fd, FIFOQ_IF_ATTACH, &iface) < 0)
186 return (QOPERR_SYSCALL);
187
188 /* set fifoq parameters */
189 fifoq_ifinfo = (struct fifoq_ifinfo *)ifinfo->private;
190 if (fifoq_ifinfo->qlimit > 0) {
191 memset(&conf, 0, sizeof(conf));
192 strncpy(conf.iface.fifoq_ifname, ifinfo->ifname, IFNAMSIZ);
193 conf.fifoq_limit = fifoq_ifinfo->qlimit;
194 if (ioctl(fifoq_fd, FIFOQ_CONFIG, &conf) < 0)
195 return (QOPERR_SYSCALL);
196 }
197 #if 1
198 LOG(LOG_INFO, 0, "fifoq attached to %s\n", iface.fifoq_ifname);
199 #endif
200 return (0);
201 }
202
203 static int
204 fifoq_detach(struct ifinfo *ifinfo)
205 {
206 struct fifoq_interface iface;
207
208 memset(&iface, 0, sizeof(iface));
209 strncpy(iface.fifoq_ifname, ifinfo->ifname, IFNAMSIZ);
210
211 if (ioctl(fifoq_fd, FIFOQ_IF_DETACH, &iface) < 0)
212 return (QOPERR_SYSCALL);
213
214 if (--fifoq_refcount == 0) {
215 close(fifoq_fd);
216 fifoq_fd = -1;
217 }
218 return (0);
219 }
220
221 static int
222 fifoq_enable(struct ifinfo *ifinfo)
223 {
224 struct fifoq_interface iface;
225
226 memset(&iface, 0, sizeof(iface));
227 strncpy(iface.fifoq_ifname, ifinfo->ifname, IFNAMSIZ);
228
229 if (ioctl(fifoq_fd, FIFOQ_ENABLE, &iface) < 0)
230 return (QOPERR_SYSCALL);
231 return (0);
232 }
233
234 static int
235 fifoq_disable(struct ifinfo *ifinfo)
236 {
237 struct fifoq_interface iface;
238
239 memset(&iface, 0, sizeof(iface));
240 strncpy(iface.fifoq_ifname, ifinfo->ifname, IFNAMSIZ);
241
242 if (ioctl(fifoq_fd, FIFOQ_DISABLE, &iface) < 0)
243 return (QOPERR_SYSCALL);
244 return (0);
245 }
246