svn commit: r317353 - head/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Mon Apr 24 07:52:29 UTC 2017
Author: sephe
Date: Mon Apr 24 07:52:27 2017
New Revision: 317353
URL: https://svnweb.freebsd.org/changeset/base/317353
Log:
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.
MFC after: 3 days
Sponsored by: Microsoft
Modified:
head/sys/dev/hyperv/netvsc/if_hn.c
Modified: head/sys/dev/hyperv/netvsc/if_hn.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/if_hn.c Mon Apr 24 06:33:08 2017 (r317352)
+++ head/sys/dev/hyperv/netvsc/if_hn.c Mon Apr 24 07:52:27 2017 (r317353)
@@ -622,6 +622,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.
*/
@@ -634,15 +644,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))
@@ -691,8 +692,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
@@ -4369,7 +4427,29 @@ hn_transmit(struct ifnet *ifp, struct mb
idx = bid % sc->hn_tx_ring_inuse;
else
#endif
- idx = m->m_pkthdr.flowid % sc->hn_tx_ring_inuse;
+ {
+#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];
More information about the svn-src-all
mailing list