Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

ALTQ 2.0

  • Loading branch information...
commit 0fca29c22ea9c7067d78438a11552ad91309c8c2 1 parent 0d7c7b6
authored October 02, 1999
50  kame/sys/net/altq_conf.c
@@ -23,7 +23,7 @@
23 23
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 24
  * SUCH DAMAGE.
25 25
  *
26  
- * $Id: altq_conf.c,v 1.1 1999/08/05 17:18:22 itojun Exp $
  26
+ * $Id: altq_conf.c,v 1.1.1.1 1999/10/02 05:52:29 itojun Exp $
27 27
  */
28 28
 
29 29
 #ifdef ALTQ
@@ -42,18 +42,12 @@
42 42
 #include <sys/socket.h>
43 43
 #include <sys/kernel.h>
44 44
 #include <sys/errno.h>
45  
-#ifdef DEVFS
  45
+#if defined(__FreeBSD__) && defined(DEVFS)
46 46
 #include <sys/devfsext.h>
47 47
 #endif /*DEVFS*/
48  
-#include <net/if_altq.h>
  48
+#include <net/if.h>
49 49
 #include <net/altq_conf.h>
50  
-
51  
-/* ioctl cmd type (copied from altq_var.h not to include netinet headers) */
52  
-#if defined(__FreeBSD__) && (__FreeBSD__ < 3)
53  
-typedef int ioctlcmd_t;
54  
-#else
55  
-typedef u_long ioctlcmd_t;
56  
-#endif
  50
+#include <netinet/altq.h>
57 51
 
58 52
 #ifdef CBQ
59 53
 altqdev_decl(cbq);
@@ -76,6 +70,15 @@ altqdev_decl(rio);
76 70
 #ifdef LOCALQ
77 71
 altqdev_decl(localq);
78 72
 #endif
  73
+#ifdef HFSC
  74
+altqdev_decl(hfsc);
  75
+#endif
  76
+#ifdef CDNR
  77
+altqdev_decl(cdnr);
  78
+#endif
  79
+#ifdef BLUE
  80
+altqdev_decl(blue);
  81
+#endif
79 82
 
80 83
 /*
81 84
  * altq minor device (discipline) table
@@ -117,6 +120,21 @@ static struct altqsw altqsw[] = {				/* minor */
117 120
 #else
118 121
 	{"noq",	noopen,		noclose,	noioctl},  /* 7 (local use) */
119 122
 #endif
  123
+#ifdef HFSC
  124
+	{"hfsc",hfscopen,	hfscclose,	hfscioctl},	/* 8 */
  125
+#else
  126
+	{"noq",	noopen,		noclose,	noioctl},	/* 8 */
  127
+#endif
  128
+#ifdef CDNR
  129
+	{"cdnr",cdnropen,	cdnrclose,	cdnrioctl},	/* 9 */
  130
+#else
  131
+	{"noq",	noopen,		noclose,	noioctl},	/* 9 */
  132
+#endif
  133
+#ifdef BLUE
  134
+	{"blue",blueopen,	blueclose,	blueioctl},	/* 10 */
  135
+#else
  136
+	{"noq",	noopen,		noclose,	noioctl},	/* 10 */
  137
+#endif
120 138
 };
121 139
 
122 140
 /*
@@ -127,9 +145,17 @@ int	naltqsw = sizeof (altqsw) / sizeof (altqsw[0]);
127 145
 static	d_open_t	altqopen;
128 146
 static	d_close_t	altqclose;
129 147
 static	d_ioctl_t	altqioctl;
  148
+#ifdef __FreeBSD__
130 149
 static void altq_drvinit __P((void *));
  150
+#else
  151
+void	altqattach __P((int));
  152
+#endif
131 153
 
132  
-#define CDEV_MAJOR 96 /* FreeBSD official number */
  154
+#if defined(__FreeBSD__)
  155
+#define CDEV_MAJOR 96		 /* FreeBSD official number */
  156
+#elif defined(__NetBSD__)
  157
+#define CDEV_MAJOR 65		 /* not official */
  158
+#endif
133 159
 
134 160
 #ifndef __NetBSD__
135 161
 static struct cdevsw altq_cdevsw = 
@@ -185,7 +211,7 @@ altqioctl(dev, cmd, addr, flag, p)
185 211
 }
186 212
 
187 213
 
188  
-static altq_devsw_installed = 0;
  214
+static int altq_devsw_installed = 0;
189 215
 
190 216
 #ifdef __FreeBSD__
191 217
 #ifdef DEVFS
6  kame/sys/net/altq_conf.h
@@ -23,7 +23,7 @@
23 23
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 24
  * SUCH DAMAGE.
25 25
  *
26  
- * $Id: altq_conf.h,v 1.1 1999/08/05 17:18:22 itojun Exp $
  26
+ * $Id: altq_conf.h,v 1.1.1.1 1999/10/02 05:52:29 itojun Exp $
27 27
  */
28 28
 #ifndef _NET_ALTQ_CONF_H_
29 29
 #define _NET_ALTQ_CONF_H_
@@ -55,6 +55,10 @@ typedef int d_open_t __P((dev_t dev, int oflags, int devtype, struct proc *p));
55 55
 typedef int d_close_t __P((dev_t dev, int fflag, int devtype, struct proc *p));
56 56
 typedef int d_ioctl_t __P((dev_t dev, u_long cmd, caddr_t data,
57 57
 			   int fflag, struct proc *p));
  58
+
  59
+#define noopen	(dev_type_open((*))) enodev
  60
+#define noclose	(dev_type_close((*))) enodev
  61
+#define noioctl	(dev_type_ioctl((*))) enodev
58 62
 #endif
59 63
 
60 64
 /*
18  kame/sys/net/if_altq.h
@@ -23,7 +23,7 @@
23 23
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 24
  * SUCH DAMAGE.
25 25
  *
26  
- * $Id: if_altq.h,v 1.1 1999/08/05 17:18:22 itojun Exp $
  26
+ * $Id: if_altq.h,v 1.1.1.1 1999/10/02 05:52:29 itojun Exp $
27 27
  */
28 28
 #ifndef _NET_IF_ALTQ_H_
29 29
 #define _NET_IF_ALTQ_H_
