summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Belopuhov <mikeb@cvs.openbsd.org>2017-05-11 12:22:27 +0000
committerMike Belopuhov <mikeb@cvs.openbsd.org>2017-05-11 12:22:27 +0000
commit003bff08fa0fc8e4c5bb42a9b1f6d24f369f9223 (patch)
tree6fe33ae83735bc2cff397ba61ab4287a5d78a1db
parentd07787d3a0926f809c287225b7e84cee3cfd60a2 (diff)
Add pf queue configuration glue for FQ-CoDel
-rw-r--r--sys/net/fq_codel.c141
-rw-r--r--sys/net/fq_codel.h1
2 files changed, 142 insertions, 0 deletions
diff --git a/sys/net/fq_codel.c b/sys/net/fq_codel.c
index eca603450de..56df011d258 100644
--- a/sys/net/fq_codel.c
+++ b/sys/net/fq_codel.c
@@ -138,6 +138,24 @@ static const struct ifq_ops fqcodel_ops = {
const struct ifq_ops * const ifq_fqcodel_ops = &fqcodel_ops;
+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 *);
+
+/*
+ * pf queue glue.
+ */
+
+static const struct pfq_ops fqcodel_pf_ops = {
+ fqcodel_pf_alloc,
+ fqcodel_pf_addqueue,
+ fqcodel_pf_free,
+ fqcodel_pf_qstats
+};
+
+const struct pfq_ops * const pfq_fqcodel_ops = &fqcodel_pf_ops;
+
/* Default aggregate queue depth */
static const unsigned int fqcodel_qlimit = 1024;
@@ -653,6 +671,129 @@ fqcodel_purge(struct ifqueue *ifq, struct mbuf_list *ml)
codel_purge(&fqc->flows[i].cd, ml);
}
+void *
+fqcodel_pf_alloc(struct ifnet *ifp)
+{
+ struct fqcodel *fqc;
+
+ fqc = malloc(sizeof(struct fqcodel), M_DEVBUF, M_WAITOK | M_ZERO);
+
+ return (fqc);
+}
+
+int
+fqcodel_pf_addqueue(void *arg, struct pf_queuespec *qs)
+{
+ struct ifnet *ifp = qs->kif->pfik_ifp;
+ struct fqcodel *fqc = arg;
+
+ KASSERT(qs->parent_qid == 0);
+
+ if (qs->flowqueue.flows == 0 || qs->flowqueue.flows > M_FLOWID_MASK)
+ return (EINVAL);
+
+ fqc->nflows = qs->flowqueue.flows;
+ fqc->quantum = qs->flowqueue.quantum;
+ if (qs->qlimit > 0)
+ fqc->qlimit = qs->qlimit;
+ else
+ fqc->qlimit = fqcodel_qlimit;
+ if (fqc->quantum > 0)
+ fqc->flags |= FQCF_FIXED_QUANTUM;
+ else
+ fqc->quantum = ifp->if_mtu + max_linkhdr;
+
+ codel_initparams(&fqc->cparams, qs->flowqueue.target,
+ qs->flowqueue.interval, fqc->quantum);
+
+ fqc->flows = mallocarray(fqc->nflows, sizeof(struct flow),
+ M_DEVBUF, M_WAITOK | M_ZERO);
+
+#ifdef FQCODEL_DEBUG
+ {
+ unsigned int i;
+
+ for (i = 0; i < fqc->nflows; i++)
+ fqc->flows[i].id = i;
+ }
+#endif
+
+ 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,
+ fqc->cparams.interval / 1000000);
+
+ return (0);
+}
+
+void
+fqcodel_pf_free(void *arg)
+{
+ struct fqcodel *fqc = arg;
+
+ codel_freeparams(&fqc->cparams);
+ free(fqc->flows, M_DEVBUF, fqc->nflows * sizeof(struct flow));
+ free(fqc, M_DEVBUF, sizeof(struct fqcodel));
+}
+
+int
+fqcodel_pf_qstats(struct pf_queuespec *qs, void *ubuf, int *nbytes)
+{
+ struct ifnet *ifp = qs->kif->pfik_ifp;
+ struct fqcodel_stats stats;
+ struct fqcodel *fqc;
+ unsigned int i, qlen;
+ int error = 0;
+
+ if (ifp == NULL)
+ return (EBADF);
+
+ if (*nbytes < sizeof(stats))
+ return (EINVAL);
+
+ memset(&stats, 0, sizeof(stats));
+
+ /* XXX: multi-q? */
+ fqc = ifq_q_enter(&ifp->if_snd, ifq_fqcodel_ops);
+ if (fqc == NULL)
+ return (EBADF);
+
+ stats.xmit_cnt = fqc->xmit_cnt;
+ stats.drop_cnt = fqc->drop_cnt;
+
+ stats.qlength = ifq_len(&ifp->if_snd);
+ stats.qlimit = fqc->qlimit;
+
+ stats.flows = stats.maxqlen = stats.minqlen = 0;
+ stats.qlensum = stats.qlensumsq = 0;
+
+ for (i = 0; i < fqc->nflows; i++) {
+ qlen = codel_qlength(&fqc->flows[i].cd);
+ if (qlen == 0)
+ continue;
+ if (stats.minqlen == 0)
+ stats.minqlen = qlen;
+ else
+ stats.minqlen = MIN(stats.minqlen, qlen);
+ if (stats.maxqlen == 0)
+ stats.maxqlen = qlen;
+ else
+ stats.maxqlen = MAX(stats.maxqlen, qlen);
+ stats.flows++;
+
+ stats.qlensum += qlen;
+ stats.qlensumsq += (uint64_t)qlen * (uint64_t)qlen;
+ }
+
+ ifq_q_leave(&ifp->if_snd, fqc);
+
+ if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0)
+ return (error);
+
+ *nbytes = sizeof(stats);
+ return (0);
+}
+
unsigned int
fqcodel_idx(unsigned int nqueues, const struct mbuf *m)
{
diff --git a/sys/net/fq_codel.h b/sys/net/fq_codel.h
index 7d79f5bcc7e..7b4d0844187 100644
--- a/sys/net/fq_codel.h
+++ b/sys/net/fq_codel.h
@@ -46,6 +46,7 @@ struct fqcodel_stats {
#ifdef _KERNEL
extern const struct ifq_ops * const ifq_fqcodel_ops;
+extern const struct pfq_ops * const pfq_fqcodel_ops;
#endif /* _KERNEL */
#endif /* _NET_FQ_CODEL_H_ */