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