Index: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c =================================================================== --- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c +++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c @@ -1289,7 +1289,7 @@ struct ifnet *ifp = rxr->hn_ifp; struct mbuf *m_new; int size, do_lro = 0, do_csum = 1; - int hash_type = M_HASHTYPE_OPAQUE_HASH; + int hash_type; if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) return (0); @@ -1421,13 +1421,13 @@ m_new->m_flags |= M_VLANTAG; } - if (info->hash_info != NULL && info->hash_value != NULL) { + if (info->hash_info != HN_NDIS_HASH_INFO_INVALID) { rxr->hn_rss_pkts++; - m_new->m_pkthdr.flowid = info->hash_value->hash_value; - if ((info->hash_info->hash_info & NDIS_HASH_FUNCTION_MASK) == + m_new->m_pkthdr.flowid = info->hash_value; + hash_type = M_HASHTYPE_OPAQUE_HASH; + if ((info->hash_info & NDIS_HASH_FUNCTION_MASK) == NDIS_HASH_FUNCTION_TOEPLITZ) { - uint32_t type = - (info->hash_info->hash_info & NDIS_HASH_TYPE_MASK); + uint32_t type = (info->hash_info & NDIS_HASH_TYPE_MASK); switch (type) { case NDIS_HASH_IPV4: @@ -1456,12 +1456,8 @@ } } } else { - if (info->hash_value != NULL) { - m_new->m_pkthdr.flowid = info->hash_value->hash_value; - } else { - m_new->m_pkthdr.flowid = rxr->hn_rx_idx; - hash_type = M_HASHTYPE_OPAQUE; - } + m_new->m_pkthdr.flowid = rxr->hn_rx_idx; + hash_type = M_HASHTYPE_OPAQUE; } M_HASHTYPE_SET(m_new, hash_type); Index: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c =================================================================== --- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c +++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c @@ -158,8 +158,7 @@ info->vlan_info = HN_NDIS_VLAN_INFO_INVALID; info->csum_info = HN_NDIS_RXCSUM_INFO_INVALID; - info->hash_info = NULL; - info->hash_value = NULL; + info->hash_info = HN_NDIS_HASH_INFO_INVALID; if (rpkt->per_pkt_info_offset == 0) return (0); @@ -207,18 +206,16 @@ break; case nbl_hash_value: - if (__predict_false(dlen < - sizeof(struct rndis_hash_value))) + if (__predict_false(dlen < HN_NDIS_HASH_VALUE_SIZE)) return (EINVAL); - info->hash_value = data; + info->hash_value = *((const uint32_t *)data); mask |= HV_RF_RECVINFO_HASHVAL; break; case nbl_hash_info: - if (__predict_false(dlen < - sizeof(struct rndis_hash_info))) + if (__predict_false(dlen < HN_NDIS_HASH_INFO_SIZE)) return (EINVAL); - info->hash_info = data; + info->hash_info = *((const uint32_t *)data); mask |= HV_RF_RECVINFO_HASHINF; break; @@ -234,6 +231,13 @@ pi = (const struct rndis_pktinfo *) ((const uint8_t *)pi + pi->rm_size); } + + /* + * Final fixup. + * - If there is no hash value, invalidate the hash info. + */ + if ((mask & HV_RF_RECVINFO_HASHVAL) == 0) + info->hash_info = HN_NDIS_HASH_INFO_INVALID; return (0); } Index: head/sys/dev/hyperv/netvsc/if_hnreg.h =================================================================== --- head/sys/dev/hyperv/netvsc/if_hnreg.h +++ head/sys/dev/hyperv/netvsc/if_hnreg.h @@ -208,4 +208,17 @@ } __packed; CTASSERT(sizeof(struct hn_nvs_rndis_ack) >= HN_NVS_REQSIZE_MIN); +/* + * RNDIS extension + */ + +/* Per-packet hash info */ +#define HN_NDIS_HASH_INFO_SIZE sizeof(uint32_t) +#define HN_NDIS_PKTINFO_TYPE_HASHINF NDIS_PKTINFO_TYPE_ORIG_NBLIST +/* NDIS_HASH_ */ + +/* Per-packet hash value */ +#define HN_NDIS_HASH_VALUE_SIZE sizeof(uint32_t) +#define HN_NDIS_PKTINFO_TYPE_HASHVAL NDIS_PKTINFO_TYPE_PKT_CANCELID + #endif /* !_IF_HNREG_H_ */ Index: head/sys/dev/hyperv/netvsc/if_hnvar.h =================================================================== --- head/sys/dev/hyperv/netvsc/if_hnvar.h +++ head/sys/dev/hyperv/netvsc/if_hnvar.h @@ -57,12 +57,13 @@ #define HN_NDIS_VLAN_INFO_INVALID 0xffffffff #define HN_NDIS_RXCSUM_INFO_INVALID 0 +#define HN_NDIS_HASH_INFO_INVALID 0 struct hn_recvinfo { uint32_t vlan_info; uint32_t csum_info; - const struct rndis_hash_info *hash_info; - const struct rndis_hash_value *hash_value; + uint32_t hash_info; + uint32_t hash_value; }; #define HN_SEND_CTX_INITIALIZER(cb, cbarg) \