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