summaryrefslogtreecommitdiff
path: root/sys/dev/hyperv
diff options
context:
space:
mode:
authorSepherosa Ziehau <sephe@FreeBSD.org>2017-10-11 05:15:49 +0000
committerSepherosa Ziehau <sephe@FreeBSD.org>2017-10-11 05:15:49 +0000
commit6f12c42e8b962495208915ba4b972b0cc4d87c5d (patch)
tree0e0e7009510904b22fcfe8abe467bcd1f87a6fdb /sys/dev/hyperv
parent8e4db4e4a1bd09c767efc1eaae41caa9ca7e322f (diff)
Notes
Diffstat (limited to 'sys/dev/hyperv')
-rw-r--r--sys/dev/hyperv/netvsc/hn_rndis.c13
-rw-r--r--sys/dev/hyperv/netvsc/if_hn.c20
-rw-r--r--sys/dev/hyperv/netvsc/ndis.h11
3 files changed, 36 insertions, 8 deletions
diff --git a/sys/dev/hyperv/netvsc/hn_rndis.c b/sys/dev/hyperv/netvsc/hn_rndis.c
index 64609bb5dcfd8..b9bf683fe8113 100644
--- a/sys/dev/hyperv/netvsc/hn_rndis.c
+++ b/sys/dev/hyperv/netvsc/hn_rndis.c
@@ -521,6 +521,10 @@ hn_rndis_query_rsscaps(struct hn_softc *sc, int *rxr_cnt0)
/* 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]);
diff --git a/sys/dev/hyperv/netvsc/if_hn.c b/sys/dev/hyperv/netvsc/if_hn.c
index 03c0aefafe8a5..9ae5102df9a26 100644
--- a/sys/dev/hyperv/netvsc/if_hn.c
+++ b/sys/dev/hyperv/netvsc/if_hn.c
@@ -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 dlen,
&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;
diff --git a/sys/dev/hyperv/netvsc/ndis.h b/sys/dev/hyperv/netvsc/ndis.h
index 42f3c25401dbe..4e34b51ca30f1 100644
--- a/sys/dev/hyperv/netvsc/ndis.h
+++ b/sys/dev/hyperv/netvsc/ndis.h
@@ -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