svn commit: r336727 - in head/sys/net: . altq
Patrick Kelsey
pkelsey at FreeBSD.org
Wed Jul 25 22:46:38 UTC 2018
Author: pkelsey
Date: Wed Jul 25 22:46:36 2018
New Revision: 336727
URL: https://svnweb.freebsd.org/changeset/base/336727
Log:
ALTQ support for iflib.
Reviewed by: jmallett, mmacy
Differential Revision: https://reviews.freebsd.org/D16433
Modified:
head/sys/net/altq/if_altq.h
head/sys/net/iflib.c
Modified: head/sys/net/altq/if_altq.h
==============================================================================
--- head/sys/net/altq/if_altq.h Wed Jul 25 21:52:49 2018 (r336726)
+++ head/sys/net/altq/if_altq.h Wed Jul 25 22:46:36 2018 (r336727)
@@ -143,7 +143,11 @@ struct tb_regulator {
#define ALTRQ_PURGE 1 /* purge all packets */
#define ALTQ_IS_READY(ifq) ((ifq)->altq_flags & ALTQF_READY)
+#ifdef ALTQ
#define ALTQ_IS_ENABLED(ifq) ((ifq)->altq_flags & ALTQF_ENABLED)
+#else
+#define ALTQ_IS_ENABLED(ifq) 0
+#endif
#define ALTQ_NEEDS_CLASSIFY(ifq) ((ifq)->altq_flags & ALTQF_CLASSIFY)
#define ALTQ_IS_CNDTNING(ifq) ((ifq)->altq_flags & ALTQF_CNDTNING)
Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c Wed Jul 25 21:52:49 2018 (r336726)
+++ head/sys/net/iflib.c Wed Jul 25 22:46:36 2018 (r336727)
@@ -739,6 +739,10 @@ static int iflib_msix_init(if_ctx_t ctx);
static int iflib_legacy_setup(if_ctx_t ctx, driver_filter_t filter, void *filterarg, int *rid, const char *str);
static void iflib_txq_check_drain(iflib_txq_t txq, int budget);
static uint32_t iflib_txq_can_drain(struct ifmp_ring *);
+#ifdef ALTQ
+static void iflib_altq_if_start(if_t ifp);
+static int iflib_altq_if_transmit(if_t ifp, struct mbuf *m);
+#endif
static int iflib_register(if_ctx_t);
static void iflib_init_locked(if_ctx_t ctx);
static void iflib_add_device_sysctl_pre(if_ctx_t ctx);
@@ -3775,6 +3779,10 @@ _task_fn_tx(void *context)
IFDI_TX_QUEUE_INTR_ENABLE(ctx, txq->ift_id);
return;
}
+#ifdef ALTQ
+ if (ALTQ_IS_ENABLED(&ifp->if_snd))
+ iflib_altq_if_start(ifp);
+#endif
if (txq->ift_db_pending)
ifmp_ring_enqueue(txq->ift_br, (void **)&txq, 1, TX_BATCH_SIZE, abdicate);
else if (!abdicate)
@@ -3963,8 +3971,9 @@ iflib_if_transmit(if_t ifp, struct mbuf *m)
}
MPASS(m->m_nextpkt == NULL);
+ /* ALTQ-enabled interfaces always use queue 0. */
qidx = 0;
- if ((NTXQSETS(ctx) > 1) && M_HASHTYPE_GET(m))
+ if ((NTXQSETS(ctx) > 1) && M_HASHTYPE_GET(m) && !ALTQ_IS_ENABLED(&ifp->if_snd))
qidx = QIDX(ctx, m);
/*
* XXX calculate buf_ring based on flowid (divvy up bits?)
@@ -4024,7 +4033,60 @@ iflib_if_transmit(if_t ifp, struct mbuf *m)
return (err);
}
+#ifdef ALTQ
+/*
+ * The overall approach to integrating iflib with ALTQ is to continue to use
+ * the iflib mp_ring machinery between the ALTQ queue(s) and the hardware
+ * ring. Technically, when using ALTQ, queueing to an intermediate mp_ring
+ * is redundant/unnecessary, but doing so minimizes the amount of
+ * ALTQ-specific code required in iflib. It is assumed that the overhead of
+ * redundantly queueing to an intermediate mp_ring is swamped by the
+ * performance limitations inherent in using ALTQ.
+ *
+ * When ALTQ support is compiled in, all iflib drivers will use a transmit
+ * routine, iflib_altq_if_transmit(), that checks if ALTQ is enabled for the
+ * given interface. If ALTQ is enabled for an interface, then all
+ * transmitted packets for that interface will be submitted to the ALTQ
+ * subsystem via IFQ_ENQUEUE(). We don't use the legacy if_transmit()
+ * implementation because it uses IFQ_HANDOFF(), which will duplicatively
+ * update stats that the iflib machinery handles, and which is sensitve to
+ * the disused IFF_DRV_OACTIVE flag. Additionally, iflib_altq_if_start()
+ * will be installed as the start routine for use by ALTQ facilities that
+ * need to trigger queue drains on a scheduled basis.
+ *
+ */
static void
+iflib_altq_if_start(if_t ifp)
+{
+ struct ifaltq *ifq = &ifp->if_snd;
+ struct mbuf *m;
+
+ IFQ_LOCK(ifq);
+ IFQ_DEQUEUE_NOLOCK(ifq, m);
+ while (m != NULL) {
+ iflib_if_transmit(ifp, m);
+ IFQ_DEQUEUE_NOLOCK(ifq, m);
+ }
+ IFQ_UNLOCK(ifq);
+}
+
+static int
+iflib_altq_if_transmit(if_t ifp, struct mbuf *m)
+{
+ int err;
+
+ if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
+ IFQ_ENQUEUE(&ifp->if_snd, m, err);
+ if (err == 0)
+ iflib_altq_if_start(ifp);
+ } else
+ err = iflib_if_transmit(ifp, m);
+
+ return (err);
+}
+#endif /* ALTQ */
+
+static void
iflib_if_qflush(if_t ifp)
{
if_ctx_t ctx = if_getsoftc(ifp);
@@ -4041,6 +4103,10 @@ iflib_if_qflush(if_t ifp)
ctx->ifc_flags &= ~IFC_QFLUSH;
STATE_UNLOCK(ctx);
+ /*
+ * When ALTQ is enabled, this will also take care of purging the
+ * ALTQ queue(s).
+ */
if_qflush(ifp);
}
@@ -5165,7 +5231,12 @@ iflib_register(if_ctx_t ctx)
if_setdev(ifp, dev);
if_setinitfn(ifp, iflib_if_init);
if_setioctlfn(ifp, iflib_if_ioctl);
+#ifdef ALTQ
+ if_setstartfn(ifp, iflib_altq_if_start);
+ if_settransmitfn(ifp, iflib_altq_if_transmit);
+#else
if_settransmitfn(ifp, iflib_if_transmit);
+#endif
if_setqflushfn(ifp, iflib_if_qflush);
if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
More information about the svn-src-head
mailing list