svn commit: r324467 - stable/10/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Tue Oct 10 03:35:25 UTC 2017
Author: sephe
Date: Tue Oct 10 03:35:24 2017
New Revision: 324467
URL: https://svnweb.freebsd.org/changeset/base/324467
Log:
MFC 324048
hyperv/hn: Set tcp header offset for CSUM/LSO offloading.
No observable effect; better safe than sorry.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D12417
Modified:
stable/10/sys/dev/hyperv/netvsc/if_hn.c
stable/10/sys/dev/hyperv/netvsc/ndis.h
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 Tue Oct 10 03:29:36 2017 (r324466)
+++ stable/10/sys/dev/hyperv/netvsc/if_hn.c Tue Oct 10 03:35:24 2017 (r324467)
@@ -716,6 +716,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) {
@@ -725,6 +726,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);
@@ -748,6 +750,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));
@@ -757,41 +760,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)
@@ -803,18 +799,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 */
@@ -2999,7 +3013,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
@@ -3008,7 +3023,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
@@ -3025,11 +3041,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;
@@ -5550,6 +5570,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
@@ -5830,11 +5857,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: stable/10/sys/dev/hyperv/netvsc/ndis.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/ndis.h Tue Oct 10 03:29:36 2017 (r324466)
+++ stable/10/sys/dev/hyperv/netvsc/ndis.h Tue Oct 10 03:35:24 2017 (r324467)
@@ -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_ */
More information about the svn-src-all
mailing list