Home | History | Annotate | Line # | Download | only in libaltq
qop_blue.c revision 1.2
      1 /*	$KAME: qop_blue.c,v 1.3 2000/10/18 09:15:18 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_blue.h>
     49 #include "altq_qop.h"
     50 #include "qop_blue.h"
     51 
     52 static int blue_attach(struct ifinfo *);
     53 static int blue_detach(struct ifinfo *);
     54 static int blue_enable(struct ifinfo *);
     55 static int blue_disable(struct ifinfo *);
     56 
     57 #define BLUE_DEVICE	"/dev/altq/blue"
     58 
     59 static int blue_fd = -1;
     60 static int blue_refcount = 0;
     61 
     62 static struct qdisc_ops blue_qdisc = {
     63 	ALTQT_BLUE,
     64 	"blue",
     65 	blue_attach,
     66 	blue_detach,
     67 	NULL,			/* clear */
     68 	blue_enable,
     69 	blue_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 blue_interface_parser(const char *ifname, int argc, char **argv)
     84 {
     85 	u_int  	bandwidth = 100000000;	/* 100Mbps */
     86 	u_int	tbrsize = 0;
     87 	int	max_pmark = 4000;
     88 	int	hold_time = 1000;
     89 	int	qlimit = 60;
     90 	int	pkttime = 0;
     91 	int	flags = 0;
     92 	int	packet_size = 1000;
     93 
     94 	/*
     95 	 * process options
     96 	 */
     97 	while (argc > 0) {
     98 		if (EQUAL(*argv, "bandwidth")) {
     99 			argc--; argv++;
    100 			if (argc > 0)
    101 				bandwidth = atobps(*argv);
    102 		} else if (EQUAL(*argv, "tbrsize")) {
    103 			argc--; argv++;
    104 			if (argc > 0)
    105 				tbrsize = atobytes(*argv);
    106 		} else if (EQUAL(*argv, "packetsize")) {
    107 			argc--; argv++;
    108 			if (argc > 0)
    109 				packet_size = atobytes(*argv);
    110 		} else if (EQUAL(*argv, "qlimit")) {
    111 			argc--; argv++;
    112 			if (argc > 0)
    113 				qlimit = (int)strtol(*argv, NULL, 0);
    114 		} else if (EQUAL(*argv, "maxpmark")) {
    115 			argc--; argv++;
    116 			if (argc > 0)
    117 				max_pmark = (int)strtol(*argv, NULL, 0);
    118 		} else if (EQUAL(*argv, "holdtime")) {
    119 			argc--; argv++;
    120 			if (argc > 0)
    121 				hold_time = (int)strtol(*argv, NULL, 0);
    122 		} else if (EQUAL(*argv, "blue")) {
    123 			/* just skip */
    124 		} else if (EQUAL(*argv, "ecn")) {
    125 			flags |= BLUEF_ECN;
    126 		} else {
    127 			LOG(LOG_ERR, 0, "Unknown keyword '%s'\n", argv);
    128 			return (0);
    129 		}
    130 		argc--; argv++;
    131 	}
    132 
    133 	if (qcmd_tbr_register(ifname, bandwidth, tbrsize) != 0)
    134 		return (0);
    135 
    136 	pkttime = packet_size * 8 * 1000 / (bandwidth / 1000);
    137 
    138 	if (qcmd_blue_add_if(ifname, bandwidth, max_pmark, hold_time,
    139 			     qlimit, pkttime, flags) != 0)
    140 		return (0);
    141 	return (1);
    142 }
    143 
    144 /*
    145  * qcmd api
    146  */
    147 int
    148 qcmd_blue_add_if(const char *ifname, u_int bandwidth, int max_pmark,
    149 		 int hold_time, int qlimit, int pkttime, int flags)
    150 {
    151 	int error;
    152 
    153 	error = qop_blue_add_if(NULL, ifname, bandwidth, max_pmark, hold_time,
    154 				qlimit, pkttime, flags);
    155 	if (error != 0)
    156 		LOG(LOG_ERR, errno, "%s: can't add blue on interface '%s'\n",
    157 		    qoperror(error), ifname);
    158 	return (error);
    159 }
    160 
    161 /*
    162  * qop api
    163  */
    164 int
    165 qop_blue_add_if(struct ifinfo **rp, const char *ifname, u_int bandwidth,
    166 		int max_pmark, int hold_time, int qlimit,
    167 		int pkttime, int flags)
    168 {
    169 	struct ifinfo *ifinfo = NULL;
    170 	struct blue_ifinfo *blue_ifinfo;
    171 	int error;
    172 
    173 	if ((blue_ifinfo = calloc(1, sizeof(*blue_ifinfo))) == NULL)
    174 		return (QOPERR_NOMEM);
    175 	blue_ifinfo->max_pmark = max_pmark;
    176 	blue_ifinfo->hold_time = hold_time;
    177 	blue_ifinfo->qlimit    = qlimit;
    178 	blue_ifinfo->pkttime   = pkttime;
    179 	blue_ifinfo->flags     = flags;
    180 
    181 	error = qop_add_if(&ifinfo, ifname, bandwidth,
    182 			   &blue_qdisc, blue_ifinfo);
    183 	if (error != 0) {
    184 		free(blue_ifinfo);
    185 		return (error);
    186 	}
    187 
    188 	if (rp != NULL)
    189 		*rp = ifinfo;
    190 	return (0);
    191 }
    192 
    193 /*
    194  *  system call interfaces for qdisc_ops
    195  */
    196 static int
    197 blue_attach(struct ifinfo *ifinfo)
    198 {
    199 	struct blue_interface iface;
    200 	struct blue_ifinfo *blue_ifinfo;
    201 	struct blue_conf conf;
    202 
    203 	if (blue_fd < 0 &&
    204 	    (blue_fd = open(BLUE_DEVICE, O_RDWR)) < 0 &&
    205 	    (blue_fd = open_module(BLUE_DEVICE, O_RDWR)) < 0) {
    206 		LOG(LOG_ERR, errno, "BLUE open\n");
    207 		return (QOPERR_SYSCALL);
    208 	}
    209 
    210 	blue_refcount++;
    211 	memset(&iface, 0, sizeof(iface));
    212 	strncpy(iface.blue_ifname, ifinfo->ifname, IFNAMSIZ);
    213 
    214 	if (ioctl(blue_fd, BLUE_IF_ATTACH, &iface) < 0)
    215 		return (QOPERR_SYSCALL);
    216 
    217 	/* set blue parameters */
    218 	blue_ifinfo = (struct blue_ifinfo *)ifinfo->private;
    219 	memset(&conf, 0, sizeof(conf));
    220 	strncpy(conf.iface.blue_ifname, ifinfo->ifname, IFNAMSIZ);
    221 	conf.blue_max_pmark = blue_ifinfo->max_pmark;
    222 	conf.blue_hold_time = blue_ifinfo->hold_time;
    223 	conf.blue_limit     = blue_ifinfo->qlimit;
    224 	conf.blue_pkttime   = blue_ifinfo->pkttime;
    225 	conf.blue_flags     = blue_ifinfo->flags;
    226 	if (ioctl(blue_fd, BLUE_CONFIG, &conf) < 0)
    227 		return (QOPERR_SYSCALL);
    228 
    229 #if 1
    230 	LOG(LOG_INFO, 0, "blue attached to %s\n", iface.blue_ifname);
    231 #endif
    232 	return (0);
    233 }
    234 
    235 static int
    236 blue_detach(struct ifinfo *ifinfo)
    237 {
    238 	struct blue_interface iface;
    239 
    240 	memset(&iface, 0, sizeof(iface));
    241 	strncpy(iface.blue_ifname, ifinfo->ifname, IFNAMSIZ);
    242 
    243 	if (ioctl(blue_fd, BLUE_IF_DETACH, &iface) < 0)
    244 		return (QOPERR_SYSCALL);
    245 
    246 	if (--blue_refcount == 0) {
    247 		close(blue_fd);
    248 		blue_fd = -1;
    249 	}
    250 	return (0);
    251 }
    252 
    253 static int
    254 blue_enable(struct ifinfo *ifinfo)
    255 {
    256 	struct blue_interface iface;
    257 
    258 	memset(&iface, 0, sizeof(iface));
    259 	strncpy(iface.blue_ifname, ifinfo->ifname, IFNAMSIZ);
    260 
    261 	if (ioctl(blue_fd, BLUE_ENABLE, &iface) < 0)
    262 		return (QOPERR_SYSCALL);
    263 	return (0);
    264 }
    265 
    266 static int
    267 blue_disable(struct ifinfo *ifinfo)
    268 {
    269 	struct blue_interface iface;
    270 
    271 	memset(&iface, 0, sizeof(iface));
    272 	strncpy(iface.blue_ifname, ifinfo->ifname, IFNAMSIZ);
    273 
    274 	if (ioctl(blue_fd, BLUE_DISABLE, &iface) < 0)
    275 		return (QOPERR_SYSCALL);
    276 	return (0);
    277 }
    278