Index: sys/dev/vmware/vmxnet3/if_vmx.c =================================================================== --- sys/dev/vmware/vmxnet3/if_vmx.c +++ sys/dev/vmware/vmxnet3/if_vmx.c @@ -23,6 +23,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_rss.h" + #include #include #include @@ -46,6 +48,9 @@ #include #include #include +#ifdef RSS +#include +#endif #include #include @@ -1140,8 +1145,11 @@ struct vmxnet3_driver_shared *ds; if_softc_ctx_t scctx; struct vmxnet3_rss_shared *rss; +#ifdef RSS + uint8_t rss_algo; +#endif int i; - + ds = sc->vmx_ds; scctx = sc->vmx_scctx; rss = sc->vmx_rss; @@ -1152,10 +1160,29 @@ rss->hash_func = UPT1_RSS_HASH_FUNC_TOEPLITZ; rss->hash_key_size = UPT1_RSS_MAX_KEY_SIZE; rss->ind_table_size = UPT1_RSS_MAX_IND_TABLE_SIZE; - memcpy(rss->hash_key, rss_key, UPT1_RSS_MAX_KEY_SIZE); - - for (i = 0; i < UPT1_RSS_MAX_IND_TABLE_SIZE; i++) - rss->ind_table[i] = i % scctx->isc_nrxqsets; +#ifdef RSS + /* + * If the software RSS is configured to anything else other than + * Toeplitz, then just do Toeplitz in "hardware" for the sake of + * the packet distribution, but report the hash as opaque to + * disengage from the software RSS. + */ + rss_algo = rss_gethashalgo(); + if (rss_algo == RSS_HASH_TOEPLITZ) { + rss_getkey(rss->hash_key); + for (i = 0; i < UPT1_RSS_MAX_IND_TABLE_SIZE; i++) { + rss->ind_table[i] = rss_get_indirection_to_bucket(i) % + scctx->isc_nrxqsets; + } + sc->vmx_flags |= VMXNET3_FLAG_SOFT_RSS; + } else +#endif + { + memcpy(rss->hash_key, rss_key, UPT1_RSS_MAX_KEY_SIZE); + for (i = 0; i < UPT1_RSS_MAX_IND_TABLE_SIZE; i++) + rss->ind_table[i] = i % scctx->isc_nrxqsets; + sc->vmx_flags &= ~VMXNET3_FLAG_SOFT_RSS; + } } static void @@ -1499,29 +1526,47 @@ KASSERT(rxcd->sop, ("%s: expected sop", __func__)); /* - * RSS and flow ID + * RSS and flow ID. + * Types other than M_HASHTYPE_NONE and M_HASHTYPE_OPAQUE_HASH should + * be used only if the software RSS is enabled and it uses the same + * algorithm and the hash key as the "hardware". If the software RSS + * is not enabled, then it's simply pointless to use those types, + * otherwise there will be mismatching hash values resulting in broken + * connectivity. */ ri->iri_flowid = rxcd->rss_hash; - switch (rxcd->rss_type) { - case VMXNET3_RCD_RSS_TYPE_NONE: - ri->iri_flowid = ri->iri_qsidx; - ri->iri_rsstype = M_HASHTYPE_NONE; - break; - case VMXNET3_RCD_RSS_TYPE_IPV4: - ri->iri_rsstype = M_HASHTYPE_RSS_IPV4; - break; - case VMXNET3_RCD_RSS_TYPE_TCPIPV4: - ri->iri_rsstype = M_HASHTYPE_RSS_TCP_IPV4; - break; - case VMXNET3_RCD_RSS_TYPE_IPV6: - ri->iri_rsstype = M_HASHTYPE_RSS_IPV6; - break; - case VMXNET3_RCD_RSS_TYPE_TCPIPV6: - ri->iri_rsstype = M_HASHTYPE_RSS_TCP_IPV6; - break; - default: - ri->iri_rsstype = M_HASHTYPE_OPAQUE_HASH; - break; + if ((sc->vmx_flags & VMXNET3_FLAG_SOFT_RSS) != 0) { + switch (rxcd->rss_type) { + case VMXNET3_RCD_RSS_TYPE_NONE: + ri->iri_flowid = ri->iri_qsidx; + ri->iri_rsstype = M_HASHTYPE_NONE; + break; + case VMXNET3_RCD_RSS_TYPE_IPV4: + ri->iri_rsstype = M_HASHTYPE_RSS_IPV4; + break; + case VMXNET3_RCD_RSS_TYPE_TCPIPV4: + ri->iri_rsstype = M_HASHTYPE_RSS_TCP_IPV4; + break; + case VMXNET3_RCD_RSS_TYPE_IPV6: + ri->iri_rsstype = M_HASHTYPE_RSS_IPV6; + break; + case VMXNET3_RCD_RSS_TYPE_TCPIPV6: + ri->iri_rsstype = M_HASHTYPE_RSS_TCP_IPV6; + break; + default: + ri->iri_rsstype = M_HASHTYPE_OPAQUE_HASH; + break; + } + } else { + switch (rxcd->rss_type) { + case VMXNET3_RCD_RSS_TYPE_NONE: + ri->iri_flowid = ri->iri_qsidx; + ri->iri_rsstype = M_HASHTYPE_NONE; + break; + default: + ri->iri_rsstype = M_HASHTYPE_OPAQUE_HASH; + break; + } } /* VLAN */ Index: sys/dev/vmware/vmxnet3/if_vmxvar.h =================================================================== --- sys/dev/vmware/vmxnet3/if_vmxvar.h +++ sys/dev/vmware/vmxnet3/if_vmxvar.h @@ -113,6 +113,8 @@ struct vmxnet3_driver_shared *vmx_ds; uint32_t vmx_flags; #define VMXNET3_FLAG_RSS 0x0002 +#define VMXNET3_FLAG_SOFT_RSS 0x0004 /* Software RSS is enabled with + compatible algorithm. */ struct vmxnet3_rxqueue *vmx_rxq; struct vmxnet3_txqueue *vmx_txq;