summaryrefslogtreecommitdiffstats
path: root/share/man/man9/altq.9
diff options
context:
space:
mode:
Diffstat (limited to 'share/man/man9/altq.9')
-rw-r--r--share/man/man9/altq.9599
1 files changed, 599 insertions, 0 deletions
diff --git a/share/man/man9/altq.9 b/share/man/man9/altq.9
new file mode 100644
index 0000000..fd94404
--- /dev/null
+++ b/share/man/man9/altq.9
@@ -0,0 +1,599 @@
+.\" $NetBSD: altq.9,v 1.8 2002/05/28 11:41:45 wiz Exp $
+.\" $OpenBSD: altq.9,v 1.4 2001/07/12 12:41:42 itojun Exp $
+.\"
+.\" Copyright (C) 2004 Max Laier. All rights reserved.
+.\" Copyright (C) 2001
+.\" Sony Computer Science Laboratories Inc. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 25, 2004
+.Dt ALTQ 9
+.Os
+.\"
+.Sh NAME
+.Nm ALTQ
+.Nd kernel interfaces for manipulating output queues on network interfaces
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In net/if.h
+.In net/if_var.h
+.\"
+.Ss Enqueue macros
+.Fn IFQ_ENQUEUE "struct ifaltq *ifq" "struct mbuf *m" "int error"
+.Fn IFQ_HANDOFF "struct ifnet *ifp" "struct mbuf *m" "int error"
+.Fo IFQ_HANDOFF_ADJ
+.Fa "struct ifnet *ifp" "struct mbuf *m" "int adjust" "int error"
+.Fc
+.\"
+.Ss Dequeue macros
+.Fn IFQ_DEQUEUE "struct ifaltq *ifq" "struct mbuf *m"
+.Fn IFQ_POLL_NOLOCK "struct ifaltq *ifq" "struct mbuf *m"
+.Fn IFQ_PURGE "struct ifaltq *ifq"
+.Fn IFQ_IS_EMPTY "struct ifaltq *ifq"
+.\"
+.Ss Driver managed dequeue macros
+.Fn IFQ_DRV_DEQUEUE "struct ifaltq *ifq" "struct mbuf *m"
+.Fn IFQ_DRV_PREPEND "struct ifaltq *ifq" "struct mbuf *m"
+.Fn IFQ_DRV_PURGE "struct ifaltq *ifq"
+.Fn IFQ_DRV_IS_EMPTY "struct ifaltq *ifq"
+.\"
+.Ss General setup macros
+.Fn IFQ_SET_MAXLEN "struct ifaltq *ifq" "int len"
+.Fn IFQ_INC_LEN "struct ifaltq *ifq"
+.Fn IFQ_DEC_LEN "struct ifaltq *ifq"
+.Fn IFQ_INC_DROPS "struct ifaltq *ifq"
+.Fn IFQ_SET_READY "struct ifaltq *ifq"
+.Sh DESCRIPTION
+The
+.Nm
+system is a framework to manage queuing disciplines on network
+interfaces.
+.Nm
+introduces new macros to manipulate output queues.
+The output queue macros are used to abstract queue operations and not to
+touch the internal fields of the output queue structure.
+The macros are independent from the
+.Nm
+implementation, and compatible with the traditional
+.Vt ifqueue
+macros for ease of transition.
+.Pp
+.Fn IFQ_ENQUEUE ,
+.Fn IFQ_HANDOFF
+and
+.Fn IFQ_HANDOFF_ADJ
+enqueue a packet
+.Fa m
+to the queue
+.Fa ifq .
+The underlying queuing discipline may discard the packet.
+The
+.Fa error
+argument is set to 0 on success, or
+.Er ENOBUFS
+if the packet is discarded.
+The packet pointed to by
+.Fa m
+will be freed by the device driver on success, or by the queuing discipline on
+failure, so the caller should not touch
+.Fa m
+after enqueuing.
+.Fn IFQ_HANDOFF
+and
+.Fn IFQ_HANDOFF_ADJ
+combine the enqueue operation with statistic generation and call
+.Fn if_start
+upon successful enqueue to initiate the actual send.
+.Pp
+.Fn IFQ_DEQUEUE
+dequeues a packet from the queue.
+The dequeued packet is returned in
+.Fa m ,
+or
+.Fa m
+is set to
+.Dv NULL
+if no packet is dequeued.
+The caller must always check
+.Fa m
+since a non-empty queue could return
+.Dv NULL
+under rate-limiting.
+.Pp
+.Fn IFQ_POLL_NOLOCK
+returns the next packet without removing it from the queue.
+The caller must hold the queue mutex when calling
+.Fn IFQ_POLL_NOLOCK
+in order to guarantee that a subsequent call to
+.Fn IFQ_DEQUEUE_NOLOCK
+dequeues the same packet.
+.Pp
+.Fn IFQ_*_NOLOCK
+variants (if available) always assume that the caller holds the queue mutex.
+They can be grabbed with
+.Fn IFQ_LOCK
+and released with
+.Fn IFQ_UNLOCK .
+.Pp
+.Fn IFQ_PURGE
+discards all the packets in the queue.
+The purge operation is needed since a non-work conserving queue cannot be
+emptied by a dequeue loop.
+.Pp
+.Fn IFQ_IS_EMPTY
+can be used to check if the queue is empty.
+Note that
+.Fn IFQ_DEQUEUE
+could still return
+.Dv NULL
+if the queuing discipline is non-work conserving.
+.Pp
+.Fn IFQ_DRV_DEQUEUE
+moves up to
+.Fa ifq->ifq_drv_maxlen
+packets from the queue to the
+.Dq "driver managed"
+queue and returns the first one via
+.Fa m .
+As for
+.Fn IFQ_DEQUEUE ,
+.Fa m
+can be
+.Dv NULL
+even for a non-empty queue.
+Subsequent calls to
+.Fn IFQ_DRV_DEQUEUE
+pass the packets from the
+.Dq "driver managed"
+queue without obtaining the queue mutex.
+It is the responsibility of the caller to protect against concurrent access.
+Enabling
+.Nm
+for a given queue sets
+.Va ifq_drv_maxlen
+to 0 as the
+.Dq "bulk dequeue"
+performed by
+.Fn IFQ_DRV_DEQUEUE
+for higher values of
+.Va ifq_drv_maxlen
+is adverse to
+.Nm ALTQ Ns 's
+internal timing.
+Note that a driver must not mix
+.Fn IFQ_DRV_*
+macros with the default dequeue macros as the default macros do not look at the
+.Dq "driver managed"
+queue which might lead to an mbuf leak.
+.Pp
+.Fn IFQ_DRV_PREPEND
+prepends
+.Fa m
+to the
+.Dq "driver managed"
+queue from where it will be obtained with the next call to
+.Fn IFQ_DRV_DEQUEUE .
+.Pp
+.Fn IFQ_DRV_PURGE
+flushes all packets in the
+.Dq "driver managed"
+queue and calls to
+.Fn IFQ_PURGE
+afterwards.
+.Pp
+.Fn IFQ_DRV_IS_EMPTY
+checks for packets in the
+.Dq "driver managed"
+part of the queue.
+If it is empty, it forwards to
+.Fn IFQ_IS_EMPTY .
+.Pp
+.Fn IFQ_SET_MAXLEN
+sets the queue length limit to the default FIFO queue.
+The
+.Va ifq_drv_maxlen
+member of the
+.Vt ifaltq
+structure controls the length limit of the
+.Dq "driver managed"
+queue.
+.Pp
+.Fn IFQ_INC_LEN
+and
+.Fn IFQ_DEC_LEN
+increment or decrement the current queue length in packets.
+This is mostly for internal purposes.
+.Pp
+.Fn IFQ_INC_DROPS
+increments the drop counter and is identical to
+.Fn IF_DROP .
+It is defined for naming consistency only.
+.Pp
+.Fn IFQ_SET_READY
+sets a flag to indicate that a driver was converted to use the new macros.
+.Nm
+can be enabled only on interfaces with this flag.
+.Sh COMPATIBILITY
+.Ss Vt ifaltq Ss structure
+In order to keep compatibility with the existing code, the new
+output queue structure
+.Vt ifaltq
+has the same fields.
+The traditional
+.Fn IF_*
+macros and the code directly referencing the fields within
+.Va if_snd
+still work with
+.Vt ifaltq .
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ struct ifqueue { | struct ifaltq {
+ struct mbuf *ifq_head; | struct mbuf *ifq_head;
+ struct mbuf *ifq_tail; | struct mbuf *ifq_tail;
+ int ifq_len; | int ifq_len;
+ int ifq_maxlen; | int ifq_maxlen;
+ int ifq_drops; | int ifq_drops;
+ }; | /* driver queue fields */
+ | ......
+ | /* altq related fields */
+ | ......
+ | };
+ |
+.Ed
+The new structure replaces
+.Vt "struct ifqueue"
+in
+.Vt "struct ifnet" .
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ struct ifnet { | struct ifnet {
+ .... | ....
+ |
+ struct ifqueue if_snd; | struct ifaltq if_snd;
+ |
+ .... | ....
+ }; | };
+ |
+.Ed
+The (simplified) new
+.Fn IFQ_*
+macros look like:
+.Bd -literal
+ #define IFQ_DEQUEUE(ifq, m) \e
+ if (ALTQ_IS_ENABLED((ifq)) \e
+ ALTQ_DEQUEUE((ifq), (m)); \e
+ else \e
+ IF_DEQUEUE((ifq), (m));
+.Ed
+.Ss Enqueue operation
+The semantics of the enqueue operation is changed.
+In the new style,
+enqueue and packet drop are combined since they cannot be easily
+separated in many queuing disciplines.
+The new enqueue operation corresponds to the following macro that is
+written with the old macros.
+.Bd -literal
+#define IFQ_ENQUEUE(ifq, m, error) \e
+do { \e
+ if (IF_QFULL((ifq))) { \e
+ m_freem((m)); \e
+ (error) = ENOBUFS; \e
+ IF_DROP(ifq); \e
+ } else { \e
+ IF_ENQUEUE((ifq), (m)); \e
+ (error) = 0; \e
+ } \e
+} while (0)
+.Ed
+.Pp
+.Fn IFQ_ENQUEUE
+does the following:
+.Pp
+.Bl -hyphen -compact
+.It
+queue a packet,
+.It
+drop (and free) a packet if the enqueue operation fails.
+.El
+.Pp
+If the enqueue operation fails,
+.Fa error
+is set to
+.Er ENOBUFS .
+The
+.Fa m
+mbuf is freed by the queuing discipline.
+The caller should not touch mbuf after calling
+.Fn IFQ_ENQUEUE
+so that the caller may need to copy
+.Va m_pkthdr.len
+or
+.Va m_flags
+field beforehand for statistics.
+.Fn IFQ_HANDOFF
+and
+.Fn IFQ_HANDOFF_ADJ
+can be used if only default interface statistics and an immediate call to
+.Fn if_start
+are desired.
+The caller should not use
+.Fn senderr
+since mbuf was already freed.
+.Pp
+The new style
+.Fn if_output
+looks as follows:
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ int | int
+ ether_output(ifp, m0, dst, rt0) | ether_output(ifp, m0, dst, rt0)
+ { | {
+ ...... | ......
+ |
+ | mflags = m->m_flags;
+ | len = m->m_pkthdr.len;
+ s = splimp(); | s = splimp();
+ if (IF_QFULL(&ifp->if_snd)) { | IFQ_ENQUEUE(&ifp->if_snd, m,
+ | error);
+ IF_DROP(&ifp->if_snd); | if (error != 0) {
+ splx(s); | splx(s);
+ senderr(ENOBUFS); | return (error);
+ } | }
+ IF_ENQUEUE(&ifp->if_snd, m); |
+ ifp->if_obytes += | ifp->if_obytes += len;
+ m->m_pkthdr.len; |
+ if (m->m_flags & M_MCAST) | if (mflags & M_MCAST)
+ ifp->if_omcasts++; | ifp->if_omcasts++;
+ |
+ if ((ifp->if_flags & IFF_OACTIVE) | if ((ifp->if_flags & IFF_OACTIVE)
+ == 0) | == 0)
+ (*ifp->if_start)(ifp); | (*ifp->if_start)(ifp);
+ splx(s); | splx(s);
+ return (error); | return (error);
+ |
+ bad: | bad:
+ if (m) | if (m)
+ m_freem(m); | m_freem(m);
+ return (error); | return (error);
+ } | }
+ |
+.Ed
+.Sh HOW TO CONVERT THE EXISTING DRIVERS
+First, make sure the corresponding
+.Fn if_output
+is already converted to the new style.
+.Pp
+Look for
+.Va if_snd
+in the driver.
+Probably, you need to make changes to the lines that include
+.Va if_snd .
+.Ss Empty check operation
+If the code checks
+.Va ifq_head
+to see whether the queue is empty or not, use
+.Fn IFQ_IS_EMPTY .
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ if (ifp->if_snd.ifq_head != NULL) | if (!IFQ_IS_EMPTY(&ifp->if_snd))
+ |
+.Ed
+.Fn IFQ_IS_EMPTY
+only checks if there is any packet stored in the queue.
+Note that even when
+.Fn IFQ_IS_EMPTY
+is
+.Dv FALSE ,
+.Fn IFQ_DEQUEUE
+could still return
+.Dv NULL
+if the queue is under rate-limiting.
+.Ss Dequeue operation
+Replace
+.Fn IF_DEQUEUE
+by
+.Fn IFQ_DEQUEUE .
+Always check whether the dequeued mbuf is
+.Dv NULL
+or not.
+Note that even when
+.Fn IFQ_IS_EMPTY
+is
+.Dv FALSE ,
+.Fn IFQ_DEQUEUE
+could return
+.Dv NULL
+due to rate-limiting.
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ IF_DEQUEUE(&ifp->if_snd, m); | IFQ_DEQUEUE(&ifp->if_snd, m);
+ | if (m == NULL)
+ | return;
+ |
+.Ed
+A driver is supposed to call
+.Fn if_start
+from transmission complete interrupts in order to trigger the next dequeue.
+.Ss Poll-and-dequeue operation
+If the code polls the packet at the head of the queue and actually uses
+the packet before dequeuing it, use
+.Fn IFQ_POLL_NOLOCK
+and
+.Fn IFQ_DEQUEUE_NOLOCK .
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ | IFQ_LOCK(&ifp->if_snd);
+ m = ifp->if_snd.ifq_head; | IFQ_POLL_NOLOCK(&ifp->if_snd, m);
+ if (m != NULL) { | if (m != NULL) {
+ |
+ /* use m to get resources */ | /* use m to get resources */
+ if (something goes wrong) | if (something goes wrong)
+ | IFQ_UNLOCK(&ifp->if_snd);
+ return; | return;
+ |
+ IF_DEQUEUE(&ifp->if_snd, m); | IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
+ | IFQ_UNLOCK(&ifp->if_snd);
+ |
+ /* kick the hardware */ | /* kick the hardware */
+ } | }
+ |
+.Ed
+It is guaranteed that
+.Fn IFQ_DEQUEUE_NOLOCK
+under the same lock as a previous
+.Fn IFQ_POLL_NOLOCK
+returns the same packet.
+Note that they need to be guarded by
+.Fn IFQ_LOCK .
+.Ss Eliminating Fn IF_PREPEND
+If the code uses
+.Fn IF_PREPEND ,
+you have to eliminate it unless you can use a
+.Dq "driver managed"
+queue which allows the use of
+.Fn IFQ_DRV_PREPEND
+as a substitute.
+A common usage of
+.Fn IF_PREPEND
+is to cancel the previous dequeue operation.
+You have to convert the logic into poll-and-dequeue.
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ | IFQ_LOCK(&ifp->if_snd);
+ IF_DEQUEUE(&ifp->if_snd, m); | IFQ_POLL_NOLOCK(&ifp->if_snd, m);
+ if (m != NULL) { | if (m != NULL) {
+ |
+ if (something_goes_wrong) { | if (something_goes_wrong) {
+ IF_PREPEND(&ifp->if_snd, m); | IFQ_UNLOCK(&ifp->if_snd);
+ return; | return;
+ } | }
+ |
+ | /* at this point, the driver
+ | * is committed to send this
+ | * packet.
+ | */
+ | IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
+ | IFQ_UNLOCK(&ifp->if_snd);
+ |
+ /* kick the hardware */ | /* kick the hardware */
+ } | }
+ |
+.Ed
+.Ss Purge operation
+Use
+.Fn IFQ_PURGE
+to empty the queue.
+Note that a non-work conserving queue cannot be emptied by a dequeue loop.
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ while (ifp->if_snd.ifq_head != NULL) {| IFQ_PURGE(&ifp->if_snd);
+ IF_DEQUEUE(&ifp->if_snd, m); |
+ m_freem(m); |
+ } |
+ |
+.Ed
+.Ss Conversion using a driver managed queue
+Convert
+.Fn IF_*
+macros to their equivalent
+.Fn IFQ_DRV_*
+and employ
+.Fn IFQ_DRV_IS_EMPTY
+where appropriate.
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ if (ifp->if_snd.ifq_head != NULL) | if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ |
+.Ed
+Make sure that calls to
+.Fn IFQ_DRV_DEQUEUE ,
+.Fn IFQ_DRV_PREPEND
+and
+.Fn IFQ_DRV_PURGE
+are protected with a mutex of some kind.
+.Ss Attach routine
+Use
+.Fn IFQ_SET_MAXLEN
+to set
+.Va ifq_maxlen
+to
+.Fa len .
+Initialize
+.Va ifq_drv_maxlen
+with a sensible value if you plan to use the
+.Fn IFQ_DRV_*
+macros.
+Add
+.Fn IFQ_SET_READY
+to show this driver is converted to the new style.
+(This is used to distinguish new-style drivers.)
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ ifp->if_snd.ifq_maxlen = qsize; | IFQ_SET_MAXLEN(&ifp->if_snd, qsize);
+ | ifp->if_snd.ifq_drv_maxlen = qsize;
+ | IFQ_SET_READY(&ifp->if_snd);
+ if_attach(ifp); | if_attach(ifp);
+ |
+.Ed
+.Ss Other issues
+The new macros for statistics:
+.Bd -literal
+ ##old-style## ##new-style##
+ |
+ IF_DROP(&ifp->if_snd); | IFQ_INC_DROPS(&ifp->if_snd);
+ |
+ ifp->if_snd.ifq_len++; | IFQ_INC_LEN(&ifp->if_snd);
+ |
+ ifp->if_snd.ifq_len--; | IFQ_DEC_LEN(&ifp->if_snd);
+ |
+.Ed
+.Sh QUEUING DISCIPLINES
+Queuing disciplines need to maintain
+.Fa ifq_len
+(used by
+.Fn IFQ_IS_EMPTY ) .
+Queuing disciplines also need to guarantee that the same mbuf is returned if
+.Fn IFQ_DEQUEUE
+is called immediately after
+.Fn IFQ_POLL .
+.Sh SEE ALSO
+.Xr pf 4 ,
+.Xr pf.conf 5 ,
+.Xr pfctl 8
+.Sh HISTORY
+The
+.Nm
+system first appeared in March 1997.
OpenPOWER on IntegriCloud