xref: /freebsd/sys/net/ifq.h (revision 93e779a26c651610ac6e7986d67ecc9ed2cadcbf)
1 /*-
2  * Copyright (c) 1982, 1986, 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 4. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
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  *	From: @(#)if.h	8.1 (Berkeley) 6/10/93
30  * $FreeBSD$
31  */
32 
33 #ifndef	_NET_IFQ_H_
34 #define	_NET_IFQ_H_
35 
36 #ifdef _KERNEL
37 #include <sys/mbuf.h>		/* ifqueue only? */
38 #include <sys/buf_ring.h>
39 #include <net/vnet.h>
40 #endif /* _KERNEL */
41 #include <sys/lock.h>		/* XXX */
42 #include <sys/mutex.h>		/* struct ifqueue */
43 
44 /*
45  * Couple of ugly extra definitions that are required since ifq.h
46  * is splitted from if_var.h.
47  */
48 #define	IF_DUNIT_NONE	-1
49 
50 #include <net/altq/if_altq.h>
51 
52 /*
53  * Structure defining a queue for a network interface.
54  */
55 struct	ifqueue {
56 	struct	mbuf *ifq_head;
57 	struct	mbuf *ifq_tail;
58 	int	ifq_len;
59 	int	ifq_maxlen;
60 	struct	mtx ifq_mtx;
61 };
62 
63 #ifdef _KERNEL
64 /*
65  * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq)
66  * are queues of messages stored on ifqueue structures
67  * (defined above).  Entries are added to and deleted from these structures
68  * by these macros.
69  */
70 #define IF_LOCK(ifq)		mtx_lock(&(ifq)->ifq_mtx)
71 #define IF_UNLOCK(ifq)		mtx_unlock(&(ifq)->ifq_mtx)
72 #define	IF_LOCK_ASSERT(ifq)	mtx_assert(&(ifq)->ifq_mtx, MA_OWNED)
73 #define	_IF_QFULL(ifq)		((ifq)->ifq_len >= (ifq)->ifq_maxlen)
74 #define	_IF_QLEN(ifq)		((ifq)->ifq_len)
75 
76 #define	_IF_ENQUEUE(ifq, m) do { 				\
77 	(m)->m_nextpkt = NULL;					\
78 	if ((ifq)->ifq_tail == NULL) 				\
79 		(ifq)->ifq_head = m; 				\
80 	else 							\
81 		(ifq)->ifq_tail->m_nextpkt = m; 		\
82 	(ifq)->ifq_tail = m; 					\
83 	(ifq)->ifq_len++; 					\
84 } while (0)
85 
86 #define IF_ENQUEUE(ifq, m) do {					\
87 	IF_LOCK(ifq); 						\
88 	_IF_ENQUEUE(ifq, m); 					\
89 	IF_UNLOCK(ifq); 					\
90 } while (0)
91 
92 #define	_IF_PREPEND(ifq, m) do {				\
93 	(m)->m_nextpkt = (ifq)->ifq_head; 			\
94 	if ((ifq)->ifq_tail == NULL) 				\
95 		(ifq)->ifq_tail = (m); 				\
96 	(ifq)->ifq_head = (m); 					\
97 	(ifq)->ifq_len++; 					\
98 } while (0)
99 
100 #define IF_PREPEND(ifq, m) do {		 			\
101 	IF_LOCK(ifq); 						\
102 	_IF_PREPEND(ifq, m); 					\
103 	IF_UNLOCK(ifq); 					\
104 } while (0)
105 
106 #define	_IF_DEQUEUE(ifq, m) do { 				\
107 	(m) = (ifq)->ifq_head; 					\
108 	if (m) { 						\
109 		if (((ifq)->ifq_head = (m)->m_nextpkt) == NULL)	\
110 			(ifq)->ifq_tail = NULL; 		\
111 		(m)->m_nextpkt = NULL; 				\
112 		(ifq)->ifq_len--; 				\
113 	} 							\
114 } while (0)
115 
116 #define IF_DEQUEUE(ifq, m) do { 				\
117 	IF_LOCK(ifq); 						\
118 	_IF_DEQUEUE(ifq, m); 					\
119 	IF_UNLOCK(ifq); 					\
120 } while (0)
121 
122 #define	_IF_DEQUEUE_ALL(ifq, m) do {				\
123 	(m) = (ifq)->ifq_head;					\
124 	(ifq)->ifq_head = (ifq)->ifq_tail = NULL;		\
125 	(ifq)->ifq_len = 0;					\
126 } while (0)
127 
128 #define	IF_DEQUEUE_ALL(ifq, m) do {				\
129 	IF_LOCK(ifq); 						\
130 	_IF_DEQUEUE_ALL(ifq, m);				\
131 	IF_UNLOCK(ifq); 					\
132 } while (0)
133 
134 #define	_IF_POLL(ifq, m)	((m) = (ifq)->ifq_head)
135 #define	IF_POLL(ifq, m)		_IF_POLL(ifq, m)
136 
137 #define _IF_DRAIN(ifq) do { 					\
138 	struct mbuf *m; 					\
139 	for (;;) { 						\
140 		_IF_DEQUEUE(ifq, m); 				\
141 		if (m == NULL) 					\
142 			break; 					\
143 		m_freem(m); 					\
144 	} 							\
145 } while (0)
146 
147 #define IF_DRAIN(ifq) do {					\
148 	IF_LOCK(ifq);						\
149 	_IF_DRAIN(ifq);						\
150 	IF_UNLOCK(ifq);						\
151 } while(0)
152 
153 int	if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp,
154 	    int adjust);
155 #define	IF_HANDOFF(ifq, m, ifp)			\
156 	if_handoff((struct ifqueue *)ifq, m, ifp, 0)
157 #define	IF_HANDOFF_ADJ(ifq, m, ifp, adj)	\
158 	if_handoff((struct ifqueue *)ifq, m, ifp, adj)
159 
160 void	if_start(struct ifnet *);
161 
162 #define	IFQ_ENQUEUE(ifq, m, err)					\
163 do {									\
164 	IF_LOCK(ifq);							\
165 	if (ALTQ_IS_ENABLED(ifq))					\
166 		ALTQ_ENQUEUE(ifq, m, NULL, err);			\
167 	else {								\
168 		if (_IF_QFULL(ifq)) {					\
169 			m_freem(m);					\
170 			(err) = ENOBUFS;				\
171 		} else {						\
172 			_IF_ENQUEUE(ifq, m);				\
173 			(err) = 0;					\
174 		}							\
175 	}								\
176 	IF_UNLOCK(ifq);							\
177 } while (0)
178 
179 #define	IFQ_DEQUEUE_NOLOCK(ifq, m)					\
180 do {									\
181 	if (TBR_IS_ENABLED(ifq))					\
182 		(m) = tbr_dequeue_ptr(ifq, ALTDQ_REMOVE);		\
183 	else if (ALTQ_IS_ENABLED(ifq))					\
184 		ALTQ_DEQUEUE(ifq, m);					\
185 	else								\
186 		_IF_DEQUEUE(ifq, m);					\
187 } while (0)
188 
189 #define	IFQ_DEQUEUE(ifq, m)						\
190 do {									\
191 	IF_LOCK(ifq);							\
192 	IFQ_DEQUEUE_NOLOCK(ifq, m);					\
193 	IF_UNLOCK(ifq);							\
194 } while (0)
195 
196 #define	IFQ_POLL_NOLOCK(ifq, m)						\
197 do {									\
198 	if (TBR_IS_ENABLED(ifq))					\
199 		(m) = tbr_dequeue_ptr(ifq, ALTDQ_POLL);			\
200 	else if (ALTQ_IS_ENABLED(ifq))					\
201 		ALTQ_POLL(ifq, m);					\
202 	else								\
203 		_IF_POLL(ifq, m);					\
204 } while (0)
205 
206 #define	IFQ_POLL(ifq, m)						\
207 do {									\
208 	IF_LOCK(ifq);							\
209 	IFQ_POLL_NOLOCK(ifq, m);					\
210 	IF_UNLOCK(ifq);							\
211 } while (0)
212 
213 #define	IFQ_PURGE_NOLOCK(ifq)						\
214 do {									\
215 	if (ALTQ_IS_ENABLED(ifq)) {					\
216 		ALTQ_PURGE(ifq);					\
217 	} else								\
218 		_IF_DRAIN(ifq);						\
219 } while (0)
220 
221 #define	IFQ_PURGE(ifq)							\
222 do {									\
223 	IF_LOCK(ifq);							\
224 	IFQ_PURGE_NOLOCK(ifq);						\
225 	IF_UNLOCK(ifq);							\
226 } while (0)
227 
228 #define	IFQ_SET_READY(ifq)						\
229 	do { ((ifq)->altq_flags |= ALTQF_READY); } while (0)
230 
231 #define	IFQ_LOCK(ifq)			IF_LOCK(ifq)
232 #define	IFQ_UNLOCK(ifq)			IF_UNLOCK(ifq)
233 #define	IFQ_LOCK_ASSERT(ifq)		IF_LOCK_ASSERT(ifq)
234 #define	IFQ_IS_EMPTY(ifq)		((ifq)->ifq_len == 0)
235 #define	IFQ_INC_LEN(ifq)		((ifq)->ifq_len++)
236 #define	IFQ_DEC_LEN(ifq)		(--(ifq)->ifq_len)
237 #define	IFQ_SET_MAXLEN(ifq, len)	((ifq)->ifq_maxlen = (len))
238 
239 /*
240  * The IFF_DRV_OACTIVE test should really occur in the device driver, not in
241  * the handoff logic, as that flag is locked by the device driver.
242  */
243 #define	IFQ_HANDOFF_ADJ(ifp, m, adj, err)				\
244 do {									\
245 	int len;							\
246 	short mflags;							\
247 									\
248 	len = (m)->m_pkthdr.len;					\
249 	mflags = (m)->m_flags;						\
250 	IFQ_ENQUEUE(&(ifp)->if_snd, m, err);				\
251 	if ((err) == 0) {						\
252 		if_inc_counter((ifp), IFCOUNTER_OBYTES, len + (adj));	\
253 		if (mflags & M_MCAST)					\
254 			if_inc_counter((ifp), IFCOUNTER_OMCASTS, 1);	\
255 		if (((ifp)->if_drv_flags & IFF_DRV_OACTIVE) == 0)	\
256 			if_start(ifp);					\
257 	} else								\
258 		if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1);		\
259 } while (0)
260 
261 #define	IFQ_HANDOFF(ifp, m, err)					\
262 	IFQ_HANDOFF_ADJ(ifp, m, 0, err)
263 
264 #define	IFQ_DRV_DEQUEUE(ifq, m)						\
265 do {									\
266 	(m) = (ifq)->ifq_drv_head;					\
267 	if (m) {							\
268 		if (((ifq)->ifq_drv_head = (m)->m_nextpkt) == NULL)	\
269 			(ifq)->ifq_drv_tail = NULL;			\
270 		(m)->m_nextpkt = NULL;					\
271 		(ifq)->ifq_drv_len--;					\
272 	} else {							\
273 		IFQ_LOCK(ifq);						\
274 		IFQ_DEQUEUE_NOLOCK(ifq, m);				\
275 		while ((ifq)->ifq_drv_len < (ifq)->ifq_drv_maxlen) {	\
276 			struct mbuf *m0;				\
277 			IFQ_DEQUEUE_NOLOCK(ifq, m0);			\
278 			if (m0 == NULL)					\
279 				break;					\
280 			m0->m_nextpkt = NULL;				\
281 			if ((ifq)->ifq_drv_tail == NULL)		\
282 				(ifq)->ifq_drv_head = m0;		\
283 			else						\
284 				(ifq)->ifq_drv_tail->m_nextpkt = m0;	\
285 			(ifq)->ifq_drv_tail = m0;			\
286 			(ifq)->ifq_drv_len++;				\
287 		}							\
288 		IFQ_UNLOCK(ifq);					\
289 	}								\
290 } while (0)
291 
292 #define	IFQ_DRV_PREPEND(ifq, m)						\
293 do {									\
294 	(m)->m_nextpkt = (ifq)->ifq_drv_head;				\
295 	if ((ifq)->ifq_drv_tail == NULL)				\
296 		(ifq)->ifq_drv_tail = (m);				\
297 	(ifq)->ifq_drv_head = (m);					\
298 	(ifq)->ifq_drv_len++;						\
299 } while (0)
300 
301 #define	IFQ_DRV_IS_EMPTY(ifq)						\
302 	(((ifq)->ifq_drv_len == 0) && ((ifq)->ifq_len == 0))
303 
304 #define	IFQ_DRV_PURGE(ifq)						\
305 do {									\
306 	struct mbuf *m, *n = (ifq)->ifq_drv_head;			\
307 	while((m = n) != NULL) {					\
308 		n = m->m_nextpkt;					\
309 		m_freem(m);						\
310 	}								\
311 	(ifq)->ifq_drv_head = (ifq)->ifq_drv_tail = NULL;		\
312 	(ifq)->ifq_drv_len = 0;						\
313 	IFQ_PURGE(ifq);							\
314 } while (0)
315 
316 static __inline int
317 drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
318 {
319 	int error = 0;
320 
321 #ifdef ALTQ
322 	if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
323 		IFQ_ENQUEUE(&ifp->if_snd, m, error);
324 		if (error)
325 			if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1);
326 		return (error);
327 	}
328 #endif
329 	error = buf_ring_enqueue(br, m);
330 	if (error)
331 		m_freem(m);
332 
333 	return (error);
334 }
335 
336 static __inline void
337 drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *new)
338 {
339 	/*
340 	 * The top of the list needs to be swapped
341 	 * for this one.
342 	 */
343 #ifdef ALTQ
344 	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
345 		/*
346 		 * Peek in altq case dequeued it
347 		 * so put it back.
348 		 */
349 		IFQ_DRV_PREPEND(&ifp->if_snd, new);
350 		return;
351 	}
352 #endif
353 	buf_ring_putback_sc(br, new);
354 }
355 
356 static __inline struct mbuf *
357 drbr_peek(struct ifnet *ifp, struct buf_ring *br)
358 {
359 #ifdef ALTQ
360 	struct mbuf *m;
361 	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
362 		/*
363 		 * Pull it off like a dequeue
364 		 * since drbr_advance() does nothing
365 		 * for altq and drbr_putback() will
366 		 * use the old prepend function.
367 		 */
368 		IFQ_DEQUEUE(&ifp->if_snd, m);
369 		return (m);
370 	}
371 #endif
372 	return(buf_ring_peek(br));
373 }
374 
375 static __inline void
376 drbr_flush(struct ifnet *ifp, struct buf_ring *br)
377 {
378 	struct mbuf *m;
379 
380 #ifdef ALTQ
381 	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
382 		IFQ_PURGE(&ifp->if_snd);
383 #endif
384 	while ((m = buf_ring_dequeue_sc(br)) != NULL)
385 		m_freem(m);
386 }
387 
388 static __inline void
389 drbr_free(struct buf_ring *br, struct malloc_type *type)
390 {
391 
392 	drbr_flush(NULL, br);
393 	buf_ring_free(br, type);
394 }
395 
396 static __inline struct mbuf *
397 drbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
398 {
399 #ifdef ALTQ
400 	struct mbuf *m;
401 
402 	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
403 		IFQ_DEQUEUE(&ifp->if_snd, m);
404 		return (m);
405 	}
406 #endif
407 	return (buf_ring_dequeue_sc(br));
408 }
409 
410 static __inline void
411 drbr_advance(struct ifnet *ifp, struct buf_ring *br)
412 {
413 #ifdef ALTQ
414 	/* Nothing to do here since peek dequeues in altq case */
415 	if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
416 		return;
417 #endif
418 	return (buf_ring_advance_sc(br));
419 }
420 
421 
422 static __inline struct mbuf *
423 drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
424     int (*func) (struct mbuf *, void *), void *arg)
425 {
426 	struct mbuf *m;
427 #ifdef ALTQ
428 	if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
429 		IFQ_LOCK(&ifp->if_snd);
430 		IFQ_POLL_NOLOCK(&ifp->if_snd, m);
431 		if (m != NULL && func(m, arg) == 0) {
432 			IFQ_UNLOCK(&ifp->if_snd);
433 			return (NULL);
434 		}
435 		IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
436 		IFQ_UNLOCK(&ifp->if_snd);
437 		return (m);
438 	}
439 #endif
440 	m = buf_ring_peek(br);
441 	if (m == NULL || func(m, arg) == 0)
442 		return (NULL);
443 
444 	return (buf_ring_dequeue_sc(br));
445 }
446 
447 static __inline int
448 drbr_empty(struct ifnet *ifp, struct buf_ring *br)
449 {
450 #ifdef ALTQ
451 	if (ALTQ_IS_ENABLED(&ifp->if_snd))
452 		return (IFQ_IS_EMPTY(&ifp->if_snd));
453 #endif
454 	return (buf_ring_empty(br));
455 }
456 
457 static __inline int
458 drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
459 {
460 #ifdef ALTQ
461 	if (ALTQ_IS_ENABLED(&ifp->if_snd))
462 		return (1);
463 #endif
464 	return (!buf_ring_empty(br));
465 }
466 
467 static __inline int
468 drbr_inuse(struct ifnet *ifp, struct buf_ring *br)
469 {
470 #ifdef ALTQ
471 	if (ALTQ_IS_ENABLED(&ifp->if_snd))
472 		return (ifp->if_snd.ifq_len);
473 #endif
474 	return (buf_ring_count(br));
475 }
476 
477 extern	int ifqmaxlen;
478 
479 void	if_qflush(struct ifnet *);
480 void	ifq_init(struct ifaltq *, struct ifnet *ifp);
481 void	ifq_delete(struct ifaltq *);
482 
483 #endif /* _KERNEL */
484 #endif /* !_NET_IFQ_H_ */
485