Deleted Added
full compact
altq.9 (133265) altq.9 (133386)
1.\" $FreeBSD: head/share/man/man9/altq.9 133265 2004-08-07 12:35:56Z mlaier $
2.\" $NetBSD: altq.9,v 1.8 2002/05/28 11:41:45 wiz Exp $
3.\" $OpenBSD: altq.9,v 1.4 2001/07/12 12:41:42 itojun Exp $
4.\"
5.\" Copyright (C) 2004 Max Laier. All rights reserved.
6.\" Copyright (C) 2001
7.\" Sony Computer Science Laboratories Inc. All rights reserved.
8.\"
9.\" Redistribution and use in source and binary forms, with or without

--- 12 unchanged lines hidden (view full) ---

22.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28.\" SUCH DAMAGE.
29.\"
1.\" $NetBSD: altq.9,v 1.8 2002/05/28 11:41:45 wiz Exp $
2.\" $OpenBSD: altq.9,v 1.4 2001/07/12 12:41:42 itojun Exp $
3.\"
4.\" Copyright (C) 2004 Max Laier. All rights reserved.
5.\" Copyright (C) 2001
6.\" Sony Computer Science Laboratories Inc. All rights reserved.
7.\"
8.\" Redistribution and use in source and binary forms, with or without

--- 12 unchanged lines hidden (view full) ---

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.\" $FreeBSD: head/share/man/man9/altq.9 133386 2004-08-09 15:58:39Z mlaier $
30.\"
30.Dd August 7, 2004
31.Dt ALTQ 9
32.Os
33.\"
34.Sh NAME
35.Nm ALTQ
36.Nd kernel interfaces for manipulating output queues on network interfaces
37.Sh SYNOPSIS
38.In sys/types.h
39.In sys/socket.h
40.In net/if.h
41.In net/if_var.h
42.\"
43.Ss Enqueue macros
44.Fn IFQ_ENQUEUE "struct ifaltq *ifq" "struct mbuf *m" "int error"
45.Fn IFQ_HANDOFF "struct ifnet *ifp" "struct mbuf *m" "int error"
31.Dd August 7, 2004
32.Dt ALTQ 9
33.Os
34.\"
35.Sh NAME
36.Nm ALTQ
37.Nd kernel interfaces for manipulating output queues on network interfaces
38.Sh SYNOPSIS
39.In sys/types.h
40.In sys/socket.h
41.In net/if.h
42.In net/if_var.h
43.\"
44.Ss Enqueue macros
45.Fn IFQ_ENQUEUE "struct ifaltq *ifq" "struct mbuf *m" "int error"
46.Fn IFQ_HANDOFF "struct ifnet *ifp" "struct mbuf *m" "int error"
46.Fn IFQ_HANDOFF_ADJ "struct ifnet *ifp" "struct mbuf *m" "int adjust" "int error"
47.Fo IFQ_HANDOFF_ADJ
48.Fa "struct ifnet *ifp" "struct mbuf *m" "int adjust" "int error"
49.Fc
47.\"
48.Ss Dequeue macros
49.Fn IFQ_DEQUEUE "struct ifaltq *ifq" "struct mbuf *m"
50.Fn IFQ_POLL_NOLOCK "struct ifaltq *ifq" "struct mbuf *m"
51.Fn IFQ_PURGE "struct ifaltq *ifq"
52.Fn IFQ_IS_EMPTY "struct ifaltq *ifq"
53.\"
54.Ss Driver managed dequeue macros

--- 15 unchanged lines hidden (view full) ---

70interfaces.
71.Nm
72introduces new macros to manipulate output queues.
73The output queue macros are used to abstract queue operations and not to
74touch the internal fields of the output queue structure.
75The macros are independent from the
76.Nm
77implementation, and compatible with the traditional
50.\"
51.Ss Dequeue macros
52.Fn IFQ_DEQUEUE "struct ifaltq *ifq" "struct mbuf *m"
53.Fn IFQ_POLL_NOLOCK "struct ifaltq *ifq" "struct mbuf *m"
54.Fn IFQ_PURGE "struct ifaltq *ifq"
55.Fn IFQ_IS_EMPTY "struct ifaltq *ifq"
56.\"
57.Ss Driver managed dequeue macros

--- 15 unchanged lines hidden (view full) ---

