]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/net/ifq.h
MFC r345312: iflib: mark isc_driver_version as constant
[FreeBSD/FreeBSD.git] / sys / net / ifq.h
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_clear_sc(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_ */