2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * From: @(#)if.h 8.1 (Berkeley) 6/10/93
39 #include <sys/mbuf.h> /* ifqueue only? */
40 #include <sys/buf_ring.h>
43 #include <sys/lock.h> /* XXX */
44 #include <sys/mutex.h> /* struct ifqueue */
47 * Couple of ugly extra definitions that are required since ifq.h
48 * is splitted from if_var.h.
50 #define IF_DUNIT_NONE -1
52 #include <net/altq/if_altq.h>
55 * Structure defining a queue for a network interface.
58 struct mbuf *ifq_head;
59 struct mbuf *ifq_tail;
67 * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq)
68 * are queues of messages stored on ifqueue structures
69 * (defined above). Entries are added to and deleted from these structures
72 #define IF_LOCK(ifq) mtx_lock(&(ifq)->ifq_mtx)
73 #define IF_UNLOCK(ifq) mtx_unlock(&(ifq)->ifq_mtx)
74 #define IF_LOCK_ASSERT(ifq) mtx_assert(&(ifq)->ifq_mtx, MA_OWNED)
75 #define _IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen)
76 #define _IF_QLEN(ifq) ((ifq)->ifq_len)
78 #define _IF_ENQUEUE(ifq, m) do { \
79 (m)->m_nextpkt = NULL; \
80 if ((ifq)->ifq_tail == NULL) \
81 (ifq)->ifq_head = m; \
83 (ifq)->ifq_tail->m_nextpkt = m; \
84 (ifq)->ifq_tail = m; \
88 #define IF_ENQUEUE(ifq, m) do { \
90 _IF_ENQUEUE(ifq, m); \
94 #define _IF_PREPEND(ifq, m) do { \
95 (m)->m_nextpkt = (ifq)->ifq_head; \
96 if ((ifq)->ifq_tail == NULL) \
97 (ifq)->ifq_tail = (m); \
98 (ifq)->ifq_head = (m); \
102 #define IF_PREPEND(ifq, m) do { \
104 _IF_PREPEND(ifq, m); \
108 #define _IF_DEQUEUE(ifq, m) do { \
109 (m) = (ifq)->ifq_head; \
111 if (((ifq)->ifq_head = (m)->m_nextpkt) == NULL) \
112 (ifq)->ifq_tail = NULL; \
113 (m)->m_nextpkt = NULL; \
118 #define IF_DEQUEUE(ifq, m) do { \
120 _IF_DEQUEUE(ifq, m); \
124 #define _IF_DEQUEUE_ALL(ifq, m) do { \
125 (m) = (ifq)->ifq_head; \
126 (ifq)->ifq_head = (ifq)->ifq_tail = NULL; \
127 (ifq)->ifq_len = 0; \
130 #define IF_DEQUEUE_ALL(ifq, m) do { \
132 _IF_DEQUEUE_ALL(ifq, m); \
136 #define _IF_POLL(ifq, m) ((m) = (ifq)->ifq_head)
137 #define IF_POLL(ifq, m) _IF_POLL(ifq, m)
139 #define _IF_DRAIN(ifq) do { \
142 _IF_DEQUEUE(ifq, m); \
149 #define IF_DRAIN(ifq) do { \
155 int if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp,
157 #define IF_HANDOFF(ifq, m, ifp) \
158 if_handoff((struct ifqueue *)ifq, m, ifp, 0)
159 #define IF_HANDOFF_ADJ(ifq, m, ifp, adj) \
160 if_handoff((struct ifqueue *)ifq, m, ifp, adj)
162 void if_start(struct ifnet *);
164 #define IFQ_ENQUEUE(ifq, m, err) \
167 if (ALTQ_IS_ENABLED(ifq)) \
168 ALTQ_ENQUEUE(ifq, m, NULL, err); \
170 if (_IF_QFULL(ifq)) { \
174 _IF_ENQUEUE(ifq, m); \
181 #define IFQ_DEQUEUE_NOLOCK(ifq, m) \
183 if (TBR_IS_ENABLED(ifq)) \
184 (m) = tbr_dequeue_ptr(ifq, ALTDQ_REMOVE); \
185 else if (ALTQ_IS_ENABLED(ifq)) \
186 ALTQ_DEQUEUE(ifq, m); \
188 _IF_DEQUEUE(ifq, m); \
191 #define IFQ_DEQUEUE(ifq, m) \
194 IFQ_DEQUEUE_NOLOCK(ifq, m); \
198 #define IFQ_POLL_NOLOCK(ifq, m) \
200 if (TBR_IS_ENABLED(ifq)) \
201 (m) = tbr_dequeue_ptr(ifq, ALTDQ_POLL); \
202 else if (ALTQ_IS_ENABLED(ifq)) \
208 #define IFQ_POLL(ifq, m) \
211 IFQ_POLL_NOLOCK(ifq, m); \
215 #define IFQ_PURGE_NOLOCK(ifq) \
217 if (ALTQ_IS_ENABLED(ifq)) { \
223 #define IFQ_PURGE(ifq) \
226 IFQ_PURGE_NOLOCK(ifq); \
230 #define IFQ_SET_READY(ifq) \
231 do { ((ifq)->altq_flags |= ALTQF_READY); } while (0)
233 #define IFQ_LOCK(ifq) IF_LOCK(ifq)
234 #define IFQ_UNLOCK(ifq) IF_UNLOCK(ifq)
235 #define IFQ_LOCK_ASSERT(ifq) IF_LOCK_ASSERT(ifq)
236 #define IFQ_IS_EMPTY(ifq) ((ifq)->ifq_len == 0)
237 #define IFQ_INC_LEN(ifq) ((ifq)->ifq_len++)
238 #define IFQ_DEC_LEN(ifq) (--(ifq)->ifq_len)
239 #define IFQ_SET_MAXLEN(ifq, len) ((ifq)->ifq_maxlen = (len))
242 * The IFF_DRV_OACTIVE test should really occur in the device driver, not in
243 * the handoff logic, as that flag is locked by the device driver.
245 #define IFQ_HANDOFF_ADJ(ifp, m, adj, err) \
250 len = (m)->m_pkthdr.len; \
251 mflags = (m)->m_flags; \
252 IFQ_ENQUEUE(&(ifp)->if_snd, m, err); \
254 if_inc_counter((ifp), IFCOUNTER_OBYTES, len + (adj)); \
255 if (mflags & M_MCAST) \
256 if_inc_counter((ifp), IFCOUNTER_OMCASTS, 1); \
257 if (((ifp)->if_drv_flags & IFF_DRV_OACTIVE) == 0) \
260 if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1); \
263 #define IFQ_HANDOFF(ifp, m, err) \
264 IFQ_HANDOFF_ADJ(ifp, m, 0, err)
266 #define IFQ_DRV_DEQUEUE(ifq, m) \
268 (m) = (ifq)->ifq_drv_head; \
270 if (((ifq)->ifq_drv_head = (m)->m_nextpkt) == NULL) \
271 (ifq)->ifq_drv_tail = NULL; \
272 (m)->m_nextpkt = NULL; \
273 (ifq)->ifq_drv_len--; \
276 IFQ_DEQUEUE_NOLOCK(ifq, m); \
277 while ((ifq)->ifq_drv_len < (ifq)->ifq_drv_maxlen) { \
279 IFQ_DEQUEUE_NOLOCK(ifq, m0); \
282 m0->m_nextpkt = NULL; \
283 if ((ifq)->ifq_drv_tail == NULL) \
284 (ifq)->ifq_drv_head = m0; \
286 (ifq)->ifq_drv_tail->m_nextpkt = m0; \
287 (ifq)->ifq_drv_tail = m0; \
288 (ifq)->ifq_drv_len++; \
294 #define IFQ_DRV_PREPEND(ifq, m) \
296 (m)->m_nextpkt = (ifq)->ifq_drv_head; \
297 if ((ifq)->ifq_drv_tail == NULL) \
298 (ifq)->ifq_drv_tail = (m); \
299 (ifq)->ifq_drv_head = (m); \
300 (ifq)->ifq_drv_len++; \
303 #define IFQ_DRV_IS_EMPTY(ifq) \
304 (((ifq)->ifq_drv_len == 0) && ((ifq)->ifq_len == 0))
306 #define IFQ_DRV_PURGE(ifq) \
308 struct mbuf *m, *n = (ifq)->ifq_drv_head; \
309 while((m = n) != NULL) { \
313 (ifq)->ifq_drv_head = (ifq)->ifq_drv_tail = NULL; \
314 (ifq)->ifq_drv_len = 0; \
319 drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
324 if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
325 IFQ_ENQUEUE(&ifp->if_snd, m, error);
327 if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1);
331 error = buf_ring_enqueue(br, m);
339 drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *new)
342 * The top of the list needs to be swapped
346 if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
348 * Peek in altq case dequeued it
351 IFQ_DRV_PREPEND(&ifp->if_snd, new);
355 buf_ring_putback_sc(br, new);
358 static __inline struct mbuf *
359 drbr_peek(struct ifnet *ifp, struct buf_ring *br)
363 if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
365 * Pull it off like a dequeue
366 * since drbr_advance() does nothing
367 * for altq and drbr_putback() will
368 * use the old prepend function.
370 IFQ_DEQUEUE(&ifp->if_snd, m);
374 return(buf_ring_peek_clear_sc(br));
378 drbr_flush(struct ifnet *ifp, struct buf_ring *br)
383 if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
384 IFQ_PURGE(&ifp->if_snd);
386 while ((m = buf_ring_dequeue_sc(br)) != NULL)
391 drbr_free(struct buf_ring *br, struct malloc_type *type)
394 drbr_flush(NULL, br);
395 buf_ring_free(br, type);
398 static __inline struct mbuf *
399 drbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
404 if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
405 IFQ_DEQUEUE(&ifp->if_snd, m);
409 return (buf_ring_dequeue_sc(br));
413 drbr_advance(struct ifnet *ifp, struct buf_ring *br)
416 /* Nothing to do here since peek dequeues in altq case */
417 if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
420 return (buf_ring_advance_sc(br));
424 static __inline struct mbuf *
425 drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
426 int (*func) (struct mbuf *, void *), void *arg)
430 if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
431 IFQ_LOCK(&ifp->if_snd);
432 IFQ_POLL_NOLOCK(&ifp->if_snd, m);
433 if (m != NULL && func(m, arg) == 0) {
434 IFQ_UNLOCK(&ifp->if_snd);
437 IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
438 IFQ_UNLOCK(&ifp->if_snd);
442 m = buf_ring_peek(br);
443 if (m == NULL || func(m, arg) == 0)
446 return (buf_ring_dequeue_sc(br));
450 drbr_empty(struct ifnet *ifp, struct buf_ring *br)
453 if (ALTQ_IS_ENABLED(&ifp->if_snd))
454 return (IFQ_IS_EMPTY(&ifp->if_snd));
456 return (buf_ring_empty(br));
460 drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
463 if (ALTQ_IS_ENABLED(&ifp->if_snd))
466 return (!buf_ring_empty(br));
470 drbr_inuse(struct ifnet *ifp, struct buf_ring *br)
473 if (ALTQ_IS_ENABLED(&ifp->if_snd))
474 return (ifp->if_snd.ifq_len);
476 return (buf_ring_count(br));
479 extern int ifqmaxlen;
481 void if_qflush(struct ifnet *);
482 void ifq_init(struct ifaltq *, struct ifnet *ifp);
483 void ifq_delete(struct ifaltq *);
486 #endif /* !_NET_IFQ_H_ */