]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/ifq.h
Merge llvm-project release/16.x llvmorg-16.0.3-0-gda3cd333bea5
[FreeBSD/FreeBSD.git] / sys / net / ifq.h
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1982, 1986, 1989, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
18  *
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
29  * SUCH DAMAGE.
30  *
31  *      From: @(#)if.h  8.1 (Berkeley) 6/10/93
32  * $FreeBSD$
33  */
34
35 #ifndef _NET_IFQ_H_
36 #define _NET_IFQ_H_
37
38 #ifdef _KERNEL
39 #include <sys/mbuf.h>           /* ifqueue only? */
40 #include <sys/buf_ring.h>
41 #include <net/vnet.h>
42 #endif /* _KERNEL */
43 #include <sys/lock.h>           /* XXX */
44 #include <sys/mutex.h>          /* struct ifqueue */
45
46 /*
47  * Couple of ugly extra definitions that are required since ifq.h
48  * is splitted from if_var.h.
49  */
50 #define IF_DUNIT_NONE   -1
51
52 #include <net/altq/if_altq.h>
53
54 /*
55  * Structure defining a queue for a network interface.
56  */
57 struct  ifqueue {
58         struct  mbuf *ifq_head;
59         struct  mbuf *ifq_tail;
60         int     ifq_len;
61         int     ifq_maxlen;
62         struct  mtx ifq_mtx;
63 };
64
65 #ifdef _KERNEL
66 /*
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
70  * by these macros.
71  */
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)
77
78 #define _IF_ENQUEUE(ifq, m) do {                                \
79         (m)->m_nextpkt = NULL;                                  \
80         if ((ifq)->ifq_tail == NULL)                            \
81                 (ifq)->ifq_head = m;                            \
82         else                                                    \
83                 (ifq)->ifq_tail->m_nextpkt = m;                 \
84         (ifq)->ifq_tail = m;                                    \
85         (ifq)->ifq_len++;                                       \
86 } while (0)
87
88 #define IF_ENQUEUE(ifq, m) do {                                 \
89         IF_LOCK(ifq);                                           \
90         _IF_ENQUEUE(ifq, m);                                    \
91         IF_UNLOCK(ifq);                                         \
92 } while (0)
93
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);                                  \
99         (ifq)->ifq_len++;                                       \
100 } while (0)
101
102 #define IF_PREPEND(ifq, m) do {                                 \
103         IF_LOCK(ifq);                                           \
104         _IF_PREPEND(ifq, m);                                    \
105         IF_UNLOCK(ifq);                                         \
106 } while (0)
107
108 #define _IF_DEQUEUE(ifq, m) do {                                \
109         (m) = (ifq)->ifq_head;                                  \
110         if (m) {                                                \
111                 if (((ifq)->ifq_head = (m)->m_nextpkt) == NULL) \
112                         (ifq)->ifq_tail = NULL;                 \
113                 (m)->m_nextpkt = NULL;                          \
114                 (ifq)->ifq_len--;                               \
115         }                                                       \
116 } while (0)
117
118 #define IF_DEQUEUE(ifq, m) do {                                 \
119         IF_LOCK(ifq);                                           \
120         _IF_DEQUEUE(ifq, m);                                    \
121         IF_UNLOCK(ifq);                                         \
122 } while (0)
123
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;                                     \
128 } while (0)
129
130 #define IF_DEQUEUE_ALL(ifq, m) do {                             \
131         IF_LOCK(ifq);                                           \
132         _IF_DEQUEUE_ALL(ifq, m);                                \
133         IF_UNLOCK(ifq);                                         \
134 } while (0)
135
136 #define _IF_POLL(ifq, m)        ((m) = (ifq)->ifq_head)
137 #define IF_POLL(ifq, m)         _IF_POLL(ifq, m)
138
139 #define _IF_DRAIN(ifq) do {                                     \
140         struct mbuf *m;                                         \
141         for (;;) {                                              \
142                 _IF_DEQUEUE(ifq, m);                            \
143                 if (m == NULL)                                  \
144                         break;                                  \
145                 m_freem(m);                                     \
146         }                                                       \
147 } while (0)
148
149 #define IF_DRAIN(ifq) do {                                      \
150         IF_LOCK(ifq);                                           \
151         _IF_DRAIN(ifq);                                         \
152         IF_UNLOCK(ifq);                                         \
153 } while(0)
154
155 int     if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp,
156             int adjust);
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)
161
162 void    if_start(struct ifnet *);
163
164 #define IFQ_ENQUEUE(ifq, m, err)                                        \
165 do {                                                                    \
166         IF_LOCK(ifq);                                                   \
167         if (ALTQ_IS_ENABLED(ifq))                                       \
168                 ALTQ_ENQUEUE(ifq, m, NULL, err);                        \
169         else {                                                          \
170                 if (_IF_QFULL(ifq)) {                                   \
171                         m_freem(m);                                     \
172                         (err) = ENOBUFS;                                \
173                 } else {                                                \
174                         _IF_ENQUEUE(ifq, m);                            \
175                         (err) = 0;                                      \
176                 }                                                       \
177         }                                                               \
178         IF_UNLOCK(ifq);                                                 \
179 } while (0)
180
181 #define IFQ_DEQUEUE_NOLOCK(ifq, m)                                      \
182 do {                                                                    \
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);                                   \
187         else                                                            \
188                 _IF_DEQUEUE(ifq, m);                                    \
189 } while (0)
190
191 #define IFQ_DEQUEUE(ifq, m)                                             \
192 do {                                                                    \
193         IF_LOCK(ifq);                                                   \
194         IFQ_DEQUEUE_NOLOCK(ifq, m);                                     \
195         IF_UNLOCK(ifq);                                                 \
196 } while (0)
197
198 #define IFQ_POLL_NOLOCK(ifq, m)                                         \
199 do {                                                                    \
200         if (TBR_IS_ENABLED(ifq))                                        \
201                 (m) = tbr_dequeue_ptr(ifq, ALTDQ_POLL);                 \
202         else if (ALTQ_IS_ENABLED(ifq))                                  \
203                 ALTQ_POLL(ifq, m);                                      \
204         else                                                            \
205                 _IF_POLL(ifq, m);                                       \
206 } while (0)
207
208 #define IFQ_POLL(ifq, m)                                                \
209 do {                                                                    \
210         IF_LOCK(ifq);                                                   \
211         IFQ_POLL_NOLOCK(ifq, m);                                        \
212         IF_UNLOCK(ifq);                                                 \
213 } while (0)
214
215 #define IFQ_PURGE_NOLOCK(ifq)                                           \
216 do {                                                                    \
217         if (ALTQ_IS_ENABLED(ifq)) {                                     \
218                 ALTQ_PURGE(ifq);                                        \
219         } else                                                          \
220                 _IF_DRAIN(ifq);                                         \
221 } while (0)
222
223 #define IFQ_PURGE(ifq)                                                  \
224 do {                                                                    \
225         IF_LOCK(ifq);                                                   \
226         IFQ_PURGE_NOLOCK(ifq);                                          \
227         IF_UNLOCK(ifq);                                                 \
228 } while (0)
229
230 #define IFQ_SET_READY(ifq)                                              \
231         do { ((ifq)->altq_flags |= ALTQF_READY); } while (0)
232
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))
240
241 /*
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.
244  */
245 #define IFQ_HANDOFF_ADJ(ifp, m, adj, err)                               \
246 do {                                                                    \
247         int len;                                                        \
248         short mflags;                                                   \
249                                                                         \
250         len = (m)->m_pkthdr.len;                                        \
251         mflags = (m)->m_flags;                                          \
252         IFQ_ENQUEUE(&(ifp)->if_snd, m, err);                            \
253         if ((err) == 0) {                                               \
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)       \
258                         if_start(ifp);                                  \
259         } else                                                          \
260                 if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1);            \
261 } while (0)
262
263 #define IFQ_HANDOFF(ifp, m, err)                                        \
264         IFQ_HANDOFF_ADJ(ifp, m, 0, err)
265
266 #define IFQ_DRV_DEQUEUE(ifq, m)                                         \
267 do {                                                                    \
268         (m) = (ifq)->ifq_drv_head;                                      \
269         if (m) {                                                        \
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--;                                   \
274         } else {                                                        \
275                 IFQ_LOCK(ifq);                                          \
276                 IFQ_DEQUEUE_NOLOCK(ifq, m);                             \
277                 while ((ifq)->ifq_drv_len < (ifq)->ifq_drv_maxlen) {    \
278                         struct mbuf *m0;                                \
279                         IFQ_DEQUEUE_NOLOCK(ifq, m0);                    \
280                         if (m0 == NULL)                                 \
281                                 break;                                  \
282                         m0->m_nextpkt = NULL;                           \
283                         if ((ifq)->ifq_drv_tail == NULL)                \
284                                 (ifq)->ifq_drv_head = m0;               \
285                         else                                            \
286                                 (ifq)->ifq_drv_tail->m_nextpkt = m0;    \
287                         (ifq)->ifq_drv_tail = m0;                       \
288                         (ifq)->ifq_drv_len++;                           \
289                 }                                                       \
290                 IFQ_UNLOCK(ifq);                                        \
291         }                                                               \
292 } while (0)
293
294 #define IFQ_DRV_PREPEND(ifq, m)                                         \
295 do {                                                                    \
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++;                                           \
301 } while (0)
302
303 #define IFQ_DRV_IS_EMPTY(ifq)                                           \
304         (((ifq)->ifq_drv_len == 0) && ((ifq)->ifq_len == 0))
305
306 #define IFQ_DRV_PURGE(ifq)                                              \
307 do {                                                                    \
308         struct mbuf *m, *n = (ifq)->ifq_drv_head;                       \
309         while((m = n) != NULL) {                                        \
310                 n = m->m_nextpkt;                                       \
311                 m_freem(m);                                             \
312         }                                                               \
313         (ifq)->ifq_drv_head = (ifq)->ifq_drv_tail = NULL;               \
314         (ifq)->ifq_drv_len = 0;                                         \
315         IFQ_PURGE(ifq);                                                 \
316 } while (0)
317
318 #ifdef ALTQ
319 int drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m);
320 void drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m_new);
321 struct mbuf *drbr_peek(struct ifnet *ifp, struct buf_ring *br);
322 void drbr_flush(struct ifnet *ifp, struct buf_ring *br);
323 struct mbuf *drbr_dequeue(struct ifnet *ifp, struct buf_ring *br);
324 void    drbr_advance(struct ifnet *ifp, struct buf_ring *br);
325 struct mbuf *drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
326     int (*func) (struct mbuf *, void *), void *arg);
327 int     drbr_empty(struct ifnet *ifp, struct buf_ring *br);
328 int     drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br);
329 int     drbr_inuse(struct ifnet *ifp, struct buf_ring *br);
330
331 #else /* !ALTQ */
332 static __inline int
333 drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
334 {       
335         int error = 0;
336
337         error = buf_ring_enqueue(br, m);
338         if (error)
339                 m_freem(m);
340
341         return (error);
342 }
343
344 static __inline void
345 drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m_new)
346 {
347         /*
348          * The top of the list needs to be swapped 
349          * for this one.
350          */
351         buf_ring_putback_sc(br, m_new);
352 }
353
354 static __inline struct mbuf *
355 drbr_peek(struct ifnet *ifp, struct buf_ring *br)
356 {
357         return ((struct mbuf *)buf_ring_peek_clear_sc(br));
358 }
359
360 static __inline void
361 drbr_flush(struct ifnet *ifp, struct buf_ring *br)
362 {
363         struct mbuf *m;
364
365         while ((m = (struct mbuf *)buf_ring_dequeue_sc(br)) != NULL)
366                 m_freem(m);
367 }
368
369 static __inline struct mbuf *
370 drbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
371 {
372         return ((struct mbuf *)buf_ring_dequeue_sc(br));
373 }
374
375 static __inline void
376 drbr_advance(struct ifnet *ifp, struct buf_ring *br)
377 {
378         return (buf_ring_advance_sc(br));
379 }
380
381 static __inline struct mbuf *
382 drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
383     int (*func) (struct mbuf *, void *), void *arg) 
384 {
385         struct mbuf *m;
386         m = (struct mbuf *)buf_ring_peek(br);
387         if (m == NULL || func(m, arg) == 0)
388                 return (NULL);
389
390         return ((struct mbuf *)buf_ring_dequeue_sc(br));
391 }
392
393 static __inline int
394 drbr_empty(struct ifnet *ifp, struct buf_ring *br)
395 {
396         return (buf_ring_empty(br));
397 }
398
399 static __inline int
400 drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
401 {
402         return (!buf_ring_empty(br));
403 }
404
405 static __inline int
406 drbr_inuse(struct ifnet *ifp, struct buf_ring *br)
407 {
408         return (buf_ring_count(br));
409 }
410 #endif /* ALTQ */
411
412 static __inline void
413 drbr_free(struct buf_ring *br, struct malloc_type *type)
414 {
415
416         drbr_flush(NULL, br);
417         buf_ring_free(br, type);
418 }
419
420 extern  int ifqmaxlen;
421
422 void    if_qflush(struct ifnet *);
423 void    ifq_init(struct ifaltq *, struct ifnet *ifp);
424 void    ifq_delete(struct ifaltq *);
425
426 #endif /* _KERNEL */
427 #endif /* !_NET_IFQ_H_ */