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
This commit is contained in:
parent
a79d52d739
commit
c49d47daf3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=324048
@ -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, struct hn_txdesc *txd,
|
||||
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, struct hn_txdesc *txd,
|
||||
#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, struct hn_txdesc *txd,
|
||||
*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,8 +5873,8 @@ 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);
|
||||
@ -5855,6 +5882,13 @@ hn_transmit(struct ifnet *ifp, struct mbuf *m)
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user