svn commit: r325487 - head/sys/net

Stephen Hurd shurd at FreeBSD.org
Mon Nov 6 16:23:22 UTC 2017


Author: shurd
Date: Mon Nov  6 16:23:21 2017
New Revision: 325487
URL: https://svnweb.freebsd.org/changeset/base/325487

Log:
  Only chain non-LRO mbufs when LRO is not possible
  
  Preserve packet order between tcp_lro_rx() and if_input() to avoid
  creating extra corner cases. If no packets can be LROed, combine them
  into one chain for submission via if_input(). If any packet can
  potentially be LROed however, retain old behaviour and call if_input()
  for each packet.
  
  This should keep the 12% improvement for small packet forwarding intact,
  but mostly avoids impacting the LRO case.
  
  Reviewed by:	cem, sbruno
  Approved by:	sbruno (mentor)
  Sponsored by:	Limelight Networks
  Differential Revision:	https://reviews.freebsd.org/D12876

Modified:
  head/sys/net/iflib.c

Modified: head/sys/net/iflib.c
==============================================================================
--- head/sys/net/iflib.c	Mon Nov  6 15:29:33 2017	(r325486)
+++ head/sys/net/iflib.c	Mon Nov  6 16:23:21 2017	(r325487)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 #include <net/bpf.h>
 #include <net/ethernet.h>
 #include <net/mp_ring.h>
+#include <net/vnet.h>
 
 #include <netinet/in.h>
 #include <netinet/in_pcb.h>
@@ -68,6 +69,8 @@ __FBSDID("$FreeBSD$");
 #include <netinet/ip.h>
 #include <netinet/ip6.h>
 #include <netinet/tcp.h>
+#include <netinet/ip_var.h>
+#include <netinet6/ip6_var.h>
 
 #include <machine/bus.h>
 #include <machine/in_cksum.h>
@@ -2463,7 +2466,48 @@ iflib_rxd_pkt_get(iflib_rxq_t rxq, if_rxd_info_t ri)
 	return (m);
 }
 
+#if defined(INET6) || defined(INET)
+/*
+ * Returns true if it's possible this packet could be LROed.
+ * if it returns false, it is guaranteed that tcp_lro_rx()
+ * would not return zero.
+ */
 static bool
+iflib_check_lro_possible(struct lro_ctrl *lc, struct mbuf *m)
+{
+	struct ether_header *eh;
+	uint16_t eh_type;
+
+	eh = mtod(m, struct ether_header *);
+	eh_type = ntohs(eh->ether_type);
+	switch (eh_type) {
+		case ETHERTYPE_IPV6:
+		{
+			CURVNET_SET(lc->ifp->if_vnet);
+			if (VNET(ip6_forwarding) == 0) {
+				CURVNET_RESTORE();
+				return true;
+			}
+			CURVNET_RESTORE();
+			break;
+		}
+		case ETHERTYPE_IP:
+		{
+			CURVNET_SET(lc->ifp->if_vnet);
+			if (VNET(ipforwarding) == 0) {
+				CURVNET_RESTORE();
+				return true;
+			}
+			CURVNET_RESTORE();
+			break;
+		}
+	}
+
+	return false;
+}
+#endif
+
+static bool
 iflib_rxeof(iflib_rxq_t rxq, qidx_t budget)
 {
 	if_ctx_t ctx = rxq->ifr_ctx;
@@ -2476,6 +2520,7 @@ iflib_rxeof(iflib_rxq_t rxq, qidx_t budget)
 	iflib_fl_t fl;
 	struct ifnet *ifp;
 	int lro_enabled;
+	bool lro_possible = false;
 
 	/*
 	 * XXX early demux data packets so that if_input processing only handles
@@ -2555,8 +2600,6 @@ iflib_rxeof(iflib_rxq_t rxq, qidx_t budget)
 	mt = mf = NULL;
 	while (mh != NULL) {
 		m = mh;
-		if (mf == NULL)
-			mf = m;
 		mh = mh->m_nextpkt;
 		m->m_nextpkt = NULL;
 #ifndef __NO_STRICT_ALIGNMENT
@@ -2566,12 +2609,27 @@ iflib_rxeof(iflib_rxq_t rxq, qidx_t budget)
 		rx_bytes += m->m_pkthdr.len;
 		rx_pkts++;
 #if defined(INET6) || defined(INET)
-		if (lro_enabled && tcp_lro_rx(&rxq->ifr_lc, m, 0) == 0) {
-			if (mf == m)
-				mf = NULL;
-			continue;
+		if (lro_enabled) {
+			if (!lro_possible) {
+				lro_possible = iflib_check_lro_possible(&rxq->ifr_lc, m);
+				if (lro_possible && mf != NULL) {
+					ifp->if_input(ifp, mf);
+					DBG_COUNTER_INC(rx_if_input);
+					mt = mf = NULL;
+				}
+			}
+			if (lro_possible && tcp_lro_rx(&rxq->ifr_lc, m, 0) == 0)
+				continue;
 		}
 #endif
+		if (lro_possible) {
+			ifp->if_input(ifp, m);
+			DBG_COUNTER_INC(rx_if_input);
+			continue;
+		}
+
+		if (mf == NULL)
+			mf = m;
 		if (mt != NULL)
 			mt->m_nextpkt = m;
 		mt = m;


More information about the svn-src-all mailing list