The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/net/ifq.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: releng/12.0/sys/net/ifq.h 326023 2017-11-20 19:43:44Z pfg $
   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 static __inline int
  319 drbr_enqueue(struct ifnet *ifp, struct buf_ring *br, struct mbuf *m)
  320 {       
  321         int error = 0;
  322 
  323 #ifdef ALTQ
  324         if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
  325                 IFQ_ENQUEUE(&ifp->if_snd, m, error);
  326                 if (error)
  327                         if_inc_counter((ifp), IFCOUNTER_OQDROPS, 1);
  328                 return (error);
  329         }
  330 #endif
  331         error = buf_ring_enqueue(br, m);
  332         if (error)
  333                 m_freem(m);
  334 
  335         return (error);
  336 }
  337 
  338 static __inline void
  339 drbr_putback(struct ifnet *ifp, struct buf_ring *br, struct mbuf *new)
  340 {
  341         /*
  342          * The top of the list needs to be swapped 
  343          * for this one.
  344          */
  345 #ifdef ALTQ
  346         if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
  347                 /* 
  348                  * Peek in altq case dequeued it
  349                  * so put it back.
  350                  */
  351                 IFQ_DRV_PREPEND(&ifp->if_snd, new);
  352                 return;
  353         }
  354 #endif
  355         buf_ring_putback_sc(br, new);
  356 }
  357 
  358 static __inline struct mbuf *
  359 drbr_peek(struct ifnet *ifp, struct buf_ring *br)
  360 {
  361 #ifdef ALTQ
  362         struct mbuf *m;
  363         if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
  364                 /* 
  365                  * Pull it off like a dequeue
  366                  * since drbr_advance() does nothing
  367                  * for altq and drbr_putback() will
  368                  * use the old prepend function.
  369                  */
  370                 IFQ_DEQUEUE(&ifp->if_snd, m);
  371                 return (m);
  372         }
  373 #endif
  374         return(buf_ring_peek_clear_sc(br));
  375 }
  376 
  377 static __inline void
  378 drbr_flush(struct ifnet *ifp, struct buf_ring *br)
  379 {
  380         struct mbuf *m;
  381 
  382 #ifdef ALTQ
  383         if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
  384                 IFQ_PURGE(&ifp->if_snd);
  385 #endif  
  386         while ((m = buf_ring_dequeue_sc(br)) != NULL)
  387                 m_freem(m);
  388 }
  389 
  390 static __inline void
  391 drbr_free(struct buf_ring *br, struct malloc_type *type)
  392 {
  393 
  394         drbr_flush(NULL, br);
  395         buf_ring_free(br, type);
  396 }
  397 
  398 static __inline struct mbuf *
  399 drbr_dequeue(struct ifnet *ifp, struct buf_ring *br)
  400 {
  401 #ifdef ALTQ
  402         struct mbuf *m;
  403 
  404         if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {     
  405                 IFQ_DEQUEUE(&ifp->if_snd, m);
  406                 return (m);
  407         }
  408 #endif
  409         return (buf_ring_dequeue_sc(br));
  410 }
  411 
  412 static __inline void
  413 drbr_advance(struct ifnet *ifp, struct buf_ring *br)
  414 {
  415 #ifdef ALTQ
  416         /* Nothing to do here since peek dequeues in altq case */
  417         if (ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd))
  418                 return;
  419 #endif
  420         return (buf_ring_advance_sc(br));
  421 }
  422 
  423 
  424 static __inline struct mbuf *
  425 drbr_dequeue_cond(struct ifnet *ifp, struct buf_ring *br,
  426     int (*func) (struct mbuf *, void *), void *arg) 
  427 {
  428         struct mbuf *m;
  429 #ifdef ALTQ
  430         if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
  431                 IFQ_LOCK(&ifp->if_snd);
  432                 IFQ_POLL_NOLOCK(&ifp->if_snd, m);
  433                 if (m != NULL && func(m, arg) == 0) {
  434                         IFQ_UNLOCK(&ifp->if_snd);
  435                         return (NULL);
  436                 }
  437                 IFQ_DEQUEUE_NOLOCK(&ifp->if_snd, m);
  438                 IFQ_UNLOCK(&ifp->if_snd);
  439                 return (m);
  440         }
  441 #endif
  442         m = buf_ring_peek(br);
  443         if (m == NULL || func(m, arg) == 0)
  444                 return (NULL);
  445 
  446         return (buf_ring_dequeue_sc(br));
  447 }
  448 
  449 static __inline int
  450 drbr_empty(struct ifnet *ifp, struct buf_ring *br)
  451 {
  452 #ifdef ALTQ
  453         if (ALTQ_IS_ENABLED(&ifp->if_snd))
  454                 return (IFQ_IS_EMPTY(&ifp->if_snd));
  455 #endif
  456         return (buf_ring_empty(br));
  457 }
  458 
  459 static __inline int
  460 drbr_needs_enqueue(struct ifnet *ifp, struct buf_ring *br)
  461 {
  462 #ifdef ALTQ
  463         if (ALTQ_IS_ENABLED(&ifp->if_snd))
  464                 return (1);
  465 #endif
  466         return (!buf_ring_empty(br));
  467 }
  468 
  469 static __inline int
  470 drbr_inuse(struct ifnet *ifp, struct buf_ring *br)
  471 {
  472 #ifdef ALTQ
  473         if (ALTQ_IS_ENABLED(&ifp->if_snd))
  474                 return (ifp->if_snd.ifq_len);
  475 #endif
  476         return (buf_ring_count(br));
  477 }
  478 
  479 extern  int ifqmaxlen;
  480 
  481 void    if_qflush(struct ifnet *);
  482 void    ifq_init(struct ifaltq *, struct ifnet *ifp);
  483 void    ifq_delete(struct ifaltq *);
  484 
  485 #endif /* _KERNEL */
  486 #endif /* !_NET_IFQ_H_ */

Cache object: c35cf8d914280a91376fe08ac0e59626


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.