---
name: "altq"
section: "9freebsd"
platform: "linux"
package: "freebsd-manpages"
version: "12.2-2"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/ALTQ/9freebsd"
---

# altq(9freebsd)

kernel interfaces for manipulating output queues on network interfaces

Part of [ALTQ(9freebsd)](/ALTQ/9freebsd.md).

## NAME

**ALTQ** – kernel interfaces for manipulating output queues on network interfaces

## SYNOPSIS

**#include \<sys/types.h\>**

**#include \<sys/socket.h\>**

**#include \<net/if.h\>**

**#include \<net/if\_var.h\>**

### Enqueue macros

**IFQ\_ENQUEUE**(*struct ifaltq \*ifq*, *struct mbuf \*m*, *int error*);

**IFQ\_HANDOFF**(*struct ifnet \*ifp*, *struct mbuf \*m*, *int error*);

**IFQ\_HANDOFF\_ADJ**(*struct ifnet \*ifp*, *struct mbuf \*m*, *int adjust*, *int error*);

### Dequeue macros

**IFQ\_DEQUEUE**(*struct ifaltq \*ifq*, *struct mbuf \*m*);

**IFQ\_POLL\_NOLOCK**(*struct ifaltq \*ifq*, *struct mbuf \*m*);

**IFQ\_PURGE**(*struct ifaltq \*ifq*);

**IFQ\_IS\_EMPTY**(*struct ifaltq \*ifq*);

### Driver managed dequeue macros

**IFQ\_DRV\_DEQUEUE**(*struct ifaltq \*ifq*, *struct mbuf \*m*);

**IFQ\_DRV\_PREPEND**(*struct ifaltq \*ifq*, *struct mbuf \*m*);

**IFQ\_DRV\_PURGE**(*struct ifaltq \*ifq*);

**IFQ\_DRV\_IS\_EMPTY**(*struct ifaltq \*ifq*);

### General setup macros

**IFQ\_SET\_MAXLEN**(*struct ifaltq \*ifq*, *int len*);

**IFQ\_INC\_LEN**(*struct ifaltq \*ifq*);

**IFQ\_DEC\_LEN**(*struct ifaltq \*ifq*);

**IFQ\_INC\_DROPS**(*struct ifaltq \*ifq*);

**IFQ\_SET\_READY**(*struct ifaltq \*ifq*);

## DESCRIPTION

The **ALTQ** system is a framework to manage queuing disciplines on network interfaces. **ALTQ** 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 **ALTQ** implementation, and compatible with the traditional *ifqueue* macros for ease of transition.

**IFQ\_ENQUEUE**(), **IFQ\_HANDOFF**() and **IFQ\_HANDOFF\_ADJ**() enqueue a packet *m* to the queue *ifq*. The underlying queuing discipline may discard the packet. The *error* argument is set to 0 on success, or ENOBUFS if the packet is discarded. The packet pointed to by *m* will be freed by the device driver on success, or by the queuing discipline on failure, so the caller should not touch *m* after enqueuing. **IFQ\_HANDOFF**() and **IFQ\_HANDOFF\_ADJ**() combine the enqueue operation with statistic generation and call **if\_start**() upon successful enqueue to initiate the actual send.

**IFQ\_DEQUEUE**() dequeues a packet from the queue. The dequeued packet is returned in *m*, or *m* is set to NULL if no packet is dequeued. The caller must always check *m* since a non-empty queue could return NULL under rate-limiting.

**IFQ\_POLL\_NOLOCK**() returns the next packet without removing it from the queue. The caller must hold the queue mutex when calling **IFQ\_POLL\_NOLOCK**() in order to guarantee that a subsequent call to **IFQ\_DEQUEUE\_NOLOCK**() dequeues the same packet.

**IFQ\_\*\_NOLOCK**() variants (if available) always assume that the caller holds the queue mutex. They can be grabbed with **IFQ\_LOCK**() and released with **IFQ\_UNLOCK**().

**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.

**IFQ\_IS\_EMPTY**() can be used to check if the queue is empty. Note that **IFQ\_DEQUEUE**() could still return NULL if the queuing discipline is non-work conserving.

