Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Sep 2017 04:42:41 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r324048 - head/sys/dev/hyperv/netvsc
Message-ID:  <201709270442.v8R4gfi3042194@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Wed Sep 27 04:42:40 2017
New Revision: 324048
URL: https://svnweb.freebsd.org/changeset/base/324048

Log:
  hyperv/hn: Set tcp header offset for CSUM/LSO offloading.
  
  No observable effect; better safe than sorry.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D12417

Modified:
  head/sys/dev/hyperv/netvsc/if_hn.c
  head/sys/dev/hyperv/netvsc/ndis.h

Modified: head/sys/dev/hyperv/netvsc/if_hn.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hn.c	Wed Sep 27 01:47:54 2017	(r324047)
+++ head/sys/dev/hyperv/netvsc/if_hn.c	Wed Sep 27 04:42:40 2017	(r324048)
@@ -727,6 +727,7 @@ hn_tso_fixup(struct mbuf *m_head)
 		ehlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
 	else
 		ehlen = ETHER_HDR_LEN;
+	m_head->m_pkthdr.l2hlen = ehlen;
 
 #ifdef INET
 	if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) {
@@ -736,6 +737,7 @@ hn_tso_fixup(struct mbuf *m_head)
 		PULLUP_HDR(m_head, ehlen + sizeof(*ip));
 		ip = mtodo(m_head, ehlen);
 		iphlen = ip->ip_hl << 2;
+		m_head->m_pkthdr.l3hlen = iphlen;
 
 		PULLUP_HDR(m_head, ehlen + iphlen + sizeof(*th));
 		th = mtodo(m_head, ehlen + iphlen);
@@ -759,6 +761,7 @@ hn_tso_fixup(struct mbuf *m_head)
 			m_freem(m_head);
 			return (NULL);
 		}
+		m_head->m_pkthdr.l3hlen = sizeof(*ip6);
 
 		PULLUP_HDR(m_head, ehlen + sizeof(*ip6) + sizeof(*th));
 		th = mtodo(m_head, ehlen + sizeof(*ip6));
@@ -768,41 +771,34 @@ hn_tso_fixup(struct mbuf *m_head)
 	}
 #endif
 	return (m_head);
-
 }
 
 /*
  * NOTE: If this function failed, the m_head would be freed.
  */
 static __inline struct mbuf *
-hn_check_tcpsyn(struct mbuf *m_head, int *tcpsyn)
+hn_set_hlen(struct mbuf *m_head)
 {
 	const struct ether_vlan_header *evl;
-	const struct tcphdr *th;
 	int ehlen;
 
-	*tcpsyn = 0;
-
 	PULLUP_HDR(m_head, sizeof(*evl));
 	evl = mtod(m_head, const struct ether_vlan_header *);
 	if (evl->evl_encap_proto == ntohs(ETHERTYPE_VLAN))
 		ehlen = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN;
 	else
 		ehlen = ETHER_HDR_LEN;
+	m_head->m_pkthdr.l2hlen = ehlen;
 
 #ifdef INET
-	if (m_head->m_pkthdr.csum_flags & CSUM_IP_TCP) {
+	if (m_head->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP_UDP)) {
 		const struct ip *ip;
 		int iphlen;
 
 		PULLUP_HDR(m_head, ehlen + sizeof(*ip));
 		ip = mtodo(m_head, ehlen);
 		iphlen = ip->ip_hl << 2;
-
-		PULLUP_HDR(m_head, ehlen + iphlen + sizeof(*th));
-		th = mtodo(m_head, ehlen + iphlen);
-		if (th->th_flags & TH_SYN)
-			*tcpsyn = 1;
+		m_head->m_pkthdr.l3hlen = iphlen;
 	}
 #endif
 #if defined(INET6) && defined(INET)
@@ -814,18 +810,36 @@ hn_check_tcpsyn(struct mbuf *m_head, int *tcpsyn)
 
 		PULLUP_HDR(m_head, ehlen + sizeof(*ip6));
 		ip6 = mtodo(m_head, ehlen);
-		if (ip6->ip6_nxt != IPPROTO_TCP)
-			return (m_head);
-
-		PULLUP_HDR(m_head, ehlen + sizeof(*ip6) + sizeof(*th));
-		th = mtodo(m_head, ehlen + sizeof(*ip6));
-		if (th->th_flags & TH_SYN)
-			*tcpsyn = 1;
+		if (ip6->ip6_nxt != IPPROTO_TCP) {
+			m_freem(m_head);
+			return (NULL);
+		}
+		m_head->m_pkthdr.l3hlen = sizeof(*ip6);
 	}
 #endif
 	return (m_head);
 }
 
+/*
+ * NOTE: If this function failed, the m_head would be freed.
+ */
+static __inline struct mbuf *
+hn_check_tcpsyn(struct mbuf *m_head, int *tcpsyn)
+{
+	const struct tcphdr *th;
+	int ehlen, iphlen;
+
+	*tcpsyn = 0;
+	ehlen = m_head->m_pkthdr.l2hlen;
+	iphlen = m_head->m_pkthdr.l3hlen;
+
+	PULLUP_HDR(m_head, ehlen + iphlen + sizeof(*th));
+	th = mtodo(m_head, ehlen + iphlen);
+	if (th->th_flags & TH_SYN)
+		*tcpsyn = 1;
+	return (m_head);
+}
+
 #undef PULLUP_HDR
 
 #endif	/* INET6 || INET */
