zfs: merge openzfs/zfs@90ba19eb7
[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
32 #ifndef _NET_IFQ_H_
33 #define _NET_IFQ_H_
34
35 #ifdef _KERNEL
36 #include <sys/mbuf.h>           /* ifqueue only? */
37 #include <sys/buf_ring.h>
38 #include <net/vnet.h>
39 #endif /* _KERNEL */
40 #include <sys/lock.h>           /* XXX */
41 #include <sys/mutex.h>          /* struct ifqueue */
42
43 /*
44  * Couple of ugly extra definitions that are required since ifq.h
45  * is splitted from if_var.h.
46  */
47 #define IF_DUNIT_NONE   -1
48
49 #include <net/altq/if_altq.h>
50
51 /*
52  * Structure defining a queue for a network interface.
53  */
54 struct  ifqueue {
55         struct  mbuf *ifq_head;
56         struct  mbuf *ifq_tail;
57         int     ifq_len;
58         int     ifq_maxlen;
59         struct  mtx ifq_mtx;
60 };
61
62 #ifdef _KERNEL
63 /*
64  * Output queues (ifp->if_snd) and slow device input queues (*ifp->if_slowq)
65  * are queues of messages stored on ifqueue structures
66  * (defined above).  Entries are added to and deleted from these structures
67  * by these macros.
68  */
69 #define IF_LOCK(ifq)            mtx_lock(&(ifq)->ifq_mtx)
70 #define IF_UNLOCK(ifq)          mtx_unlock(&(ifq)->ifq_mtx)
71 #define IF_LOCK_ASSERT(ifq)     mtx_assert(&(ifq)->ifq_mtx, MA_OWNED)
72 #define _IF_QFULL(ifq)          ((ifq)->ifq_len >= (ifq)->ifq_maxlen)
73 #define _IF_QLEN(ifq)           ((ifq)->ifq_len)
74
75 #define _IF_ENQUEUE(ifq, m) do {                                \
76         (m)->m_nextpkt = NULL;                                  \
77         if ((ifq)->ifq_tail == NULL)                            \
78                 (ifq)->ifq_head = m;                            \
79         else                                                    \
80                 (ifq)->ifq_tail->m_nextpkt = m;                 \
81         (ifq)->ifq_tail = m;                                    \
82         (ifq)->ifq_len++;                                       \
83 } while (0)
84
85 #define IF_ENQUEUE(ifq, m) do {                                 \
86         IF_LOCK(ifq);                                           \
87         _IF_ENQUEUE(ifq, m);                                    \
88         IF_UNLOCK(ifq);                                         \
89 } while (0)
90
91 #define _IF_PREPEND(ifq, m) do {                                \
92         (m)->m_nextpkt = (ifq)->ifq_head;                       \
93         if ((ifq)->ifq_tail == NULL)                            \
94                 (ifq)->ifq_tail = (m);                          \
95         (ifq)->ifq_head = (m);                                  \
96         (ifq)->ifq_len++;                                       \
97 } while (0)
98
99 #define IF_PREPEND(ifq, m) do {                                 \
100         IF_LOCK(ifq);                                           \
101         _IF_PREPEND(ifq, m);                                    \
102         IF_UNLOCK(ifq);                                         \
103 } while (0)
104
105 #define _IF_DEQUEUE(ifq, m) do {                                \
106         (m) = (ifq)->ifq_head;                                  \
107         if (m) {                                                \
108                 if (((ifq)->ifq_head = (m)->m_nextpkt) == NULL) \
109                         (ifq)->ifq_tail = NULL;                 \
110                 (m)->m_nextpkt = NULL;                          \
111                 (ifq)->ifq_len--;                               \
112         }                                                       \
113 } while (0)
114
115 #define IF_DEQUEUE(ifq, m) do {                                 \
116         IF_LOCK(ifq);                                           \
117         _IF_DEQUEUE(ifq, m);                                    \
118         IF_UNLOCK(ifq);                                         \
119 } while (0)
120
121 #define _IF_DEQUEUE_ALL(ifq, m) do {                            \
122         (m) = (ifq)->ifq_head;                                  \
123         (ifq)->ifq_head = (ifq)->ifq_tail = NULL;               \
124         (ifq)->ifq_len = 0;                                     \
125 } while (0)
126
127 #define IF_DEQUEUE_ALL(ifq, m) do {                             \
128         IF_LOCK(ifq);                                           \
129         _IF_DEQUEUE_ALL(ifq, m);                                \
130         IF_UNLOCK(ifq);                                         \
131 } while (0)
132
133 #define _IF_POLL(ifq, m)        ((m) = (ifq)->ifq_head)
134 #define IF_POLL(ifq, m)         _IF_POLL(ifq, m)
135
136 #define _IF_DRAIN(ifq) do {                                     \
137         struct mbuf *m;                                         \
138         for (;;) {                                              \
139                 _IF_DEQUEUE(ifq, m);                            \
140                 if (m == NULL)                                  \
141                         break;                                  \
142                 m_freem(m);                                     \
143         }                                                       \
144 } while (0)
145
146 #define IF_DRAIN(ifq) do {                                      \
147         IF_LOCK(ifq);                                           \
148         _IF_DRAIN(ifq);                                         \
149         IF_UNLOCK(ifq);                                         \
150 } while(0)
151
152 int     if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp,
153             int adjust);
154 #define IF_HANDOFF(ifq, m, ifp)                 \
155         if_handoff((struct ifqueue *)ifq, m, ifp, 0)
156 #define IF_HANDOFF_ADJ(ifq, m, ifp, adj)        \
157         if_handoff((struct ifqueue *)ifq, m, ifp, adj)
158
159 void    if_start(struct ifnet *);
160
161 #define IFQ_ENQUEUE(ifq, m, err)                                        \
162 do {                                                                    \
163         IF_LOCK(ifq);                                                   \
164         if (ALTQ_IS_ENABLED(ifq))                                       \
165                 ALTQ_ENQUEUE(ifq, m, NULL, err);                        \
166         else {                                                          \
167                 if (_IF_QFULL(ifq)) {                                   \
168                         m_freem(m);                                     \
169                         (err) = ENOBUFS;                                \
170                 } else {                                                \
171                         _IF_ENQUEUE(ifq, m);                            \
172                         (err) = 0;                                      \
173                 }                                                       \
174         }                                                               \
175         IF_UNLOCK(ifq);                                                 \
176 } while (0)
177
178 #define IFQ_DEQUEUE_NOLOCK(ifq, m)                                      \
179 do {                                                                    \
180         if (TBR_IS_ENABLED(ifq))                                        \
181                 (m) = tbr_dequeue_ptr(ifq, ALTDQ_REMOVE);               \
182         else if (ALTQ_IS_ENABLED(ifq))                                  \
183                 ALTQ_DEQUEUE(ifq, m);                                   \
184         else                                                            \
185                 _IF_DEQUEUE(ifq, m);                                    \
186 } while (0)
187
188 #define IFQ_DEQUEUE(ifq, m)                                             \
189 do {                                                                    \
190         IF_LOCK(ifq);                                                   \
191         IFQ_DEQUEUE_NOLOCK(ifq, m);                                     \
192         IF_UNLOCK(ifq);                                                 \
193 } while (0)
194
195 #define IFQ_POLL_NOLOCK(ifq, m)                                         \
196 do {                                                                    \
197         if (TBR_IS_ENABLED(ifq))                                        \
198                 (m) = tbr_dequeue_ptr(ifq, ALTDQ_POLL);                 \
199         else if (ALTQ_IS_ENABLED(ifq))                                  \
200                 ALTQ_POLL(ifq, m);                                      \
201         else                                                            \
202                 _IF_POLL(ifq, m);                                       \
203 } while (0)
204
205 #define IFQ_POLL(ifq, m)                                                \
206 do {                                                                    \
207         IF_LOCK(ifq);                                                   \
208         IFQ_POLL_NOLOCK(ifq, m);                                        \
209         IF_UNLOCK(ifq);                                                 \
210 } while (0)
211
212 #define IFQ_PURGE_NOLOCK(ifq)                                           \
213 do {                                                                    \
214         if (ALTQ_IS_ENABLED(ifq)) {                                     \
215                 ALTQ_PURGE(ifq);                                        \
216         } else                                                          \
217                 _IF_DRAIN(ifq);                                         \
218 } while (0)
219
220 #define IFQ_PURGE(ifq)                                                  \
221 do {                                                                    \
222         IF_LOCK(ifq);                                                   \
223         IFQ_PURGE_NOLOCK(ifq);                                          \
224         IF_UNLOCK(ifq);                                                 \
225 } while (0)
226
227 #define IFQ_SET_READY(ifq)                                              \
228         do { ((ifq)->altq_flags |= ALTQF_READY); } while (0)
229
230 #define IFQ_LOCK(ifq)                   IF_LOCK(ifq)
231 #define IFQ_UNLOCK(ifq)                 IF_UNLOCK(ifq)
232 #define IFQ_LOCK_ASSERT(ifq)            IF_LOCK_ASSERT(ifq)
233 #define IFQ_IS_EMPTY(ifq)               ((ifq)->ifq_len == 0)
234 #define IFQ_INC_LEN(ifq)                ((ifq)->ifq_len++)
235 #define IFQ_DEC_LEN(ifq)                (--(ifq)->ifq_len)
236 #define IFQ_SET_MAXLEN(ifq, len)        ((ifq)->ifq_maxlen = (len))
237
238 /*
239  * The IFF_DRV_OACTIVE test should really occur in the device driver, not in
240  * the handoff logic, as that flag is locked by the device driver.
241  */
242 #define IFQ_HANDOFF_ADJ(ifp, m, adj, err)                               \
243 do {                                                                    \
244         int len;                                                        \
245         short mflags;                                                   \
246                                                                         \
247         len = (m)->m_pkthdr.len;                                        \
248         mflags = (m)->m_flags;                                          \
249         IFQ_ENQUEUE(&(ifp)->if_snd, m, err);                            \
250         if ((err) == 0) {                                               \
251                 if_inc_counter((ifp), IFCOUNTER_OBYTES, len + (adj));   \
252                 if (mflags & M_MCAST)                                   \
253                         if_inc_counter((ifp), IFCOUNTER_OMCASTS, 1);    \
254                 if (((ifp)->if_drv_flags & IFF_DRV_OACTIVE) == 0)       \
255                         if_start(ifp);                                  \
256         } else                                                          \
257                 if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1);            \
258 } while (0)
259
260 #define IFQ_HANDOFF(ifp, m, err)                                        \
261         IFQ_HANDOFF_ADJ(ifp, m, 0, err)
262
263 #define IFQ_DRV_DEQUEUE(ifq, m)                                         \
264 do {                                                                    \
265         (m) = (ifq)->ifq_drv_head;                                      \
266         if (m) {                                                        \
267                 if (((ifq)->ifq_drv_head = (m)->m_nextpkt) == NULL)     \
268                         (ifq)->ifq_drv_tail = NULL;                     \
269                 (m)->m_nextpkt = NULL;                                  \
270                 (ifq)->ifq_drv_len--;                                   \
271         } else {                                                        \
272                 IFQ_LOCK(ifq);                                          \
273                 IFQ_DEQUEUE_NOLOCK(ifq, m);                             \
274                 while ((ifq)->ifq_drv_len < (ifq)->ifq_drv_maxlen) {    \
275                         struct mbuf *m0;                                \
276                         IFQ_DEQUEUE_NOLOCK(ifq, m0);                    \
277                         if (m0 == NULL)                                 \
278                                 break;                                  \
279                         m0->m_nextpkt = NULL;                           \
280                         if ((ifq)->ifq_drv_tail == NULL)                \
281                                 (ifq)->ifq_drv_head = m0;               \
282                         else                                            \
283                                 (ifq)->ifq_drv_tail->m_nextpkt = m0;    \
284                         (ifq)->ifq_drv_tail = m0;                       \
285                         (ifq)->ifq_drv_len++;                           \
286                 }                                                       \
287                 IFQ_UNLOCK(ifq);                                        \
288         }                                                               \
289 } while (0)
290
291 #define IFQ_DRV_PREPEND(ifq, m)                                         \
292 do {                                                                    \
293         (m)->m_nextpkt = (ifq)->ifq_drv_head;                           \
294         if ((ifq)->ifq_drv_tail == NULL)                                \
295                 (ifq)->ifq_drv_tail = (m);                              \
296         (ifq)->ifq_drv_head = (m);                                      \
297         (ifq)->ifq_drv_len++;                                           \
298 } while (0)
299
300 #define IFQ_DRV_IS_EMPTY(ifq)                                           \
301         (((ifq)->ifq_drv_len == 0) && ((ifq)->ifq_len == 0))
302
303 #define IFQ_DRV_PURGE(ifq)                                              \
304 do {                                                                    \
305         struct mbuf *m, *n = (ifq)->ifq_drv_head;                       \
306         while((m = n) != NULL) {                                        \
307                 n = m->m_nextpkt;                                       \
308                 m_freem(m);                                             \
309         }                                                               \
310         (ifq)->ifq_drv_head = (ifq)->ifq_drv_tail = NULL;               \
311         (ifq)->ifq_drv_len = 0;                                         \
312         IFQ_PURGE(ifq);                                                 \
313 } while (0)
314
315 #ifdef ALTQ
316 int drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m);
317 void drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m_new);
318 struct mbuf *drbr_peek(struct ifnet *ifp, struct buf_ring *br);
319 void drbr_flush(struct ifnet *ifp, struct buf_ring *br);
320 struct mbuf *drbr_dequeue(struct ifnet *ifp, struct buf_ring *br);
321 void    drbr_advance(struct ifnet *ifp, struct buf_ring *br);
322 struct mbuf *drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
323     int (*func) (struct mbuf *, void *), void *arg);
324 int     drbr_empty(struct ifnet *ifp, struct buf_ring *br);
325 int     drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br);
326 int     drbr_inuse(struct ifnet *ifp, struct buf_ring *br);
327
328 #else /* !ALTQ */
329 static __inline int
330 drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
331 {       
332         int error = 0;
333
334         error = buf_ring_enqueue(br, m);
335         if (error)
336                 m_freem(m);
337
338         return (error);
339 }
340
341 static __inline void
342 drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m_new)
343 {
344         /*
345          * The top of the list needs to be swapped 
346          * for this one.
347          */
348         buf_ring_putback_sc(br, m_new);
349 }
350
351 static __inline struct mbuf *
352 drbr_peek(struct ifnet *ifp, struct buf_ring *br)
353 {
354         return ((struct mbuf *)buf_ring_peek_clear_sc(br));
355 }
356
357 static __inline void
358 drbr_flush(struct ifnet *ifp, struct buf_ring *br)
359 {
360         struct mbuf *m;
361
362         while ((m = (struct mbuf *)buf_ring_dequeue_sc(br)) != NULL)
363                 m_freem(m);
364 }
365
366 static __inline struct mbuf *
367 drbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
368 {
369         return ((struct mbuf *)buf_ring_dequeue_sc(br));
370 }
371
372 static __inline void
373 drbr_advance(struct ifnet *ifp, struct buf_ring *br)
374 {
375         return (buf_ring_advance_sc(br));
376 }
377
378 static __inline struct mbuf *
379 drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
380     int (*func) (struct mbuf *, void *), void *arg) 
381 {
382         struct mbuf *m;
383         m = (struct mbuf *)buf_ring_peek(br);
384         if (m == NULL || func(m, arg) == 0)
385                 return (NULL);
386
387         return ((struct mbuf *)buf_ring_dequeue_sc(br));
388 }
389
390 static __inline int
391 drbr_empty(struct ifnet *ifp, struct buf_ring *br)
392 {
393         return (buf_ring_empty(br));
394 }
395
396 static __inline int
397 drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
398 {
399         return (!buf_ring_empty(br));
400 }
401
402 static __inline int
403 drbr_inuse(struct ifnet *ifp, struct buf_ring *br)
404 {
405         return (buf_ring_count(br));
406 }
407 #endif /* ALTQ */
408
409 static __inline void
410 drbr_free(struct buf_ring *br, struct malloc_type *type)
411 {
412
413         drbr_flush(NULL, br);
414         buf_ring_free(br, type);
415 }
416
417 extern  int ifqmaxlen;
418
419 void    if_qflush(struct ifnet *);
420 void    ifq_init(struct ifaltq *, struct ifnet *ifp);
421 void    ifq_delete(struct ifaltq *);
422
423 #endif /* _KERNEL */
424 #endif /* !_NET_IFQ_H_ */