Provide pf queue manager API
authormikeb <mikeb@openbsd.org>
Wed, 28 Jun 2017 19:13:35 +0000 (19:13 +0000)
committermikeb <mikeb@openbsd.org>
Wed, 28 Jun 2017 19:13:35 +0000 (19:13 +0000)
Discussed with and OK henning@ at d2k17 as a part of a larger diff.

sys/net/fq_codel.c

index 8e9e065..07b36c9 100644 (file)
@@ -97,6 +97,9 @@ struct fqcodel {
        struct flowq             oldq;
 
        struct flow             *flows;
+       unsigned int             qlength;
+
+       struct ifnet            *ifp;
 
        struct codel_params      cparams;
 
@@ -115,10 +118,16 @@ struct fqcodel {
 unsigned int    fqcodel_idx(unsigned int, const struct mbuf *);
 void           *fqcodel_alloc(unsigned int, void *);
 void            fqcodel_free(unsigned int, void *);
-struct mbuf    *fqcodel_enq(struct ifqueue *, struct mbuf *);
-struct mbuf    *fqcodel_deq_begin(struct ifqueue *, void **);
-void            fqcodel_deq_commit(struct ifqueue *, struct mbuf *, void *);
-void            fqcodel_purge(struct ifqueue *, struct mbuf_list *);
+struct mbuf    *fqcodel_if_enq(struct ifqueue *, struct mbuf *);
+struct mbuf    *fqcodel_if_deq_begin(struct ifqueue *, void **);
+void            fqcodel_if_deq_commit(struct ifqueue *, struct mbuf *, void *);
+void            fqcodel_if_purge(struct ifqueue *, struct mbuf_list *);
+
+struct mbuf    *fqcodel_enq(struct fqcodel *, struct mbuf *);
+struct mbuf    *fqcodel_deq_begin(struct fqcodel *, void **,
+                   struct mbuf_list *);
+void            fqcodel_deq_commit(struct fqcodel *, struct mbuf *, void *);
+void            fqcodel_purge(struct fqcodel *, struct mbuf_list *);
 
 /*
  * ifqueue glue.
@@ -126,12 +135,12 @@ void               fqcodel_purge(struct ifqueue *, struct mbuf_list *);
 
 static const struct ifq_ops fqcodel_ops = {
        fqcodel_idx,
-       fqcodel_enq,
-       fqcodel_deq_begin,
-       fqcodel_deq_commit,
-       fqcodel_purge,
+       fqcodel_if_enq,
+       fqcodel_if_deq_begin,
+       fqcodel_if_deq_commit,
+       fqcodel_if_purge,
        fqcodel_alloc,
-       fqcodel_free,
+       fqcodel_free
 };
 
 const struct ifq_ops * const ifq_fqcodel_ops = &fqcodel_ops;
@@ -140,6 +149,11 @@ void               *fqcodel_pf_alloc(struct ifnet *);
 int             fqcodel_pf_addqueue(void *, struct pf_queuespec *);
 void            fqcodel_pf_free(void *);
 int             fqcodel_pf_qstats(struct pf_queuespec *, void *, int *);
+unsigned int    fqcodel_pf_qlength(void *);
+struct mbuf *   fqcodel_pf_enqueue(void *, struct mbuf *);
+struct mbuf *   fqcodel_pf_deq_begin(void *, void **, struct mbuf_list *);
+void            fqcodel_pf_deq_commit(void *, struct mbuf *, void *);
+void            fqcodel_pf_purge(void *, struct mbuf_list *);
 
 /*
  * pf queue glue.
@@ -149,7 +163,12 @@ static const struct pfq_ops fqcodel_pf_ops = {
        fqcodel_pf_alloc,
        fqcodel_pf_addqueue,
        fqcodel_pf_free,
-       fqcodel_pf_qstats
+       fqcodel_pf_qstats,
+       fqcodel_pf_qlength,
+       fqcodel_pf_enqueue,
+       fqcodel_pf_deq_begin,
+       fqcodel_pf_deq_commit,
+       fqcodel_pf_purge
 };
 
 const struct pfq_ops * const pfq_fqcodel_ops = &fqcodel_pf_ops;
@@ -513,9 +532,8 @@ classify_flow(struct fqcodel *fqc, struct mbuf *m)
 }
 
 struct mbuf *
-fqcodel_enq(struct ifqueue *ifq, struct mbuf *m)
+fqcodel_enq(struct fqcodel *fqc, struct mbuf *m)
 {
-       struct fqcodel *fqc = ifq->ifq_q;
        struct flow *flow;
        unsigned int backlog = 0;
        int64_t now;
@@ -527,6 +545,7 @@ fqcodel_enq(struct ifqueue *ifq, struct mbuf *m)
 
        codel_gettime(&now);
        codel_enqueue(&flow->cd, now, m);
+       fqc->qlength++;
 
        if (!flow->active) {
                SIMPLEQ_INSERT_TAIL(&fqc->newq, flow, flowentry);
@@ -540,7 +559,7 @@ fqcodel_enq(struct ifqueue *ifq, struct mbuf *m)
         * Check the limit for all queues and remove a packet
         * from the longest one.
         */
-       if (ifq_len(ifq) >= fqcodel_qlimit) {
+       if (fqc->qlength >= fqcodel_qlimit) {
                for (i = 0; i < fqc->nflows; i++) {
                        if (codel_backlog(&fqc->flows[i].cd) > backlog) {
                                flow = &fqc->flows[i];
@@ -554,6 +573,8 @@ fqcodel_enq(struct ifqueue *ifq, struct mbuf *m)
                fqc->drop_cnt.packets++;
                fqc->drop_cnt.bytes += m->m_pkthdr.len;
 
+               fqc->qlength--;
+
                DPRINTF("%s: dropping from flow %u\n", __func__,
                    flow->id);
                return (m);
@@ -617,27 +638,26 @@ next_flow(struct fqcodel *fqc, struct flow *flow, struct flowq **fq)
 }
 
 struct mbuf *
-fqcodel_deq_begin(struct ifqueue *ifq, void **cookiep)
+fqcodel_deq_begin(struct fqcodel *fqc, void **cookiep,
+    struct mbuf_list *free_ml)
 {
-       struct mbuf_list free_ml = MBUF_LIST_INITIALIZER();
-       struct ifnet *ifp = ifq->ifq_if;
-       struct fqcodel *fqc = ifq->ifq_q;
        struct flowq *fq;
        struct flow *flow;
        struct mbuf *m;
        int64_t now;
 
        if ((fqc->flags & FQCF_FIXED_QUANTUM) == 0)
-               fqc->quantum = ifp->if_mtu + max_linkhdr;
+               fqc->quantum = fqc->ifp->if_mtu + max_linkhdr;
 
        codel_gettime(&now);
 
        for (flow = first_flow(fqc, &fq); flow != NULL;
             flow = next_flow(fqc, flow, &fq)) {
-               m = codel_dequeue(&flow->cd, &fqc->cparams, now, &free_ml,
+               m = codel_dequeue(&flow->cd, &fqc->cparams, now, free_ml,
                    &fqc->drop_cnt.packets, &fqc->drop_cnt.bytes);
 
-               ifq_mfreeml(ifq, &free_ml);
+               KASSERT(fqc->qlength >= ml_len(free_ml));
+               fqc->qlength -= ml_len(free_ml);
 
                if (m != NULL) {
                        flow->deficit -= m->m_pkthdr.len;
@@ -652,11 +672,13 @@ fqcodel_deq_begin(struct ifqueue *ifq, void **cookiep)
 }
 
 void
-fqcodel_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie)
+fqcodel_deq_commit(struct fqcodel *fqc, struct mbuf *m, void *cookie)
 {
-       struct fqcodel *fqc = ifq->ifq_q;
        struct flow *flow = cookie;
 
+       KASSERT(fqc->qlength > 0);
+       fqc->qlength--;
+
        fqc->xmit_cnt.packets++;
        fqc->xmit_cnt.bytes += m->m_pkthdr.len;
 
@@ -664,13 +686,42 @@ fqcodel_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie)
 }
 
 void
-fqcodel_purge(struct ifqueue *ifq, struct mbuf_list *ml)
+fqcodel_purge(struct fqcodel *fqc, struct mbuf_list *ml)
 {
-       struct fqcodel *fqc = ifq->ifq_q;
        unsigned int i;
 
        for (i = 0; i < fqc->nflows; i++)
                codel_purge(&fqc->flows[i].cd, ml);
+       fqc->qlength = 0;
+}
+
+struct mbuf *
+fqcodel_if_enq(struct ifqueue *ifq, struct mbuf *m)
+{
+       return fqcodel_enq(ifq->ifq_q, m);
+}
+
+struct mbuf *
+fqcodel_if_deq_begin(struct ifqueue *ifq, void **cookiep)
+{
+       struct mbuf_list free_ml = MBUF_LIST_INITIALIZER();
+       struct mbuf *m;
+
+       m = fqcodel_deq_begin(ifq->ifq_q, cookiep, &free_ml);
+       ifq_mfreeml(ifq, &free_ml);
+       return (m);
+}
+
+void
+fqcodel_if_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie)
+{
+       return fqcodel_deq_commit(ifq->ifq_q, m, cookie);
+}
+
+void
+fqcodel_if_purge(struct ifqueue *ifq, struct mbuf_list *ml)
+{
+       return fqcodel_purge(ifq->ifq_q, ml);
 }
 
 void *
@@ -680,6 +731,9 @@ fqcodel_pf_alloc(struct ifnet *ifp)
 
        fqc = malloc(sizeof(struct fqcodel), M_DEVBUF, M_WAITOK | M_ZERO);
 
+       SIMPLEQ_INIT(&fqc->newq);
+       SIMPLEQ_INIT(&fqc->oldq);
+
        return (fqc);
 }
 
@@ -689,9 +743,6 @@ fqcodel_pf_addqueue(void *arg, struct pf_queuespec *qs)
        struct ifnet *ifp = qs->kif->pfik_ifp;
        struct fqcodel *fqc = arg;
 
-       if (qs->parent_qid != 0)
-               return (EINVAL);
-
        if (qs->flowqueue.flows == 0 || qs->flowqueue.flows > M_FLOWID_MASK)
                return (EINVAL);
 
@@ -721,6 +772,8 @@ fqcodel_pf_addqueue(void *arg, struct pf_queuespec *qs)
        }
 #endif
 
+       fqc->ifp = ifp;
+
        DPRINTF("fq-codel on %s: %d queues %d deep, quantum %d target %llums "
            "interval %llums\n", ifp->if_xname, fqc->nflows, fqc->qlimit,
            fqc->quantum, fqc->cparams.target / 1000000,
@@ -790,6 +843,36 @@ fqcodel_pf_qstats(struct pf_queuespec *qs, void *ubuf, int *nbytes)
        return (0);
 }
 
+unsigned int
+fqcodel_pf_qlength(void *fqc)
+{
+       return ((struct fqcodel *)fqc)->qlength;
+}
+
+struct mbuf *
+fqcodel_pf_enqueue(void *fqc, struct mbuf *m)
+{
+       return fqcodel_enq(fqc, m);
+}
+
+struct mbuf *
+fqcodel_pf_deq_begin(void *fqc, void **cookiep, struct mbuf_list *free_ml)
+{
+       return fqcodel_deq_begin(fqc, cookiep, free_ml);
+}
+
+void
+fqcodel_pf_deq_commit(void *fqc, struct mbuf *m, void *cookie)
+{
+       return fqcodel_deq_commit(fqc, m, cookie);
+}
+
+void
+fqcodel_pf_purge(void *fqc, struct mbuf_list *ml)
+{
+       return fqcodel_purge(fqc, ml);
+}
+
 unsigned int
 fqcodel_idx(unsigned int nqueues, const struct mbuf *m)
 {
@@ -799,12 +882,8 @@ fqcodel_idx(unsigned int nqueues, const struct mbuf *m)
 void *
 fqcodel_alloc(unsigned int idx, void *arg)
 {
-       struct fqcodel *fqc = arg;
-
-       SIMPLEQ_INIT(&fqc->newq);
-       SIMPLEQ_INIT(&fqc->oldq);
-
-       return (fqc);
+       /* Allocation is done in fqcodel_pf_alloc */
+       return (arg);
 }
 
 void