LCOV - code coverage report
Current view: top level - net - ifq.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 333 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: ifq.c,v 1.22 2018/01/25 14:04:36 mpi Exp $ */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2015 David Gwynne <dlg@openbsd.org>
       5             :  *
       6             :  * Permission to use, copy, modify, and distribute this software for any
       7             :  * purpose with or without fee is hereby granted, provided that the above
       8             :  * copyright notice and this permission notice appear in all copies.
       9             :  *
      10             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      11             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      12             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      13             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      14             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      15             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      16             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      17             :  */
      18             : 
      19             : #include "bpfilter.h"
      20             : 
      21             : #include <sys/param.h>
      22             : #include <sys/systm.h>
      23             : #include <sys/socket.h>
      24             : #include <sys/mbuf.h>
      25             : #include <sys/proc.h>
      26             : 
      27             : #include <net/if.h>
      28             : #include <net/if_var.h>
      29             : 
      30             : #if NBPFILTER > 0
      31             : #include <net/bpf.h>
      32             : #endif
      33             : 
      34             : /*
      35             :  * priq glue
      36             :  */
      37             : unsigned int     priq_idx(unsigned int, const struct mbuf *);
      38             : struct mbuf     *priq_enq(struct ifqueue *, struct mbuf *);
      39             : struct mbuf     *priq_deq_begin(struct ifqueue *, void **);
      40             : void             priq_deq_commit(struct ifqueue *, struct mbuf *, void *);
      41             : void             priq_purge(struct ifqueue *, struct mbuf_list *);
      42             : 
      43             : void            *priq_alloc(unsigned int, void *);
      44             : void             priq_free(unsigned int, void *);
      45             : 
      46             : const struct ifq_ops priq_ops = {
      47             :         priq_idx,
      48             :         priq_enq,
      49             :         priq_deq_begin,
      50             :         priq_deq_commit,
      51             :         priq_purge,
      52             :         priq_alloc,
      53             :         priq_free,
      54             : };
      55             : 
      56             : const struct ifq_ops * const ifq_priq_ops = &priq_ops;
      57             : 
      58             : /*
      59             :  * priq internal structures
      60             :  */
      61             : 
      62             : struct priq {
      63             :         struct mbuf_list         pq_lists[IFQ_NQUEUES];
      64             : };
      65             : 
      66             : /*
      67             :  * ifqueue serialiser
      68             :  */
      69             : 
      70             : void    ifq_start_task(void *);
      71             : void    ifq_restart_task(void *);
      72             : void    ifq_barrier_task(void *);
      73             : 
      74             : #define TASK_ONQUEUE 0x1
      75             : 
      76             : void
      77           0 : ifq_serialize(struct ifqueue *ifq, struct task *t)
      78             : {
      79           0 :         struct task work;
      80             : 
      81           0 :         if (ISSET(t->t_flags, TASK_ONQUEUE))
      82           0 :                 return;
      83             : 
      84           0 :         mtx_enter(&ifq->ifq_task_mtx);
      85           0 :         if (!ISSET(t->t_flags, TASK_ONQUEUE)) {
      86           0 :                 SET(t->t_flags, TASK_ONQUEUE);
      87           0 :                 TAILQ_INSERT_TAIL(&ifq->ifq_task_list, t, t_entry);
      88           0 :         }
      89             : 
      90           0 :         if (ifq->ifq_serializer == NULL) {
      91           0 :                 ifq->ifq_serializer = curcpu();
      92             : 
      93           0 :                 while ((t = TAILQ_FIRST(&ifq->ifq_task_list)) != NULL) {
      94           0 :                         TAILQ_REMOVE(&ifq->ifq_task_list, t, t_entry);
      95           0 :                         CLR(t->t_flags, TASK_ONQUEUE);
      96           0 :                         work = *t; /* copy to caller to avoid races */
      97             : 
      98           0 :                         mtx_leave(&ifq->ifq_task_mtx);
      99             : 
     100           0 :                         (*work.t_func)(work.t_arg);
     101             : 
     102           0 :                         mtx_enter(&ifq->ifq_task_mtx);
     103             :                 }
     104             : 
     105           0 :                 ifq->ifq_serializer = NULL;
     106           0 :         }
     107           0 :         mtx_leave(&ifq->ifq_task_mtx);
     108           0 : }
     109             : 
     110             : int
     111           0 : ifq_is_serialized(struct ifqueue *ifq)
     112             : {
     113           0 :         return (ifq->ifq_serializer == curcpu());
     114             : }
     115             : 
     116             : void
     117           0 : ifq_start_task(void *p)
     118             : {
     119           0 :         struct ifqueue *ifq = p;
     120           0 :         struct ifnet *ifp = ifq->ifq_if;
     121             : 
     122           0 :         if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
     123           0 :             ifq_empty(ifq) || ifq_is_oactive(ifq))
     124           0 :                 return;
     125             : 
     126           0 :         ifp->if_qstart(ifq);
     127           0 : }
     128             : 
     129             : void
     130           0 : ifq_restart_task(void *p)
     131             : {
     132           0 :         struct ifqueue *ifq = p;
     133           0 :         struct ifnet *ifp = ifq->ifq_if;
     134             : 
     135           0 :         ifq_clr_oactive(ifq);
     136           0 :         ifp->if_qstart(ifq);
     137           0 : }
     138             : 
     139             : void
     140           0 : ifq_barrier(struct ifqueue *ifq)
     141             : {
     142           0 :         struct cond c = COND_INITIALIZER();
     143           0 :         struct task t = TASK_INITIALIZER(ifq_barrier_task, &c);
     144             : 
     145           0 :         if (ifq->ifq_serializer == NULL)
     146           0 :                 return;
     147             : 
     148           0 :         ifq_serialize(ifq, &t);
     149             : 
     150           0 :         cond_wait(&c, "ifqbar");
     151           0 : }
     152             : 
     153             : void
     154           0 : ifq_barrier_task(void *p)
     155             : {
     156           0 :         struct cond *c = p;
     157             : 
     158           0 :         cond_signal(c);
     159           0 : }
     160             : 
     161             : /*
     162             :  * ifqueue mbuf queue API
     163             :  */
     164             : 
     165             : void
     166           0 : ifq_init(struct ifqueue *ifq, struct ifnet *ifp, unsigned int idx)
     167             : {
     168           0 :         ifq->ifq_if = ifp;
     169           0 :         ifq->ifq_softc = NULL;
     170             : 
     171           0 :         mtx_init(&ifq->ifq_mtx, IPL_NET);
     172           0 :         ifq->ifq_qdrops = 0;
     173             : 
     174             :         /* default to priq */
     175           0 :         ifq->ifq_ops = &priq_ops;
     176           0 :         ifq->ifq_q = priq_ops.ifqop_alloc(idx, NULL);
     177             : 
     178           0 :         ml_init(&ifq->ifq_free);
     179           0 :         ifq->ifq_len = 0;
     180             : 
     181           0 :         ifq->ifq_packets = 0;
     182           0 :         ifq->ifq_bytes = 0;
     183           0 :         ifq->ifq_qdrops = 0;
     184           0 :         ifq->ifq_errors = 0;
     185           0 :         ifq->ifq_mcasts = 0;
     186             : 
     187           0 :         mtx_init(&ifq->ifq_task_mtx, IPL_NET);
     188           0 :         TAILQ_INIT(&ifq->ifq_task_list);
     189           0 :         ifq->ifq_serializer = NULL;
     190             : 
     191           0 :         task_set(&ifq->ifq_start, ifq_start_task, ifq);
     192           0 :         task_set(&ifq->ifq_restart, ifq_restart_task, ifq);
     193             : 
     194           0 :         if (ifq->ifq_maxlen == 0)
     195           0 :                 ifq_set_maxlen(ifq, IFQ_MAXLEN);
     196             : 
     197           0 :         ifq->ifq_idx = idx;
     198           0 : }
     199             : 
     200             : void
     201           0 : ifq_attach(struct ifqueue *ifq, const struct ifq_ops *newops, void *opsarg)
     202             : {
     203           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
     204           0 :         struct mbuf_list free_ml = MBUF_LIST_INITIALIZER();
     205             :         struct mbuf *m;
     206             :         const struct ifq_ops *oldops;
     207             :         void *newq, *oldq;
     208             : 
     209           0 :         newq = newops->ifqop_alloc(ifq->ifq_idx, opsarg);
     210             : 
     211           0 :         mtx_enter(&ifq->ifq_mtx);
     212           0 :         ifq->ifq_ops->ifqop_purge(ifq, &ml);
     213           0 :         ifq->ifq_len = 0;
     214             : 
     215           0 :         oldops = ifq->ifq_ops;
     216           0 :         oldq = ifq->ifq_q;
     217             : 
     218           0 :         ifq->ifq_ops = newops;
     219           0 :         ifq->ifq_q = newq;
     220             : 
     221           0 :         while ((m = ml_dequeue(&ml)) != NULL) {
     222           0 :                 m = ifq->ifq_ops->ifqop_enq(ifq, m);
     223           0 :                 if (m != NULL) {
     224           0 :                         ifq->ifq_qdrops++;
     225           0 :                         ml_enqueue(&free_ml, m);
     226           0 :                 } else
     227           0 :                         ifq->ifq_len++;
     228             :         }
     229           0 :         mtx_leave(&ifq->ifq_mtx);
     230             : 
     231           0 :         oldops->ifqop_free(ifq->ifq_idx, oldq);
     232             : 
     233           0 :         ml_purge(&free_ml);
     234           0 : }
     235             : 
     236             : void
     237           0 : ifq_destroy(struct ifqueue *ifq)
     238             : {
     239           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
     240             : 
     241             :         /* don't need to lock because this is the last use of the ifq */
     242             : 
     243           0 :         ifq->ifq_ops->ifqop_purge(ifq, &ml);
     244           0 :         ifq->ifq_ops->ifqop_free(ifq->ifq_idx, ifq->ifq_q);
     245             : 
     246           0 :         ml_purge(&ml);
     247           0 : }
     248             : 
     249             : void
     250           0 : ifq_add_data(struct ifqueue *ifq, struct if_data *data)
     251             : {
     252           0 :         mtx_enter(&ifq->ifq_mtx);
     253           0 :         data->ifi_opackets += ifq->ifq_packets;
     254           0 :         data->ifi_obytes += ifq->ifq_bytes;
     255           0 :         data->ifi_oqdrops += ifq->ifq_qdrops;
     256           0 :         data->ifi_omcasts += ifq->ifq_mcasts;
     257             :         /* ifp->if_data.ifi_oerrors */
     258           0 :         mtx_leave(&ifq->ifq_mtx);
     259           0 : }
     260             : 
     261             : int
     262           0 : ifq_enqueue(struct ifqueue *ifq, struct mbuf *m)
     263             : {
     264             :         struct mbuf *dm;
     265             : 
     266           0 :         mtx_enter(&ifq->ifq_mtx);
     267           0 :         dm = ifq->ifq_ops->ifqop_enq(ifq, m);
     268           0 :         if (dm != m) {
     269           0 :                 ifq->ifq_packets++;
     270           0 :                 ifq->ifq_bytes += m->m_pkthdr.len;
     271           0 :                 if (ISSET(m->m_flags, M_MCAST))
     272           0 :                         ifq->ifq_mcasts++;
     273             :         }
     274             : 
     275           0 :         if (dm == NULL)
     276           0 :                 ifq->ifq_len++;
     277             :         else
     278           0 :                 ifq->ifq_qdrops++;
     279           0 :         mtx_leave(&ifq->ifq_mtx);
     280             : 
     281           0 :         if (dm != NULL)
     282           0 :                 m_freem(dm);
     283             : 
     284           0 :         return (dm == m ? ENOBUFS : 0);
     285             : }
     286             : 
     287             : static inline void
     288           0 : ifq_deq_enter(struct ifqueue *ifq)
     289             : {
     290           0 :         mtx_enter(&ifq->ifq_mtx);
     291           0 : }
     292             : 
     293             : static inline void
     294           0 : ifq_deq_leave(struct ifqueue *ifq)
     295             : {
     296           0 :         struct mbuf_list ml;
     297             : 
     298           0 :         ml = ifq->ifq_free;
     299           0 :         ml_init(&ifq->ifq_free);
     300             : 
     301           0 :         mtx_leave(&ifq->ifq_mtx);
     302             : 
     303           0 :         if (!ml_empty(&ml))
     304           0 :                 ml_purge(&ml);
     305           0 : }
     306             : 
     307             : struct mbuf *
     308           0 : ifq_deq_begin(struct ifqueue *ifq)
     309             : {
     310             :         struct mbuf *m = NULL;
     311           0 :         void *cookie;
     312             : 
     313           0 :         ifq_deq_enter(ifq);
     314           0 :         if (ifq->ifq_len == 0 ||
     315           0 :             (m = ifq->ifq_ops->ifqop_deq_begin(ifq, &cookie)) == NULL) {
     316           0 :                 ifq_deq_leave(ifq);
     317           0 :                 return (NULL);
     318             :         }
     319             : 
     320           0 :         m->m_pkthdr.ph_cookie = cookie;
     321             : 
     322           0 :         return (m);
     323           0 : }
     324             : 
     325             : void
     326           0 : ifq_deq_commit(struct ifqueue *ifq, struct mbuf *m)
     327             : {
     328             :         void *cookie;
     329             : 
     330           0 :         KASSERT(m != NULL);
     331           0 :         cookie = m->m_pkthdr.ph_cookie;
     332             : 
     333           0 :         ifq->ifq_ops->ifqop_deq_commit(ifq, m, cookie);
     334           0 :         ifq->ifq_len--;
     335           0 :         ifq_deq_leave(ifq);
     336           0 : }
     337             : 
     338             : void
     339           0 : ifq_deq_rollback(struct ifqueue *ifq, struct mbuf *m)
     340             : {
     341           0 :         KASSERT(m != NULL);
     342             : 
     343           0 :         ifq_deq_leave(ifq);
     344           0 : }
     345             : 
     346             : struct mbuf *
     347           0 : ifq_dequeue(struct ifqueue *ifq)
     348             : {
     349             :         struct mbuf *m;
     350             : 
     351           0 :         m = ifq_deq_begin(ifq);
     352           0 :         if (m == NULL)
     353           0 :                 return (NULL);
     354             : 
     355           0 :         ifq_deq_commit(ifq, m);
     356             : 
     357           0 :         return (m);
     358           0 : }
     359             : 
     360             : unsigned int
     361           0 : ifq_purge(struct ifqueue *ifq)
     362             : {
     363           0 :         struct mbuf_list ml = MBUF_LIST_INITIALIZER();
     364             :         unsigned int rv;
     365             : 
     366           0 :         mtx_enter(&ifq->ifq_mtx);
     367           0 :         ifq->ifq_ops->ifqop_purge(ifq, &ml);
     368           0 :         rv = ifq->ifq_len;
     369           0 :         ifq->ifq_len = 0;
     370           0 :         ifq->ifq_qdrops += rv;
     371           0 :         mtx_leave(&ifq->ifq_mtx);
     372             : 
     373           0 :         KASSERT(rv == ml_len(&ml));
     374             : 
     375           0 :         ml_purge(&ml);
     376             : 
     377           0 :         return (rv);
     378           0 : }
     379             : 
     380             : void *
     381           0 : ifq_q_enter(struct ifqueue *ifq, const struct ifq_ops *ops)
     382             : {
     383           0 :         mtx_enter(&ifq->ifq_mtx);
     384           0 :         if (ifq->ifq_ops == ops)
     385           0 :                 return (ifq->ifq_q);
     386             : 
     387           0 :         mtx_leave(&ifq->ifq_mtx);
     388             : 
     389           0 :         return (NULL);
     390           0 : }
     391             : 
     392             : void
     393           0 : ifq_q_leave(struct ifqueue *ifq, void *q)
     394             : {
     395           0 :         KASSERT(q == ifq->ifq_q);
     396           0 :         mtx_leave(&ifq->ifq_mtx);
     397           0 : }
     398             : 
     399             : void
     400           0 : ifq_mfreem(struct ifqueue *ifq, struct mbuf *m)
     401             : {
     402           0 :         MUTEX_ASSERT_LOCKED(&ifq->ifq_mtx);
     403             : 
     404           0 :         ifq->ifq_len--;
     405           0 :         ifq->ifq_qdrops++;
     406           0 :         ml_enqueue(&ifq->ifq_free, m);
     407           0 : }
     408             : 
     409             : void
     410           0 : ifq_mfreeml(struct ifqueue *ifq, struct mbuf_list *ml)
     411             : {
     412           0 :         MUTEX_ASSERT_LOCKED(&ifq->ifq_mtx);
     413             : 
     414           0 :         ifq->ifq_len -= ml_len(ml);
     415           0 :         ifq->ifq_qdrops += ml_len(ml);
     416           0 :         ml_enlist(&ifq->ifq_free, ml);
     417           0 : }
     418             : 
     419             : /*
     420             :  * ifiq
     421             :  */
     422             : 
     423             : static void     ifiq_process(void *);
     424             : 
     425             : void
     426           0 : ifiq_init(struct ifiqueue *ifiq, struct ifnet *ifp, unsigned int idx)
     427             : {
     428           0 :         ifiq->ifiq_if = ifp;
     429           0 :         ifiq->ifiq_softnet = net_tq(ifp->if_index); /* + idx */
     430           0 :         ifiq->ifiq_softc = NULL;
     431             : 
     432           0 :         mtx_init(&ifiq->ifiq_mtx, IPL_NET);
     433           0 :         ml_init(&ifiq->ifiq_ml);
     434           0 :         task_set(&ifiq->ifiq_task, ifiq_process, ifiq);
     435             : 
     436           0 :         ifiq->ifiq_qdrops = 0;
     437           0 :         ifiq->ifiq_packets = 0;
     438           0 :         ifiq->ifiq_bytes = 0;
     439           0 :         ifiq->ifiq_qdrops = 0;
     440           0 :         ifiq->ifiq_errors = 0;
     441             : 
     442           0 :         ifiq->ifiq_idx = idx;
     443           0 : }
     444             : 
     445             : void
     446           0 : ifiq_destroy(struct ifiqueue *ifiq)
     447             : {
     448           0 :         if (!task_del(ifiq->ifiq_softnet, &ifiq->ifiq_task)) {
     449           0 :                 NET_ASSERT_UNLOCKED();
     450           0 :                 taskq_barrier(ifiq->ifiq_softnet);
     451           0 :         }
     452             : 
     453             :         /* don't need to lock because this is the last use of the ifiq */
     454           0 :         ml_purge(&ifiq->ifiq_ml);
     455           0 : }
     456             : 
     457             : int
     458           0 : ifiq_input(struct ifiqueue *ifiq, struct mbuf_list *ml, unsigned int cwm)
     459             : {
     460           0 :         struct ifnet *ifp = ifiq->ifiq_if;
     461             :         struct mbuf *m;
     462             :         uint64_t packets;
     463             :         uint64_t bytes = 0;
     464             : #if NBPFILTER > 0
     465             :         caddr_t if_bpf;
     466             : #endif
     467             :         int rv = 1;
     468             : 
     469           0 :         if (ml_empty(ml))
     470           0 :                 return (0);
     471             : 
     472           0 :         MBUF_LIST_FOREACH(ml, m) {
     473           0 :                 m->m_pkthdr.ph_ifidx = ifp->if_index;
     474           0 :                 m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
     475           0 :                 bytes += m->m_pkthdr.len;
     476             :         }
     477           0 :         packets = ml_len(ml);
     478             : 
     479             : #if NBPFILTER > 0
     480           0 :         if_bpf = ifp->if_bpf;
     481           0 :         if (if_bpf) {
     482           0 :                 struct mbuf_list ml0 = *ml;
     483             : 
     484           0 :                 ml_init(ml);
     485             : 
     486           0 :                 while ((m = ml_dequeue(&ml0)) != NULL) {
     487           0 :                         if (bpf_mtap_ether(if_bpf, m, BPF_DIRECTION_IN))
     488           0 :                                 m_freem(m);
     489             :                         else
     490           0 :                                 ml_enqueue(ml, m);
     491             :                 }
     492             : 
     493           0 :                 if (ml_empty(ml)) {
     494           0 :                         mtx_enter(&ifiq->ifiq_mtx);
     495           0 :                         ifiq->ifiq_packets += packets;
     496           0 :                         ifiq->ifiq_bytes += bytes;
     497           0 :                         mtx_leave(&ifiq->ifiq_mtx);
     498             : 
     499           0 :                         return (0);
     500             :                 }
     501           0 :         }
     502             : #endif
     503             : 
     504           0 :         mtx_enter(&ifiq->ifiq_mtx);
     505           0 :         ifiq->ifiq_packets += packets;
     506           0 :         ifiq->ifiq_bytes += bytes;
     507             : 
     508           0 :         if (ifiq_len(ifiq) >= cwm * 5)
     509           0 :                 ifiq->ifiq_qdrops += ml_len(ml);
     510             :         else {
     511           0 :                 rv = (ifiq_len(ifiq) >= cwm * 3);
     512           0 :                 ml_enlist(&ifiq->ifiq_ml, ml);
     513             :         }
     514           0 :         mtx_leave(&ifiq->ifiq_mtx);
     515             : 
     516           0 :         if (ml_empty(ml))
     517           0 :                 task_add(ifiq->ifiq_softnet, &ifiq->ifiq_task);
     518             :         else
     519           0 :                 ml_purge(ml);
     520             : 
     521           0 :         return (rv);
     522           0 : }
     523             : 
     524             : void
     525           0 : ifiq_add_data(struct ifiqueue *ifiq, struct if_data *data)
     526             : {
     527           0 :         mtx_enter(&ifiq->ifiq_mtx);
     528           0 :         data->ifi_ipackets += ifiq->ifiq_packets;
     529           0 :         data->ifi_ibytes += ifiq->ifiq_bytes;
     530           0 :         data->ifi_iqdrops += ifiq->ifiq_qdrops;
     531           0 :         mtx_leave(&ifiq->ifiq_mtx);
     532           0 : }
     533             : 
     534             : void
     535           0 : ifiq_barrier(struct ifiqueue *ifiq)
     536             : {
     537           0 :         if (!task_del(ifiq->ifiq_softnet, &ifiq->ifiq_task))
     538           0 :                 taskq_barrier(ifiq->ifiq_softnet);
     539           0 : }
     540             : 
     541             : int
     542           0 : ifiq_enqueue(struct ifiqueue *ifiq, struct mbuf *m)
     543             : {
     544           0 :         mtx_enter(&ifiq->ifiq_mtx);
     545           0 :         ml_enqueue(&ifiq->ifiq_ml, m);
     546           0 :         mtx_leave(&ifiq->ifiq_mtx);
     547             : 
     548           0 :         task_add(ifiq->ifiq_softnet, &ifiq->ifiq_task);
     549             : 
     550           0 :         return (0);
     551             : }
     552             : 
     553             : static void
     554           0 : ifiq_process(void *arg)
     555             : {
     556           0 :         struct ifiqueue *ifiq = arg;
     557           0 :         struct mbuf_list ml;
     558             : 
     559           0 :         if (ifiq_empty(ifiq))
     560           0 :                 return;
     561             : 
     562           0 :         mtx_enter(&ifiq->ifiq_mtx);
     563           0 :         ml = ifiq->ifiq_ml;
     564           0 :         ml_init(&ifiq->ifiq_ml);
     565           0 :         mtx_leave(&ifiq->ifiq_mtx);
     566             : 
     567           0 :         if_input_process(ifiq->ifiq_if, &ml);
     568           0 : }
     569             : 
     570             : /*
     571             :  * priq implementation
     572             :  */
     573             : 
     574             : unsigned int
     575           0 : priq_idx(unsigned int nqueues, const struct mbuf *m)
     576             : {
     577             :         unsigned int flow = 0;
     578             : 
     579           0 :         if (ISSET(m->m_pkthdr.ph_flowid, M_FLOWID_VALID))
     580           0 :                 flow = m->m_pkthdr.ph_flowid & M_FLOWID_MASK;
     581             : 
     582           0 :         return (flow % nqueues);
     583             : }
     584             : 
     585             : void *
     586           0 : priq_alloc(unsigned int idx, void *null)
     587             : {
     588             :         struct priq *pq;
     589             :         int i;
     590             : 
     591           0 :         pq = malloc(sizeof(struct priq), M_DEVBUF, M_WAITOK);
     592           0 :         for (i = 0; i < IFQ_NQUEUES; i++)
     593           0 :                 ml_init(&pq->pq_lists[i]);
     594           0 :         return (pq);
     595             : }
     596             : 
     597             : void
     598           0 : priq_free(unsigned int idx, void *pq)
     599             : {
     600           0 :         free(pq, M_DEVBUF, sizeof(struct priq));
     601           0 : }
     602             : 
     603             : struct mbuf *
     604           0 : priq_enq(struct ifqueue *ifq, struct mbuf *m)
     605             : {
     606             :         struct priq *pq;
     607             :         struct mbuf_list *pl;
     608             :         struct mbuf *n = NULL;
     609             :         unsigned int prio;
     610             : 
     611           0 :         pq = ifq->ifq_q;
     612           0 :         KASSERT(m->m_pkthdr.pf.prio <= IFQ_MAXPRIO);
     613             : 
     614             :         /* Find a lower priority queue to drop from */
     615           0 :         if (ifq_len(ifq) >= ifq->ifq_maxlen) {
     616           0 :                 for (prio = 0; prio < m->m_pkthdr.pf.prio; prio++) {
     617           0 :                         pl = &pq->pq_lists[prio];
     618           0 :                         if (ml_len(pl) > 0) {
     619           0 :                                 n = ml_dequeue(pl);
     620           0 :                                 goto enqueue;
     621             :                         }
     622             :                 }
     623             :                 /*
     624             :                  * There's no lower priority queue that we can
     625             :                  * drop from so don't enqueue this one.
     626             :                  */
     627           0 :                 return (m);
     628             :         }
     629             : 
     630             :  enqueue:
     631           0 :         pl = &pq->pq_lists[m->m_pkthdr.pf.prio];
     632           0 :         ml_enqueue(pl, m);
     633             : 
     634           0 :         return (n);
     635           0 : }
     636             : 
     637             : struct mbuf *
     638           0 : priq_deq_begin(struct ifqueue *ifq, void **cookiep)
     639             : {
     640           0 :         struct priq *pq = ifq->ifq_q;
     641             :         struct mbuf_list *pl;
     642             :         unsigned int prio = nitems(pq->pq_lists);
     643             :         struct mbuf *m;
     644             : 
     645           0 :         do {
     646           0 :                 pl = &pq->pq_lists[--prio];
     647           0 :                 m = MBUF_LIST_FIRST(pl);
     648           0 :                 if (m != NULL) {
     649           0 :                         *cookiep = pl;
     650           0 :                         return (m);
     651             :                 }
     652           0 :         } while (prio > 0);
     653             : 
     654           0 :         return (NULL);
     655           0 : }
     656             : 
     657             : void
     658           0 : priq_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie)
     659             : {
     660           0 :         struct mbuf_list *pl = cookie;
     661             : 
     662           0 :         KASSERT(MBUF_LIST_FIRST(pl) == m);
     663             : 
     664           0 :         ml_dequeue(pl);
     665           0 : }
     666             : 
     667             : void
     668           0 : priq_purge(struct ifqueue *ifq, struct mbuf_list *ml)
     669             : {
     670           0 :         struct priq *pq = ifq->ifq_q;
     671             :         struct mbuf_list *pl;
     672             :         unsigned int prio = nitems(pq->pq_lists);
     673             : 
     674           0 :         do {
     675           0 :                 pl = &pq->pq_lists[--prio];
     676           0 :                 ml_enlist(ml, pl);
     677           0 :         } while (prio > 0);
     678           0 : }

Generated by: LCOV version 1.13