73interfaces.
74.Nm
75introduces new macros to manipulate output queues.
76The output queue macros are used to abstract queue operations and not to
77touch the internal fields of the output queue structure.
78The macros are independent from the
79.Nm
80implementation, and compatible with the traditional
78.Dv ifqueue
81.Vt ifqueue
79macros for ease of transition.
80.Pp
81.Fn IFQ_ENQUEUE ,
82.Fn IFQ_HANDOFF
83and
84.Fn IFQ_HANDOFF_ADJ
85enqueue a packet
86.Fa m
87to the queue
88.Fa ifq .
89The underlying queuing discipline may discard the packet.
82macros for ease of transition.
83.Pp
84.Fn IFQ_ENQUEUE ,
85.Fn IFQ_HANDOFF
86and
87.Fn IFQ_HANDOFF_ADJ
88enqueue a packet
89.Fa m
90to the queue
91.Fa ifq .
92The underlying queuing discipline may discard the packet.
93The
90.Fa error
94.Fa error
91is set to 0 on success, or
92.Dv ENOBUFS
95argument is set to 0 on success, or
96.Er ENOBUFS
93if the packet is discarded.
97if the packet is discarded.
98The packet pointed to by
94.Fa m
99.Fa m
95will be freed by the device driver on success or by the queuing discipline on
96failure so that the caller should not touch
100will be freed by the device driver on success, or by the queuing discipline on
101failure, so the caller should not touch
97.Fa m
98after enqueuing.
99.Fn IFQ_HANDOFF
100and
101.Fn IFQ_HANDOFF_ADJ
102combine the enqueue operation with statistic generation and call
103.Fn if_start
104upon successful enqueue to initiate the actual send.

--- 10 unchanged lines hidden (view full) ---

115The caller must always check
116.Fa m
117since a non-empty queue could return
118.Dv NULL
119under rate-limiting.
120.Pp
121.Fn IFQ_POLL_NOLOCK
122returns the next packet without removing it from the queue.
102.Fa m
103after enqueuing.
104.Fn IFQ_HANDOFF
105and
106.Fn IFQ_HANDOFF_ADJ
107combine the enqueue operation with statistic generation and call
108.Fn if_start
109upon successful enqueue to initiate the actual send.

--- 10 unchanged lines hidden (view full) ---

120The caller must always check
121.Fa m
122since a non-empty queue could return
123.Dv NULL
124under rate-limiting.
125.Pp
126.Fn IFQ_POLL_NOLOCK
127returns the next packet without removing it from the queue.
123The caller must hold the queue mutex when calling to
128The caller must hold the queue mutex when calling
124.Fn IFQ_POLL_NOLOCK
125in order to guarantee that a subsequent call to
126.Fn IFQ_DEQUEUE_NOLOCK
127dequeues the same packet.
128.Pp
129.Fn IFQ_POLL_NOLOCK
130in order to guarantee that a subsequent call to
131.Fn IFQ_DEQUEUE_NOLOCK
132dequeues the same packet.
133.Pp
129.Fn IFQ_XXX_NOLOCK
130variants - if available - always assume that the caller holds the queue mutex.
134.Fn IFQ_*_NOLOCK
135variants (if available) always assume that the caller holds the queue mutex.
131They can be grabbed with
132.Fn IFQ_LOCK
133and released with
134.Fn IFQ_UNLOCK .
135.Pp
136.Fn IFQ_PURGE
137discards all the packets in the queue.
138The purge operation is needed since a non-work conserving queue cannot be

--- 4 unchanged lines hidden (view full) ---

143Note that
144.Fn IFQ_DEQUEUE
145could still return
146.Dv NULL
147if the queuing discipline is non-work conserving.
148.Pp
149.Fn IFQ_DRV_DEQUEUE
150moves up to
136They can be grabbed with
137.Fn IFQ_LOCK
138and released with
139.Fn IFQ_UNLOCK .
140.Pp
141.Fn IFQ_PURGE
142discards all the packets in the queue.
143The purge operation is needed since a non-work conserving queue cannot be

--- 4 unchanged lines hidden (view full) ---

