Date: Wed, 11 Oct 2017 05:15:49 +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: r324516 - head/sys/dev/hyperv/netvsc Message-ID: <201710110515.v9B5Fn0o088732@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Wed Oct 11 05:15:49 2017 New Revision: 324516 URL: https://svnweb.freebsd.org/changeset/base/324516 Log: hyperv/hn: Workaround erroneous hash type observed on WS2016 for VF. The background was described in r324489. MFC after: 3 days Sponsored by: Microsoft Modified: head/sys/dev/hyperv/netvsc/hn_rndis.c head/sys/dev/hyperv/netvsc/if_hn.c head/sys/dev/hyperv/netvsc/ndis.h Modified: head/sys/dev/hyperv/netvsc/hn_rndis.c ============================================================================== --- head/sys/dev/hyperv/netvsc/hn_rndis.c Wed Oct 11 05:07:37 2017 (r324515) +++ head/sys/dev/hyperv/netvsc/hn_rndis.c Wed Oct 11 05:15:49 2017 (r324516) @@ -521,6 +521,10 @@ hn_rndis_query_rsscaps(struct hn_softc *sc, int *rxr_c /* Commit! */ sc->hn_rss_ind_size = indsz; sc->hn_rss_hcap = hash_func | hash_types; + if (sc->hn_caps & HN_CAP_UDPHASH) { + /* UDP 4-tuple hash is unconditionally enabled. */ + sc->hn_rss_hcap |= NDIS_HASH_UDP_IPV4_X; + } *rxr_cnt0 = rxr_cnt; return (0); } @@ -760,8 +764,10 @@ hn_rndis_conf_rss(struct hn_softc *sc, uint16_t flags) ("NDIS 6.20+ is required, NDIS version 0x%08x", sc->hn_ndis_ver)); /* XXX only one can be specified through, popcnt? */ - KASSERT((sc->hn_rss_hash & NDIS_HASH_FUNCTION_MASK), ("no hash func")); - KASSERT((sc->hn_rss_hash & NDIS_HASH_TYPE_MASK), ("no hash types")); + KASSERT((sc->hn_rss_hash & NDIS_HASH_FUNCTION_MASK), + ("no hash func %08x", sc->hn_rss_hash)); + KASSERT((sc->hn_rss_hash & NDIS_HASH_STD), + ("no standard hash types %08x", sc->hn_rss_hash)); KASSERT(sc->hn_rss_ind_size > 0, ("no indirect table size")); if (bootverbose) { @@ -780,7 +786,8 @@ hn_rndis_conf_rss(struct hn_softc *sc, uint16_t flags) prm->ndis_hdr.ndis_rev = NDIS_RSS_PARAMS_REV_2; prm->ndis_hdr.ndis_size = rss_size; prm->ndis_flags = flags; - prm->ndis_hash = sc->hn_rss_hash; + prm->ndis_hash = sc->hn_rss_hash & + (NDIS_HASH_FUNCTION_MASK | NDIS_HASH_STD); prm->ndis_indsize = sizeof(rss->rss_ind[0]) * sc->hn_rss_ind_size; prm->ndis_indoffset = __offsetof(struct ndis_rssprm_toeplitz, rss_ind[0]); Modified: head/sys/dev/hyperv/netvsc/if_hn.c ============================================================================== --- head/sys/dev/hyperv/netvsc/if_hn.c Wed Oct 11 05:07:37 2017 (r324515) +++ head/sys/dev/hyperv/netvsc/if_hn.c Wed Oct 11 05:15:49 2017 (r324516) @@ -1424,6 +1424,8 @@ hn_rss_type_fromndis(uint32_t rss_hash) types |= RSS_TYPE_TCP_IPV6; if (rss_hash & NDIS_HASH_TCP_IPV6_EX) types |= RSS_TYPE_TCP_IPV6_EX; + if (rss_hash & NDIS_HASH_UDP_IPV4_X) + types |= RSS_TYPE_UDP_IPV4; return (types); } @@ -1432,9 +1434,8 @@ hn_rss_type_tondis(uint32_t types) { uint32_t rss_hash = 0; - KASSERT((types & - (RSS_TYPE_UDP_IPV4 | RSS_TYPE_UDP_IPV6 | RSS_TYPE_UDP_IPV6_EX)) == 0, - ("UDP4, UDP6 and UDP6EX are not supported")); + KASSERT((types & (RSS_TYPE_UDP_IPV6 | RSS_TYPE_UDP_IPV6_EX)) == 0, + ("UDP6 and UDP6EX are not supported")); if (types & RSS_TYPE_IPV4) rss_hash |= NDIS_HASH_IPV4; @@ -1448,6 +1449,8 @@ hn_rss_type_tondis(uint32_t types) rss_hash |= NDIS_HASH_TCP_IPV6; if (types & RSS_TYPE_TCP_IPV6_EX) rss_hash |= NDIS_HASH_TCP_IPV6_EX; + if (types & RSS_TYPE_UDP_IPV4) + rss_hash |= NDIS_HASH_UDP_IPV4_X; return (rss_hash); } @@ -1546,6 +1549,13 @@ hn_vf_rss_fixup(struct hn_softc *sc, bool reconf) * NOTE: * We don't disable the hash type, but stop delivery the hash * value/type through mbufs on RX path. + * + * XXX If HN_CAP_UDPHASH is set in hn_caps, then UDP 4-tuple + * hash is delivered with type of TCP_IPV4. This means if + * UDP_IPV4 is enabled, then TCP_IPV4 should be forced, at + * least to hn_mbuf_hash. However, given that _all_ of the + * NICs implement TCP_IPV4, this will _not_ impose any issues + * here. */ if ((my_types & RSS_TYPE_IPV4) && (diff_types & ifrh.ifrh_types & @@ -3582,7 +3592,9 @@ hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int &l3proto, &l4proto); } if (l3proto == ETHERTYPE_IP) { - if (l4proto == IPPROTO_UDP) { + if (l4proto == IPPROTO_UDP && + (rxr->hn_mbuf_hash & + NDIS_HASH_UDP_IPV4_X)) { hash_type = M_HASHTYPE_RSS_UDP_IPV4; do_lro = 0; Modified: head/sys/dev/hyperv/netvsc/ndis.h ============================================================================== --- head/sys/dev/hyperv/netvsc/ndis.h Wed Oct 11 05:07:37 2017 (r324515) +++ head/sys/dev/hyperv/netvsc/ndis.h Wed Oct 11 05:15:49 2017 (r324516) @@ -56,17 +56,26 @@ #define NDIS_HASH_IPV6_EX 0x00000800 #define NDIS_HASH_TCP_IPV6 0x00001000 #define NDIS_HASH_TCP_IPV6_EX 0x00002000 +#define NDIS_HASH_UDP_IPV4_X 0x00004000 /* XXX non-standard */ #define NDIS_HASH_ALL (NDIS_HASH_IPV4 | \ NDIS_HASH_TCP_IPV4 | \ NDIS_HASH_IPV6 | \ NDIS_HASH_IPV6_EX | \ NDIS_HASH_TCP_IPV6 | \ + NDIS_HASH_TCP_IPV6_EX |\ + NDIS_HASH_UDP_IPV4_X) + +#define NDIS_HASH_STD (NDIS_HASH_IPV4 | \ + NDIS_HASH_TCP_IPV4 | \ + NDIS_HASH_IPV6 | \ + NDIS_HASH_IPV6_EX | \ + NDIS_HASH_TCP_IPV6 | \ NDIS_HASH_TCP_IPV6_EX) /* Hash description for use with printf(9) %b identifier. */ #define NDIS_HASH_BITS \ - "\20\1TOEPLITZ\11IP4\12TCP4\13IP6\14IP6EX\15TCP6\16TCP6EX" + "\20\1TOEPLITZ\11IP4\12TCP4\13IP6\14IP6EX\15TCP6\16TCP6EX\17UDP4_X" #define NDIS_HASH_KEYSIZE_TOEPLITZ 40 #define NDIS_HASH_INDCNT 128
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710110515.v9B5Fn0o088732>