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