summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/hfsc.c327
-rw-r--r--sys/net/hfsc.h19
-rw-r--r--sys/net/if.c334
-rw-r--r--sys/net/if_tun.c46
-rw-r--r--sys/net/if_var.h167
-rw-r--r--sys/net/pf_if.c7
-rw-r--r--sys/net/pf_ioctl.c167
-rw-r--r--sys/net/pfvar.h5
8 files changed, 702 insertions, 370 deletions
diff --git a/sys/net/hfsc.c b/sys/net/hfsc.c
index 1b0f3752c94..05cd4f9e978 100644
--- a/sys/net/hfsc.c
+++ b/sys/net/hfsc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hfsc.c,v 1.30 2015/11/09 01:06:31 dlg Exp $ */
+/* $OpenBSD: hfsc.c,v 1.31 2015/11/20 03:35:23 dlg Exp $ */
/*
* Copyright (c) 2012-2013 Henning Brauer <henning@openbsd.org>
@@ -181,11 +181,11 @@ struct hfsc_class {
*/
struct hfsc_if {
struct hfsc_if *hif_next; /* interface state list */
- struct ifqueue *hif_ifq; /* backpointer to ifq */
struct hfsc_class *hif_rootclass; /* root class */
struct hfsc_class *hif_defaultclass; /* default class */
struct hfsc_class **hif_class_tbl;
- struct hfsc_class *hif_pollcache; /* cache for poll operation */
+
+ u_int64_t hif_microtime; /* time at deq_begin */
u_int hif_allocated; /* # of slots in hif_class_tbl */
u_int hif_classes; /* # of classes in the tree */
@@ -206,9 +206,8 @@ int hfsc_class_destroy(struct hfsc_if *,
struct hfsc_class *);
struct hfsc_class *hfsc_nextclass(struct hfsc_class *);
-struct mbuf *hfsc_cl_dequeue(struct hfsc_class *);
-struct mbuf *hfsc_cl_poll(struct hfsc_class *);
-void hfsc_cl_purge(struct hfsc_if *, struct hfsc_class *);
+void hfsc_cl_purge(struct hfsc_if *, struct hfsc_class *,
+ struct mbuf_list *);
void hfsc_deferred(void *);
void hfsc_update_cfmin(struct hfsc_class *);
@@ -256,6 +255,30 @@ struct hfsc_class *hfsc_clh2cph(struct hfsc_if *, u_int32_t);
struct pool hfsc_class_pl, hfsc_internal_sc_pl;
+/*
+ * ifqueue glue.
+ */
+
+void *hfsc_alloc(void *);
+void hfsc_free(void *);
+int hfsc_enq(struct ifqueue *, struct mbuf *);
+struct mbuf *hfsc_deq_begin(struct ifqueue *, void **);
+void hfsc_deq_commit(struct ifqueue *, struct mbuf *, void *);
+void hfsc_deq_rollback(struct ifqueue *, struct mbuf *, void *);
+void hfsc_purge(struct ifqueue *, struct mbuf_list *);
+
+const struct ifq_ops hfsc_ops = {
+ hfsc_alloc,
+ hfsc_free,
+ hfsc_enq,
+ hfsc_deq_begin,
+ hfsc_deq_commit,
+ hfsc_deq_rollback,
+ hfsc_purge,
+};
+
+const struct ifq_ops * const ifq_hfsc_ops = &hfsc_ops;
+
u_int64_t
hfsc_microuptime(void)
{
@@ -296,64 +319,37 @@ hfsc_initialize(void)
{
pool_init(&hfsc_class_pl, sizeof(struct hfsc_class), 0, 0, PR_WAITOK,
"hfscclass", NULL);
+ pool_setipl(&hfsc_class_pl, IPL_NONE);
pool_init(&hfsc_internal_sc_pl, sizeof(struct hfsc_internal_sc), 0, 0,
PR_WAITOK, "hfscintsc", NULL);
+ pool_setipl(&hfsc_internal_sc_pl, IPL_NONE);
}
-int
-hfsc_attach(struct ifnet *ifp)
+struct hfsc_if *
+hfsc_pf_alloc(struct ifnet *ifp)
{
struct hfsc_if *hif;
- if (ifp == NULL || ifp->if_snd.ifq_hfsc != NULL)
- return (0);
+ KASSERT(ifp != NULL);
- hif = malloc(sizeof(struct hfsc_if), M_DEVBUF, M_WAITOK | M_ZERO);
+ hif = malloc(sizeof(*hif), M_DEVBUF, M_WAITOK | M_ZERO);
TAILQ_INIT(&hif->hif_eligible);
hif->hif_class_tbl = mallocarray(HFSC_DEFAULT_CLASSES, sizeof(void *),
M_DEVBUF, M_WAITOK | M_ZERO);
hif->hif_allocated = HFSC_DEFAULT_CLASSES;
- hif->hif_ifq = &ifp->if_snd;
- ifp->if_snd.ifq_hfsc = hif;
-
timeout_set(&hif->hif_defer, hfsc_deferred, ifp);
- /* XXX HRTIMER don't schedule it yet, only when some packets wait. */
- timeout_add(&hif->hif_defer, 1);
- return (0);
+ return (hif);
}
int
-hfsc_detach(struct ifnet *ifp)
+hfsc_pf_addqueue(struct hfsc_if *hif, struct pf_queuespec *q)
{
- struct hfsc_if *hif;
-
- if (ifp == NULL)
- return (0);
-
- hif = ifp->if_snd.ifq_hfsc;
- timeout_del(&hif->hif_defer);
- ifp->if_snd.ifq_hfsc = NULL;
-
- free(hif->hif_class_tbl, M_DEVBUF, hif->hif_allocated * sizeof(void *));
- free(hif, M_DEVBUF, sizeof(struct hfsc_if));
-
- return (0);
-}
-
-int
-hfsc_addqueue(struct pf_queuespec *q)
-{
- struct hfsc_if *hif;
struct hfsc_class *cl, *parent;
struct hfsc_sc rtsc, lssc, ulsc;
- if (q->kif->pfik_ifp == NULL)
- return (0);
-
- if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL)
- return (EINVAL);
+ KASSERT(hif != NULL);
if (q->parent_qid == HFSC_NULLCLASS_HANDLE &&
hif->hif_rootclass == NULL)
@@ -386,61 +382,82 @@ hfsc_addqueue(struct pf_queuespec *q)
}
int
-hfsc_delqueue(struct pf_queuespec *q)
-{
- struct hfsc_if *hif;
- struct hfsc_class *cl;
-
- if (q->kif->pfik_ifp == NULL)
- return (0);
-
- if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL)
- return (EINVAL);
-
- if ((cl = hfsc_clh2cph(hif, q->qid)) == NULL)
- return (EINVAL);
-
- return (hfsc_class_destroy(hif, cl));
-}
-
-int
-hfsc_qstats(struct pf_queuespec *q, void *ubuf, int *nbytes)
+hfsc_pf_qstats(struct pf_queuespec *q, void *ubuf, int *nbytes)
{
+ struct ifnet *ifp = q->kif->pfik_ifp;
struct hfsc_if *hif;
struct hfsc_class *cl;
struct hfsc_class_stats stats;
int error = 0;
- if (q->kif->pfik_ifp == NULL)
- return (EBADF);
-
- if ((hif = q->kif->pfik_ifp->if_snd.ifq_hfsc) == NULL)
+ if (ifp == NULL)
return (EBADF);
- if ((cl = hfsc_clh2cph(hif, q->qid)) == NULL)
+ if (*nbytes < sizeof(stats))
return (EINVAL);
- if (*nbytes < sizeof(stats))
+ hif = ifq_q_enter(&ifp->if_snd, ifq_hfsc_ops);
+ if (hif == NULL)
+ return (EBADF);
+
+ if ((cl = hfsc_clh2cph(hif, q->qid)) == NULL) {
+ ifq_q_leave(&ifp->if_snd, hif);
return (EINVAL);
+ }
hfsc_getclstats(&stats, cl);
+ ifq_q_leave(&ifp->if_snd, hif);
if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0)
return (error);
+
*nbytes = sizeof(stats);
return (0);
}
void
-hfsc_purge(struct ifqueue *ifq)
+hfsc_pf_free(struct hfsc_if *hif)
+{
+ hfsc_free(hif);
+}
+
+void *
+hfsc_alloc(void *q)
+{
+ struct hfsc_if *hif = q;
+ KASSERT(hif != NULL);
+
+ timeout_add(&hif->hif_defer, 1);
+ return (hif);
+}
+
+void
+hfsc_free(void *q)
{
- struct hfsc_if *hif = ifq->ifq_hfsc;
+ struct hfsc_if *hif = q;
+ int i;
+
+ KERNEL_ASSERT_LOCKED();
+
+ timeout_del(&hif->hif_defer);
+
+ i = hif->hif_allocated;
+ do
+ hfsc_class_destroy(hif, hif->hif_class_tbl[--i]);
+ while (i > 0);
+
+ free(hif->hif_class_tbl, M_DEVBUF, hif->hif_allocated * sizeof(void *));
+ free(hif, M_DEVBUF, sizeof(*hif));
+}
+
+void
+hfsc_purge(struct ifqueue *ifq, struct mbuf_list *ml)
+{
+ struct hfsc_if *hif = ifq->ifq_q;
struct hfsc_class *cl;
for (cl = hif->hif_rootclass; cl != NULL; cl = hfsc_nextclass(cl))
- if (ml_len(&cl->cl_q.q) > 0)
- hfsc_cl_purge(hif, cl);
- hif->hif_ifq->ifq_len = 0;
+ hfsc_cl_purge(hif, cl, ml);
}
struct hfsc_class *
@@ -555,9 +572,7 @@ hfsc_class_destroy(struct hfsc_if *hif, struct hfsc_class *cl)
return (EBUSY);
s = splnet();
-
- if (ml_len(&cl->cl_q.q) > 0)
- hfsc_cl_purge(hif, cl);
+ KASSERT(ml_empty(&cl->cl_q.q));
if (cl->cl_parent != NULL) {
struct hfsc_class *p = cl->cl_parent->cl_children;
@@ -624,9 +639,9 @@ hfsc_nextclass(struct hfsc_class *cl)
}
int
-hfsc_enqueue(struct ifqueue *ifq, struct mbuf *m)
+hfsc_enq(struct ifqueue *ifq, struct mbuf *m)
{
- struct hfsc_if *hif = ifq->ifq_hfsc;
+ struct hfsc_if *hif = ifq->ifq_q;
struct hfsc_class *cl;
if ((cl = hfsc_clh2cph(hif, m->m_pkthdr.pf.qid)) == NULL ||
@@ -638,12 +653,12 @@ hfsc_enqueue(struct ifqueue *ifq, struct mbuf *m)
}
if (ml_len(&cl->cl_q.q) >= cl->cl_q.qlimit) {
- /* drop. mbuf needs to be freed */
+ /* drop occurred. mbuf needs to be freed */
PKTCNTR_INC(&cl->cl_stats.drop_cnt, m->m_pkthdr.len);
return (ENOBUFS);
}
+
ml_enqueue(&cl->cl_q.q, m);
- ifq->ifq_len++;
m->m_pkthdr.pf.prio = IFQ_MAXPRIO;
/* successfully queued. */
@@ -654,71 +669,68 @@ hfsc_enqueue(struct ifqueue *ifq, struct mbuf *m)
}
struct mbuf *
-hfsc_dequeue(struct ifqueue *ifq, int remove)
+hfsc_deq_begin(struct ifqueue *ifq, void **cookiep)
{
- struct hfsc_if *hif = ifq->ifq_hfsc;
+ struct hfsc_if *hif = ifq->ifq_q;
struct hfsc_class *cl, *tcl;
struct mbuf *m;
- int next_len, realtime = 0;
u_int64_t cur_time;
- if (IFQ_LEN(ifq) == 0)
- return (NULL);
-
cur_time = hfsc_microuptime();
- if (remove && hif->hif_pollcache != NULL) {
- cl = hif->hif_pollcache;
- hif->hif_pollcache = NULL;
- /* check if the class was scheduled by real-time criteria */
- if (cl->cl_rsc != NULL)
- realtime = (cl->cl_e <= cur_time);
- } else {
+ /*
+ * if there are eligible classes, use real-time criteria.
+ * find the class with the minimum deadline among
+ * the eligible classes.
+ */
+ cl = hfsc_ellist_get_mindl(hif, cur_time);
+ if (cl == NULL) {
/*
- * if there are eligible classes, use real-time criteria.
- * find the class with the minimum deadline among
- * the eligible classes.
+ * use link-sharing criteria
+ * get the class with the minimum vt in the hierarchy
*/
- if ((cl = hfsc_ellist_get_mindl(hif, cur_time)) != NULL) {
- realtime = 1;
- } else {
+ cl = NULL;
+ tcl = hif->hif_rootclass;
+
+ while (tcl != NULL && tcl->cl_children != NULL) {
+ tcl = hfsc_actlist_firstfit(tcl, cur_time);
+ if (tcl == NULL)
+ continue;
+
/*
- * use link-sharing criteria
- * get the class with the minimum vt in the hierarchy
+ * update parent's cl_cvtmin.
+ * don't update if the new vt is smaller.
*/
- cl = NULL;
- tcl = hif->hif_rootclass;
+ if (tcl->cl_parent->cl_cvtmin < tcl->cl_vt)
+ tcl->cl_parent->cl_cvtmin = tcl->cl_vt;
- while (tcl != NULL && tcl->cl_children != NULL) {
- tcl = hfsc_actlist_firstfit(tcl, cur_time);
- if (tcl == NULL)
- continue;
+ cl = tcl;
+ }
+ /* XXX HRTIMER plan hfsc_deferred precisely here. */
+ if (cl == NULL)
+ return (NULL);
+ }
- /*
- * update parent's cl_cvtmin.
- * don't update if the new vt is smaller.
- */
- if (tcl->cl_parent->cl_cvtmin < tcl->cl_vt)
- tcl->cl_parent->cl_cvtmin = tcl->cl_vt;
+ m = ml_dequeue(&cl->cl_q.q);
+ KASSERT(m != NULL);
- cl = tcl;
- }
- /* XXX HRTIMER plan hfsc_deferred precisely here. */
- if (cl == NULL)
- return (NULL);
- }
+ hif->hif_microtime = cur_time;
+ *cookiep = cl;
+ return (m);
+}
- if (!remove) {
- hif->hif_pollcache = cl;
- m = hfsc_cl_poll(cl);
- return (m);
- }
- }
+void
+hfsc_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie)
+{
+ struct hfsc_if *hif = ifq->ifq_q;
+ struct hfsc_class *cl = cookie;
+ int next_len, realtime = 0;
+ u_int64_t cur_time = hif->hif_microtime;
- if ((m = hfsc_cl_dequeue(cl)) == NULL)
- panic("hfsc_dequeue");
+ /* check if the class was scheduled by real-time criteria */
+ if (cl->cl_rsc != NULL)
+ realtime = (cl->cl_e <= cur_time);
- ifq->ifq_len--;
PKTCNTR_INC(&cl->cl_stats.xmit_cnt, m->m_pkthdr.len);
hfsc_update_vf(cl, m->m_pkthdr.len, cur_time);
@@ -739,51 +751,49 @@ hfsc_dequeue(struct ifqueue *ifq, int remove)
/* the class becomes passive */
hfsc_set_passive(hif, cl);
}
+}
- return (m);
+void
+hfsc_deq_rollback(struct ifqueue *ifq, struct mbuf *m, void *cookie)
+{
+ struct hfsc_class *cl = cookie;
+
+ ml_requeue(&cl->cl_q.q, m);
}
void
hfsc_deferred(void *arg)
{
struct ifnet *ifp = arg;
+ struct hfsc_if *hif;
int s;
+ KERNEL_ASSERT_LOCKED();
+ KASSERT(HFSC_ENABLED(&ifp->if_snd));
+
s = splnet();
- if (HFSC_ENABLED(&ifp->if_snd) && !IFQ_IS_EMPTY(&ifp->if_snd))
+ if (!IFQ_IS_EMPTY(&ifp->if_snd))
if_start(ifp);
splx(s);
- /* XXX HRTIMER nearest virtual/fit time is likely less than 1/HZ. */
- timeout_add(&ifp->if_snd.ifq_hfsc->hif_defer, 1);
-}
-
-struct mbuf *
-hfsc_cl_dequeue(struct hfsc_class *cl)
-{
- return (ml_dequeue(&cl->cl_q.q));
-}
+ hif = ifp->if_snd.ifq_q;
-struct mbuf *
-hfsc_cl_poll(struct hfsc_class *cl)
-{
- /* XXX */
- return (cl->cl_q.q.ml_head);
+ /* XXX HRTIMER nearest virtual/fit time is likely less than 1/HZ. */
+ timeout_add(&hif->hif_defer, 1);
}
void
-hfsc_cl_purge(struct hfsc_if *hif, struct hfsc_class *cl)
+hfsc_cl_purge(struct hfsc_if *hif, struct hfsc_class *cl, struct mbuf_list *ml)
{
struct mbuf *m;
if (ml_empty(&cl->cl_q.q))
return;
- while ((m = hfsc_cl_dequeue(cl)) != NULL) {
+ MBUF_LIST_FOREACH(&cl->cl_q.q, m)
PKTCNTR_INC(&cl->cl_stats.drop_cnt, m->m_pkthdr.len);
- m_freem(m);
- hif->hif_ifq->ifq_len--;
- }
+
+ ml_enlist(ml, &cl->cl_q.q);
hfsc_update_vf(cl, 0, 0); /* remove cl from the actlist */
hfsc_set_passive(hif, cl);
@@ -1544,25 +1554,4 @@ hfsc_clh2cph(struct hfsc_if *hif, u_int32_t chandle)
return (cl);
return (NULL);
}
-
-#else /* NPF > 0 */
-
-void
-hfsc_purge(struct ifqueue *q)
-{
- panic("hfsc_purge called on hfsc-less kernel");
-}
-
-int
-hfsc_enqueue(struct ifqueue *q, struct mbuf *m)
-{
- panic("hfsc_enqueue called on hfsc-less kernel");
-}
-
-struct mbuf *
-hfsc_dequeue(struct ifqueue *q, int i)
-{
- panic("hfsc_enqueue called on hfsc-less kernel");
-}
-
#endif
diff --git a/sys/net/hfsc.h b/sys/net/hfsc.h
index ae746e50ad0..544d9df6259 100644
--- a/sys/net/hfsc.h
+++ b/sys/net/hfsc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hfsc.h,v 1.10 2015/11/09 01:06:31 dlg Exp $ */
+/* $OpenBSD: hfsc.h,v 1.11 2015/11/20 03:35:23 dlg Exp $ */
/*
* Copyright (c) 2012-2013 Henning Brauer <henning@openbsd.org>
@@ -112,19 +112,18 @@ struct ifqueue;
struct pf_queuespec;
struct hfsc_if;
-#define HFSC_ENABLED(ifq) ((ifq)->ifq_hfsc != NULL)
+extern const struct ifq_ops * const ifq_hfsc_ops;
+
+#define HFSC_ENABLED(ifq) ((ifq)->ifq_ops == ifq_hfsc_ops)
#define HFSC_DEFAULT_QLIMIT 50
+struct hfsc_if *hfsc_pf_alloc(struct ifnet *);
+int hfsc_pf_addqueue(struct hfsc_if *, struct pf_queuespec *);
+void hfsc_pf_free(struct hfsc_if *);
+int hfsc_pf_qstats(struct pf_queuespec *, void *, int *);
+
void hfsc_initialize(void);
-int hfsc_attach(struct ifnet *);
-int hfsc_detach(struct ifnet *);
-void hfsc_purge(struct ifqueue *);
-int hfsc_enqueue(struct ifqueue *, struct mbuf *);
-struct mbuf *hfsc_dequeue(struct ifqueue *, int);
u_int64_t hfsc_microuptime(void);
-int hfsc_addqueue(struct pf_queuespec *);
-int hfsc_delqueue(struct pf_queuespec *);
-int hfsc_qstats(struct pf_queuespec *, void *, int *);
#endif /* _KERNEL */
#endif /* _HFSC_H_ */
diff --git a/sys/net/if.c b/sys/net/if.c
index 2f4d0399f6f..75b3e96b7f8 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.407 2015/11/18 13:58:02 mpi Exp $ */
+/* $OpenBSD: if.c,v 1.408 2015/11/20 03:35:23 dlg Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -397,9 +397,6 @@ if_attachsetup(struct ifnet *ifp)
if_addgroup(ifp, IFG_ALL);
- if (ifp->if_snd.ifq_maxlen == 0)
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
-
if_attachdomain(ifp);
#if NPF > 0
pfi_attach_ifnet(ifp);
@@ -510,6 +507,8 @@ if_attach_common(struct ifnet *ifp)
TAILQ_INIT(&ifp->if_addrlist);
TAILQ_INIT(&ifp->if_maddrlist);
+ ifq_init(&ifp->if_snd);
+
ifp->if_addrhooks = malloc(sizeof(*ifp->if_addrhooks),
M_TEMP, M_WAITOK);
TAILQ_INIT(ifp->if_addrhooks);
@@ -538,7 +537,7 @@ if_start(struct ifnet *ifp)
splassert(IPL_NET);
- if (ifp->if_snd.ifq_len >= min(8, ifp->if_snd.ifq_maxlen) &&
+ if (ifq_len(&ifp->if_snd) >= min(8, ifp->if_snd.ifq_maxlen) &&
!ISSET(ifp->if_flags, IFF_OACTIVE)) {
if (ISSET(ifp->if_xflags, IFXF_TXREADY)) {
TAILQ_REMOVE(&iftxlist, ifp, if_txlist);
@@ -783,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);
@@ -942,6 +939,8 @@ if_detach(struct ifnet *ifp)
if_idxmap_remove(ifp);
splx(s);
+
+ ifq_destroy(&ifp->if_snd);
}
/*
@@ -2725,6 +2724,327 @@ niq_enlist(struct niqueue *niq, struct mbuf_list *ml)
return (rv);
}
+/*
+ * send queues.
+ */
+
+void *priq_alloc(void *);
+void priq_free(void *);
+int priq_enq(struct ifqueue *, struct mbuf *);
+struct mbuf *priq_deq_begin(struct ifqueue *, void **);
+void priq_deq_commit(struct ifqueue *, struct mbuf *, void *);
+void priq_deq_rollback(struct ifqueue *, struct mbuf *, void *);
+void priq_purge(struct ifqueue *, struct mbuf_list *);
+
+const struct ifq_ops priq_ops = {
+ priq_alloc,
+ priq_free,
+ priq_enq,
+ priq_deq_begin,
+ priq_deq_commit,
+ priq_deq_rollback,
+ priq_purge,
+};
+
+const struct ifq_ops * const ifq_priq_ops = &priq_ops;
+
+struct priq_list {
+ struct mbuf *head;
+ struct mbuf *tail;
+};
+
+struct priq {
+ struct priq_list pq_lists[IFQ_NQUEUES];
+};
+
+void *
+priq_alloc(void *null)
+{
+ return (malloc(sizeof(struct priq), M_DEVBUF, M_WAITOK | M_ZERO));
+}
+
+void
+priq_free(void *pq)
+{
+ free(pq, M_DEVBUF, sizeof(struct priq));
+}
+
+int
+priq_enq(struct ifqueue *ifq, struct mbuf *m)
+{
+ struct priq *pq;
+ struct priq_list *pl;
+
+ if (ifq_len(ifq) >= ifq->ifq_maxlen)
+ return (ENOBUFS);
+
+ pq = ifq->ifq_q;
+ KASSERT(m->m_pkthdr.pf.prio < IFQ_MAXPRIO);
+ pl = &pq->pq_lists[m->m_pkthdr.pf.prio];
+
+ m->m_nextpkt = NULL;
+ if (pl->tail == NULL)
+ pl->head = m;
+ else
+ pl->tail->m_nextpkt = m;
+ pl->tail = m;
+
+ return (0);
+}
+
+struct mbuf *
+priq_deq_begin(struct ifqueue *ifq, void **cookiep)
+{
+ struct priq *pq = ifq->ifq_q;
+ struct priq_list *pl;
+ unsigned int prio = nitems(pq->pq_lists);
+ struct mbuf *m;
+
+ do {
+ pl = &pq->pq_lists[--prio];
+ m = pl->head;
+ if (m != NULL) {
+ *cookiep = pl;
+ return (m);
+ }
+ } while (prio > 0);
+
+ return (NULL);
+}
+
+void
+priq_deq_commit(struct ifqueue *ifq, struct mbuf *m, void *cookie)
+{
+ struct priq_list *pl = cookie;
+
+ KASSERT(pl->head == m);
+
+ pl->head = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+
+ if (pl->head == NULL)
+ pl->tail = NULL;
+}
+
+void
+priq_deq_rollback(struct ifqueue *ifq, struct mbuf *m, void *cookie)
+{
+#ifdef DIAGNOSTIC
+ struct priq_list *pl = cookie;
+
+ KASSERT(pl->head == m);
+#endif
+}
+
+void
+priq_purge(struct ifqueue *ifq, struct mbuf_list *ml)
+{
+ struct priq *pq = ifq->ifq_q;
+ struct priq_list *pl;
+ unsigned int prio = nitems(pq->pq_lists);
+ struct mbuf *m, *n;
+
+ do {
+ pl = &pq->pq_lists[--prio];
+
+ for (m = pl->head; m != NULL; m = n) {
+ n = m->m_nextpkt;
+ ml_enqueue(ml, m);
+ }
+
+ pl->head = pl->tail = NULL;
+ } while (prio > 0);
+}
+
+int
+ifq_enqueue_try(struct ifqueue *ifq, struct mbuf *m)
+{
+ int rv;
+
+ mtx_enter(&ifq->ifq_mtx);
+ rv = ifq->ifq_ops->ifqop_enq(ifq, m);
+ if (rv == 0)
+ ifq->ifq_len++;
+ else
+ ifq->ifq_drops++;
+ mtx_leave(&ifq->ifq_mtx);
+
+ return (rv);
+}
+
+int
+ifq_enq(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_deq_begin(struct ifqueue *ifq)
+{
+ struct mbuf *m = NULL;
+ void *cookie;
+
+ mtx_enter(&ifq->ifq_mtx);
+ if (ifq->ifq_len == 0 ||
+ (m = ifq->ifq_ops->ifqop_deq_begin(ifq, &cookie)) == NULL) {
+ mtx_leave(&ifq->ifq_mtx);
+ return (NULL);
+ }
+
+ m->m_pkthdr.ph_cookie = cookie;
+
+ return (m);
+}
+
+void
+ifq_deq_commit(struct ifqueue *ifq, struct mbuf *m)
+{
+ void *cookie;
+
+ KASSERT(m != NULL);
+ cookie = m->m_pkthdr.ph_cookie;
+
+ ifq->ifq_ops->ifqop_deq_commit(ifq, m, cookie);
+ ifq->ifq_len--;
+ mtx_leave(&ifq->ifq_mtx);
+}
+
+void
+ifq_deq_rollback(struct ifqueue *ifq, struct mbuf *m)
+{
+ void *cookie;
+
+ KASSERT(m != NULL);
+ cookie = m->m_pkthdr.ph_cookie;
+
+ ifq->ifq_ops->ifqop_deq_rollback(ifq, m, cookie);
+ mtx_leave(&ifq->ifq_mtx);
+}
+
+struct mbuf *
+ifq_deq(struct ifqueue *ifq)
+{
+ struct mbuf *m;
+
+ m = ifq_deq_begin(ifq);
+ if (m == NULL)
+ return (NULL);
+
+ ifq_deq_commit(ifq, m);
+
+ return (m);
+}
+
+unsigned int
+ifq_purge(struct ifqueue *ifq)
+{
+ struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+ unsigned int rv;
+
+ mtx_enter(&ifq->ifq_mtx);
+ ifq->ifq_ops->ifqop_purge(ifq, &ml);
+ rv = ifq->ifq_len;
+ ifq->ifq_len = 0;
+ ifq->ifq_drops += rv;
+ mtx_leave(&ifq->ifq_mtx);
+
+ KASSERT(rv == ml_len(&ml));
+
+ ml_purge(&ml);
+
+ 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 = priq_ops.ifqop_alloc(NULL);
+
+ ifq->ifq_serializer = 0;
+ ifq->ifq_len = 0;
+
+ if (ifq->ifq_maxlen == 0)
+ ifq_set_maxlen(ifq, IFQ_MAXLEN);
+}
+
+void
+ifq_attach(struct ifqueue *ifq, const struct ifq_ops *newops, void *opsarg)
+{
+ struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+ struct mbuf_list free_ml = MBUF_LIST_INITIALIZER();
+ struct mbuf *m;
+ const struct ifq_ops *oldops;
+ void *newq, *oldq;
+
+ newq = newops->ifqop_alloc(opsarg);
+
+ mtx_enter(&ifq->ifq_mtx);
+ ifq->ifq_ops->ifqop_purge(ifq, &ml);
+ ifq->ifq_len = 0;
+
+ oldops = ifq->ifq_ops;
+ oldq = ifq->ifq_q;
+
+ ifq->ifq_ops = newops;
+ ifq->ifq_q = newq;
+
+ while ((m = ml_dequeue(&ml)) != NULL) {
+ if (ifq->ifq_ops->ifqop_enq(ifq, m) != 0) {
+ ifq->ifq_drops++;
+ ml_enqueue(&free_ml, m);
+ } else
+ ifq->ifq_len++;
+ }
+ mtx_leave(&ifq->ifq_mtx);
+
+ oldops->ifqop_free(oldq);
+
+ ml_purge(&free_ml);
+}
+
+void *
+ifq_q_enter(struct ifqueue *ifq, const struct ifq_ops *ops)
+{
+ mtx_enter(&ifq->ifq_mtx);
+ if (ifq->ifq_ops == ops)
+ return (ifq->ifq_q);
+
+ mtx_leave(&ifq->ifq_mtx);
+
+ return (NULL);
+}
+
+void
+ifq_q_leave(struct ifqueue *ifq, void *q)
+{
+ KASSERT(q == ifq->ifq_q);
+ mtx_leave(&ifq->ifq_mtx);
+}
+
+void
+ifq_destroy(struct ifqueue *ifq)
+{
+ struct mbuf_list ml = MBUF_LIST_INITIALIZER();
+
+ /* don't need to lock because this is the last use of the ifq */
+
+ ifq->ifq_ops->ifqop_purge(ifq, &ml);
+ ifq->ifq_ops->ifqop_free(ifq->ifq_q);
+
+ ml_purge(&ml);
+}
+
__dead void
unhandled_af(int af)
{
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index 6f0dff68a9d..948a0f0f296 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tun.c,v 1.159 2015/10/25 12:05:40 mpi Exp $ */
+/* $OpenBSD: if_tun.c,v 1.160 2015/11/20 03:35:23 dlg Exp $ */
/* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */
/*
@@ -685,10 +685,11 @@ tun_dev_ioctl(struct tun_softc *tp, u_long cmd, caddr_t data, int flag,
tp->tun_flags &= ~TUN_ASYNC;
break;
case FIONREAD:
- IFQ_POLL(&tp->tun_if.if_snd, m);
- if (m != NULL)
+ m = ifq_deq_begin(&tp->tun_if.if_snd);
+ if (m != NULL) {
*(int *)data = m->m_pkthdr.len;
- else
+ ifq_deq_rollback(&tp->tun_if.if_snd, m);
+ } else
*(int *)data = 0;
break;
case TIOCSPGRP:
@@ -810,6 +811,14 @@ tun_dev_read(struct tun_softc *tp, struct uio *uio, int ioflag)
} while (m0 == NULL);
splx(s);
+ if (tp->tun_flags & TUN_LAYER2) {
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif
+ ifp->if_opackets++;
+ }
+
while (m0 != NULL && uio->uio_resid > 0 && error == 0) {
len = min(uio->uio_resid, m0->m_len);
if (len != 0)
@@ -1007,7 +1016,7 @@ tun_dev_poll(struct tun_softc *tp, int events, struct proc *p)
{
int revents, s;
struct ifnet *ifp;
- struct mbuf *m;
+ unsigned int len;
ifp = &tp->tun_if;
revents = 0;
@@ -1015,10 +1024,9 @@ tun_dev_poll(struct tun_softc *tp, int events, struct proc *p)
TUNDEBUG(("%s: tunpoll\n", ifp->if_xname));
if (events & (POLLIN | POLLRDNORM)) {
- IFQ_POLL(&ifp->if_snd, m);
- if (m != NULL) {
- TUNDEBUG(("%s: tunselect q=%d\n", ifp->if_xname,
- IFQ_LEN(ifp->if_snd)));
+ len = IFQ_LEN(&ifp->if_snd);
+ if (len > 0) {
+ TUNDEBUG(("%s: tunselect q=%d\n", ifp->if_xname, len));
revents |= events & (POLLIN | POLLRDNORM);
} else {
TUNDEBUG(("%s: tunpoll waiting\n", ifp->if_xname));
@@ -1114,7 +1122,7 @@ filt_tunread(struct knote *kn, long hint)
int s;
struct tun_softc *tp;
struct ifnet *ifp;
- struct mbuf *m;
+ unsigned int len;
if (kn->kn_status & KN_DETACHED) {
kn->kn_data = 0;
@@ -1125,10 +1133,10 @@ filt_tunread(struct knote *kn, long hint)
ifp = &tp->tun_if;
s = splnet();
- IFQ_POLL(&ifp->if_snd, m);
- if (m != NULL) {
+ len = IFQ_LEN(&ifp->if_snd);
+ if (len > 0) {
splx(s);
- kn->kn_data = IFQ_LEN(&ifp->if_snd);
+ kn->kn_data = len;
TUNDEBUG(("%s: tunkqread q=%d\n", ifp->if_xname,
IFQ_LEN(&ifp->if_snd)));
@@ -1175,21 +1183,11 @@ void
tun_start(struct ifnet *ifp)
{
struct tun_softc *tp = ifp->if_softc;
- struct mbuf *m;
splassert(IPL_NET);
- IFQ_POLL(&ifp->if_snd, m);
- if (m != NULL) {
- if (tp->tun_flags & TUN_LAYER2) {
-#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
-#endif
- ifp->if_opackets++;
- }
+ if (IFQ_LEN(&ifp->if_snd))
tun_wakeup(tp);
- }
}
void
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index abc6af69dbc..470e5543f99 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_var.h,v 1.53 2015/11/18 13:58:02 mpi Exp $ */
+/* $OpenBSD: if_var.h,v 1.54 2015/11/20 03:35:23 dlg Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -98,17 +98,33 @@ struct if_clone {
{ { 0 }, name, sizeof(name) - 1, create, destroy }
/*
- * Structure defining a queue for a network interface.
+ * Structure defining the send 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 ifqueue;
+
+struct ifq_ops {
+ void *(*ifqop_alloc)(void *);
+ void (*ifqop_free)(void *);
+ int (*ifqop_enq)(struct ifqueue *, struct mbuf *);
+ struct mbuf *(*ifqop_deq_begin)(struct ifqueue *, void **);
+ void (*ifqop_deq_commit)(struct ifqueue *,
+ struct mbuf *, void *);
+ void (*ifqop_deq_rollback)(struct ifqueue *,
+ struct mbuf *, void *);
+ void (*ifqop_purge)(struct ifqueue *,
+ struct mbuf_list *);
+};
+
+struct ifqueue {
+ struct mutex ifq_mtx;
+ uint64_t ifq_drops;
+ const struct ifq_ops *ifq_ops;
+ void *ifq_q;
+ unsigned int ifq_len;
+ unsigned int ifq_serializer;
+
+ unsigned int ifq_maxlen;
};
/*
@@ -256,121 +272,55 @@ struct ifg_list {
};
#ifdef _KERNEL
-#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().
+ * Interface send queues.
*/
-#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)
+void ifq_init(struct ifqueue *);
+void ifq_attach(struct ifqueue *, const struct ifq_ops *, void *);
+void ifq_destroy(struct ifqueue *);
+int ifq_enq_try(struct ifqueue *, struct mbuf *);
+int ifq_enq(struct ifqueue *, struct mbuf *);
+struct mbuf *ifq_deq_begin(struct ifqueue *);
+void ifq_deq_commit(struct ifqueue *, struct mbuf *);
+void ifq_deq_rollback(struct ifqueue *, struct mbuf *);
+struct mbuf *ifq_deq(struct ifqueue *);
+unsigned int ifq_purge(struct ifqueue *);
+void *ifq_q_enter(struct ifqueue *, const struct ifq_ops *);
+void ifq_q_leave(struct ifqueue *, void *);
+
+#define ifq_len(_ifq) ((_ifq)->ifq_len)
+#define ifq_empty(_ifq) (ifq_len(_ifq) == 0)
+#define ifq_set_maxlen(_ifq, _l) ((_ifq)->ifq_maxlen = (_l))
+
+extern const struct ifq_ops * const ifq_priq_ops;
-#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 IFQ_MAXLEN 256
+#define IFNET_SLOWHZ 1 /* granularity is 1 second */
-#define IF_PURGE(ifq) \
-do { \
- struct mbuf *__m0; \
- \
- for (;;) { \
- IF_DEQUEUE((ifq), __m0); \
- if (__m0 == NULL) \
- break; \
- else \
- m_freem(__m0); \
- } \
-} while (/* CONSTCOND */0)
-#define IF_LEN(ifq) ((ifq)->ifq_len)
-#define IF_IS_EMPTY(ifq) ((ifq)->ifq_len == 0)
+/*
+ * IFQ compat on ifq API
+ */
#define IFQ_ENQUEUE(ifq, m, err) \
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++; \
- } \
+ (err) = ifq_enq((ifq), (m)); \
} while (/* CONSTCOND */0)
#define IFQ_DEQUEUE(ifq, m) \
do { \
- if (HFSC_ENABLED((ifq))) \
- (m) = hfsc_dequeue(((struct ifqueue *)(ifq)), 1); \
- else \
- IF_DEQUEUE((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_deq(ifq); \
} while (/* CONSTCOND */0)
#define IFQ_PURGE(ifq) \
do { \
- if (HFSC_ENABLED((ifq))) \
- hfsc_purge(((struct ifqueue *)(ifq))); \
- else \
- IF_PURGE((ifq)); \
+ (void)ifq_purge(ifq); \
} while (/* CONSTCOND */0)
-#define IFQ_SET_READY(ifq) /* nothing */
-
-#define IFQ_LEN(ifq) IF_LEN(ifq)
-#define IFQ_IS_EMPTY(ifq) ((ifq)->ifq_len == 0)
-#define IFQ_SET_MAXLEN(ifq, len) ((ifq)->ifq_maxlen = (len))
+#define IFQ_LEN(ifq) ifq_len(ifq)
+#define IFQ_IS_EMPTY(ifq) ifq_empty(ifq)
+#define IFQ_SET_MAXLEN(ifq, len) ifq_set_maxlen(ifq, len)
+#define IFQ_SET_READY(ifq) do { } while (0)
/* default interface priorities */
#define IF_WIRED_DEFAULT_PRIORITY 0
@@ -405,6 +355,7 @@ extern struct ifnet_head ifnet;
extern unsigned int lo0ifidx;
void if_start(struct ifnet *);
+int if_enqueue_try(struct ifnet *, struct mbuf *);
int if_enqueue(struct ifnet *, struct mbuf *);
void if_input(struct ifnet *, struct mbuf_list *);
int if_input_local(struct ifnet *, struct mbuf *, sa_family_t);
diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c
index 25bf59347d6..fdef0783f43 100644
--- a/sys/net/pf_if.c
+++ b/sys/net/pf_if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_if.c,v 1.81 2015/10/30 11:33:55 mikeb Exp $ */
+/* $OpenBSD: pf_if.c,v 1.82 2015/11/20 03:35:23 dlg Exp $ */
/*
* Copyright 2005 Henning Brauer <henning@openbsd.org>
@@ -258,11 +258,6 @@ pfi_detach_ifnet(struct ifnet *ifp)
hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie);
pfi_kif_update(kif);
- if (HFSC_ENABLED(&ifp->if_snd)) {
- pf_remove_queues(ifp);
- pf_free_queues(pf_queues_active, ifp);
- }
-
kif->pfik_ifp = NULL;
ifp->if_pf_kif = NULL;
pfi_kif_unref(kif, PFI_KIF_REF_NONE);
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index 0709b8fb9ed..7d8d74f2435 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pf_ioctl.c,v 1.291 2015/10/13 19:32:31 sashan Exp $ */
+/* $OpenBSD: pf_ioctl.c,v 1.292 2015/11/20 03:35:23 dlg Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -85,8 +85,10 @@ int pfclose(dev_t, int, int, struct proc *);
int pfioctl(dev_t, u_long, caddr_t, int, struct proc *);
int pf_begin_rules(u_int32_t *, const char *);
int pf_rollback_rules(u_int32_t, char *);
-int pf_create_queues(void);
+int pf_enable_queues(void);
+void pf_remove_queues(void);
int pf_commit_queues(void);
+void pf_free_queues(struct pf_queuehead *);
int pf_setup_pfsync_matching(struct pf_ruleset *);
void pf_hash_rule(MD5_CTX *, struct pf_rule *);
void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
@@ -517,68 +519,144 @@ pf_rollback_rules(u_int32_t ticket, char *anchor)
/* queue defs only in the main ruleset */
if (anchor[0])
return (0);
- return (pf_free_queues(pf_queues_inactive, NULL));
+
+ pf_free_queues(pf_queues_inactive);
+
+ return (0);
}
-int
-pf_free_queues(struct pf_queuehead *where, struct ifnet *ifp)
+void
+pf_free_queues(struct pf_queuehead *where)
{
struct pf_queuespec *q, *qtmp;
TAILQ_FOREACH_SAFE(q, where, entries, qtmp) {
- if (ifp && q->kif->pfik_ifp != ifp)
- continue;
TAILQ_REMOVE(where, q, entries);
pfi_kif_unref(q->kif, PFI_KIF_REF_RULE);
pool_put(&pf_queue_pl, q);
}
- return (0);
}
-int
-pf_remove_queues(struct ifnet *ifp)
+void
+pf_remove_queues(void)
{
struct pf_queuespec *q;
- int error = 0;
-
- /* remove queues */
- TAILQ_FOREACH_REVERSE(q, pf_queues_active, pf_queuehead, entries) {
- if (ifp && q->kif->pfik_ifp != ifp)
- continue;
- if ((error = hfsc_delqueue(q)) != 0)
- return (error);
- }
+ struct ifnet *ifp;
/* put back interfaces in normal queueing mode */
TAILQ_FOREACH(q, pf_queues_active, entries) {
- if (ifp && q->kif->pfik_ifp != ifp)
+ if (q->parent_qid != 0)
+ continue;
+
+ ifp = q->kif->pfik_ifp;
+ if (ifp == NULL)
continue;
- if (q->parent_qid == 0)
- if ((error = hfsc_detach(q->kif->pfik_ifp)) != 0)
- return (error);
+
+ KASSERT(HFSC_ENABLED(&ifp->if_snd));
+
+ ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL);
}
+}
- return (0);
+struct pf_hfsc_queue {
+ struct ifnet *ifp;
+ struct hfsc_if *hif;
+ struct pf_hfsc_queue *next;
+};
+
+static inline struct pf_hfsc_queue *
+pf_hfsc_ifp2q(struct pf_hfsc_queue *list, struct ifnet *ifp)
+{
+ struct pf_hfsc_queue *phq = list;
+
+ while (phq != NULL) {
+ if (phq->ifp == ifp)
+ return (phq);
+
+ phq = phq->next;
+ }
+
+ return (phq);
}
int
pf_create_queues(void)
{
struct pf_queuespec *q;
- int error = 0;
+ struct ifnet *ifp;
+ struct pf_hfsc_queue *list = NULL, *phq;
+ int error;
+
+ /* find root queues and alloc hfsc for these interfaces */
+ TAILQ_FOREACH(q, pf_queues_active, entries) {
+ if (q->parent_qid != 0)
+ continue;
+
+ ifp = q->kif->pfik_ifp;
+ if (ifp == NULL)
+ continue;
+
+ phq = malloc(sizeof(*phq), M_TEMP, M_WAITOK);
+ phq->ifp = ifp;
+ phq->hif = hfsc_pf_alloc(ifp);
- /* find root queues and attach hfsc to these interfaces */
- TAILQ_FOREACH(q, pf_queues_active, entries)
- if (q->parent_qid == 0)
- if ((error = hfsc_attach(q->kif->pfik_ifp)) != 0)
- return (error);
+ phq->next = list;
+ list = phq;
+ }
/* and now everything */
- TAILQ_FOREACH(q, pf_queues_active, entries)
- if ((error = hfsc_addqueue(q)) != 0)
- return (error);
+ TAILQ_FOREACH(q, pf_queues_active, entries) {
+ ifp = q->kif->pfik_ifp;
+ if (ifp == NULL)
+ continue;
+
+ phq = pf_hfsc_ifp2q(list, ifp);
+ KASSERT(phq != NULL);
+
+ error = hfsc_pf_addqueue(phq->hif, q);
+ if (error != 0)
+ goto error;
+ }
+
+ /* find root queues in old list to disable them if necessary */
+ TAILQ_FOREACH(q, pf_queues_inactive, entries) {
+ if (q->parent_qid != 0)
+ continue;
+
+ ifp = q->kif->pfik_ifp;
+ if (ifp == NULL)
+ continue;
+
+ phq = pf_hfsc_ifp2q(list, ifp);
+ if (phq != NULL)
+ continue;
+
+ ifq_attach(&ifp->if_snd, ifq_priq_ops, NULL);
+ }
+
+ /* commit the new queues */
+ while (list != NULL) {
+ phq = list;
+ list = phq->next;
+
+ ifp = phq->ifp;
+
+ ifq_attach(&ifp->if_snd, ifq_hfsc_ops, phq->hif);
+ free(phq, M_TEMP, sizeof(*phq));
+ }
return (0);
+
+error:
+ while (list != NULL) {
+ phq = list;
+ list = phq->next;
+
+ hfsc_pf_free(phq->hif);
+ free(phq, M_TEMP, sizeof(*phq));
+ }
+
+ return (error);
}
int
@@ -587,16 +665,21 @@ pf_commit_queues(void)
struct pf_queuehead *qswap;
int error;
- if ((error = pf_remove_queues(NULL)) != 0)
+ /* swap */
+ qswap = pf_queues_active;
+ pf_queues_active = pf_queues_inactive;
+ pf_queues_inactive = qswap;
+
+ error = pf_create_queues();
+ if (error != 0) {
+ pf_queues_inactive = pf_queues_active;
+ pf_queues_active = qswap;
return (error);
+ }
- /* swap */
- qswap = pf_queues_active;
- pf_queues_active = pf_queues_inactive;
- pf_queues_inactive = qswap;
- pf_free_queues(pf_queues_inactive, NULL);
+ pf_free_queues(pf_queues_inactive);
- return (pf_create_queues());
+ return (0);
}
#define PF_MD5_UPD(st, elm) \
@@ -935,7 +1018,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
else {
pf_status.running = 0;
pf_status.since = time_second;
- pf_remove_queues(NULL);
+ pf_remove_queues();
DPFPRINTF(LOG_NOTICE, "pf: stopped");
}
break;
@@ -1001,7 +1084,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(qs, &pq->queue, sizeof(pq->queue));
- error = hfsc_qstats(qs, pq->buf, &nbytes);
+ error = hfsc_pf_qstats(qs, pq->buf, &nbytes);
if (error == 0)
pq->nbytes = nbytes;
break;
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index aad10865ed3..5c5a30e3879 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pfvar.h,v 1.422 2015/10/30 11:33:55 mikeb Exp $ */
+/* $OpenBSD: pfvar.h,v 1.423 2015/11/20 03:35:23 dlg Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@@ -1657,9 +1657,6 @@ extern struct pf_queuehead pf_queues[2];
extern struct pf_queuehead *pf_queues_active, *pf_queues_inactive;
extern u_int32_t ticket_pabuf;
-extern int pf_free_queues(struct pf_queuehead *,
- struct ifnet *);
-extern int pf_remove_queues(struct ifnet *);
extern int pf_tbladdr_setup(struct pf_ruleset *,
struct pf_addr_wrap *);
extern void pf_tbladdr_remove(struct pf_addr_wrap *);