**IFQ\_DRV\_DEQUEUE**() moves up to *ifq-\>ifq\_drv\_maxlen* packets from the queue to the “driver managed” queue and returns the first one via *m*. As for **IFQ\_DEQUEUE**(), *m* can be NULL even for a non-empty queue. Subsequent calls to **IFQ\_DRV\_DEQUEUE**() pass the packets from the “driver managed” queue without obtaining the queue mutex. It is the responsibility of the caller to protect against concurrent access. Enabling **ALTQ** for a given queue sets *ifq\_drv\_maxlen* to 0 as the “bulk dequeue” performed by **IFQ\_DRV\_DEQUEUE**() for higher values of *ifq\_drv\_maxlen* is adverse to **ALTQ**'s internal timing. Note that a driver must not mix **IFQ\_DRV\_\***() macros with the default dequeue macros as the default macros do not look at the “driver managed” queue which might lead to an mbuf leak.

**IFQ\_DRV\_PREPEND**() prepends *m* to the “driver managed” queue from where it will be obtained with the next call to **IFQ\_DRV\_DEQUEUE**().

**IFQ\_DRV\_PURGE**() flushes all packets in the “driver managed” queue and calls to **IFQ\_PURGE**() afterwards.

**IFQ\_DRV\_IS\_EMPTY**() checks for packets in the “driver managed” part of the queue. If it is empty, it forwards to **IFQ\_IS\_EMPTY**().

**IFQ\_SET\_MAXLEN**() sets the queue length limit to the default FIFO queue. The *ifq\_drv\_maxlen* member of the *ifaltq* structure controls the length limit of the “driver managed” queue.

**IFQ\_INC\_LEN**() and **IFQ\_DEC\_LEN**() increment or decrement the current queue length in packets. This is mostly for internal purposes.

**IFQ\_INC\_DROPS**() increments the drop counter and is identical to **IF\_DROP**(). It is defined for naming consistency only.

**IFQ\_SET\_READY**() sets a flag to indicate that a driver was converted to use the new macros. **ALTQ** can be enabled only on interfaces with this flag.

## COMPATIBILITY

### Vt ifaltq structure

In order to keep compatibility with the existing code, the new output queue structure *ifaltq* has the same fields. The traditional **IF\_\***() macros and the code directly referencing the fields within *if\_snd* still work with *ifaltq*.

```
            ##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;
 };                                    |    /* driver queue fields */
                                       |    ......
                                       |    /* altq related fields */
                                       |    ......
                                       | };
                                       |
```

The new structure replaces *struct ifqueue* in *struct ifnet*.

```
            ##old-style##                           ##new-style##
                                       |
 struct ifnet {                        | struct ifnet {
     ....                              |     ....
                                       |
     struct ifqueue if_snd;            |     struct ifaltq if_snd;
                                       |
     ....                              |     ....
 };                                    | };
                                       |
```

The (simplified) new **IFQ\_\***() macros look like:

```
	#define IFQ_DEQUEUE(ifq, m)			\
		if (ALTQ_IS_ENABLED((ifq))		\
			ALTQ_DEQUEUE((ifq), (m));	\
		else					\
			IF_DEQUEUE((ifq), (m));
```

### 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.

```
#define	IFQ_ENQUEUE(ifq, m, error)                      \
do {                                                    \
        if (IF_QFULL((ifq))) {                          \
                m_freem((m));                           \
                (error) = ENOBUFS;                      \
                IF_DROP(ifq);                           \
        } else {                                        \
                IF_ENQUEUE((ifq), (m));                 \
                (error) = 0;                            \
        }                                               \
} while (0)
```

**IFQ\_ENQUEUE**() does the following:

- queue a packet,

- drop (and free) a packet if the enqueue operation fails.

If the enqueue operation fails, *error* is set to ENOBUFS. The *m* mbuf is freed by the queuing discipline. The caller should not touch mbuf after calling **IFQ\_ENQUEUE**() so that the caller may need to copy *m\_pkthdr.len* or *m\_flags* field beforehand for statistics. **IFQ\_HANDOFF**() and **IFQ\_HANDOFF\_ADJ**() can be used if only default interface statistics and an immediate call to **if\_start**() are desired. The caller should not use **senderr**() since mbuf was already freed.

The new style **if\_output**() looks as follows:

```
            ##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);
 }                                     | }
                                       |
```

