1 /* $NetBSD: altq_priq.c,v 1.20 2008/06/18 09:06:27 yamt Exp $ */
2 /* $KAME: altq_priq.c,v 1.13 2005/04/13 03:44:25 suz Exp $ */
4 * Copyright (C) 2000-2003
5 * Sony Computer Science Laboratories Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: altq_priq.c,v 1.20 2008/06/18 09:06:27 yamt Exp $");
42 #ifdef ALTQ_PRIQ /* priq is enabled by ALTQ_PRIQ option in opt_altq.h */
44 #include <sys/param.h>
45 #include <sys/malloc.h>
47 #include <sys/socket.h>
48 #include <sys/sockio.h>
49 #include <sys/systm.h>
51 #include <sys/errno.h>
52 #include <sys/kernel.h>
53 #include <sys/queue.h>
54 #include <sys/kauth.h>
57 #include <netinet/in.h>
60 #include <net/pfvar.h>
62 #include <altq/altq.h>
63 #include <altq/altq_conf.h>
64 #include <altq/altq_priq.h>
70 static struct priq_if
*priq_attach(struct ifaltq
*, u_int
);
71 static int priq_detach(struct priq_if
*);
73 static int priq_clear_interface(struct priq_if
*);
74 static int priq_request(struct ifaltq
*, int, void *);
75 static void priq_purge(struct priq_if
*);
76 static struct priq_class
*priq_class_create(struct priq_if
*, int, int, int,
78 static int priq_class_destroy(struct priq_class
*);
79 static int priq_enqueue(struct ifaltq
*, struct mbuf
*, struct altq_pktattr
*);
80 static struct mbuf
*priq_dequeue(struct ifaltq
*, int);
82 static int priq_addq(struct priq_class
*, struct mbuf
*);
83 static struct mbuf
*priq_getq(struct priq_class
*);
84 static struct mbuf
*priq_pollq(struct priq_class
*);
85 static void priq_purgeq(struct priq_class
*);
88 static int priqcmd_if_attach(struct priq_interface
*);
89 static int priqcmd_if_detach(struct priq_interface
*);
90 static int priqcmd_add_class(struct priq_add_class
*);
91 static int priqcmd_delete_class(struct priq_delete_class
*);
92 static int priqcmd_modify_class(struct priq_modify_class
*);
93 static int priqcmd_add_filter(struct priq_add_filter
*);
94 static int priqcmd_delete_filter(struct priq_delete_filter
*);
95 static int priqcmd_class_stats(struct priq_class_stats
*);
96 #endif /* ALTQ3_COMPAT */
98 static void get_class_stats(struct priq_classstats
*, struct priq_class
*);
99 static struct priq_class
*clh_to_clp(struct priq_if
*, u_int32_t
);
104 /* pif_list keeps all priq_if's allocated. */
105 static struct priq_if
*pif_list
= NULL
;
106 #endif /* ALTQ3_COMPAT */
110 priq_pfattach(struct pf_altq
*a
)
115 if ((ifp
= ifunit(a
->ifname
)) == NULL
|| a
->altq_disc
== NULL
)
118 error
= altq_attach(&ifp
->if_snd
, ALTQT_PRIQ
, a
->altq_disc
,
119 priq_enqueue
, priq_dequeue
, priq_request
, NULL
, NULL
);
125 priq_add_altq(struct pf_altq
*a
)
130 if ((ifp
= ifunit(a
->ifname
)) == NULL
)
132 if (!ALTQ_IS_READY(&ifp
->if_snd
))
135 pif
= malloc(sizeof(struct priq_if
), M_DEVBUF
, M_WAITOK
|M_ZERO
);
138 pif
->pif_bandwidth
= a
->ifbandwidth
;
139 pif
->pif_maxpri
= -1;
140 pif
->pif_ifq
= &ifp
->if_snd
;
142 /* keep the state in pf_altq */
149 priq_remove_altq(struct pf_altq
*a
)
153 if ((pif
= a
->altq_disc
) == NULL
)
157 (void)priq_clear_interface(pif
);
164 priq_add_queue(struct pf_altq
*a
)
167 struct priq_class
*cl
;
169 if ((pif
= a
->altq_disc
) == NULL
)
172 /* check parameters */
173 if (a
->priority
>= PRIQ_MAXPRI
)
177 if (pif
->pif_classes
[a
->priority
] != NULL
)
179 if (clh_to_clp(pif
, a
->qid
) != NULL
)
182 cl
= priq_class_create(pif
, a
->priority
, a
->qlimit
,
183 a
->pq_u
.priq_opts
.flags
, a
->qid
);
191 priq_remove_queue(struct pf_altq
*a
)
194 struct priq_class
*cl
;
196 if ((pif
= a
->altq_disc
) == NULL
)
199 if ((cl
= clh_to_clp(pif
, a
->qid
)) == NULL
)
202 return (priq_class_destroy(cl
));
206 priq_getqstats(struct pf_altq
*a
, void *ubuf
, int *nbytes
)
209 struct priq_class
*cl
;
210 struct priq_classstats stats
;
213 if ((pif
= altq_lookup(a
->ifname
, ALTQT_PRIQ
)) == NULL
)
216 if ((cl
= clh_to_clp(pif
, a
->qid
)) == NULL
)
219 if (*nbytes
< sizeof(stats
))
222 get_class_stats(&stats
, cl
);
224 if ((error
= copyout((void *)&stats
, ubuf
, sizeof(stats
))) != 0)
226 *nbytes
= sizeof(stats
);
232 * bring the interface back to the initial state by discarding
233 * all the filters and classes.
236 priq_clear_interface(struct priq_if
*pif
)
238 struct priq_class
*cl
;
241 #ifdef ALTQ3_CLFIER_COMPAT
242 /* free the filters for this interface */
243 acc_discard_filters(&pif
->pif_classifier
, NULL
, 1);
246 /* clear out the classes */
247 for (pri
= 0; pri
<= pif
->pif_maxpri
; pri
++)
248 if ((cl
= pif
->pif_classes
[pri
]) != NULL
)
249 priq_class_destroy(cl
);
255 priq_request(struct ifaltq
*ifq
, int req
, void *arg
)
257 struct priq_if
*pif
= (struct priq_if
*)ifq
->altq_disc
;
267 /* discard all the queued packets on the interface */
269 priq_purge(struct priq_if
*pif
)
271 struct priq_class
*cl
;
274 for (pri
= 0; pri
<= pif
->pif_maxpri
; pri
++) {
275 if ((cl
= pif
->pif_classes
[pri
]) != NULL
&& !qempty(cl
->cl_q
))
278 if (ALTQ_IS_ENABLED(pif
->pif_ifq
))
279 pif
->pif_ifq
->ifq_len
= 0;
282 static struct priq_class
*
283 priq_class_create(struct priq_if
*pif
, int pri
, int qlimit
, int flags
, int qid
)
285 struct priq_class
*cl
;
289 if (flags
& PRCF_RED
) {
291 printf("priq_class_create: RED not configured for PRIQ!\n");
297 if ((cl
= pif
->pif_classes
[pri
]) != NULL
) {
298 /* modify the class instead of creating a new one */
300 if (!qempty(cl
->cl_q
))
304 if (q_is_rio(cl
->cl_q
))
305 rio_destroy((rio_t
*)cl
->cl_red
);
308 if (q_is_red(cl
->cl_q
))
309 red_destroy(cl
->cl_red
);
312 cl
= malloc(sizeof(struct priq_class
), M_DEVBUF
,
317 cl
->cl_q
= malloc(sizeof(class_queue_t
), M_DEVBUF
,
319 if (cl
->cl_q
== NULL
)
323 pif
->pif_classes
[pri
] = cl
;
324 if (flags
& PRCF_DEFAULTCLASS
)
325 pif
->pif_default
= cl
;
327 qlimit
= 50; /* use default */
328 qlimit(cl
->cl_q
) = qlimit
;
329 qtype(cl
->cl_q
) = Q_DROPTAIL
;
331 cl
->cl_flags
= flags
;
333 if (pri
> pif
->pif_maxpri
)
334 pif
->pif_maxpri
= pri
;
339 if (flags
& (PRCF_RED
|PRCF_RIO
)) {
340 int red_flags
, red_pkttime
;
343 if (flags
& PRCF_ECN
)
344 red_flags
|= REDF_ECN
;
346 if (flags
& PRCF_CLEARDSCP
)
347 red_flags
|= RIOF_CLEARDSCP
;
349 if (pif
->pif_bandwidth
< 8)
350 red_pkttime
= 1000 * 1000 * 1000; /* 1 sec */
352 red_pkttime
= (int64_t)pif
->pif_ifq
->altq_ifp
->if_mtu
353 * 1000 * 1000 * 1000 / (pif
->pif_bandwidth
/ 8);
355 if (flags
& PRCF_RIO
) {
356 cl
->cl_red
= (red_t
*)rio_alloc(0, NULL
,
357 red_flags
, red_pkttime
);
358 if (cl
->cl_red
!= NULL
)
359 qtype(cl
->cl_q
) = Q_RIO
;
362 if (flags
& PRCF_RED
) {
363 cl
->cl_red
= red_alloc(0, 0,
364 qlimit(cl
->cl_q
) * 10/100,
365 qlimit(cl
->cl_q
) * 30/100,
366 red_flags
, red_pkttime
);
367 if (cl
->cl_red
!= NULL
)
368 qtype(cl
->cl_q
) = Q_RED
;
371 #endif /* ALTQ_RED */
376 if (cl
->cl_red
!= NULL
) {
378 if (q_is_rio(cl
->cl_q
))
379 rio_destroy((rio_t
*)cl
->cl_red
);
382 if (q_is_red(cl
->cl_q
))
383 red_destroy(cl
->cl_red
);
386 if (cl
->cl_q
!= NULL
)
387 free(cl
->cl_q
, M_DEVBUF
);
393 priq_class_destroy(struct priq_class
*cl
)
400 #ifdef ALTQ3_CLFIER_COMPAT
401 /* delete filters referencing to this class */
402 acc_discard_filters(&cl
->cl_pif
->pif_classifier
, cl
, 0);
405 if (!qempty(cl
->cl_q
))
409 pif
->pif_classes
[cl
->cl_pri
] = NULL
;
410 if (pif
->pif_maxpri
== cl
->cl_pri
) {
411 for (pri
= cl
->cl_pri
; pri
>= 0; pri
--)
412 if (pif
->pif_classes
[pri
] != NULL
) {
413 pif
->pif_maxpri
= pri
;
417 pif
->pif_maxpri
= -1;
421 if (cl
->cl_red
!= NULL
) {
423 if (q_is_rio(cl
->cl_q
))
424 rio_destroy((rio_t
*)cl
->cl_red
);
427 if (q_is_red(cl
->cl_q
))
428 red_destroy(cl
->cl_red
);
431 free(cl
->cl_q
, M_DEVBUF
);
437 * priq_enqueue is an enqueue function to be registered to
438 * (*altq_enqueue) in struct ifaltq.
441 priq_enqueue(struct ifaltq
*ifq
, struct mbuf
*m
, struct altq_pktattr
*pktattr
)
443 struct priq_if
*pif
= (struct priq_if
*)ifq
->altq_disc
;
444 struct priq_class
*cl
;
448 /* grab class set by classifier */
449 if ((m
->m_flags
& M_PKTHDR
) == 0) {
450 /* should not happen */
451 printf("altq: packet for %s does not have pkthdr\n",
452 ifq
->altq_ifp
->if_xname
);
457 if ((t
= m_tag_find(m
, PACKET_TAG_ALTQ_QID
, NULL
)) != NULL
)
458 cl
= clh_to_clp(pif
, ((struct altq_tag
*)(t
+1))->qid
);
460 else if ((ifq
->altq_flags
& ALTQF_CLASSIFY
) && pktattr
!= NULL
)
461 cl
= pktattr
->pattr_class
;
464 cl
= pif
->pif_default
;
472 cl
->cl_pktattr
= pktattr
; /* save proto hdr used by ECN */
475 cl
->cl_pktattr
= NULL
;
477 if (priq_addq(cl
, m
) != 0) {
478 /* drop occurred. mbuf was freed in priq_addq. */
479 PKTCNTR_ADD(&cl
->cl_dropcnt
, len
);
484 /* successfully queued. */
489 * priq_dequeue is a dequeue function to be registered to
490 * (*altq_dequeue) in struct ifaltq.
492 * note: ALTDQ_POLL returns the next packet without removing the packet
493 * from the queue. ALTDQ_REMOVE is a normal dequeue operation.
494 * ALTDQ_REMOVE must return the same packet if called immediately
498 priq_dequeue(struct ifaltq
*ifq
, int op
)
500 struct priq_if
*pif
= (struct priq_if
*)ifq
->altq_disc
;
501 struct priq_class
*cl
;
505 if (IFQ_IS_EMPTY(ifq
))
506 /* no packet in the queue */
509 for (pri
= pif
->pif_maxpri
; pri
>= 0; pri
--) {
510 if ((cl
= pif
->pif_classes
[pri
]) != NULL
&&
512 if (op
== ALTDQ_POLL
)
513 return (priq_pollq(cl
));
518 if (qempty(cl
->cl_q
))
520 PKTCNTR_ADD(&cl
->cl_xmitcnt
, m_pktlen(m
));
529 priq_addq(struct priq_class
*cl
, struct mbuf
*m
)
533 if (q_is_rio(cl
->cl_q
))
534 return rio_addq((rio_t
*)cl
->cl_red
, cl
->cl_q
, m
,
538 if (q_is_red(cl
->cl_q
))
539 return red_addq(cl
->cl_red
, cl
->cl_q
, m
, cl
->cl_pktattr
);
541 if (qlen(cl
->cl_q
) >= qlimit(cl
->cl_q
)) {
546 if (cl
->cl_flags
& PRCF_CLEARDSCP
)
547 write_dsfield(m
, cl
->cl_pktattr
, 0);
555 priq_getq(struct priq_class
*cl
)
558 if (q_is_rio(cl
->cl_q
))
559 return rio_getq((rio_t
*)cl
->cl_red
, cl
->cl_q
);
562 if (q_is_red(cl
->cl_q
))
563 return red_getq(cl
->cl_red
, cl
->cl_q
);
565 return _getq(cl
->cl_q
);
569 priq_pollq(struct priq_class
*cl
)
571 return qhead(cl
->cl_q
);
575 priq_purgeq(struct priq_class
*cl
)
579 if (qempty(cl
->cl_q
))
582 while ((m
= _getq(cl
->cl_q
)) != NULL
) {
583 PKTCNTR_ADD(&cl
->cl_dropcnt
, m_pktlen(m
));
586 ASSERT(qlen(cl
->cl_q
) == 0);
590 get_class_stats(struct priq_classstats
*sp
, struct priq_class
*cl
)
592 sp
->class_handle
= cl
->cl_handle
;
593 sp
->qlength
= qlen(cl
->cl_q
);
594 sp
->qlimit
= qlimit(cl
->cl_q
);
595 sp
->period
= cl
->cl_period
;
596 sp
->xmitcnt
= cl
->cl_xmitcnt
;
597 sp
->dropcnt
= cl
->cl_dropcnt
;
599 sp
->qtype
= qtype(cl
->cl_q
);
601 if (q_is_red(cl
->cl_q
))
602 red_getstats(cl
->cl_red
, &sp
->red
[0]);
605 if (q_is_rio(cl
->cl_q
))
606 rio_getstats((rio_t
*)cl
->cl_red
, &sp
->red
[0]);
611 /* convert a class handle to the corresponding class pointer */
612 static struct priq_class
*
613 clh_to_clp(struct priq_if
*pif
, u_int32_t chandle
)
615 struct priq_class
*cl
;
621 for (idx
= pif
->pif_maxpri
; idx
>= 0; idx
--)
622 if ((cl
= pif
->pif_classes
[idx
]) != NULL
&&
623 cl
->cl_handle
== chandle
)
632 static struct priq_if
*
633 priq_attach(struct ifaltq
*ifq
, u_int bandwidth
)
637 pif
= malloc(sizeof(struct priq_if
), M_DEVBUF
, M_WAITOK
|M_ZERO
);
640 pif
->pif_bandwidth
= bandwidth
;
641 pif
->pif_maxpri
= -1;
644 /* add this state to the priq list */
645 pif
->pif_next
= pif_list
;
652 priq_detach(struct priq_if
*pif
)
654 (void)priq_clear_interface(pif
);
656 /* remove this interface from the pif list */
658 pif_list
= pif
->pif_next
;
662 for (p
= pif_list
; p
!= NULL
; p
= p
->pif_next
)
663 if (p
->pif_next
== pif
) {
664 p
->pif_next
= pif
->pif_next
;
675 * priq device interface
678 priqopen(dev_t dev
, int flag
, int fmt
,
681 /* everything will be done when the queueing scheme is attached. */
686 priqclose(dev_t dev
, int flag
, int fmt
,
692 while ((pif
= pif_list
) != NULL
) {
694 if (ALTQ_IS_ENABLED(pif
->pif_ifq
))
695 altq_disable(pif
->pif_ifq
);
697 err
= altq_detach(pif
->pif_ifq
);
699 err
= priq_detach(pif
);
700 if (err
!= 0 && error
== 0)
708 priqioctl(dev_t dev
, ioctlcmd_t cmd
, void *addr
, int flag
,
712 struct priq_interface
*ifacep
;
715 /* check super-user privilege */
720 #if (__FreeBSD_version > 400000)
721 if ((error
= suser(p
)) != 0)
724 if ((error
= kauth_authorize_network(l
->l_cred
,
725 KAUTH_NETWORK_ALTQ
, KAUTH_REQ_NETWORK_ALTQ_PRIQ
, NULL
,
735 error
= priqcmd_if_attach((struct priq_interface
*)addr
);
739 error
= priqcmd_if_detach((struct priq_interface
*)addr
);
745 ifacep
= (struct priq_interface
*)addr
;
746 if ((pif
= altq_lookup(ifacep
->ifname
,
747 ALTQT_PRIQ
)) == NULL
) {
754 if (pif
->pif_default
== NULL
) {
756 printf("priq: no default class\n");
761 error
= altq_enable(pif
->pif_ifq
);
765 error
= altq_disable(pif
->pif_ifq
);
769 priq_clear_interface(pif
);
775 error
= priqcmd_add_class((struct priq_add_class
*)addr
);
779 error
= priqcmd_delete_class((struct priq_delete_class
*)addr
);
783 error
= priqcmd_modify_class((struct priq_modify_class
*)addr
);
786 case PRIQ_ADD_FILTER
:
787 error
= priqcmd_add_filter((struct priq_add_filter
*)addr
);
790 case PRIQ_DEL_FILTER
:
791 error
= priqcmd_delete_filter((struct priq_delete_filter
*)addr
);
795 error
= priqcmd_class_stats((struct priq_class_stats
*)addr
);
806 priqcmd_if_attach(struct priq_interface
*ap
)
812 if ((ifp
= ifunit(ap
->ifname
)) == NULL
)
815 if ((pif
= priq_attach(&ifp
->if_snd
, ap
->arg
)) == NULL
)
819 * set PRIQ to this ifnet structure.
821 if ((error
= altq_attach(&ifp
->if_snd
, ALTQT_PRIQ
, pif
,
822 priq_enqueue
, priq_dequeue
, priq_request
,
823 &pif
->pif_classifier
, acc_classify
)) != 0)
824 (void)priq_detach(pif
);
830 priqcmd_if_detach(struct priq_interface
*ap
)
835 if ((pif
= altq_lookup(ap
->ifname
, ALTQT_PRIQ
)) == NULL
)
838 if (ALTQ_IS_ENABLED(pif
->pif_ifq
))
839 altq_disable(pif
->pif_ifq
);
841 if ((error
= altq_detach(pif
->pif_ifq
)))
844 return priq_detach(pif
);
848 priqcmd_add_class(struct priq_add_class
*ap
)
851 struct priq_class
*cl
;
854 if ((pif
= altq_lookup(ap
->iface
.ifname
, ALTQT_PRIQ
)) == NULL
)
857 if (ap
->pri
< 0 || ap
->pri
>= PRIQ_MAXPRI
)
859 if (pif
->pif_classes
[ap
->pri
] != NULL
)
863 if ((cl
= priq_class_create(pif
, ap
->pri
,
864 ap
->qlimit
, ap
->flags
, qid
)) == NULL
)
867 /* return a class handle to the user */
868 ap
->class_handle
= cl
->cl_handle
;
874 priqcmd_delete_class(struct priq_delete_class
*ap
)
877 struct priq_class
*cl
;
879 if ((pif
= altq_lookup(ap
->iface
.ifname
, ALTQT_PRIQ
)) == NULL
)
882 if ((cl
= clh_to_clp(pif
, ap
->class_handle
)) == NULL
)
885 return priq_class_destroy(cl
);
889 priqcmd_modify_class(struct priq_modify_class
*ap
)
892 struct priq_class
*cl
;
894 if ((pif
= altq_lookup(ap
->iface
.ifname
, ALTQT_PRIQ
)) == NULL
)
897 if (ap
->pri
< 0 || ap
->pri
>= PRIQ_MAXPRI
)
900 if ((cl
= clh_to_clp(pif
, ap
->class_handle
)) == NULL
)
904 * if priority is changed, move the class to the new priority
906 if (pif
->pif_classes
[ap
->pri
] != cl
) {
907 if (pif
->pif_classes
[ap
->pri
] != NULL
)
909 pif
->pif_classes
[cl
->cl_pri
] = NULL
;
910 pif
->pif_classes
[ap
->pri
] = cl
;
911 cl
->cl_pri
= ap
->pri
;
914 /* call priq_class_create to change class parameters */
915 if ((cl
= priq_class_create(pif
, ap
->pri
,
916 ap
->qlimit
, ap
->flags
, ap
->class_handle
)) == NULL
)
922 priqcmd_add_filter(struct priq_add_filter
*ap
)
925 struct priq_class
*cl
;
927 if ((pif
= altq_lookup(ap
->iface
.ifname
, ALTQT_PRIQ
)) == NULL
)
930 if ((cl
= clh_to_clp(pif
, ap
->class_handle
)) == NULL
)
933 return acc_add_filter(&pif
->pif_classifier
, &ap
->filter
,
934 cl
, &ap
->filter_handle
);
938 priqcmd_delete_filter(struct priq_delete_filter
*ap
)
942 if ((pif
= altq_lookup(ap
->iface
.ifname
, ALTQT_PRIQ
)) == NULL
)
945 return acc_delete_filter(&pif
->pif_classifier
,
950 priqcmd_class_stats(struct priq_class_stats
*ap
)
953 struct priq_class
*cl
;
954 struct priq_classstats stats
, *usp
;
957 if ((pif
= altq_lookup(ap
->iface
.ifname
, ALTQT_PRIQ
)) == NULL
)
960 ap
->maxpri
= pif
->pif_maxpri
;
962 /* then, read the next N classes in the tree */
964 for (pri
= 0; pri
<= pif
->pif_maxpri
; pri
++) {
965 cl
= pif
->pif_classes
[pri
];
967 get_class_stats(&stats
, cl
);
969 memset(&stats
, 0, sizeof(stats
));
970 if ((error
= copyout((void *)&stats
, (void *)usp
++,
971 sizeof(stats
))) != 0)
979 static struct altqsw priq_sw
=
980 {"priq", priqopen
, priqclose
, priqioctl
};
982 ALTQ_MODULE(altq_priq
, ALTQT_PRIQ
, &priq_sw
);
983 MODULE_DEPEND(altq_priq
, altq_red
, 1, 1, 1);
984 MODULE_DEPEND(altq_priq
, altq_rio
, 1, 1, 1);
986 #endif /* KLD_MODULE */
988 #endif /* ALTQ3_COMPAT */
989 #endif /* ALTQ_PRIQ */