148Note that
149.Fn IFQ_DEQUEUE
150could still return
151.Dv NULL
152if the queuing discipline is non-work conserving.
153.Pp
154.Fn IFQ_DRV_DEQUEUE
155moves up to
151.Va ifq->ifq_drv_maxlen
156.Fa ifq->ifq_drv_maxlen
152packets from the queue to the
157packets from the queue to the
153.Ql driver managed
158.Dq "driver managed"
154queue and returns the first one via
155.Fa m .
156As for
157.Fn IFQ_DEQUEUE ,
158.Fa m
159can be
160.Dv NULL
161even for a non-empty queue.
162Subsequent calls to
163.Fn IFQ_DRV_DEQUEUE
164pass the packets from the
159queue and returns the first one via
160.Fa m .
161As for
162.Fn IFQ_DEQUEUE ,
163.Fa m
164can be
165.Dv NULL
166even for a non-empty queue.
167Subsequent calls to
168.Fn IFQ_DRV_DEQUEUE
169pass the packets from the
165.Ql driver managed
170.Dq "driver managed"
166queue without obtaining the queue mutex.
167It is the responsibility of the caller to protect against concurrent access.
168Enabling
169.Nm
170for a given queue sets
171.Va ifq_drv_maxlen
171queue without obtaining the queue mutex.
172It is the responsibility of the caller to protect against concurrent access.
173Enabling
174.Nm
175for a given queue sets
176.Va ifq_drv_maxlen
172to
173.Dv 0
174as the
175.Ql bulk dequeue
177to 0 as the
178.Dq "bulk dequeue"
176performed by
177.Fn IFQ_DRV_DEQUEUE
178for higher values of
179.Va ifq_drv_maxlen
180is adverse to
179performed by
180.Fn IFQ_DRV_DEQUEUE
181for higher values of
182.Va ifq_drv_maxlen
183is adverse to
181.Sy ALTQ's
184.Nm ALTQ Ns 's
182internal timing.
183Note that a driver must not mix
185internal timing.
186Note that a driver must not mix
184.Fn IFQ_DRV_XXX
187.Fn IFQ_DRV_*
185macros with the default dequeue macros as the default macros do not look at the
188macros with the default dequeue macros as the default macros do not look at the
186.Ql driver managed
189.Dq "driver managed"
187queue which might lead to an mbuf leak.
188.Pp
189.Fn IFQ_DRV_PREPEND
190prepends
191.Fa m
192to the
190queue which might lead to an mbuf leak.
191.Pp
192.Fn IFQ_DRV_PREPEND
193prepends
194.Fa m
195to the
193.Ql driver managed
196.Dq "driver managed"
194queue from where it will be obtained with the next call to
195.Fn IFQ_DRV_DEQUEUE .
196.Pp
197.Fn IFQ_DRV_PURGE
198flushes all packets in the
197queue from where it will be obtained with the next call to
198.Fn IFQ_DRV_DEQUEUE .
199.Pp
200.Fn IFQ_DRV_PURGE
201flushes all packets in the
199.Ql driver managed
202.Dq "driver managed"
200queue and calls to
201.Fn IFQ_PURGE
202afterwards.
203.Pp
204.Fn IFQ_DRV_IS_EMPTY
205checks for packets in the
203queue and calls to
204.Fn IFQ_PURGE
205afterwards.
206.Pp
207.Fn IFQ_DRV_IS_EMPTY
208checks for packets in the
206.Ql driver managed
207part of the queue. If it is empty it forwards to
209.Dq "driver managed"
210part of the queue.
211If it is empty, it forwards to
208.Fn IFQ_IS_EMPTY .
209.Pp
212.Fn IFQ_IS_EMPTY .
213.Pp
210.Pp
211.Fn IFQ_SET_MAXLEN
212sets the queue length limit to the default FIFO queue.
214.Fn IFQ_SET_MAXLEN
215sets the queue length limit to the default FIFO queue.
213.Va ifaltq.ifq_drv_maxlen
214controls the length limit of the
215.Ql driver managed
216The
217.Va ifq_drv_maxlen
218member of the
219.Vt ifaltq
220structure controls the length limit of the
221.Dq "driver managed"
216queue.
217.Pp
218.Fn IFQ_INC_LEN
219and
220.Fn IFQ_DEC_LEN
221increment or decrement the current queue length in packets.
222This is mostly for internal purposes.
223.Pp
224.Fn IFQ_INC_DROPS
222queue.
223.Pp
224.Fn IFQ_INC_LEN
225and
226.Fn IFQ_DEC_LEN
227increment or decrement the current queue length in packets.
228This is mostly for internal purposes.
229.Pp
230.Fn IFQ_INC_DROPS
225increments the drop counter and is equal to
231increments the drop counter and is identical to
226.Fn IF_DROP .
232.Fn IF_DROP .
227It is defined for naming consistency.
233It is defined for naming consistency only.
228.Pp
229.Fn IFQ_SET_READY
234.Pp
235.Fn IFQ_SET_READY
230sets a flag to indicate this driver is converted to use the new macros.
236sets a flag to indicate that a driver was converted to use the new macros.
231.Nm
232can be enabled only on interfaces with this flag.
233.Sh COMPATIBILITY
237.Nm
238can be enabled only on interfaces with this flag.
239.Sh COMPATIBILITY
234.Ss ifaltq structure
240.Ss Vt ifaltq Ss structure
235In order to keep compatibility with the existing code, the new
236output queue structure
241In order to keep compatibility with the existing code, the new
242output queue structure
237.Dv ifaltq
243.Vt ifaltq
238has the same fields.
239The traditional
244has the same fields.
245The traditional
240.Fn IF_XXX
246.Fn IF_*
241macros and the code directly referencing the fields within
247macros and the code directly referencing the fields within
242.Dv if_snd
248.Va if_snd
243still work with
249still work with
244.Dv ifaltq .
250.Vt ifaltq .
245.Bd -literal
246 ##old-style## ##new-style##
247 |
248 struct ifqueue { | struct ifaltq {
249 struct mbuf *ifq_head; | struct mbuf *ifq_head;
250 struct mbuf *ifq_tail; | struct mbuf *ifq_tail;
251 int ifq_len; | int ifq_len;
252 int ifq_maxlen; | int ifq_maxlen;
253 int ifq_drops; | int ifq_drops;
254 }; | /* driver queue fields */
255 | ......
256 | /* altq related fields */
257 | ......
258 | };
259 |
260.Ed
261The new structure replaces
251.Bd -literal
252 ##old-style## ##new-style##
253 |
254 struct ifqueue { | struct ifaltq {
255 struct mbuf *ifq_head; | struct mbuf *ifq_head;
256 struct mbuf *ifq_tail; | struct mbuf *ifq_tail;
257 int ifq_len; | int ifq_len;
258 int ifq_maxlen; | int ifq_maxlen;
259 int ifq_drops; | int ifq_drops;
260 }; | /* driver queue fields */
261 | ......
262 | /* altq related fields */
263 | ......
264 | };
265 |
266.Ed
267The new structure replaces
262.Dv struct ifqueue
268.Vt "struct ifqueue"
263in
269in
264.Dv struct ifnet .
270.Vt "struct ifnet" .
265.Bd -literal
266 ##old-style## ##new-style##
267 |
268 struct ifnet { | struct ifnet {
269 .... | ....
270 |
271 struct ifqueue if_snd; | struct ifaltq if_snd;
272 |
273 .... | ....
274 }; | };
275 |
276.Ed
277The (simplified) new
271.Bd -literal
272 ##old-style## ##new-style##
273 |
274 struct ifnet { | struct ifnet {
275 .... | ....
276 |
277 struct ifqueue if_snd; | struct ifaltq if_snd;
278 |
279 .... | ....
280 }; | };
281 |
282.Ed
283The (simplified) new
278.Fn IFQ_XXX
279macros looks like:
284.Fn IFQ_*
285macros look like:
280.Bd -literal
281 #define IFQ_DEQUEUE(ifq, m) \e
282 if (ALTQ_IS_ENABLED((ifq)) \e
283 ALTQ_DEQUEUE((ifq), (m)); \e
284 else \e
285 IF_DEQUEUE((ifq), (m));
286.Ed
287.Ss Enqueue operation

--- 14 unchanged lines hidden (view full) ---

302 IF_ENQUEUE((ifq), (m)); \e
303 (error) = 0; \e
304 } \e
305} while (0)
306.Ed
307.Pp
308.Fn IFQ_ENQUEUE
309does the following:
286.Bd -literal
287 #define IFQ_DEQUEUE(ifq, m) \e
288 if (ALTQ_IS_ENABLED((ifq)) \e
289 ALTQ_DEQUEUE((ifq), (m)); \e
290 else \e
291 IF_DEQUEUE((ifq), (m));
292.Ed
293.Ss Enqueue operation

--- 14 unchanged lines hidden (view full) ---

308 IF_ENQUEUE((ifq), (m)); \e
309 (error) = 0; \e
310 } \e
311} while (0)
312.Ed
313.Pp
314.Fn IFQ_ENQUEUE
315does the following:
316.Pp
310.Bl -hyphen -compact
311.It
317.Bl -hyphen -compact
318.It
312queue a packet
319queue a packet,
313.It
320.It
314drop (and free) a packet if the enqueue operation fails
321drop (and free) a packet if the enqueue operation fails.
315.El
322.El
323.Pp
316If the enqueue operation fails,
317.Fa error
318is set to
324If the enqueue operation fails,
325.Fa error
326is set to
319.Dv ENOBUFS .
320.Fa mbuf
321is freed by the queuing discipline.
327.Er ENOBUFS .
328The
329.Fa m
330mbuf is freed by the queuing discipline.
322The caller should not touch mbuf after calling
323.Fn IFQ_ENQUEUE
324so that the caller may need to copy
331The caller should not touch mbuf after calling
332.Fn IFQ_ENQUEUE
333so that the caller may need to copy
325.Fa m_pkthdr.len
334.Va m_pkthdr.len
326or
335or
327.Fa m_flags
336.Va m_flags
328field beforehand for statistics.
329.Fn IFQ_HANDOFF
330and
331.Fn IFQ_HANDOFF_ADJ
332can be used if only default interface statistics and an immediate call to
333.Fn if_start
334are desired.
335The caller should not use

