Home | History | Annotate | Line # | Download | only in altq
altq_blue.c revision 1.12.12.2
      1 /*	$NetBSD: altq_blue.c,v 1.12.12.2 2006/06/09 19:52:35 peter Exp $	*/
      2 /*	$KAME: altq_blue.c,v 1.15 2005/04/13 03:44:24 suz Exp $	*/
      3 
      4 /*
      5  * Copyright (C) 1997-2002
      6  *	Sony Computer Science Laboratories Inc.  All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  *
     29  */
     30 /*
     31  * Copyright (c) 1990-1994 Regents of the University of California.
     32  * All rights reserved.
     33  *
     34  * Redistribution and use in source and binary forms, with or without
     35  * modification, are permitted provided that the following conditions
     36  * are met:
     37  * 1. Redistributions of source code must retain the above copyright
     38  *    notice, this list of conditions and the following disclaimer.
     39  * 2. Redistributions in binary form must reproduce the above copyright
     40  *    notice, this list of conditions and the following disclaimer in the
     41  *    documentation and/or other materials provided with the distribution.
     42  * 3. All advertising materials mentioning features or use of this software
     43  *    must display the following acknowledgement:
     44  *	This product includes software developed by the Computer Systems
     45  *	Engineering Group at Lawrence Berkeley Laboratory.
     46  * 4. Neither the name of the University nor of the Laboratory may be used
     47  *    to endorse or promote products derived from this software without
     48  *    specific prior written permission.
     49  *
     50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     60  * SUCH DAMAGE.
     61  */
     62 
     63 #include <sys/cdefs.h>
     64 __KERNEL_RCSID(0, "$NetBSD: altq_blue.c,v 1.12.12.2 2006/06/09 19:52:35 peter Exp $");
     65 
     66 #ifdef _KERNEL_OPT
     67 #include "opt_altq.h"
     68 #include "opt_inet.h"
     69 #endif
     70 
     71 #ifdef ALTQ_BLUE	/* blue is enabled by ALTQ_BLUE option in opt_altq.h */
     72 
     73 #include <sys/param.h>
     74 #include <sys/malloc.h>
     75 #include <sys/mbuf.h>
     76 #include <sys/socket.h>
     77 #include <sys/sockio.h>
     78 #include <sys/systm.h>
     79 #include <sys/proc.h>
     80 #include <sys/errno.h>
     81 #include <sys/kernel.h>
     82 #include <sys/kauth.h>
     83 
     84 #include <net/if.h>
     85 #include <net/if_types.h>
     86 #include <netinet/in.h>
     87 #include <netinet/in_systm.h>
     88 #include <netinet/ip.h>
     89 #ifdef INET6
     90 #include <netinet/ip6.h>
     91 #endif
     92 
     93 #include <altq/altq.h>
     94 #include <altq/altq_conf.h>
     95 #include <altq/altq_blue.h>
     96 
     97 #ifdef ALTQ3_COMPAT
     98 /*
     99  * Blue is proposed and implemented by Wu-chang Feng <wuchang (at) eecs.umich.edu>.
    100  * more information on Blue is available from
    101  * http://www.eecs.umich.edu/~wuchang/blue/
    102  */
    103 
    104 /* fixed-point uses 12-bit decimal places */
    105 #define	FP_SHIFT	12	/* fixed-point shift */
    106 
    107 #define	BLUE_LIMIT	200	/* default max queue lenght */
    108 #define	BLUE_STATS		/* collect statistics */
    109 
    110 /* blue_list keeps all blue_state_t's allocated. */
    111 static blue_queue_t *blue_list = NULL;
    112 
    113 /* internal function prototypes */
    114 static int blue_enqueue(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
    115 static struct mbuf *blue_dequeue(struct ifaltq *, int);
    116 static int drop_early(blue_t *);
    117 static int mark_ecn(struct mbuf *, struct altq_pktattr *, int);
    118 static int blue_detach(blue_queue_t *);
    119 static int blue_request(struct ifaltq *, int, void *);
    120 
    121 /*
    122  * blue device interface
    123  */
    124 altqdev_decl(blue);
    125 
    126 int
    127 blueopen(dev, flag, fmt, l)
    128 	dev_t dev;
    129 	int flag, fmt;
    130 	struct lwp *l;
    131 {
    132 	/* everything will be done when the queueing scheme is attached. */
    133 	return 0;
    134 }
    135 
    136 int
    137 blueclose(dev, flag, fmt, l)
    138 	dev_t dev;
    139 	int flag, fmt;
    140 	struct lwp *l;
    141 {
    142 	blue_queue_t *rqp;
    143 	int err, error = 0;
    144 
    145 	while ((rqp = blue_list) != NULL) {
    146 		/* destroy all */
    147 		err = blue_detach(rqp);
    148 		if (err != 0 && error == 0)
    149 			error = err;
    150 	}
    151 
    152 	return error;
    153 }
    154 
    155 int
    156 blueioctl(dev, cmd, addr, flag, l)
    157 	dev_t dev;
    158 	ioctlcmd_t cmd;
    159 	caddr_t addr;
    160 	int flag;
    161 	struct lwp *l;
    162 {
    163 	blue_queue_t *rqp;
    164 	struct blue_interface *ifacep;
    165 	struct ifnet *ifp;
    166 	struct proc *p = l->l_proc;
    167 	int	error = 0;
    168 
    169 	/* check super-user privilege */
    170 	switch (cmd) {
    171 	case BLUE_GETSTATS:
    172 		break;
    173 	default:
    174 #if (__FreeBSD_version > 400000)
    175 		if ((error = suser(p)) != 0)
    176 			return (error);
    177 #else
    178 		if ((error = kauth_authorize_generic(p->p_cred,
    179 		    KAUTH_GENERIC_ISSUSER, &p->p_acflag)) != 0)
    180 			return (error);
    181 #endif
    182 		break;
    183 	}
    184 
    185 	switch (cmd) {
    186 
    187 	case BLUE_ENABLE:
    188 		ifacep = (struct blue_interface *)addr;
    189 		if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
    190 			error = EBADF;
    191 			break;
    192 		}
    193 		error = altq_enable(rqp->rq_ifq);
    194 		break;
    195 
    196 	case BLUE_DISABLE:
    197 		ifacep = (struct blue_interface *)addr;
    198 		if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
    199 			error = EBADF;
    200 			break;
    201 		}
    202 		error = altq_disable(rqp->rq_ifq);
    203 		break;
    204 
    205 	case BLUE_IF_ATTACH:
    206 		ifp = ifunit(((struct blue_interface *)addr)->blue_ifname);
    207 		if (ifp == NULL) {
    208 			error = ENXIO;
    209 			break;
    210 		}
    211 
    212 		/* allocate and initialize blue_state_t */
    213 		rqp = malloc(sizeof(blue_queue_t), M_DEVBUF, M_WAITOK|M_ZERO);
    214 		if (rqp == NULL) {
    215 			error = ENOMEM;
    216 			break;
    217 		}
    218 
    219 		rqp->rq_q = malloc(sizeof(class_queue_t), M_DEVBUF,
    220 		    M_WAITOK|M_ZERO);
    221 		if (rqp->rq_q == NULL) {
    222 			free(rqp, M_DEVBUF);
    223 			error = ENOMEM;
    224 			break;
    225 		}
    226 
    227 		rqp->rq_blue = malloc(sizeof(blue_t), M_DEVBUF,
    228 		    M_WAITOK|M_ZERO);
    229 		if (rqp->rq_blue == NULL) {
    230 			free(rqp->rq_q, M_DEVBUF);
    231 			free(rqp, M_DEVBUF);
    232 			error = ENOMEM;
    233 			break;
    234 		}
    235 
    236 		rqp->rq_ifq = &ifp->if_snd;
    237 		qtail(rqp->rq_q) = NULL;
    238 		qlen(rqp->rq_q) = 0;
    239 		qlimit(rqp->rq_q) = BLUE_LIMIT;
    240 
    241 		/* default packet time: 1000 bytes / 10Mbps * 8 * 1000000 */
    242 		blue_init(rqp->rq_blue, 0, 800, 1000, 50000);
    243 
    244 		/*
    245 		 * set BLUE to this ifnet structure.
    246 		 */
    247 		error = altq_attach(rqp->rq_ifq, ALTQT_BLUE, rqp,
    248 				    blue_enqueue, blue_dequeue, blue_request,
    249 				    NULL, NULL);
    250 		if (error) {
    251 			free(rqp->rq_blue, M_DEVBUF);
    252 			free(rqp->rq_q, M_DEVBUF);
    253 			free(rqp, M_DEVBUF);
    254 			break;
    255 		}
    256 
    257 		/* add this state to the blue list */
    258 		rqp->rq_next = blue_list;
    259 		blue_list = rqp;
    260 		break;
    261 
    262 	case BLUE_IF_DETACH:
    263 		ifacep = (struct blue_interface *)addr;
    264 		if ((rqp = altq_lookup(ifacep->blue_ifname, ALTQT_BLUE)) == NULL) {
    265 			error = EBADF;
    266 			break;
    267 		}
    268 		error = blue_detach(rqp);
    269 		break;
    270 
    271 	case BLUE_GETSTATS:
    272 		do {
    273 			struct blue_stats *q_stats;
    274 			blue_t *rp;
    275 
    276 			q_stats = (struct blue_stats *)addr;
    277 			if ((rqp = altq_lookup(q_stats->iface.blue_ifname,
    278 					     ALTQT_BLUE)) == NULL) {
    279 				error = EBADF;
    280 				break;
    281 			}
    282 
    283 			q_stats->q_len 	   = qlen(rqp->rq_q);
    284 			q_stats->q_limit   = qlimit(rqp->rq_q);
    285 
    286 			rp = rqp->rq_blue;
    287 			q_stats->q_pmark = rp->blue_pmark;
    288 			q_stats->xmit_packets  = rp->blue_stats.xmit_packets;
    289 			q_stats->xmit_bytes    = rp->blue_stats.xmit_bytes;
    290 			q_stats->drop_packets  = rp->blue_stats.drop_packets;
    291 			q_stats->drop_bytes    = rp->blue_stats.drop_bytes;
    292 			q_stats->drop_forced   = rp->blue_stats.drop_forced;
    293 			q_stats->drop_unforced = rp->blue_stats.drop_unforced;
    294 			q_stats->marked_packets = rp->blue_stats.marked_packets;
    295 
    296 		} while (/*CONSTCOND*/ 0);
    297 		break;
    298 
    299 	case BLUE_CONFIG:
    300 		do {
    301 			struct blue_conf *fc;
    302 			int limit;
    303 
    304 			fc = (struct blue_conf *)addr;
    305 			if ((rqp = altq_lookup(fc->iface.blue_ifname,
    306 					       ALTQT_BLUE)) == NULL) {
    307 				error = EBADF;
    308 				break;
    309 			}
    310 			limit = fc->blue_limit;
    311 			qlimit(rqp->rq_q) = limit;
    312 			fc->blue_limit = limit;	/* write back the new value */
    313 			if (fc->blue_pkttime > 0)
    314 				rqp->rq_blue->blue_pkttime = fc->blue_pkttime;
    315 			if (fc->blue_max_pmark > 0)
    316 				rqp->rq_blue->blue_max_pmark = fc->blue_max_pmark;
    317 			if (fc->blue_hold_time > 0)
    318 				rqp->rq_blue->blue_hold_time = fc->blue_hold_time;
    319 			rqp->rq_blue->blue_flags = fc->blue_flags;
    320 
    321 			blue_init(rqp->rq_blue, rqp->rq_blue->blue_flags,
    322 				  rqp->rq_blue->blue_pkttime,
    323 				  rqp->rq_blue->blue_max_pmark,
    324 				  rqp->rq_blue->blue_hold_time);
    325 		} while (/*CONSTCOND*/ 0);
    326 		break;
    327 
    328 	default:
    329 		error = EINVAL;
    330 		break;
    331 	}
    332 	return error;
    333 }
    334 
    335 static int blue_detach(rqp)
    336 	blue_queue_t *rqp;
    337 {
    338 	blue_queue_t *tmp;
    339 	int error = 0;
    340 
    341 	if (ALTQ_IS_ENABLED(rqp->rq_ifq))
    342 		altq_disable(rqp->rq_ifq);
    343 
    344 	if ((error = altq_detach(rqp->rq_ifq)))
    345 		return (error);
    346 
    347 	if (blue_list == rqp)
    348 		blue_list = rqp->rq_next;
    349 	else {
    350 		for (tmp = blue_list; tmp != NULL; tmp = tmp->rq_next)
    351 			if (tmp->rq_next == rqp) {
    352 				tmp->rq_next = rqp->rq_next;
    353 				break;
    354 			}
    355 		if (tmp == NULL)
    356 			printf("blue_detach: no state found in blue_list!\n");
    357 	}
    358 
    359 	free(rqp->rq_q, M_DEVBUF);
    360 	free(rqp->rq_blue, M_DEVBUF);
    361 	free(rqp, M_DEVBUF);
    362 	return (error);
    363 }
    364 
    365 /*
    366  * blue support routines
    367  */
    368 
    369 int
    370 blue_init(rp, flags, pkttime, blue_max_pmark, blue_hold_time)
    371 	blue_t 	*rp;
    372 	int	flags;
    373 	int	pkttime;
    374 	int	blue_max_pmark;
    375 	int	blue_hold_time;
    376 {
    377 	int npkts_per_sec;
    378 
    379 	rp->blue_idle = 1;
    380 	rp->blue_flags = flags;
    381 	rp->blue_pkttime = pkttime;
    382 	rp->blue_max_pmark = blue_max_pmark;
    383 	rp->blue_hold_time = blue_hold_time;
    384 	if (pkttime == 0)
    385 		rp->blue_pkttime = 1;
    386 
    387 	/* when the link is very slow, adjust blue parameters */
    388 	npkts_per_sec = 1000000 / rp->blue_pkttime;
    389 	if (npkts_per_sec < 50) {
    390 	}
    391 	else if (npkts_per_sec < 300) {
    392 	}
    393 
    394 	microtime(&rp->blue_last);
    395 	return (0);
    396 }
    397 
    398 /*
    399  * enqueue routine:
    400  *
    401  *	returns: 0 when successfully queued.
    402  *		 ENOBUFS when drop occurs.
    403  */
    404 static int
    405 blue_enqueue(ifq, m, pktattr)
    406 	struct ifaltq *ifq;
    407 	struct mbuf *m;
    408 	struct altq_pktattr *pktattr;
    409 {
    410 	blue_queue_t *rqp = (blue_queue_t *)ifq->altq_disc;
    411 	int error = 0;
    412 
    413 	if (blue_addq(rqp->rq_blue, rqp->rq_q, m, pktattr) == 0)
    414 		ifq->ifq_len++;
    415 	else
    416 		error = ENOBUFS;
    417 	return error;
    418 }
    419 
    420 #define	DTYPE_NODROP	0	/* no drop */
    421 #define	DTYPE_FORCED	1	/* a "forced" drop */
    422 #define	DTYPE_EARLY	2	/* an "unforced" (early) drop */
    423 
    424 int
    425 blue_addq(rp, q, m, pktattr)
    426 	blue_t *rp;
    427 	class_queue_t *q;
    428 	struct mbuf *m;
    429 	struct altq_pktattr *pktattr;
    430 {
    431 	int droptype;
    432 
    433 	/*
    434 	 * if we were idle, this is an enqueue onto an empty queue
    435 	 * and we should decrement marking probability
    436 	 *
    437 	 */
    438 	if (rp->blue_idle) {
    439 		struct timeval now;
    440 		int t;
    441 		rp->blue_idle = 0;
    442 		microtime(&now);
    443 		t = (now.tv_sec - rp->blue_last.tv_sec);
    444 		if ( t > 1) {
    445 			rp->blue_pmark = 1;
    446 			microtime(&rp->blue_last);
    447 		} else {
    448 			t = t * 1000000 + (now.tv_usec - rp->blue_last.tv_usec);
    449 			if (t > rp->blue_hold_time) {
    450 				rp->blue_pmark--;
    451 				if (rp->blue_pmark < 0) rp->blue_pmark = 0;
    452 				microtime(&rp->blue_last);
    453 			}
    454 		}
    455 	}
    456 
    457 	/* see if we drop early */
    458 	droptype = DTYPE_NODROP;
    459 	if (drop_early(rp) && qlen(q) > 1) {
    460 		/* mark or drop by blue */
    461 		if ((rp->blue_flags & BLUEF_ECN) &&
    462 		    mark_ecn(m, pktattr, rp->blue_flags)) {
    463 			/* successfully marked.  do not drop. */
    464 #ifdef BLUE_STATS
    465 			rp->blue_stats.marked_packets++;
    466 #endif
    467 		} else {
    468 			/* unforced drop by blue */
    469 			droptype = DTYPE_EARLY;
    470 		}
    471 	}
    472 
    473 	/*
    474 	 * if the queue length hits the hard limit, it's a forced drop.
    475 	 */
    476 	if (droptype == DTYPE_NODROP && qlen(q) >= qlimit(q))
    477 		droptype = DTYPE_FORCED;
    478 
    479 	/* if successful or forced drop, enqueue this packet. */
    480 	if (droptype != DTYPE_EARLY)
    481 		_addq(q, m);
    482 
    483 	if (droptype != DTYPE_NODROP) {
    484 		if (droptype == DTYPE_EARLY) {
    485 			/* drop the incoming packet */
    486 #ifdef BLUE_STATS
    487 			rp->blue_stats.drop_unforced++;
    488 #endif
    489 		} else {
    490 			struct timeval now;
    491 			int t;
    492 			/* forced drop, select a victim packet in the queue. */
    493 			m = _getq_random(q);
    494 			microtime(&now);
    495 			t = (now.tv_sec - rp->blue_last.tv_sec);
    496 			t = t * 1000000 + (now.tv_usec - rp->blue_last.tv_usec);
    497 			if (t > rp->blue_hold_time) {
    498 				rp->blue_pmark += rp->blue_max_pmark >> 3;
    499 				if (rp->blue_pmark > rp->blue_max_pmark)
    500 					rp->blue_pmark = rp->blue_max_pmark;
    501 				microtime(&rp->blue_last);
    502 			}
    503 #ifdef BLUE_STATS
    504 			rp->blue_stats.drop_forced++;
    505 #endif
    506 		}
    507 #ifdef BLUE_STATS
    508 		rp->blue_stats.drop_packets++;
    509 		rp->blue_stats.drop_bytes += m->m_pkthdr.len;
    510 #endif
    511 		m_freem(m);
    512 		return (-1);
    513 	}
    514 	/* successfully queued */
    515 	return (0);
    516 }
    517 
    518 /*
    519  * early-drop probability is kept in blue_pmark
    520  *
    521  */
    522 static int
    523 drop_early(rp)
    524 	blue_t *rp;
    525 {
    526 	if ((arc4random() % rp->blue_max_pmark) < rp->blue_pmark) {
    527 		/* drop or mark */
    528 		return (1);
    529 	}
    530 	/* no drop/mark */
    531 	return (0);
    532 }
    533 
    534 /*
    535  * try to mark CE bit to the packet.
    536  *    returns 1 if successfully marked, 0 otherwise.
    537  */
    538 static int
    539 mark_ecn(m, pktattr, flags)
    540 	struct mbuf *m;
    541 	struct altq_pktattr *pktattr;
    542 	int flags;
    543 {
    544 	struct mbuf *m0;
    545 
    546 	if (pktattr == NULL ||
    547 	    (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6))
    548 		return (0);
    549 
    550 	/* verify that pattr_hdr is within the mbuf data */
    551 	for (m0 = m; m0 != NULL; m0 = m0->m_next)
    552 		if ((pktattr->pattr_hdr >= m0->m_data) &&
    553 		    (pktattr->pattr_hdr < m0->m_data + m0->m_len))
    554 			break;
    555 	if (m0 == NULL) {
    556 		/* ick, pattr_hdr is stale */
    557 		pktattr->pattr_af = AF_UNSPEC;
    558 		return (0);
    559 	}
    560 
    561 	switch (pktattr->pattr_af) {
    562 	case AF_INET:
    563 		if (flags & BLUEF_ECN4) {
    564 			struct ip *ip = (struct ip *)pktattr->pattr_hdr;
    565 			u_int8_t otos;
    566 			int sum;
    567 
    568 			if (ip->ip_v != 4)
    569 				return (0);	/* version mismatch! */
    570 			if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT)
    571 				return (0);	/* not-ECT */
    572 			if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
    573 				return (1);	/* already marked */
    574 
    575 			/*
    576 			 * ecn-capable but not marked,
    577 			 * mark CE and update checksum
    578 			 */
    579 			otos = ip->ip_tos;
    580 			ip->ip_tos |= IPTOS_ECN_CE;
    581 			/*
    582 			 * update checksum (from RFC1624)
    583 			 *	   HC' = ~(~HC + ~m + m')
    584 			 */
    585 			sum = ~ntohs(ip->ip_sum) & 0xffff;
    586 			sum += (~otos & 0xffff) + ip->ip_tos;
    587 			sum = (sum >> 16) + (sum & 0xffff);
    588 			sum += (sum >> 16);  /* add carry */
    589 			ip->ip_sum = htons(~sum & 0xffff);
    590 			return (1);
    591 		}
    592 		break;
    593 #ifdef INET6
    594 	case AF_INET6:
    595 		if (flags & BLUEF_ECN6) {
    596 			struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
    597 			u_int32_t flowlabel;
    598 
    599 			flowlabel = ntohl(ip6->ip6_flow);
    600 			if ((flowlabel >> 28) != 6)
    601 				return (0);	/* version mismatch! */
    602 			if ((flowlabel & (IPTOS_ECN_MASK << 20)) ==
    603 			    (IPTOS_ECN_NOTECT << 20))
    604 				return (0);	/* not-ECT */
    605 			if ((flowlabel & (IPTOS_ECN_MASK << 20)) ==
    606 			    (IPTOS_ECN_CE << 20))
    607 				return (1);	/* already marked */
    608 			/*
    609 			 * ecn-capable but not marked,  mark CE
    610 			 */
    611 			flowlabel |= (IPTOS_ECN_CE << 20);
    612 			ip6->ip6_flow = htonl(flowlabel);
    613 			return (1);
    614 		}
    615 		break;
    616 #endif  /* INET6 */
    617 	}
    618 
    619 	/* not marked */
    620 	return (0);
    621 }
    622 
    623 /*
    624  * dequeue routine:
    625  *	must be called in splnet.
    626  *
    627  *	returns: mbuf dequeued.
    628  *		 NULL when no packet is available in the queue.
    629  */
    630 
    631 static struct mbuf *
    632 blue_dequeue(ifq, op)
    633 	struct ifaltq *ifq;
    634 	int op;
    635 {
    636 	blue_queue_t *rqp = (blue_queue_t *)ifq->altq_disc;
    637 	struct mbuf *m = NULL;
    638 
    639 	if (op == ALTDQ_POLL)
    640 		return (qhead(rqp->rq_q));
    641 
    642 	m = blue_getq(rqp->rq_blue, rqp->rq_q);
    643 	if (m != NULL)
    644 		ifq->ifq_len--;
    645 	return m;
    646 }
    647 
    648 struct mbuf *blue_getq(rp, q)
    649 	blue_t *rp;
    650 	class_queue_t *q;
    651 {
    652 	struct mbuf *m;
    653 
    654 	if ((m = _getq(q)) == NULL) {
    655 		if (rp->blue_idle == 0) {
    656 			rp->blue_idle = 1;
    657 			microtime(&rp->blue_last);
    658 		}
    659 		return NULL;
    660 	}
    661 
    662 	rp->blue_idle = 0;
    663 #ifdef BLUE_STATS
    664 	rp->blue_stats.xmit_packets++;
    665 	rp->blue_stats.xmit_bytes += m->m_pkthdr.len;
    666 #endif
    667 	return (m);
    668 }
    669 
    670 static int
    671 blue_request(ifq, req, arg)
    672 	struct ifaltq *ifq;
    673 	int req;
    674 	void *arg;
    675 {
    676 	blue_queue_t *rqp = (blue_queue_t *)ifq->altq_disc;
    677 
    678 	switch (req) {
    679 	case ALTRQ_PURGE:
    680 		_flushq(rqp->rq_q);
    681 		if (ALTQ_IS_ENABLED(ifq))
    682 			ifq->ifq_len = 0;
    683 		break;
    684 	}
    685 	return (0);
    686 }
    687 
    688 
    689 #ifdef KLD_MODULE
    690 
    691 static struct altqsw blue_sw =
    692 	{"blue", blueopen, blueclose, blueioctl};
    693 
    694 ALTQ_MODULE(altq_blue, ALTQT_BLUE, &blue_sw);
    695 
    696 #endif /* KLD_MODULE */
    697 
    698 #endif /* ALTQ3_COMPAT */
    699 #endif /* ALTQ_BLUE */
    700