@@ -42,28 +42,20 @@ struct pr_hdr {
42 42
 #define ALTQF_READY	 0x01	/* driver supports alternate queueing */
43 43
 #define ALTQF_ENABLE	 0x02	/* altq is in use */
44 44
 #define ALTQF_ACCOUNTING 0x04	/* altq accounting is enabled */
  45
+#define ALTQF_CNDTNING	 0x08	/* altq traffic conditioning is enabled */
45 46
 #define ALTQF_DRIVER1	 0x40	/* driver specific */
46 47
 
47  
-/* if_altqtype */
48  
-#define ALTQT_NONE	0	/* reserved */
49  
-#define ALTQT_CBQ	1	/* cbq */
50  
-#define ALTQT_WFQ	2	/* wfq */
51  
-#define ALTQT_AFMAP	3	/* afmap */
52  
-#define ALTQT_FIFOQ	4	/* fifoq */
53  
-#define ALTQT_RED	5	/* red */
54  
-#define ALTQT_RIO	6	/* rio */
55  
-#define ALTQT_LOCALQ	7	/* local use */
56  
-#define ALTQT_MAX	8
57  
-
58 48
 /* if_altqflags set internally only: */
59 49
 #define	ALTQF_CANTCHANGE 	(ALTQF_READY)
60 50
 
61 51
 #define ALTQ_IS_READY(ifp)	((ifp)->if_altqflags & ALTQF_READY)
62 52
 #define ALTQ_IS_ON(ifp)		((ifp)->if_altqflags & ALTQF_ENABLE)
  53
+#define ALTQ_IS_CNDTNING(ifp)	((ifp)->if_altqflags & ALTQF_CNDTNING)
63 54
 
64 55
 #define SET_ACCOUNTING(ifp)	((ifp)->if_altqflags |= ALTQF_ACCOUNTING)
65 56
 #define CLEAR_ACCOUNTING(ifp)	((ifp)->if_altqflags &= ~ALTQF_ACCOUNTING)
66  
-
  57
+#define SET_CNDTNING(ifp)	((ifp)->if_altqflags |= ALTQF_CNDTNING)
  58
+#define CLEAR_CNDTNING(ifp)	((ifp)->if_altqflags &= ~ALTQF_CNDTNING)
67 59
 
68 60
 /* if_altqenqueue 4th arg */
69 61
 #define ALTEQ_NORMAL	0	/* normal queueing */
27  kame/sys/netinet/altq.h
@@ -23,13 +23,27 @@
23 23
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 24
  * SUCH DAMAGE.
25 25
  *
26  
- * $Id: altq.h,v 1.1 1999/08/05 17:18:17 itojun Exp $
  26
+ * $Id: altq.h,v 1.1.1.1 1999/10/02 05:52:42 itojun Exp $
27 27
  */
28 28
 #ifndef _NETINET_ALTQ_H_
29 29
 #define _NETINET_ALTQ_H_
30 30
 
31 31
 #include <netinet/in.h>
32 32
 
  33
+/* altq discipline type */
  34
+#define ALTQT_NONE	0	/* reserved */
  35
+#define ALTQT_CBQ	1	/* cbq */
  36
+#define ALTQT_WFQ	2	/* wfq */
  37
+#define ALTQT_AFMAP	3	/* afmap */
  38
+#define ALTQT_FIFOQ	4	/* fifoq */
  39
+#define ALTQT_RED	5	/* red */
  40
+#define ALTQT_RIO	6	/* rio */
  41
+#define ALTQT_LOCALQ	7	/* local use */
  42
+#define ALTQT_HFSC	8	/* hfsc */
  43
+#define ALTQT_CDNR	9	/* traffic conditioner */
  44
+#define ALTQT_BLUE	10	/* blue */
  45
+#define ALTQT_MAX	10
  46
+
33 47
 /*
34 48
  * common network flow info structure
35 49
  */
@@ -78,6 +92,7 @@ struct flowinfo_in6 {
78 92
  * flow filters for AF_INET and AF_INET6
79 93
  */
80 94
 struct flow_filter {
  95
+	int			ff_ruleno;
81 96
 	struct flowinfo_in	ff_flow;
82 97
 	struct {
83 98
 		struct in_addr	mask_dst;
@@ -90,6 +105,7 @@ struct flow_filter {
90 105
 
91 106
 #ifdef SIN6_LEN
92 107
 struct flow_filter6 {
  108
+	int			ff_ruleno;
93 109
 	struct flowinfo_in6	ff_flow6;
94 110
 	struct {
95 111
 		struct in6_addr	mask6_dst;
@@ -104,4 +120,13 @@ struct flow_filter6 {
104 120
 #include <netinet/altq_var.h>
105 121
 #endif
106 122
 
  123
+/* queue macros only in FreeBSD */
  124
+#ifndef LIST_EMPTY
  125
+#define	LIST_EMPTY(head) ((head)->lh_first == NULL)
  126
+#endif
  127
+#ifndef LIST_FOREACH
  128
+#define LIST_FOREACH(var, head, field)					\
  129
+	for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
  130
+#endif
  131
+
107 132
 #endif /* _NETINET_ALTQ_H_ */
31  kame/sys/netinet/altq_afmap.c
@@ -23,7 +23,7 @@
23 23
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 24
  * SUCH DAMAGE.
25 25
  *
26  
- * $Id: altq_afmap.c,v 1.2 1999/08/16 20:03:56 shin Exp $
  26
+ * $Id: altq_afmap.c,v 1.1.1.1 1999/10/02 05:52:42 itojun Exp $
27 27
  */
28 28
 
29 29
 /*
@@ -58,6 +58,7 @@
58 58
 #include <net/altq_conf.h>
59 59
 
60 60
 #include <netinet/in.h>
  61
+#include <netinet/altq.h>
61 62
 #include <netinet/altq_afmap.h>
62 63
 
63 64
 LIST_HEAD(, afm_head) afhead_chain;
@@ -262,29 +263,29 @@ afm_match6(head, fp)
262 263
 
263 264
 	for (afm = head->afh_head.lh_first; afm != NULL;
264 265
 	     afm = afm->afm_list.le_next) {
265  
-		if (afm->afm_flowinfo6.fi_flowlabel != 0 &&
266  
-		    afm->afm_flowinfo6.fi_flowlabel != fp->fi_flowlabel)
  266
+		if (afm->afm_flowinfo6.fi6_flowlabel != 0 &&
  267
+		    afm->afm_flowinfo6.fi6_flowlabel != fp->fi6_flowlabel)
267 268
 			continue;
268 269
 #ifdef notyet
269  
-		if (!IN6_IS_ADDR_UNSPECIFIED(&afm->afm_flowinfo6.fi_dst) &&
270  
-		    !IN6_ARE_ADDR_EQUAL(&afm->afm_flowinfo6.fi_dst,
271  
-					&fp->fi_dst))
  270
+		if (!IN6_IS_ADDR_UNSPECIFIED(&afm->afm_flowinfo6.fi6_dst) &&
  271
+		    !IN6_ARE_ADDR_EQUAL(&afm->afm_flowinfo6.fi6_dst,
  272
+					&fp->fi6_dst))
272 273
 			continue;
273  
-		if (afm->afm_flowinfo6.fi_dport != 0 &&
274  
-		    afm->afm_flowinfo6.fi_dport != fp->fi_dport)
  274
+		if (afm->afm_flowinfo6.fi6_dport != 0 &&
  275
+		    afm->afm_flowinfo6.fi6_dport != fp->fi6_dport)
275 276
 			continue;
276 277
 #endif
277  
-		if (!IN6_IS_ADDR_UNSPECIFIED(&afm->afm_flowinfo6.fi_src) &&
278  
-		    !IN6_ARE_ADDR_EQUAL(&afm->afm_flowinfo6.fi_src,
279  
-					&fp->fi_src))
  278
+		if (!IN6_IS_ADDR_UNSPECIFIED(&afm->afm_flowinfo6.fi6_src) &&
  279
+		    !IN6_ARE_ADDR_EQUAL(&afm->afm_flowinfo6.fi6_src,
  280
+					&fp->fi6_src))
280 281
 			continue;
281 282
 #ifdef notyet
282  
-		if (afm->afm_flowinfo6.fi_sport != 0 &&
283  
-		    afm->afm_flowinfo6.fi_sport != fp->fi_sport)
  283
+		if (afm->afm_flowinfo6.fi6_sport != 0 &&
  284
+		    afm->afm_flowinfo6.fi6_sport != fp->fi6_sport)
284 285
 			continue;
285 286
 #endif
286  
-		if (afm->afm_flowinfo6.fi_proto != 0 &&
287  
-		    afm->afm_flowinfo6.fi_proto != fp->fi_proto)
  287
+		if (afm->afm_flowinfo6.fi6_proto != 0 &&
  288
+		    afm->afm_flowinfo6.fi6_proto != fp->fi6_proto)
288 289
 			continue;
289 290
 		/* match found! */
290 291
 		return (afm);
2  kame/sys/netinet/altq_afmap.h
@@ -23,7 +23,7 @@
23 23
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 24
  * SUCH DAMAGE.
25 25
  *
26  
- * $Id: altq_afmap.h,v 1.2 1999/08/16 20:03:56 shin Exp $
  26
+ * $Id: altq_afmap.h,v 1.1.1.1 1999/10/02 05:52:42 itojun Exp $
27 27
  */
28 28
 
29 29
 #ifndef _NETINET_ALTQ_AFMAP_H_
677  kame/sys/netinet/altq_blue.c
... ...
@@ -0,0 +1,677 @@
  1
+/*
  2
+ * Copyright (C) 1997-1999
  3
+ *	Sony Computer Science Laboratory Inc.  All rights reserved.
  4
+ *
  5
+ * Redistribution and use in source and binary forms, with or without
  6
+ * modification, are permitted provided that the following conditions
  7
+ * are met:
  8
+ * 1. Redistributions of source code must retain the above copyright
  9
+ *    notice, this list of conditions and the following disclaimer.
  10
+ * 2. Redistributions in binary form must reproduce the above copyright
  11
+ *    notice, this list of conditions and the following disclaimer in the
  12
+ *    documentation and/or other materials provided with the distribution.
  13
+ *
  14
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
  15
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17
+ * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
  18
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24
+ * SUCH DAMAGE.
  25
+ *
  26
+ */
  27
+/*
  28
+ * Copyright (c) 1990-1994 Regents of the University of California.
  29
+ * All rights reserved.
  30
+ *
  31
+ * Redistribution and use in source and binary forms, with or without
  32
+ * modification, are permitted provided that the following conditions
  33
+ * are met:
  34
+ * 1. Redistributions of source code must retain the above copyright
  35
+ *    notice, this list of conditions and the following disclaimer.
  36
+ * 2. Redistributions in binary form must reproduce the above copyright
  37
+ *    notice, this list of conditions and the following disclaimer in the
  38
+ *    documentation and/or other materials provided with the distribution.
  39
+ * 3. All advertising materials mentioning features or use of this software
  40
+ *    must display the following acknowledgement:
  41
+ *	This product includes software developed by the Computer Systems
  42
+ *	Engineering Group at Lawrence Berkeley Laboratory.
  43
+ * 4. Neither the name of the University nor of the Laboratory may be used
  44
+ *    to endorse or promote products derived from this software without
  45
+ *    specific prior written permission.
  46
+ *
  47
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  48
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  49
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  50
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  51
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  52
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  53
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  54
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  55
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  56
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  57
+ * SUCH DAMAGE.
  58
+ *
  59
+ * $Id: altq_blue.c,v 1.1 1999/10/01 04:38:05 kjc Exp $
  60
+ */
  61
+
  62
+#ifndef _NO_OPT_ALTQ_H_
  63
+#include "opt_altq.h"
  64
+#if !defined(__FreeBSD__) || (__FreeBSD__ > 2)
  65
+#include "opt_inet.h"
  66
+#endif
  67
+#endif /* !_NO_OPT_ALTQ_H_ */
  68
+#ifdef BLUE	/* blue is enabled by BLUE option in opt_altq.h */
  69
+
  70
+#include <sys/param.h>
  71
+#include <sys/malloc.h>
  72
+#include <sys/mbuf.h>
  73
+#include <sys/socket.h>
  74
+#include <sys/sockio.h>
  75
+#include <sys/systm.h>
  76
+#include <sys/proc.h>
  77
+#include <sys/errno.h>
  78
+#include <sys/kernel.h>
  79
+#include <sys/conf.h>
  80
+
  81
+#include <net/if.h>
  82
+#include <net/if_types.h>
  83
+#include <net/altq_conf.h>
  84
+
  85
+#include <netinet/in.h>
  86
+#include <netinet/in_systm.h>
  87
+#include <netinet/ip.h>
  88
+#ifdef INET6
  89
+#include <netinet/ip6.h>
  90
+#endif
  91
+#include <netinet/altq.h>
  92
+#include <netinet/altq_classq.h>
  93
+#include <netinet/altq_blue.h>
  94
+
  95
+/*
  96
+ * Blue is proposed and implemented by Wu-chang Feng <wuchang@eecs.umich.edu>.
  97
+ * more information on Blue is available from
  98
+ * http://www.eecs.umich.edu/~wuchang/blue/
  99
+ */
  100
+
  101
+/* fixed-point uses 12-bit decimal places */
  102
+#define FP_SHIFT	12	/* fixed-point shift */
  103
+
  104
+#define BLUE_LIMIT	200	/* default max queue lenght */
  105
+#define BLUE_STATS		/* collect statistics */
  106
+
  107
+/* blue_list keeps all blue_state_t's allocated. */
  108
+static blue_queue_t *blue_list = NULL;
  109
+
  110
+/* internal function prototypes */
  111
+static int blue_enqueue __P((struct ifnet *, struct mbuf *,
  112
+			    struct pr_hdr *, int));
  113
+static struct mbuf *blue_dequeue __P((struct ifnet *, int));
  114
+static int drop_early __P((blue_t *));
  115
+static int mark_ecn __P((struct pr_hdr *, int));
  116
+static int blue_detach __P((blue_queue_t *));
  117
+
  118
+/*
  119
+ * blue device interface
  120
+ */
  121
+altqdev_decl(blue);
  122
+
  123
+int
  124
+blueopen(dev, flag, fmt, p)
  125
+	dev_t dev;
  126
+	int flag, fmt;
  127
+	struct proc *p;
  128
+{
  129
+	/* everything will be done when the queueing scheme is attached. */
  130
+	return 0;
  131
+}
  132
+
  133
+int
  134
+blueclose(dev, flag, fmt, p)
  135
+	dev_t dev;
  136
+	int flag, fmt;
  137
+	struct proc *p;
  138
+{
  139
+	blue_queue_t *rqp;
  140
+	int err, error = 0;
  141
+
  142
+	while ((rqp = blue_list) != NULL) {
  143
+		/* destroy all */
  144
+		err = blue_detach(rqp);
  145
+		if (err != 0 && error == 0)
  146
+			error = err;
  147
+	}
  148
+
  149
+	return error;
  150
+}
  151
+
  152
+int
  153
+blueioctl(dev, cmd, addr, flag, p)
  154
+	dev_t dev;
  155
+	ioctlcmd_t cmd;
  156
+	caddr_t addr;
  157
+	int flag;
  158
+	struct proc *p;
  159
+{
  160
+	blue_queue_t *rqp;
  161
+	struct blue_interface *ifacep;
  162
+	struct ifnet *ifp;
  163
+	int	error = 0;
  164
+
  165
+	/* check super-user privilege */
  166
+	switch (cmd) {
  167
+	case BLUE_GETSTATS:
  168
+		break;
  169
+	default:
  170
+		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
  171
+			return (error);
  172
+		break;
  173
+	}
  174
+    
  175
+	switch (cmd) {
  176
+
  177
+	case BLUE_ENABLE:
  178
+		ifacep = (struct blue_interface *)addr;
  179
+		if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
  180
+			error = EBADF;
  181
+			break;
  182
+		}
  183
+		error = if_altqenable(rqp->rq_ifp);
  184
+		break;
  185
+
  186
+	case BLUE_DISABLE:
  187
+		ifacep = (struct blue_interface *)addr;
  188
+		if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
  189
+			error = EBADF;
  190
+			break;
  191
+		}
  192
+		error = if_altqdisable(rqp->rq_ifp);
  193
+		break;
  194
+
  195
+	case BLUE_IF_ATTACH:
  196
+		ifp = ifunit(((struct blue_interface *)addr)->blue_ifname);
  197
+		if (ifp == NULL) {
  198
+			error = ENXIO;
  199
+			break;
  200
+		}
  201
+
  202
+		/* allocate and initialize blue_state_t */
  203
+		MALLOC(rqp, blue_queue_t *, sizeof(blue_queue_t), M_DEVBUF, M_WAITOK);
  204
+		bzero(rqp, sizeof(blue_queue_t));
  205
+
  206
+		MALLOC(rqp->rq_q, class_queue_t *, sizeof(class_queue_t),
  207
+		       M_DEVBUF, M_WAITOK);
  208
+		bzero(rqp->rq_q, sizeof(class_queue_t));
  209
+
  210
+		MALLOC(rqp->rq_blue, blue_t *, sizeof(blue_t), M_DEVBUF, M_WAITOK); 
  211
+		bzero(rqp->rq_blue, sizeof(blue_t));
  212
+
  213
+		rqp->rq_ifp = ifp;
  214
+		qtail(rqp->rq_q) = NULL;
  215
+		qlen(rqp->rq_q) = 0;
  216
+		qlimit(rqp->rq_q) = BLUE_LIMIT;
  217
+
  218
+		/* default packet time: 1000 bytes / 10Mbps * 8 * 1000000 */
  219
+		blue_init(rqp->rq_blue, 0, 800, 1000, 50000);
  220
+
  221
+		/*
  222
+		 * set BLUE to this ifnet structure.
  223
+		 */
  224
+		error = if_altqattach(ifp, rqp, blue_enqueue, blue_dequeue,
  225
+				      ALTQT_BLUE);
  226
+		if (error) {
  227
+			FREE(rqp->rq_blue, M_DEVBUF);
  228
+			FREE(rqp->rq_q, M_DEVBUF);
  229
+			FREE(rqp, M_DEVBUF);
  230
+			break;
  231
+		}
  232
+
  233
+		/* add this state to the blue list */
  234
+		rqp->rq_next = blue_list;
  235
+		blue_list = rqp;
  236
+		break;
  237
+
  238
+	case BLUE_IF_DETACH:
  239
+		ifacep = (struct blue_interface *)addr;
  240
+		if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
  241
+			error = EBADF;
  242
+			break;
  243
+		}
  244
+		error = blue_detach(rqp);
  245
+		break;
  246
+
  247
+	case BLUE_GETSTATS:
  248
+		do {
  249
+			struct blue_stats *q_stats;
  250
+			blue_t *rp;
  251
+
  252
+			q_stats = (struct blue_stats *)addr;
  253
+			if ((rqp = altq_lookup(q_stats->iface.blue_ifname,
  254
+					     ALTQT_BLUE)) == NULL) {
  255
+				error = EBADF;
  256
+				break;
  257
+			}
  258
+
  259
+			q_stats->q_len 	   = qlen(rqp->rq_q);
  260
+			q_stats->q_limit   = qlimit(rqp->rq_q);
  261
+
  262
+			rp = rqp->rq_blue;
  263
+			q_stats->q_pmark = rp->blue_pmark;
  264
+			q_stats->xmit_packets  = rp->blue_stats.xmit_packets;
  265
+			q_stats->xmit_bytes    = rp->blue_stats.xmit_bytes;
  266
+			q_stats->drop_packets  = rp->blue_stats.drop_packets;
  267
+			q_stats->drop_bytes    = rp->blue_stats.drop_bytes;
  268
+			q_stats->drop_forced   = rp->blue_stats.drop_forced;
  269
+			q_stats->drop_unforced = rp->blue_stats.drop_unforced;
  270
+			q_stats->marked_packets = rp->blue_stats.marked_packets;
  271
+
  272
+		} while (0);
  273
+		break;
  274
+
  275
+	case BLUE_CONFIG:
  276
+		do {
  277
+			struct blue_conf *fc;
  278
+			int limit;
  279
+
  280
+			fc = (struct blue_conf *)addr;
  281
+			if ((rqp = altq_lookup(fc->iface.blue_ifname,
  282
+					     ALTQT_BLUE)) == NULL) {
  283
+				error = EBADF;
  284
+				break;
  285
+			}
  286
+			limit = fc->blue_limit;
  287
+			qlimit(rqp->rq_q) = limit;
  288
+			fc->blue_limit = limit;	/* write back the new value */
  289
+			if (fc->blue_pkttime > 0)
  290
+				rqp->rq_blue->blue_pkttime = fc->blue_pkttime;
  291
+			if (fc->blue_max_pmark > 0)
  292
+				rqp->rq_blue->blue_max_pmark = fc->blue_max_pmark;
  293
+			if (fc->blue_hold_time > 0)
  294
+				rqp->rq_blue->blue_hold_time = fc->blue_hold_time;
  295
+			rqp->rq_blue->blue_flags = fc->blue_flags;
  296
+			
  297
+			blue_init(rqp->rq_blue, rqp->rq_blue->blue_flags,
  298
+				 rqp->rq_blue->blue_pkttime,
  299
+				 rqp->rq_blue->blue_max_pmark,
  300
+				 rqp->rq_blue->blue_hold_time);
  301
+		} while (0);
  302
+		break;
  303
+
  304
+	case BLUE_ACC_ENABLE:
  305
+		/* enable accounting mode */
  306
+		ifacep = (struct blue_interface *)addr;
  307
+		if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
  308
+			error = EBADF;
  309
+			break;
  310
+		}
  311
+		SET_ACCOUNTING(rqp->rq_ifp);
  312
+		break;
  313
+
  314
+	case BLUE_ACC_DISABLE:
  315
+		/* disable accounting mode */
  316
+		ifacep = (struct blue_interface *)addr;
  317
+		if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
  318
+			error = EBADF;
  319
+			break;
  320
+		}
  321
+		CLEAR_ACCOUNTING(rqp->rq_ifp);
  322
+		break;
  323
+
  324
+	default:
  325
+		error = EINVAL;
  326
+		break;
  327
+	}
  328
+	return error;
  329
+}
  330
+
  331
+static int blue_detach(rqp)
  332
+	blue_queue_t *rqp;
  333
+{
  334
+	blue_queue_t *tmp;
  335
+	int error = 0;
  336
+
  337
+	if (ALTQ_IS_ON(rqp->rq_ifp))
  338
+		if_altqdisable(rqp->rq_ifp);
  339
+
  340
+	_flushq(rqp->rq_q);
  341
+
  342
+	if ((error = if_altqdetach(rqp->rq_ifp)))
  343
+		return (error);
  344
+
  345
+	if (blue_list == rqp)
  346
+		blue_list = rqp->rq_next;
  347
+	else {
  348
+		for (tmp = blue_list; tmp != NULL; tmp = tmp->rq_next)
  349
+			if (tmp->rq_next == rqp) {
  350
+				tmp->rq_next = rqp->rq_next;
  351
+				break;
  352
+			}
  353
+		if (tmp == NULL)
  354
+			printf("blue_detach: no state found in blue_list!\n");
  355
+	}
  356
+
  357
+	FREE(rqp->rq_q, M_DEVBUF);
  358
+	FREE(rqp->rq_blue, M_DEVBUF);
  359
+	FREE(rqp, M_DEVBUF);
  360
+	return (error);
  361
+}
  362
+
  363
+/*
  364
+ * blue support routines
  365
+ */
  366
+
  367
+int 
  368
+blue_init(rp, flags, pkttime, blue_max_pmark, blue_hold_time)
  369
+	blue_t 	*rp;
  370
+	int	flags;
  371
+	int	pkttime;
  372
+	int	blue_max_pmark;
  373
+	int	blue_hold_time;
  374
+{
  375
+	int npkts_per_sec;
  376
+	
  377
+	rp->blue_idle = 1;
  378
+	rp->blue_flags = flags;
  379
+	rp->blue_pkttime = pkttime;
  380
+	rp->blue_max_pmark = blue_max_pmark;
  381
+	rp->blue_hold_time = blue_hold_time;
  382
+	if (pkttime == 0)
  383
+		rp->blue_pkttime = 1;
  384
+
  385
+	/* when the link is very slow, adjust blue parameters */
  386
+	npkts_per_sec = 1000000 / rp->blue_pkttime;
  387
+	if (npkts_per_sec < 50) {
  388
+	}
  389
+	else if (npkts_per_sec < 300) {
  390
+	}
  391
+
  392
+	microtime(&rp->blue_last);
  393
+	return (0);
  394
+}
  395
+
  396
+/*
  397
+ * enqueue routine:
  398
+ *
  399
+ *	returns: 0 when successfully queued.
  400
+ *		 ENOBUFS when drop occurs.
  401
+ */
  402
+static int
  403
+blue_enqueue(ifp, m, pr_hdr, mode)
  404
+	struct ifnet *ifp;
  405
+	struct mbuf *m;
  406
+	struct pr_hdr *pr_hdr;
  407
+	int mode;
  408
+{
  409
+	blue_queue_t *rqp = (blue_queue_t *)ifp->if_altqp;
  410
+	int error = 0;
  411
+
  412
+	switch (mode) {
  413
+	case ALTEQ_NORMAL:
  414
+		if (blue_addq(rqp->rq_blue, rqp->rq_q, m, pr_hdr) == 0) {
  415
+			/* successfully queued.  start the driver */
  416
+			if (ifp->if_start && (ifp->if_flags & IFF_OACTIVE) == 0)
  417
+				(*ifp->if_start)(ifp);
  418
+		}
  419
+		else
  420
+			error = ENOBUFS;
  421
+		break;
  422
+
  423
+#if defined(ALTQ_ACCOUNT) && defined(BLUE_STATS)
  424
+		/*
  425
+		 * altq accounting mode: used just for statistics.
  426
+		 */
  427
+	case ALTEQ_ACCOK:
  428
+		rqp->rq_blue->blue_stats.xmit_packets++;
  429
+		rqp->rq_blue->blue_stats.xmit_bytes += m->m_pkthdr.len;
  430
+		break;
  431
+
  432
+	case ALTEQ_ACCDROP:
  433
+		rqp->rq_blue->blue_stats.drop_packets++;
  434
+		rqp->rq_blue->blue_stats.drop_bytes += m->m_pkthdr.len;
  435
+		break;
  436
+
  437
+#endif /* ALTQ_ACCOUNT && BLUE_STATS */
  438
+	}
  439
+	return error;
  440
+}
  441
+
  442
+#define DTYPE_NODROP	0	/* no drop */
  443
+#define DTYPE_FORCED	1	/* a "forced" drop */
  444
+#define DTYPE_EARLY	2	/* an "unforced" (early) drop */
  445
+
  446
+int blue_addq(rp, q, m, pr_hdr)
  447
+	blue_t *rp;
  448
+	class_queue_t *q;
  449
+	struct mbuf *m;
  450
+	struct pr_hdr *pr_hdr;
  451
+{
  452
+	int droptype;
  453
+    
  454
+	/*
  455
+	 * if we were idle, this is an enqueue onto an empty queue
  456
+	 * and we should decrement marking probability
  457
+	 * 
  458
+	 */
  459
+	if (rp->blue_idle) {
  460
+		struct timeval now;
  461
+		int t;
  462
+		rp->blue_idle = 0;
  463
+		microtime(&now);
  464
+		t = (now.tv_sec - rp->blue_last.tv_sec);
  465
+		if ( t > 1) {
  466
+			rp->blue_pmark = 1;
  467
+			microtime(&rp->blue_last);
  468
+		}
  469
+		else {
  470
+			t = t * 1000000 + (now.tv_usec - rp->blue_last.tv_usec);
  471
+			if (t > rp->blue_hold_time) {
  472
+				rp->blue_pmark--;
  473
+				if (rp->blue_pmark < 0) rp->blue_pmark = 0;
  474
+				microtime(&rp->blue_last);
  475
+			}
  476
+		}
  477
+	}
  478
+
  479
+	/* see if we drop early */
  480
+	droptype = DTYPE_NODROP;
  481
+	if (drop_early(rp) && qlen(q) > 1) {
  482
+		/* mark or drop by blue */
  483
+		if ((rp->blue_flags & BLUEF_ECN) &&
  484
+		    mark_ecn(pr_hdr, rp->blue_flags)) {
  485
+			/* successfully marked.  do not drop. */
  486
+#ifdef BLUE_STATS
  487
+			rp->blue_stats.marked_packets++;
  488
+#endif
  489
+		}
  490
+		else { 
  491
+			/* unforced drop by blue */
  492
+			droptype = DTYPE_EARLY;
  493
+		}
  494
+	}
  495
+
  496
+	/*
  497
+	 * if the queue length hits the hard limit, it's a forced drop.
  498
+	 */
  499
+	if (droptype == DTYPE_NODROP && qlen(q) >= qlimit(q))
  500
+		droptype = DTYPE_FORCED;
  501
+
  502
+	/* if successful or forced drop, enqueue this packet. */
  503
+	if (droptype != DTYPE_EARLY)
  504
+		_addq(q, m);
  505
+
  506
+	if (droptype != DTYPE_NODROP) {
  507
+		if (droptype == DTYPE_EARLY) {
  508
+			/* drop the incoming packet */
  509
+#ifdef BLUE_STATS
  510
+			rp->blue_stats.drop_unforced++;
  511
+#endif
  512
+		}
  513
+		else {
  514
+			struct timeval now;
  515
+			int t;
  516
+			/* forced drop, select a victim packet in the queue. */
  517
+			m = _getq_random(q);
  518
+			microtime(&now);
  519
+			t = (now.tv_sec - rp->blue_last.tv_sec);
  520
+			t = t * 1000000 + (now.tv_usec - rp->blue_last.tv_usec);
  521
+			if (t > rp->blue_hold_time) {
  522
+				rp->blue_pmark += rp->blue_max_pmark >> 3;
  523
+				if (rp->blue_pmark > rp->blue_max_pmark)
  524
+					rp->blue_pmark = rp->blue_max_pmark;
  525
+				microtime(&rp->blue_last);
  526
+			}
  527
+#ifdef BLUE_STATS
  528
+			rp->blue_stats.drop_forced++;
  529
+#endif
  530
+		}
  531
+#ifdef BLUE_STATS
  532
+		rp->blue_stats.drop_packets++;
  533
+		rp->blue_stats.drop_bytes += m->m_pkthdr.len;
  534
+#endif
  535
+		m_freem(m);
  536
+		return (-1);
  537
+	}
  538
+	/* successfully queued */
  539
+	return (0);
  540
+}
  541
+
  542
+/*
  543
+ * early-drop probability is kept in blue_pmark
  544
+ *
  545
+ */
  546
+static int drop_early(rp)
  547
+	blue_t *rp;
  548
+{
  549
+	if ((random() % rp->blue_max_pmark) < rp->blue_pmark) {
  550
+		/* drop or mark */
  551
+		return (1);
  552
+	}
  553
+	/* no drop/mark */
  554
+	return (0);
  555
+}
  556
+
  557
+/*
  558
+ * try to mark CE bit to the packet.
  559
+ *    returns 1 if successfully marked, 0 otherwise.
  560
+ */
  561
+static int mark_ecn(pr_hdr, flags)
  562
+	struct pr_hdr *pr_hdr;
  563
+	int flags;
  564
+{
  565
+
  566
+	switch (pr_hdr->ph_family) {
  567
+	case AF_INET:
  568
+		if (flags & BLUEF_ECN4) {
  569
+			struct ip *ip = (struct ip *)pr_hdr->ph_hdr;
  570
+	    
  571
+			if (ip->ip_tos & IPTOS_ECT) {
  572
+				/* ECN-capable, mark ECN bit. */
  573
+				if ((ip->ip_tos & IPTOS_CE) == 0) {
  574
+					long sum;
  575
+		    
  576
+					ip->ip_tos |= IPTOS_CE;
  577
+					/*
  578
+					 * update checksum (from RFC1624)
  579
+					 *	   HC' = ~(~HC + ~m + m')
  580
+					 */
  581
+					sum = ~ntohs(ip->ip_sum) & 0xffff;
  582
+					sum += 0xffff + IPTOS_CE;
  583
+					sum = (sum >> 16) + (sum & 0xffff);
  584
+					sum += (sum >> 16);  /* add carry */
  585
+		
  586
+					ip->ip_sum = htons(~sum & 0xffff);
  587
+				}
  588
+				return (1);
  589
+			}
  590
+		}
  591
+		break;
  592
+#ifdef INET6
  593
+	case AF_INET6:
  594
+		if (flags & BLUEF_ECN6) {
  595
+			struct ip6_hdr *ip6 = (struct ip6_hdr *)pr_hdr->ph_hdr;
  596
+
  597
+			if (ip6->ip6_flow & (IPTOS_ECT << 20)) {
  598
+				/* ECN-capable, mark ECN bit. */
  599
+				ip6->ip6_flow |= (IPTOS_CE << 20);
  600
+				return (1);
  601
+			}
  602
+		}
  603
+		break;
  604
+#endif  /* INET6 */
  605
+	}
  606
+
  607
+	/* not marked */
  608
+	return (0);
  609
+}
  610
+
  611
+/*
  612
+ * dequeue routine:
  613
+ *	must be called in splimp.
  614
+ *
  615
+ *	returns: mbuf dequeued.
  616
+ *		 NULL when no packet is available in the queue.
  617
+ */
  618
+
  619
+static struct mbuf *
  620
+blue_dequeue(ifp, mode)
  621
+	struct ifnet *ifp;
  622
+	int mode;
  623
+{
  624
+	blue_queue_t *rqp = (blue_queue_t *)ifp->if_altqp;
  625
+	struct mbuf *m = NULL;
  626
+
  627
+	switch (mode) {
  628
+	case ALTDQ_DEQUEUE:
  629
+		m = blue_getq(rqp->rq_blue, rqp->rq_q);
  630
+		break;
  631
+
  632
+	case ALTDQ_PEEK:
  633
+		m = qhead(rqp->rq_q);
  634
+		break;
  635
+
  636
+	case ALTDQ_FLUSH:
  637
+		_flushq(rqp->rq_q);
  638
+		m = NULL;
  639
+		break;
  640
+	}
  641
+	return m;
  642
+}
  643
+
  644
+struct mbuf *blue_getq(rp, q)
  645
+	blue_t *rp;
  646
+	class_queue_t *q;
  647
+{
  648
+	struct mbuf *m;
  649
+	
  650
+	if ((m = _getq(q)) == NULL) {
  651
+		if (rp->blue_idle == 0) {
  652
+			rp->blue_idle = 1;
  653
+			microtime(&rp->blue_last);
  654
+		}
  655
+		return NULL;
  656
+	}
  657
+
  658
+	rp->blue_idle = 0;
  659
+#ifdef BLUE_STATS
  660
+	rp->blue_stats.xmit_packets++;
  661
+	rp->blue_stats.xmit_bytes += m->m_pkthdr.len;
  662
+#endif
  663
+	return (m);
  664
+}
  665
+
  666
+#ifdef KLD_MODULE
  667
+
  668
+#include <net/altq_conf.h>
  669
+
  670
+static struct altqsw blue_sw =
  671
+	{"blue", blueopen, blueclose, blueioctl};
  672
+
  673
+ALTQ_MODULE(altq_blue, ALTQT_BLUE, &blue_sw);
  674
+
  675
+#endif /* KLD_MODULE */
  676
+
  677
+#endif /* BLUE */
118  kame/sys/netinet/altq_blue.h
... ...
@@ -0,0 +1,118 @@
  1
+/*
  2
+ * Copyright (C) 1997-1999
  3
+ *	Sony Computer Science Laboratory Inc.  All rights reserved.
  4
+ *
  5
+ * Redistribution and use in source and binary forms, with or without
  6
+ * modification, are permitted provided that the following conditions
  7
+ * are met:
  8
+ * 1. Redistributions of source code must retain the above copyright
  9
+ *    notice, this list of conditions and the following disclaimer.
  10
+ * 2. Redistributions in binary form must reproduce the above copyright
  11
+ *    notice, this list of conditions and the following disclaimer in the
  12
+ *    documentation and/or other materials provided with the distribution.
  13
+ *
  14
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
  15
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17
+ * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
  18
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24
+ * SUCH DAMAGE.
  25
+ *
  26
+ * $Id: altq_blue.h,v 1.1 1999/10/01 04:38:05 kjc Exp $
  27
+ */
  28
+
  29
+#ifndef _NETINET_ALTQ_BLUE_H_
  30
+#define _NETINET_ALTQ_BLUE_H_
  31
+
  32
+struct blue_interface {
  33
+	char	blue_ifname[IFNAMSIZ];
  34
+};
  35
+
  36
+struct blue_stats {
  37
+	struct blue_interface iface;
  38
+	int q_len;
  39
+	int q_limit;
  40
+	int q_pmark;
  41
+	quad_t xmit_packets;
  42
+	quad_t xmit_bytes;
  43
+	quad_t drop_packets;
  44
+	quad_t drop_bytes;
  45
+	quad_t drop_forced;
  46
+	quad_t drop_unforced;
  47
+	quad_t marked_packets;
  48
+};
  49
+
  50
+struct blue_conf {
  51
+	struct blue_interface iface;
  52
+	int blue_limit;
  53
+	int blue_max_pmark;
  54
+	int blue_hold_time;
  55
+	int blue_pkttime;	/* average packet time in usec */
  56
+	int blue_flags;		/* see below */
  57
+};
  58
+
  59
+/* blue flags */
  60
+#define BLUEF_ECN4	0x01	/* use packet marking for IPv4 packets */
  61
+#define BLUEF_ECN6	0x02	/* use packet marking for IPv6 packets */
  62
+#define BLUEF_ECN	(BLUEF_ECN4 | BLUEF_ECN6)
  63
+
  64
+/* 
  65
+ * IOCTLs for BLUE
  66
+ */
  67
+#define BLUE_ENABLE		_IOW('Q', 1, struct blue_interface)
  68
+#define BLUE_DISABLE		_IOW('Q', 2, struct blue_interface)
  69
+#define	BLUE_IF_ATTACH		_IOW('Q', 3, struct blue_interface)
  70
+#define	BLUE_IF_DETACH		_IOW('Q', 4, struct blue_interface)
  71
+#define	BLUE_ACC_ENABLE		_IOW('Q', 5, struct blue_interface)
  72
+#define	BLUE_ACC_DISABLE	_IOW('Q', 6, struct blue_interface)
  73
+#define	BLUE_GETSTATS		_IOWR('Q', 7, struct blue_stats)
  74
+#define	BLUE_CONFIG		_IOWR('Q', 8, struct blue_conf)
  75
+
  76
+#if defined(KERNEL) || defined(_KERNEL)
  77
+
  78
+typedef struct blue {
  79
+	int blue_pkttime; 	/* average packet time in micro sec
  80
+				   used for idle calibration */
  81
+	int blue_flags;		/* blue flags */
  82
+
  83
+	/* blue parameters */
  84
+	int blue_pmark;		/* 0-1000 (mark probability*10000) */
  85
+	int blue_max_pmark;	/* sets precision of marking probability */
  86
+	int blue_hold_time;	/* hold time in usec */
  87
+
  88
+	int blue_idle;		/* queue was empty */
  89
+	struct timeval blue_last;  /* timestamp when the queue becomes idle */
  90
+
  91
+	struct {
  92
+		quad_t xmit_packets;
  93
+		quad_t xmit_bytes;
  94
+		quad_t drop_packets;
  95
+		quad_t drop_bytes;
  96
+		quad_t drop_forced;
  97
+		quad_t drop_unforced;
  98
+		quad_t marked_packets;
  99
+	} blue_stats;
  100
+} blue_t;
  101
+
  102
+typedef struct blue_queue {
  103
+	struct blue_queue *rq_next;	/* next blue_state in the list */
  104
+	struct ifnet *rq_ifp;		/* backpointer to ifnet */
  105
+
  106
+	class_queue_t *rq_q;
  107
+
  108
+	blue_t *rq_blue;
  109
+} blue_queue_t;
  110
+
  111
+extern int blue_init __P((blue_t *, int, int, int, int));
  112
+extern int blue_addq __P((blue_t *, class_queue_t *, struct mbuf *,
  113
+			 struct pr_hdr *));
  114
+extern struct mbuf *blue_getq __P((blue_t *, class_queue_t *));
  115
+
  116
+#endif /* KERNEL */
  117
+
  118
+#endif /* _NETINET_ALTQ_BLUE_H_ */
75  kame/sys/netinet/altq_cbq.c
@@ -27,7 +27,7 @@
27 27
  *  
28 28
  * These notices must be retained in any copies of any part of this software.
29 29
  *
30  
- * $Id: altq_cbq.c,v 1.1 1999/08/05 17:18:18 itojun Exp $
  30
+ * $Id: altq_cbq.c,v 1.1.1.1 1999/10/02 05:52:42 itojun Exp $
31 31
  */
32 32
 
33 33
 #ifndef _NO_OPT_ALTQ_H_
@@ -38,7 +38,7 @@
38 38
 #endif /* !_NO_OPT_ALTQ_H_ */
39 39
 #ifdef CBQ	/* cbq is enabled by CBQ option in opt_altq.h */
40 40
 
41  
-#pragma ident "@(#)cbq.c  1.39     98/05/13 SMI"
  41
+/* #pragma ident "@(#)cbq.c  1.39     98/05/13 SMI" */
42 42
 
43 43
 #include <sys/param.h>
44 44
 #include <sys/malloc.h>
@@ -58,12 +58,8 @@
58 58
 #include <netinet/altq.h>
59 59
 #include <netinet/altq_classq.h>
60 60
 #include <netinet/altq_rmclass.h>
61  
-#ifdef CBQ_RED
62 61
 #include <netinet/altq_red.h>
63  
-#ifdef CBQ_RIO
64 62
 #include <netinet/altq_rio.h>
65  
-#endif
66  
-#endif /* CBQ_RED */
67 63
 #include <netinet/altq_cbq.h>
68 64
 
69 65
 /*
@@ -397,9 +393,6 @@ cbq_delete_filter(dfp)
397 393
 /*
398 394
  * cbq_clear_hierarchy deletes all classes and their filters on the
399 395
  * given interface.
400  
- * note that this doesn't affect the enable state and leaves
401  
- * the root class and the default class intact.  This behavior is
402  
- * different from Sun's CBQ implementation.
403 396
  */
404 397
 static int
405 398
 cbq_clear_hierarchy(ifacep)
@@ -432,10 +425,27 @@ cbq_clear_interface(cbqp)
432 425
 			if ((cl = cbqp->cbq_class_tbl[i]) != NULL) {
433 426
 				if (is_a_parent_class(cl))
434 427
 					again++;
435  
-				else
  428
+				else {
436 429
 					cbq_class_destroy(cbqp, cl);
  430
+					cbqp->cbq_class_tbl[i] = NULL;
  431
+				}
437 432
 			}
438 433
 		}
  434
+		if (cbqp->ifnp.ctl_ != NULL &&
  435
+		    !is_a_parent_class(cbqp->ifnp.ctl_)) {
  436
+			cbq_class_destroy(cbqp, cbqp->ifnp.ctl_);
  437
+			cbqp->ifnp.ctl_ = NULL;
  438
+		}
  439
+		if (cbqp->ifnp.default_ != NULL &&
  440
+		    !is_a_parent_class(cbqp->ifnp.default_)) {
  441
+			cbq_class_destroy(cbqp, cbqp->ifnp.default_);
  442
+			cbqp->ifnp.default_ = NULL;
  443
+		}
  444
+		if (cbqp->ifnp.root_ != NULL &&
  445
+		    !is_a_parent_class(cbqp->ifnp.root_)) {
  446
+			cbq_class_destroy(cbqp, cbqp->ifnp.root_);
  447
+			cbqp->ifnp.root_ = NULL;
  448
+		}
439 449
 	} while (again);
440 450
 
441