Index: if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.389 diff -u -p -r1.389 if.c --- if.c 12 Oct 2015 13:17:58 -0000 1.389 +++ if.c 23 Oct 2015 02:38:07 -0000 @@ -782,8 +782,6 @@ if_input_process(void *xmq) s = splnet(); while ((m = ml_dequeue(&ml)) != NULL) { - sched_pause(); - ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freem(m); @@ -792,7 +790,9 @@ if_input_process(void *xmq) #if NBRIDGE > 0 if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0) { + KERNEL_LOCK(); m = bridge_input(ifp, m); + KERNEL_UNLOCK(); if (m == NULL) { if_put(ifp); continue; @@ -2734,6 +2734,242 @@ niq_enlist(struct niqueue *niq, struct m if_congestion(); return (rv); +} + +/* + * send queues. + */ +struct priq_list { + struct mbuf *head; + struct mbuf *tail; +}; + +struct priq { + struct priq_list pq_q[IFQ_NQUEUES]; +}; + +int priq_enqueue(struct ifqueue *, struct mbuf *); +struct mbuf *priq_dequeue(struct ifqueue *); +int priq_requeue(struct ifqueue *, struct mbuf *); +unsigned int priq_purge(struct ifqueue *); + +const struct ifq_ops priq_ops = { + priq_attach, + priq_enqueue, + priq_poll, + priq_dequeue, + priq_requeue, + priq_purge, + priq_detach +}; + +void +int +priq_init(struct ifqueue *ifq) +{ + +} + +int +priq_enqueue(struct ifqueue *ifq, struct mbuf *m) +{ + struct priq *pq; + struct priq_list *pl; + + KASSERT(m->m_pkthdr.pf.prio < IFQ_MAXPRIO); + + pq = ifq->ifq_q; + pl = &pq->pq_q[m->m_pkthdr.pf.prio]; + + if (pl->tail == NULL) { + pl->head = m; + else + pl->tail->m_nextpkt = m; + pl->tail = m; + m->m_nextpkt = NULL; + + return (0); +} + +struct mbuf * +priq_poll(struct ifqueue *ifq) +{ + struct priq *pq = ifq->ifq_q; + struct priq_list *pl; + unsigned int prio = nitems(pq->pq_q); + struct mbuf *m; + + do { + pl = &pq->pq_q[--prio]; + m = pl->head; + if (m != NULL) + return (m); + } while (pl > 0); + + return (NULL); +} + +struct mbuf * +priq_dequeue(struct ifqueue *ifq) +{ + struct priq *pq = ifq->ifq_q; + struct priq_list *pl; + unsigned int prio = nitems(pq->pq_q); + struct mbuf *m; + + do { + pl = &pq->pq_q[--prio]; + m = pl->head; + if (m != NULL) { + pl->head = m->m_nextpkt; + if (pl->head == NULL) + pl->tail = NULL; + + m->m_nextpkt = NULL; + return (m); + } + } while (pl > 0); + + return (NULL); +} + +int +priq_requeue(struct ifqueue *ifq, struct mbuf *m) +{ + struct priq *pq = ifq->ifq_q; + struct priq_list *pl = &pq->pq_q[m->m_pkthdr.pf.prio]; + + if (pl->head == NULL) + pl->tail = m; + m->m_nextpkt = pl->head; + pl->pl_head = m; + + return (0); +} + +void +priq_purge(struct ifqueue *ifq, struct mbuf_list *ml) +{ + struct priq *pq = ifq->ifq_q; + unsigned int prio = nitems(pq->pq_q); + struct mbuf *n; + + do { + pl = &pq->pq_q[--prio]; + + m = pl->head; + while (m != NULL) { + n = m->m_nextpkt; + ml_enqueue(ml, m); + m = n; + } + + pl->head = pl->tail = NULL; + } while (prio > 0); +} + +int +ifq_queue(struct ifqueue *ifq, struct mbuf *m, + int (*op)(struct ifq *, struct mbuf *))) +{ + mtx_enter(&ifq->ifq_mtx); + rv = (*op)(ifq, m); + if (rv == 0) + ifq->ifq_len++; + mtx_leave(&ifq->ifq_mtx); + + return (rv); +} + +int +ifq_enqueue_try(struct ifqueue *ifq, struct mbuf *m) +{ + if (IFQ_LEN(ifq) > IFQ_MAXLEN(ifq)) + return (ENOBUFS); + + return ifq_queue(ifq, m, ifq->ifq_ops->enqueue); +} + +int +ifq_enqueue(struct ifqueue *ifq, struct mbuf *m) +{ + int err; + + err = ifq_enqueue_try(ifq, m); + if (err != 0) + m_freem(m); + + return (err); +} + +struct mbuf * +ifq_poll(struct ifqueue *ifq) +{ + struct mbuf *m; + + /* this function should be deprecated one day */ + KERNEL_ASSERT_LOCKED(); + + mtx_enter(&ifq->ifq_mtx); + m = ifq->ifq_ops->poll(ifq); + if (m != NULL) + ifq->ifq_len--; + mtx_leave(&ifq->ifq_mtx); + + return (m); +} + +struct mbuf * +ifq_dequeue(struct ifqueue *ifq) +{ + struct mbuf *m; + + mtx_enter(&ifq->ifq_mtx); + m = ifq->ifq_ops->dequeue(ifq); + if (m != NULL) + ifq->ifq_len--; + mtx_leave(&ifq->ifq_mtx); + + return (m); +} + +int +ifq_requeue(struct ifqueue *ifq, struct mbuf *m) +{ + return ifq_queue(ifq, m, ifq->ifq_ops->requeue); +} + +unsigned int +ifq_purge(struct ifqueue *ifq) +{ + struct mbuf_list ml = MBUF_LIST_INITIALIZER(); + struct mbuf *m; + unsigned int rv; + + mtx_enter(&ifq->ifq_mtx); + ifq->ifq_ops->purge(ifq, &ml); + rv = ifq->ifq_len; + ifq->ifq_len = 0; + mtx_leave(&ifq->ifq_mtx); + + KASSERT(rv == ml_len(&ml)); + + while ((m = ml_dequeue(&ml)) != NULL) + m_freem(m); + + return (rv); +} + +void +ifq_init(struct ifqueue *ifq) +{ + mtx_init(&ifq->ifq_mtx, IPL_NET); + ifq->ifq_drops = 0; + + /* default to priq */ + ifq->ifq_ops = &priq_ops; + ifq->ifq_q = malloc(sizeof(struct priq), M_DEVBUF, M_WAITOK | M_ZERO); + } __dead void Index: if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.48 diff -u -p -r1.48 if_var.h --- if_var.h 12 Oct 2015 13:17:58 -0000 1.48 +++ if_var.h 23 Oct 2015 02:38:07 -0000 @@ -97,18 +97,32 @@ struct if_clone { #define IF_CLONE_INITIALIZER(name, create, destroy) \ { { 0 }, name, sizeof(name) - 1, create, destroy } +struct ifqueue; + +struct ifq_ops { + void (*ifq_init)(struct ifqueue *); + int (*ifq_enqueue)(struct ifqueue *, + struct mbuf *); + struct mbuf *(*ifq_poll)(struct ifqueue *); + struct mbuf *(*ifq_dequeue)(struct ifqueue *); + void (*ifq_requeue)(struct ifqueue *, + struct mbuf *); + void (*ifq_purge)(struct ifqueue *, + struct mbuf_list *); +}; + /* * Structure defining a queue for a network interface. */ struct ifqueue { - struct { - struct mbuf *head; - struct mbuf *tail; - } ifq_q[IFQ_NQUEUES]; - int ifq_len; - int ifq_maxlen; - int ifq_drops; - struct hfsc_if *ifq_hfsc; + struct mutex ifq_mtx; + uint64_t ifq_drops; + void *ifq_q; + unsigned int ifq_serializer; + unsigned int ifq_len; + unsigned int ifq_maxlen; + + unsigned int ifq_hwlen; }; /* @@ -256,121 +270,48 @@ struct ifg_list { }; #ifdef _KERNEL +int ifq_enqueue_try(struct ifqueue *, struct mbuf *); +int ifq_enqueue(struct ifqueue *, struct mbuf *); +struct mbuf *ifq_poll(struct ifqueue *); +struct mbuf *ifq_dequeue(struct ifqueue *); +void ifq_requeue(struct ifqueue *, struct mbuf *); +void ifq_purge(struct ifqueue *); + #define IFQ_MAXLEN 256 #define IFNET_SLOWHZ 1 /* granularity is 1 second */ -/* - * Output queues (ifp->if_snd) and internetwork datagram level (pup level 1) - * input routines have queues of messages stored on ifqueue structures - * (defined above). Entries are added to and deleted from these structures - * by these macros, which should be called with ipl raised to splnet(). - */ -#define IF_QFULL(ifq) ((ifq)->ifq_len >= (ifq)->ifq_maxlen) -#define IF_DROP(ifq) ((ifq)->ifq_drops++) -#define IF_ENQUEUE(ifq, m) \ -do { \ - (m)->m_nextpkt = NULL; \ - if ((ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail == NULL) \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].head = m; \ - else \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail->m_nextpkt = m; \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail = m; \ - (ifq)->ifq_len++; \ -} while (/* CONSTCOND */0) -#define IF_PREPEND(ifq, m) \ -do { \ - (m)->m_nextpkt = (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].head; \ - if ((ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail == NULL) \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].tail = (m); \ - (ifq)->ifq_q[(m)->m_pkthdr.pf.prio].head = (m); \ - (ifq)->ifq_len++; \ -} while (/* CONSTCOND */0) - -#define IF_POLL(ifq, m) \ -do { \ - int if_dequeue_prio = IFQ_MAXPRIO; \ - do { \ - (m) = (ifq)->ifq_q[if_dequeue_prio].head; \ - } while (!(m) && --if_dequeue_prio >= 0); \ -} while (/* CONSTCOND */0) - -#define IF_DEQUEUE(ifq, m) \ -do { \ - int if_dequeue_prio = IFQ_MAXPRIO; \ - do { \ - (m) = (ifq)->ifq_q[if_dequeue_prio].head; \ - if (m) { \ - if (((ifq)->ifq_q[if_dequeue_prio].head = \ - (m)->m_nextpkt) == NULL) \ - (ifq)->ifq_q[if_dequeue_prio].tail = NULL; \ - (m)->m_nextpkt = NULL; \ - (ifq)->ifq_len--; \ - } \ - } while (!(m) && --if_dequeue_prio >= 0); \ -} while (/* CONSTCOND */0) - -#define IF_PURGE(ifq) \ +#define IFQ_ENQUEUE(ifq, m, err) \ do { \ - struct mbuf *__m0; \ - \ - for (;;) { \ - IF_DEQUEUE((ifq), __m0); \ - if (__m0 == NULL) \ - break; \ - else \ - m_freem(__m0); \ - } \ + (err) = ifq_enqueue((ifq), (m)); \ } while (/* CONSTCOND */0) -#define IF_LEN(ifq) ((ifq)->ifq_len) -#define IF_IS_EMPTY(ifq) ((ifq)->ifq_len == 0) -#define IFQ_ENQUEUE(ifq, m, err) \ +#define IFQ_DEQUEUE(ifq, m) \ do { \ - if (HFSC_ENABLED(ifq)) \ - (err) = hfsc_enqueue(((struct ifqueue *)(ifq)), m); \ - else { \ - if (IF_QFULL((ifq))) { \ - (err) = ENOBUFS; \ - } else { \ - IF_ENQUEUE((ifq), (m)); \ - (err) = 0; \ - } \ - } \ - if ((err)) { \ - m_freem((m)); \ - (ifq)->ifq_drops++; \ - } \ + (m) = ifq_dequeue(ifq); \ } while (/* CONSTCOND */0) -#define IFQ_DEQUEUE(ifq, m) \ +#define IFQ_REQUEUE(ifq, m) \ do { \ - if (HFSC_ENABLED((ifq))) \ - (m) = hfsc_dequeue(((struct ifqueue *)(ifq)), 1); \ - else \ - IF_DEQUEUE((ifq), (m)); \ + ifq_requeue((ifq), (m)); \ } while (/* CONSTCOND */0) #define IFQ_POLL(ifq, m) \ do { \ - if (HFSC_ENABLED((ifq))) \ - (m) = hfsc_dequeue(((struct ifqueue *)(ifq)), 0); \ - else \ - IF_POLL((ifq), (m)); \ + (m) = ifq_poll(ifq); \ } while (/* CONSTCOND */0) #define IFQ_PURGE(ifq) \ do { \ - if (HFSC_ENABLED((ifq))) \ - hfsc_purge(((struct ifqueue *)(ifq))); \ - else \ - IF_PURGE((ifq)); \ + ifq_purge(ifq); \ } while (/* CONSTCOND */0) -#define IFQ_SET_READY(ifq) /* nothing */ - -#define IFQ_LEN(ifq) IF_LEN(ifq) +#define IFQ_LEN(ifq) ((ifq)->ifq_len) #define IFQ_IS_EMPTY(ifq) ((ifq)->ifq_len == 0) -#define IFQ_SET_MAXLEN(ifq, len) ((ifq)->ifq_maxlen = (len)) +#define IFQ_SET_MAXLEN(ifq, len) ((ifq)->ifq_hwlen = (len)) +#define IFQ_SET_READY(ifq) \ +do { \ + ifq_init(ifq); \ +while (/* CONSTCOND */0) /* default interface priorities */ #define IF_WIRED_DEFAULT_PRIORITY 0