--- 6 unchanged lines hidden (view full) ---

342.Bd -literal
343 ##old-style## ##new-style##
344 |
345 int | int
346 ether_output(ifp, m0, dst, rt0) | ether_output(ifp, m0, dst, rt0)
347 { | {
348 ...... | ......
349 |
337field beforehand for statistics.
338.Fn IFQ_HANDOFF
339and
340.Fn IFQ_HANDOFF_ADJ
341can be used if only default interface statistics and an immediate call to
342.Fn if_start
343are desired.
344The caller should not use

--- 6 unchanged lines hidden (view full) ---

351.Bd -literal
352 ##old-style## ##new-style##
353 |
354 int | int
355 ether_output(ifp, m0, dst, rt0) | ether_output(ifp, m0, dst, rt0)
356 { | {
357 ...... | ......
358 |
350 | mflags = m-\*[Gt]m_flags;
351 | len = m-\*[Gt]m_pkthdr.len;
359 | mflags = m->m_flags;
360 | len = m->m_pkthdr.len;
352 s = splimp(); | s = splimp();
361 s = splimp(); | s = splimp();
353 if (IF_QFULL(\*[Am]ifp-\*[Gt]if_snd)) { | IFQ_ENQUEUE(\*[Am]ifp-\*[Gt]if_snd, m,
362 if (IF_QFULL(&ifp->if_snd)) { | IFQ_ENQUEUE(&ifp->if_snd, m,
354 | error);
363 | error);
355 IF_DROP(\*[Am]ifp-\*[Gt]if_snd); | if (error != 0) {
364 IF_DROP(&ifp->if_snd); | if (error != 0) {
356 splx(s); | splx(s);
357 senderr(ENOBUFS); | return (error);
358 } | }
365 splx(s); | splx(s);
366 senderr(ENOBUFS); | return (error);
367 } | }
359 IF_ENQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); |
360 ifp-\*[Gt]if_obytes += | ifp-\*[Gt]if_obytes += len;
361 m-\*[Gt]m_pkthdr.len; |
362 if (m-\*[Gt]m_flags \*[Am] M_MCAST) | if (mflags \*[Am] M_MCAST)
363 ifp-\*[Gt]if_omcasts++; | ifp-\*[Gt]if_omcasts++;
368 IF_ENQUEUE(&ifp->if_snd, m); |
369 ifp->if_obytes += | ifp->if_obytes += len;
370 m->m_pkthdr.len; |
371 if (m->m_flags & M_MCAST) | if (mflags & M_MCAST)
372 ifp->if_omcasts++; | ifp->if_omcasts++;
364 |
373 |
365 if ((ifp-\*[Gt]if_flags \*[Am] IFF_OACTIVE) | if ((ifp-\*[Gt]if_flags \*[Am] IFF_OACTIVE)
374 if ((ifp->if_flags & IFF_OACTIVE) | if ((ifp->if_flags & IFF_OACTIVE)
366 == 0) | == 0)
375 == 0) | == 0)
367 (*ifp-\*[Gt]if_start)(ifp); | (*ifp-\*[Gt]if_start)(ifp);
376 (*ifp->if_start)(ifp); | (*ifp->if_start)(ifp);
368 splx(s); | splx(s);
369 return (error); | return (error);
370 |
371 bad: | bad:
372 if (m) | if (m)
373 m_freem(m); | m_freem(m);
374 return (error); | return (error);
375 } | }
376 |
377.Ed
378.Sh HOW TO CONVERT THE EXISTING DRIVERS
379First, make sure the corresponding
380.Fn if_output
381is already converted to the new style.
382.Pp
383Look for
377 splx(s); | splx(s);
378 return (error); | return (error);
379 |
380 bad: | bad:
381 if (m) | if (m)
382 m_freem(m); | m_freem(m);
383 return (error); | return (error);
384 } | }
385 |
386.Ed
387.Sh HOW TO CONVERT THE EXISTING DRIVERS
388First, make sure the corresponding
389.Fn if_output
390is already converted to the new style.
391.Pp
392Look for
384.Fa if_snd
393.Va if_snd
385in the driver.
386Probably, you need to make changes to the lines that include
394in the driver.
395Probably, you need to make changes to the lines that include
387.Fa if_snd .
396.Va if_snd .
388.Ss Empty check operation
389If the code checks
397.Ss Empty check operation
398If the code checks
390.Fa ifq_head
399.Va ifq_head
391to see whether the queue is empty or not, use
392.Fn IFQ_IS_EMPTY .
393.Bd -literal
394 ##old-style## ##new-style##
395 |
400to see whether the queue is empty or not, use
401.Fn IFQ_IS_EMPTY .
402.Bd -literal
403 ##old-style## ##new-style##
404 |
396 if (ifp-\*[Gt]if_snd.ifq_head != NULL) | if (!IFQ_IS_EMPTY(\*[Am]ifp-\*[Gt]if_snd))
405 if (ifp->if_snd.ifq_head != NULL) | if (!IFQ_IS_EMPTY(&ifp->if_snd))
397 |
398.Ed
399.Fn IFQ_IS_EMPTY
406 |
407.Ed
408.Fn IFQ_IS_EMPTY
400checks only if there is any packet stored in the queue.
409only checks if there is any packet stored in the queue.
401Note that even when
402.Fn IFQ_IS_EMPTY
403is
404.Dv FALSE ,
405.Fn IFQ_DEQUEUE
406could still return
407.Dv NULL
408if the queue is under rate-limiting.

