source: rtems-libbsd/freebsd/sys/net/ifq.h @ 09bbedc

55-freebsd-126-freebsd-12
Last change on this file since 09bbedc was 3c967ca, checked in by Sebastian Huber <sebastian.huber@…>, on 06/08/17 at 11:15:12

Use <sys/lock.h> provided by Newlib

  • Property mode set to 100644
File size: 12.1 KB
Line 
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 * 3. 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 */
55struct  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
153int     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
160void    if_start(struct ifnet *);
161
162#define IFQ_ENQUEUE(ifq, m, err)                                        \
163do {                                                                    \
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)                                      \
180do {                                                                    \
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)                                             \
190do {                                                                    \
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)                                         \
197do {                                                                    \
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)                                                \
207do {                                                                    \
208        IF_LOCK(ifq);                                                   \
209        IFQ_POLL_NOLOCK(ifq, m);                                        \
210        IF_UNLOCK(ifq);                                                 \
211} while (0)
212
213#define IFQ_PURGE_NOLOCK(ifq)                                           \
214do {                                                                    \
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)                                                  \
222do {                                                                    \
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)                               \
244do {                                                                    \
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)                                         \
265do {                                                                    \
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)                                         \
293do {                                                                    \
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)                                              \
305do {                                                                    \
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
316static __inline int
317drbr_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
336static __inline void
337drbr_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
356static __inline struct mbuf *
357drbr_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
375static __inline void
376drbr_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
388static __inline void
389drbr_free(struct buf_ring *br, struct malloc_type *type)
390{
391
392        drbr_flush(NULL, br);
393        buf_ring_free(br, type);
394}
395
396static __inline struct mbuf *
397drbr_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
410static __inline void
411drbr_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
422static __inline struct mbuf *
423drbr_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
447static __inline int
448drbr_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
457static __inline int
458drbr_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
467static __inline int
468drbr_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
477extern  int ifqmaxlen;
478
479void    if_qflush(struct ifnet *);
480void    ifq_init(struct ifaltq *, struct ifnet *ifp);
481void    ifq_delete(struct ifaltq *);
482
483#endif /* _KERNEL */
484#endif /* !_NET_IFQ_H_ */
Note: See TracBrowser for help on using the repository browser.