1 .\" $NetBSD: altq.9,v 1.13 2006/10/14 07:31:41 wiz Exp $
2 .\" $OpenBSD: altq.9,v 1.4 2001/07/12 12:41:42 itojun Exp $
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
34 .Nd kernel interfaces for manipulating output queues on network interfaces
40 .Fn IFQ_ENQUEUE "struct ifaltq *ifq" "struct mbuf *m" "struct altq_pktattr *pattr" "int err"
42 .Fn IFQ_DEQUEUE "struct ifaltq *ifq" "struct mbuf *m"
44 .Fn IFQ_POLL "struct ifaltq *ifq" "struct mbuf *m"
46 .Fn IFQ_PURGE "struct ifaltq *ifq"
48 .Fn IFQ_CLASSIFY "struct ifaltq *ifq" "struct mbuf *m" "int af" "struct altq_pktattr *pattr"
50 .Fn IFQ_IS_EMPTY "struct ifaltq *ifq"
52 .Fn IFQ_SET_MAXLEN "struct ifaltq *ifq" "int len"
54 .Fn IFQ_INC_LEN "struct ifaltq *ifq"
56 .Fn IFQ_DEC_LEN "struct ifaltq *ifq"
58 .Fn IFQ_INC_DROPS "struct ifaltq *ifq"
60 .Fn IFQ_SET_READY "struct ifaltq *ifq"
64 system is a framework to manage queueing disciplines on network
67 introduces new macros to manipulate output queues.
68 The output queue macros are used to abstract queue operations and not to
69 touch the internal fields of the output queue structure.
70 The macros are independent from the
72 implementation, and compatible with the traditional
74 macros for ease of transition.
81 The underlying queueing discipline may discard the packet.
83 is set to 0 on success, or
85 if the packet is discarded.
87 will be freed by the device driver on success or by the queueing discipline on
88 failure, so that the caller should not touch
94 dequeues a packet from the queue.
95 The dequeued packet is returned in
101 if no packet is dequeued.
102 The caller must always check
104 since a non-empty queue could return
109 returns the next packet without removing it from the queue.
110 It is guaranteed by the underlying queueing discipline that
114 returns the same packet.
117 discards all the packets in the queue.
118 The purge operation is needed since a non-work conserving queue cannot be
119 emptied by a dequeue loop.
122 classifies a packet to a scheduling class, and returns the result in
126 can be used to check if the queue is empty.
131 if the queueing discipline is non-work conserving.
134 sets the queue length limit to the default FIFO queue.
139 increment or decrement the current queue length in packets.
142 increments the drop counter and is equal to
144 It is defined for naming consistency.
147 sets a flag to indicate this driver is converted to use the new macros.
149 can be enabled only on interfaces with this flag.
152 In order to keep compatibility with the existing code, the new
153 output queue structure
158 macros and the code directly referencing the fields within
162 (Once we finish conversions of all the drivers, we no longer need
165 ##old-style## ##new-style##
167 struct ifqueue { | struct ifaltq {
168 struct mbuf *ifq_head; | struct mbuf *ifq_head;
169 struct mbuf *ifq_tail; | struct mbuf *ifq_tail;
170 int ifq_len; | int ifq_len;
171 int ifq_maxlen; | int ifq_maxlen;
172 int ifq_drops; | int ifq_drops;
173 }; | /* altq related fields */
178 The new structure replaces
183 ##old-style## ##new-style##
185 struct ifnet { | struct ifnet {
188 struct ifqueue if_snd; | struct ifaltq if_snd;
199 #define IFQ_DEQUEUE(ifq, m) \e
200 if (ALTQ_IS_ENABLED((ifq)) \e
201 ALTQ_DEQUEUE((ifq), (m)); \e
203 IF_DEQUEUE((ifq), (m));
205 #define IFQ_DEQUEUE(ifq, m) IF_DEQUEUE((ifq), (m));
208 .Ss Enqueue operation
209 The semantics of the enqueue operation are changed.
211 enqueue and packet drop are combined since they cannot be easily
212 separated in many queueing disciplines.
213 The new enqueue operation corresponds to the following macro that is
214 written with the old macros.
216 #define IFQ_ENQUEUE(ifq, m, pattr, err) \e
218 if (ALTQ_IS_ENABLED((ifq))) \e
219 ALTQ_ENQUEUE((ifq), (m), (pattr), (err)); \e
221 if (IF_QFULL((ifq))) { \e
225 IF_ENQUEUE((ifq), (m)); \e
230 (ifq)-\*[Gt]ifq_drops++; \e
231 } while (/*CONSTCOND*/ 0)
240 drop (and free) a packet if the enqueue operation fails
242 If the enqueue operation fails,
247 is freed by the queueing discipline.
248 The caller should not touch mbuf after calling
250 so that the caller may need to copy
254 field beforehand for statistics.
255 The caller should not use
257 since mbuf was already freed.
263 ##old-style## ##new-style##
266 ether_output(ifp, m0, dst, rt0) | ether_output(ifp, m0, dst, rt0)
270 | mflags = m-\*[Gt]m_flags;
271 | len = m-\*[Gt]m_pkthdr.len;
272 s = splimp(); | s = splimp();
273 if (IF_QFULL(\*[Am]ifp-\*[Gt]if_snd)) { | IFQ_ENQUEUE(\*[Am]ifp-\*[Gt]if_snd, m,
275 IF_DROP(\*[Am]ifp-\*[Gt]if_snd); | if (error != 0) {
277 senderr(ENOBUFS); | return (error);
279 IF_ENQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); |
280 ifp-\*[Gt]if_obytes += | ifp-\*[Gt]if_obytes += len;
281 m-\*[Gt]m_pkthdr.len; |
282 if (m-\*[Gt]m_flags \*[Am] M_MCAST) | if (mflags \*[Am] M_MCAST)
283 ifp-\*[Gt]if_omcasts++; | ifp-\*[Gt]if_omcasts++;
285 if ((ifp-\*[Gt]if_flags \*[Am] IFF_OACTIVE) | if ((ifp-\*[Gt]if_flags \*[Am] IFF_OACTIVE)
287 (*ifp-\*[Gt]if_start)(ifp); | (*ifp-\*[Gt]if_start)(ifp);
289 return (error); | return (error);
293 m_freem(m); | m_freem(m);
294 return (error); | return (error);
299 The classifier mechanism is currently implemented in
301 .Dv struct altq_pktattr
302 is used to store the classifier result, and it is passed to the enqueue
304 (We will change the method to tag the classifier result to mbuf in the future.)
307 ether_output(ifp, m0, dst, rt0)
310 struct altq_pktattr pktattr;
314 /* classify the packet before prepending link-headers */
315 IFQ_CLASSIFY(\*[Am]ifp-\*[Gt]if_snd, m, dst-\*[Gt]sa_family, \*[Am]pktattr);
317 /* prepend link-level headers */
320 IFQ_ENQUEUE(\*[Am]ifp-\*[Gt]if_snd, m, \*[Am]pktattr, error);
325 .Sh HOW TO CONVERT THE EXISTING DRIVERS
326 First, make sure the corresponding
328 is already converted to the new style.
333 You will probably need to make changes to the lines that include
335 .Ss Empty check operation
338 to see whether the queue is empty or not, use
341 ##old-style## ##new-style##
343 if (ifp-\*[Gt]if_snd.ifq_head != NULL) | if (IFQ_IS_EMPTY(\*[Am]ifp-\*[Gt]if_snd) == 0)
348 can be used for the same purpose, but
350 could be costly for a complex scheduling algorithm since
352 needs to run the scheduling algorithm to select the next packet.
355 checks only if there is any packet stored in the queue.
356 Another difference is that even when
363 if the queue is under rate-limiting.
364 .Ss Dequeue operation
369 Always check whether the dequeued mbuf is
379 due to rate-limiting.
381 ##old-style## ##new-style##
383 IF_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); | IFQ_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m);
388 A driver is supposed to call
390 from transmission complete interrupts in order to trigger the next dequeue.
391 .Ss Poll-and-dequeue operation
392 If the code polls the packet at the head of the queue and actually uses
393 the packet before dequeueing it, use
398 ##old-style## ##new-style##
400 m = ifp-\*[Gt]if_snd.ifq_head; | IFQ_POLL(\*[Am]ifp-\*[Gt]if_snd, m);
401 if (m != NULL) { | if (m != NULL) {
403 /* use m to get resources */ | /* use m to get resources */
404 if (something goes wrong) | if (something goes wrong)
407 IF_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); | IFQ_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m);
409 /* kick the hardware */ | /* kick the hardware */
413 It is guaranteed that
417 returns the same packet.
418 Note that they need to be guarded by
420 if called from outside of
422 .Ss Eliminating IF_PREPEND
425 you have to eliminate it since the prepend operation is not possible for many
426 queueing disciplines.
429 is to cancel the previous dequeue operation.
430 You have to convert the logic into poll-and-dequeue.
432 ##old-style## ##new-style##
434 IF_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); | IFQ_POLL(\*[Am]ifp-\*[Gt]if_snd, m);
435 if (m != NULL) { | if (m != NULL) {
437 if (something_goes_wrong) { | if (something_goes_wrong) {
438 IF_PREPEND(\*[Am]ifp-\*[Gt]if_snd, m); |
442 | /* at this point, the driver
443 | * is committed to send this
446 | IFQ_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m);
448 /* kick the hardware */ | /* kick the hardware */
456 Note that a non-work conserving queue cannot be emptied by a dequeue loop.
458 ##old-style## ##new-style##
460 while (ifp-\*[Gt]if_snd.ifq_head != NULL) {| IFQ_PURGE(\*[Am]ifp-\*[Gt]if_snd);
461 IF_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); |
475 to show this driver is converted to the new style.
476 (This is used to distinguish new-style drivers.)
478 ##old-style## ##new-style##
480 ifp-\*[Gt]if_snd.ifq_maxlen = qsize; | IFQ_SET_MAXLEN(\*[Am]ifp-\*[Gt]if_snd, qsize);
481 | IFQ_SET_READY(\*[Am]ifp-\*[Gt]if_snd);
482 if_attach(ifp); | if_attach(ifp);
486 The new macros for statistics:
488 ##old-style## ##new-style##
490 IF_DROP(\*[Am]ifp-\*[Gt]if_snd); | IFQ_INC_DROPS(\*[Am]ifp-\*[Gt]if_snd);
492 ifp-\*[Gt]if_snd.ifq_len++; | IFQ_INC_LEN(\*[Am]ifp-\*[Gt]if_snd);
494 ifp-\*[Gt]if_snd.ifq_len--; | IFQ_DEC_LEN(\*[Am]ifp-\*[Gt]if_snd);
497 Some drivers instruct the hardware to invoke transmission complete
498 interrupts only when it thinks necessary.
499 Rate-limiting breaks its assumption.
500 .Ss How to convert drivers using multiple ifqueues
501 Some (pseudo) devices (such as slip) have another
503 to prioritize packets.
504 It is possible to eliminate the second queue
507 provides more flexible mechanisms but the following shows
508 how to keep the original behavior.
511 struct ifnet sc_if; /* network-visible interface */
513 struct ifqueue sc_fastq; /* interactive output queue */
517 The driver doesn't compile in the new model since it has the following
521 is no longer a type of
525 struct ifqueue *ifq = \*[Am]ifp-\*[Gt]if_snd;
527 A simple way is to use the original
535 The enqueue operation looks like:
537 ##old-style## ##new-style##
539 struct ifqueue *ifq = \*[Am]ifp-\*[Gt]if_snd; | struct ifqueue *ifq = NULL;
541 if (ip-\*[Gt]ip_tos \*[Am] IPTOS_LOWDELAY) | if ((ip-\*[Gt]ip_tos \*[Am] IPTOS_LOWDELAY) \*[Am]\*[Am]
542 ifq = \*[Am]sc-\*[Gt]sc_fastq; | !ALTQ_IS_ENABLED(\*[Am]sc-\*[Gt]sc_if.if_snd)) {
543 | ifq = \*[Am]sc-\*[Gt]sc_fastq;
544 if (IF_QFULL(ifq)) { | if (IF_QFULL(ifq)) {
545 IF_DROP(ifq); | IF_DROP(ifq);
546 m_freem(m); | m_freem(m);
547 splx(s); | error = ENOBUFS;
548 sc-\*[Gt]sc_if.if_oerrors++; | } else {
549 return (ENOBUFS); | IF_ENQUEUE(ifq, m);
551 IF_ENQUEUE(ifq, m); | }
553 | IFQ_ENQUEUE(\*[Am]sc-\*[Gt]sc_if.if_snd,
558 | sc-\*[Gt]sc_if.if_oerrors++;
561 if ((sc-\*[Gt]sc_oqlen = | if ((sc-\*[Gt]sc_oqlen =
562 sc-\*[Gt]sc_ttyp-\*[Gt]t_outq.c_cc) == 0) | sc-\*[Gt]sc_ttyp-\*[Gt]t_outq.c_cc) == 0)
563 slstart(sc-\*[Gt]sc_ttyp); | slstart(sc-\*[Gt]sc_ttyp);
567 The dequeue operations looks like:
569 ##old-style## ##new-style##
571 s = splimp(); | s = splimp();
572 IF_DEQUEUE(\*[Am]sc-\*[Gt]sc_fastq, m); | IF_DEQUEUE(\*[Am]sc-\*[Gt]sc_fastq, m);
573 if (m == NULL) | if (m == NULL)
574 IF_DEQUEUE(\*[Am]sc-\*[Gt]sc_if.if_snd, m); | IFQ_DEQUEUE(\*[Am]sc-\*[Gt]sc_if.if_snd, m);
578 .Sh QUEUEING DISCIPLINES
579 Queueing disciplines need to maintain
585 Queueing disciplines also need to guarantee the same mbuf is returned if
587 is called immediately after
598 system first appeared in March 1997.