xref: /netbsd-src/usr.sbin/altq/libaltq/qop_fifoq.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
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