From owner-svn-src-stable@freebsd.org Thu Apr 27 02:17:46 2017 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id AB480D52723; Thu, 27 Apr 2017 02:17:46 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 8846D106E; Thu, 27 Apr 2017 02:17:46 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v3R2HjZr000792; Thu, 27 Apr 2017 02:17:45 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v3R2HjVB000791; Thu, 27 Apr 2017 02:17:45 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201704270217.v3R2HjVB000791@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Thu, 27 Apr 2017 02:17:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r317482 - stable/10/sys/dev/hyperv/netvsc X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Apr 2017 02:17:46 -0000 Author: sephe Date: Thu Apr 27 02:17:45 2017 New Revision: 317482 URL: https://svnweb.freebsd.org/changeset/base/317482 Log: MFC 317353 hyperv/hn: Use channel0, i.e. TX ring0, for TCP SYN/SYN|ACK. Hyper-V hot channel effect: Operation latency on hot channel is only _half_ of the operation latency on cold channels. This commit takes the advantage of the above Hyper-V host channel effect, and can reduce more than 75% latency and more than 50% latency stdev, i.e. lower and more stable/predictable latency, for various types of web server workloads. Sponsored by: Microsoft Modified: stable/10/sys/dev/hyperv/netvsc/if_hn.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/hyperv/netvsc/if_hn.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/if_hn.c Thu Apr 27 01:58:20 2017 (r317481) +++ stable/10/sys/dev/hyperv/netvsc/if_hn.c Thu Apr 27 02:17:45 2017 (r317482) @@ -611,6 +611,16 @@ hn_chim_free(struct hn_softc *sc, uint32 } #if defined(INET6) || defined(INET) + +#define PULLUP_HDR(m, len) \ +do { \ + if (__predict_false((m)->m_len < (len))) { \ + (m) = m_pullup((m), (len)); \ + if ((m) == NULL) \ + return (NULL); \ + } \ +} while (0) + /* * NOTE: If this function failed, the m_head would be freed. */ @@ -623,15 +633,6 @@ hn_tso_fixup(struct mbuf *m_head) KASSERT(M_WRITABLE(m_head), ("TSO mbuf not writable")); -#define PULLUP_HDR(m, len) \ -do { \ - if (__predict_false((m)->m_len < (len))) { \ - (m) = m_pullup((m), (len)); \ - if ((m) == NULL) \ - return (NULL); \ - } \ -} while (0) - PULLUP_HDR(m_head, sizeof(*evl)); evl = mtod(m_head, struct ether_vlan_header *); if (evl->evl_encap_proto == ntohs(ETHERTYPE_VLAN)) @@ -680,8 +681,65 @@ do { \ #endif return (m_head); -#undef PULLUP_HDR } + +/* + * 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 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; + +#ifdef INET + if (m_head->m_pkthdr.csum_flags & CSUM_IP_TCP) { + 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; + } +#endif +#if defined(INET6) && defined(INET) + else +#endif +#ifdef INET6 + { + const struct ip6_hdr *ip6; + + 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; + } +#endif + return (m_head); +} + +#undef PULLUP_HDR + #endif /* INET6 || INET */ static int @@ -4343,8 +4401,28 @@ hn_transmit(struct ifnet *ifp, struct mb /* * Select the TX ring based on flowid */ - if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) - idx = m->m_pkthdr.flowid % sc->hn_tx_ring_inuse; + if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) { +#if defined(INET6) || defined(INET) + int tcpsyn = 0; + + if (m->m_pkthdr.len < 128 && + (m->m_pkthdr.csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP)) && + (m->m_pkthdr.csum_flags & CSUM_TSO) == 0) { + m = hn_check_tcpsyn(m, &tcpsyn); + if (__predict_false(m == NULL)) { + if_inc_counter(ifp, + IFCOUNTER_OERRORS, 1); + return (EIO); + } + } +#else + const int tcpsyn = 0; +#endif + if (tcpsyn) + idx = 0; + else + idx = m->m_pkthdr.flowid % sc->hn_tx_ring_inuse; + } txr = &sc->hn_tx_ring[idx]; error = drbr_enqueue(ifp, txr->hn_mbuf_br, m);