@@ -3010,7 +3024,8 @@ hn_encap(struct ifnet *ifp, struct hn_tx_ring *txr, st
 		    NDIS_LSO2_INFO_SIZE, NDIS_PKTINFO_TYPE_LSO);
 #ifdef INET
 		if (m_head->m_pkthdr.csum_flags & CSUM_IP_TSO) {
-			*pi_data = NDIS_LSO2_INFO_MAKEIPV4(0,
+			*pi_data = NDIS_LSO2_INFO_MAKEIPV4(
+			    m_head->m_pkthdr.l2hlen + m_head->m_pkthdr.l3hlen,
 			    m_head->m_pkthdr.tso_segsz);
 		}
 #endif
@@ -3019,7 +3034,8 @@ hn_encap(struct ifnet *ifp, struct hn_tx_ring *txr, st
 #endif
 #ifdef INET6
 		{
-			*pi_data = NDIS_LSO2_INFO_MAKEIPV6(0,
+			*pi_data = NDIS_LSO2_INFO_MAKEIPV6(
+			    m_head->m_pkthdr.l2hlen + m_head->m_pkthdr.l3hlen,
 			    m_head->m_pkthdr.tso_segsz);
 		}
 #endif
@@ -3036,11 +3052,15 @@ hn_encap(struct ifnet *ifp, struct hn_tx_ring *txr, st
 				*pi_data |= NDIS_TXCSUM_INFO_IPCS;
 		}
 
-		if (m_head->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP))
-			*pi_data |= NDIS_TXCSUM_INFO_TCPCS;
-		else if (m_head->m_pkthdr.csum_flags &
-		    (CSUM_IP_UDP | CSUM_IP6_UDP))
-			*pi_data |= NDIS_TXCSUM_INFO_UDPCS;
+		if (m_head->m_pkthdr.csum_flags &
+		    (CSUM_IP_TCP | CSUM_IP6_TCP)) {
+			*pi_data |= NDIS_TXCSUM_INFO_MKTCPCS(
+			    m_head->m_pkthdr.l2hlen + m_head->m_pkthdr.l3hlen);
+		} else if (m_head->m_pkthdr.csum_flags &
+		    (CSUM_IP_UDP | CSUM_IP6_UDP)) {
+			*pi_data |= NDIS_TXCSUM_INFO_MKUDPCS(
+			    m_head->m_pkthdr.l2hlen + m_head->m_pkthdr.l3hlen);
+		}
 	}
 
 	pkt_hlen = pkt->rm_pktinfooffset + pkt->rm_pktinfolen;
@@ -5566,6 +5586,13 @@ hn_start_locked(struct hn_tx_ring *txr, int len)
 				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 				continue;
 			}
+		} else if (m_head->m_pkthdr.csum_flags &
+		    (CSUM_IP_UDP | CSUM_IP_TCP | CSUM_IP6_UDP | CSUM_IP6_TCP)) {
+			m_head = hn_set_hlen(m_head);
+			if (__predict_false(m_head == NULL)) {
+				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+				continue;
+			}
 		}
 #endif
 
@@ -5846,11 +5873,18 @@ hn_transmit(struct ifnet *ifp, struct mbuf *m)
 
 #if defined(INET6) || defined(INET)
 	/*
-	 * Perform TSO packet header fixup now, since the TSO
-	 * packet header should be cache-hot.
+	 * Perform TSO packet header fixup or get l2/l3 header length now,
+	 * since packet headers should be cache-hot.
 	 */
 	if (m->m_pkthdr.csum_flags & CSUM_TSO) {
 		m = hn_tso_fixup(m);
+		if (__predict_false(m == NULL)) {
+			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
+			return EIO;
+		}
+	} else if (m->m_pkthdr.csum_flags &
+	    (CSUM_IP_UDP | CSUM_IP_TCP | CSUM_IP6_UDP | CSUM_IP6_TCP)) {
+		m = hn_set_hlen(m);
 		if (__predict_false(m == NULL)) {
 			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
 			return EIO;

Modified: head/sys/dev/hyperv/netvsc/ndis.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/ndis.h	Wed Sep 27 01:47:54 2017	(r324047)
+++ head/sys/dev/hyperv/netvsc/ndis.h	Wed Sep 27 04:42:40 2017	(r324048)
@@ -402,4 +402,13 @@ struct ndis_offload {
 #define	NDIS_TXCSUM_INFO_IPCS		0x00000010
 #define	NDIS_TXCSUM_INFO_THOFF		0x03ff0000
 
+#define	NDIS_TXCSUM_INFO_MKL4CS(thoff, flag)			\
+	((((uint32_t)(thoff)) << 16) | (flag))
+
+#define	NDIS_TXCSUM_INFO_MKTCPCS(thoff)				\
+	NDIS_TXCSUM_INFO_MKL4CS((thoff), NDIS_TXCSUM_INFO_TCPCS)
+
+#define	NDIS_TXCSUM_INFO_MKUDPCS(thoff)				\
+	NDIS_TXCSUM_INFO_MKL4CS((thoff), NDIS_TXCSUM_INFO_UDPCS)
+
 #endif	/* !_NET_NDIS_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201709270442.v8R4gfi3042194>