--- 11 unchanged lines hidden (view full) ---

420.Dv FALSE ,
421.Fn IFQ_DEQUEUE
422could return
423.Dv NULL
424due to rate-limiting.
425.Bd -literal
426 ##old-style## ##new-style##
427 |
410Note that even when
411.Fn IFQ_IS_EMPTY
412is
413.Dv FALSE ,
414.Fn IFQ_DEQUEUE
415could still return
416.Dv NULL
417if the queue is under rate-limiting.

--- 11 unchanged lines hidden (view full) ---

429.Dv FALSE ,
430.Fn IFQ_DEQUEUE
431could return
432.Dv NULL
433due to rate-limiting.
434.Bd -literal
435 ##old-style## ##new-style##
436 |
428 IF_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); | IFQ_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m);
437 IF_DEQUEUE(&ifp->if_snd, m); | IFQ_DEQUEUE(&ifp->if_snd, m);
429 | if (m == NULL)
430 | return;
431 |
432.Ed
433A driver is supposed to call
434.Fn if_start
435from transmission complete interrupts in order to trigger the next dequeue.
436.Ss Poll-and-dequeue operation
437If the code polls the packet at the head of the queue and actually uses
438the packet before dequeuing it, use
439.Fn IFQ_POLL_NOLOCK
440and
441.Fn IFQ_DEQUEUE_NOLOCK .
442.Bd -literal
443 ##old-style## ##new-style##
444 |
438 | if (m == NULL)
439 | return;
440 |
441.Ed
442A driver is supposed to call
443.Fn if_start
444from transmission complete interrupts in order to trigger the next dequeue.
445.Ss Poll-and-dequeue operation
446If the code polls the packet at the head of the queue and actually uses
447the packet before dequeuing it, use
448.Fn IFQ_POLL_NOLOCK
449and
450.Fn IFQ_DEQUEUE_NOLOCK .
451.Bd -literal
452 ##old-style## ##new-style##
453 |
445 | IFQ_LOCK(\*[Am]ifp-\*[Gt]if_snd);
446 m = ifp-\*[Gt]if_snd.ifq_head; | IFQ_POLL_NOLOCK(\*[Am]ifp-\*[Gt]if_snd, m);
454 | IFQ_LOCK(&ifp->if_snd);
455 m = ifp->if_snd.ifq_head; | IFQ_POLL_NOLOCK(&ifp->if_snd, m);
447 if (m != NULL) { | if (m != NULL) {
448 |
449 /* use m to get resources */ | /* use m to get resources */
450 if (something goes wrong) | if (something goes wrong)
456 if (m != NULL) { | if (m != NULL) {
457 |
458 /* use m to get resources */ | /* use m to get resources */
459 if (something goes wrong) | if (something goes wrong)
451 | IFQ_UNLOCK(\*[Am]ifp-\*[Gt]if_snd);
460 | IFQ_UNLOCK(&ifp->if_snd);
452 return; | return;
453 |
461 return; | return;
462 |
454 IF_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); | IFQ_DEQUEUE_NOLOCK(\*[Am]ifp-\*[Gt]if_snd, m);
455 | IFQ_UNLOCK(\*[Am]ifp-\*[Gt]if_snd);
463 IF_DEQUEUE(&ifp->if_snd, m); | IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
464 | IFQ_UNLOCK(&ifp->if_snd);
456 |
457 /* kick the hardware */ | /* kick the hardware */
458 } | }
459 |
460.Ed
461It is guaranteed that
462.Fn IFQ_DEQUEUE_NOLOCK
463under the same lock as a previous
464.Fn IFQ_POLL_NOLOCK
465returns the same packet.
466Note that they need to be guarded by
467.Fn IFQ_LOCK .
465 |
466 /* kick the hardware */ | /* kick the hardware */
467 } | }
468 |
469.Ed
470It is guaranteed that
471.Fn IFQ_DEQUEUE_NOLOCK
472under the same lock as a previous
473.Fn IFQ_POLL_NOLOCK
474returns the same packet.
475Note that they need to be guarded by
476.Fn IFQ_LOCK .
468.Ss Eliminating IF_PREPEND
477.Ss Eliminating Fn IF_PREPEND
469If the code uses
470.Fn IF_PREPEND ,
471you have to eliminate it unless you can use a
478If the code uses
479.Fn IF_PREPEND ,
480you have to eliminate it unless you can use a
472.Ql driver managed
473queue which allows use of
481.Dq "driver managed"
482queue which allows the use of
474.Fn IFQ_DRV_PREPEND
475as a substitute.
483.Fn IFQ_DRV_PREPEND
484as a substitute.
476A common use of
485A common usage of
477.Fn IF_PREPEND
478is to cancel the previous dequeue operation.
479You have to convert the logic into poll-and-dequeue.
480.Bd -literal
481 ##old-style## ##new-style##
482 |
486.Fn IF_PREPEND
487is to cancel the previous dequeue operation.
488You have to convert the logic into poll-and-dequeue.
489.Bd -literal
490 ##old-style## ##new-style##
491 |
483 | IFQ_LOCK(\*[Am]ifp-\*[Gt]if_snd);
484 IF_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); | IFQ_POLL_NOLOCK(\*[Am]ifp-\*[Gt]if_snd, m);
492 | IFQ_LOCK(&ifp->if_snd);
493 IF_DEQUEUE(&ifp->if_snd, m); | IFQ_POLL_NOLOCK(&ifp->if_snd, m);
485 if (m != NULL) { | if (m != NULL) {
486 |
487 if (something_goes_wrong) { | if (something_goes_wrong) {
494 if (m != NULL) { | if (m != NULL) {
495 |
496 if (something_goes_wrong) { | if (something_goes_wrong) {
488 IF_PREPEND(\*[Am]ifp-\*[Gt]if_snd, m); | IFQ_UNLOCK(\*[Am]ifp-\*[Gt]if_snd);
497 IF_PREPEND(&ifp->if_snd, m); | IFQ_UNLOCK(&ifp->if_snd);
489 return; | return;
490 } | }
491 |
492 | /* at this point, the driver
493 | * is committed to send this
494 | * packet.
495 | */
498 return; | return;
499 } | }
500 |
501 | /* at this point, the driver
502 | * is committed to send this
503 | * packet.
504 | */
496 | IFQ_DEQUEUE_NOLOCK(\*[Am]ifp-\*[Gt]if_snd, m);
497 | IFQ_UNLOCK(\*[Am]ifp-\*[Gt]if_snd);
505 | IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
506 | IFQ_UNLOCK(&ifp->if_snd);
498 |
499 /* kick the hardware */ | /* kick the hardware */
500 } | }
501 |
502.Ed
503.Ss Purge operation
504Use
505.Fn IFQ_PURGE
506to empty the queue.
507Note that a non-work conserving queue cannot be emptied by a dequeue loop.
508.Bd -literal
509 ##old-style## ##new-style##
510 |
507 |
508 /* kick the hardware */ | /* kick the hardware */
509 } | }
510 |
511.Ed
512.Ss Purge operation
513Use
514.Fn IFQ_PURGE
515to empty the queue.
516Note that a non-work conserving queue cannot be emptied by a dequeue loop.
517.Bd -literal
518 ##old-style## ##new-style##
519 |
511 while (ifp-\*[Gt]if_snd.ifq_head != NULL) {| IFQ_PURGE(\*[Am]ifp-\*[Gt]if_snd);
512 IF_DEQUEUE(\*[Am]ifp-\*[Gt]if_snd, m); |
520 while (ifp->if_snd.ifq_head != NULL) {| IFQ_PURGE(&ifp->if_snd);
521 IF_DEQUEUE(&ifp->if_snd, m); |
513 m_freem(m); |
514 } |
515 |
516.Ed
517.Ss Conversion using a driver managed queue
518Convert
522 m_freem(m); |
523 } |
524 |
525.Ed
526.Ss Conversion using a driver managed queue
527Convert
519.Fn IF_XXX
528.Fn IF_*
520macros to their equivalent
529macros to their equivalent
521.Fn IFQ_DRV_XXX
530.Fn IFQ_DRV_*
522and employ
523.Fn IFQ_DRV_IS_EMPTY
531and employ
532.Fn IFQ_DRV_IS_EMPTY
524where appropriate
533where appropriate.
525.Bd -literal
526 ##old-style## ##new-style##
527 |
534.Bd -literal
535 ##old-style## ##new-style##
536 |
528 if (ifp-\*[Gt]if_snd.ifq_head != NULL) | if (!IFQ_DRV_IS_EMPTY(\*[Am]ifp-\*[Gt]if_snd))
537 if (ifp->if_snd.ifq_head != NULL) | if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
529 |
530.Ed
531Make sure that calls to
532.Fn IFQ_DRV_DEQUEUE ,
533.Fn IFQ_DRV_PREPEND
534and
535.Fn IFQ_DRV_PURGE
536are protected with a mutex of some kind.
537Setting
538.Dv IFF_NEEDSGIANT
539in
540.Va if_flags
541might also be appropriate.
542.Ss Attach routine
543Use
544.Fn IFQ_SET_MAXLEN
545to set
538 |
539.Ed
540Make sure that calls to
541.Fn IFQ_DRV_DEQUEUE ,
542.Fn IFQ_DRV_PREPEND
543and
544.Fn IFQ_DRV_PURGE
545are protected with a mutex of some kind.
546Setting
547.Dv IFF_NEEDSGIANT
548in
549.Va if_flags
550might also be appropriate.
551.Ss Attach routine
552Use
553.Fn IFQ_SET_MAXLEN
554to set
546.Fa ifq_maxlen
555.Va ifq_maxlen
547to
548.Fa len .
549Initialize
550.Va ifq_drv_maxlen
551with a sensible value if you plan to use the
556to
557.Fa len .
558Initialize
559.Va ifq_drv_maxlen
560with a sensible value if you plan to use the
552.Fn IFQ_DRV_XXX
561.Fn IFQ_DRV_*
553macros.
554Add
555.Fn IFQ_SET_READY
556to show this driver is converted to the new style.
557(This is used to distinguish new-style drivers.)
558.Bd -literal
559 ##old-style## ##new-style##
560 |
562macros.
563Add
564.Fn IFQ_SET_READY
565to show this driver is converted to the new style.
566(This is used to distinguish new-style drivers.)
567.Bd -literal
568 ##old-style## ##new-style##
569 |
561 ifp-\*[Gt]if_snd.ifq_maxlen = qsize; | IFQ_SET_MAXLEN(\*[Am]ifp-\*[Gt]if_snd, qsize);
562 | ifp-\*[Gt]if_snd.ifq_drv_maxlen = qsize;
563 | IFQ_SET_READY(\*[Am]ifp-\*[Gt]if_snd);
570 ifp->if_snd.ifq_maxlen = qsize; | IFQ_SET_MAXLEN(&ifp->if_snd, qsize);
571 | ifp->if_snd.ifq_drv_maxlen = qsize;
572 | IFQ_SET_READY(&ifp->if_snd);
564 if_attach(ifp); | if_attach(ifp);
565 |
566.Ed
567.Ss Other issues
568The new macros for statistics:
569.Bd -literal
570 ##old-style## ##new-style##
571 |
573 if_attach(ifp); | if_attach(ifp);
574 |
575.Ed
576.Ss Other issues
577The new macros for statistics:
578.Bd -literal
579 ##old-style## ##new-style##
580 |
572 IF_DROP(\*[Am]ifp-\*[Gt]if_snd); | IFQ_INC_DROPS(\*[Am]ifp-\*[Gt]if_snd);
581 IF_DROP(&ifp->if_snd); | IFQ_INC_DROPS(&ifp->if_snd);
573 |
582 |
574 ifp-\*[Gt]if_snd.ifq_len++; | IFQ_INC_LEN(\*[Am]ifp-\*[Gt]if_snd);
583 ifp->if_snd.ifq_len++; | IFQ_INC_LEN(&ifp->if_snd);
575 |
584 |
576 ifp-\*[Gt]if_snd.ifq_len--; | IFQ_DEC_LEN(\*[Am]ifp-\*[Gt]if_snd);
585 ifp->if_snd.ifq_len--; | IFQ_DEC_LEN(&ifp->if_snd);
577 |
578.Ed
579.Sh QUEUING DISCIPLINES
580Queuing disciplines need to maintain
581.Fa ifq_len
586 |
587.Ed
588.Sh QUEUING DISCIPLINES
589Queuing disciplines need to maintain
590.Fa ifq_len
582.Po
583used by
584.Fn IFQ_IS_EMPTY
585.Pc .
586Queuing disciplines also need to guarantee the same mbuf is returned if
591(used by
592.Fn IFQ_IS_EMPTY ) .
593Queuing disciplines also need to guarantee that the same mbuf is returned if
587.Fn IFQ_DEQUEUE
588is called immediately after
589.Fn IFQ_POLL .
590.Sh SEE ALSO
591.Xr pf 4 ,
594.Fn IFQ_DEQUEUE
595is called immediately after
596.Fn IFQ_POLL .
597.Sh SEE ALSO
598.Xr pf 4 ,
592.Xr pf.conf 5
599.Xr pf.conf 5 ,
593.Xr pfctl 8
594.Sh HISTORY
595The
596.Nm
597system first appeared in March 1997.
600.Xr pfctl 8
601.Sh HISTORY
602The
603.Nm
604system first appeared in March 1997.