## HOW TO CONVERT THE EXISTING DRIVERS

First, make sure the corresponding **if\_output**() is already converted to the new style.

Look for *if\_snd* in the driver. Probably, you need to make changes to the lines that include *if\_snd*.

### Empty check operation

If the code checks *ifq\_head* to see whether the queue is empty or not, use **IFQ\_IS\_EMPTY**().

```
            ##old-style##                           ##new-style##
                                       |
 if (ifp->if_snd.ifq_head != NULL)     | if (!IFQ_IS_EMPTY(&ifp->if_snd))
                                       |
```

**IFQ\_IS\_EMPTY**() only checks if there is any packet stored in the queue. Note that even when **IFQ\_IS\_EMPTY**() is FALSE, **IFQ\_DEQUEUE**() could still return NULL if the queue is under rate-limiting.

### Dequeue operation

Replace **IF\_DEQUEUE**() by **IFQ\_DEQUEUE**(). Always check whether the dequeued mbuf is NULL or not. Note that even when **IFQ\_IS\_EMPTY**() is FALSE, **IFQ\_DEQUEUE**() could return NULL due to rate-limiting.

```
            ##old-style##                           ##new-style##
                                       |
 IF_DEQUEUE(&ifp->if_snd, m);          | IFQ_DEQUEUE(&ifp->if_snd, m);
                                       | if (m == NULL)
                                       |     return;
                                       |
```

A driver is supposed to call **if\_start**() from transmission complete interrupts in order to trigger the next dequeue.

### 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 **IFQ\_POLL\_NOLOCK**() and **IFQ\_DEQUEUE\_NOLOCK**().

```
            ##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 */
 }                                     | }
                                       |
```

It is guaranteed that **IFQ\_DEQUEUE\_NOLOCK**() under the same lock as a previous **IFQ\_POLL\_NOLOCK**() returns the same packet. Note that they need to be guarded by **IFQ\_LOCK**().

### Eliminating Fn IF\_PREPEND

If the code uses **IF\_PREPEND**(), you have to eliminate it unless you can use a “driver managed” queue which allows the use of **IFQ\_DRV\_PREPEND**() as a substitute. A common usage of **IF\_PREPEND**() is to cancel the previous dequeue operation. You have to convert the logic into poll-and-dequeue.

```
            ##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 */
 }                                     | }
                                       |
```

### Purge operation

Use **IFQ\_PURGE**() to empty the queue. Note that a non-work conserving queue cannot be emptied by a dequeue loop.

```
            ##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);                       |
 }                                     |
                                       |
```

### Conversion using a driver managed queue

Convert **IF\_\***() macros to their equivalent **IFQ\_DRV\_\***() and employ **IFQ\_DRV\_IS\_EMPTY**() where appropriate.

```
            ##old-style##                           ##new-style##
                                       |
 if (ifp->if_snd.ifq_head != NULL)     | if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
                                       |
```

Make sure that calls to **IFQ\_DRV\_DEQUEUE**(), **IFQ\_DRV\_PREPEND**() and **IFQ\_DRV\_PURGE**() are protected with a mutex of some kind.

### Attach routine

Use **IFQ\_SET\_MAXLEN**() to set *ifq\_maxlen* to *len*. Initialize *ifq\_drv\_maxlen* with a sensible value if you plan to use the **IFQ\_DRV\_\***() macros. Add **IFQ\_SET\_READY**() to show this driver is converted to the new style. (This is used to distinguish new-style drivers.)

```
            ##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);
                                       |
```

### Other issues

The new macros for statistics:

```
            ##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);
                                       |
```

## QUEUING DISCIPLINES

Queuing disciplines need to maintain *ifq\_len* (used by **IFQ\_IS\_EMPTY**()). Queuing disciplines also need to guarantee that the same mbuf is returned if **IFQ\_DEQUEUE**() is called immediately after **IFQ\_POLL**().

## SEE ALSO

[pf(4)](/pf/4.md), [pf.conf(5)](/pf.conf/5.md), [pfctl(8)](/pfctl/8.md)

## HISTORY

The **ALTQ** system first appeared in March 1997 and found home in the KAME project (http://www.kame.net). It was imported to FreeBSD in 5.3 .
