Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105796910
D8338.id21718.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D8338.id21718.diff
View Options
Index: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
===================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h
@@ -255,6 +255,8 @@
int hn_ndis_tso_szmax;
int hn_ndis_tso_sgmin;
+ int hn_rss_ind_size;
+ uint32_t hn_rss_hash; /* NDIS_HASH_ */
struct ndis_rssprm_toeplitz hn_rss;
};
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
@@ -329,6 +329,7 @@
static int hn_rxfilter_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS);
+static int hn_rss_hash_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_check_iplen(const struct mbuf *, int);
static int hn_create_tx_ring(struct hn_softc *, int);
static void hn_destroy_tx_ring(struct hn_tx_ring *);
@@ -770,6 +771,11 @@
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxfilter",
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
hn_rxfilter_sysctl, "A", "rxfilter");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rss_hash",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
+ hn_rss_hash_sysctl, "A", "RSS hash");
+ SYSCTL_ADD_INT(ctx, child, OID_AUTO, "rss_ind_size",
+ CTLFLAG_RD, &sc->hn_rss_ind_size, 0, "RSS indirect entry count");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rss_key",
CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
hn_rss_key_sysctl, "IU", "RSS key");
@@ -2479,6 +2485,20 @@
}
static int
+hn_rss_hash_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct hn_softc *sc = arg1;
+ char hash_str[128];
+ uint32_t hash;
+
+ HN_LOCK(sc);
+ hash = sc->hn_rss_hash;
+ HN_UNLOCK(sc);
+ snprintf(hash_str, sizeof(hash_str), "%b", hash, NDIS_HASH_BITS);
+ return sysctl_handle_string(oidp, hash_str, sizeof(hash_str), req);
+}
+
+static int
hn_check_iplen(const struct mbuf *m, int hoff)
{
const struct ip *ip;
@@ -3642,6 +3662,10 @@
old_caps = sc->hn_caps;
sc->hn_caps = 0;
+ /* Clear RSS stuffs. */
+ sc->hn_rss_ind_size = 0;
+ sc->hn_rss_hash = 0;
+
/*
* Attach the primary channel _before_ attaching NVS and RNDIS.
*/
@@ -3716,7 +3740,6 @@
if_printf(sc->hn_ifp, "setup default RSS indirect "
"table\n");
}
- /* TODO: Take ndis_rss_caps.ndis_nind into account. */
for (i = 0; i < NDIS_HASH_INDCNT; ++i)
rss->rss_ind[i] = i % nchan;
sc->hn_flags |= HN_FLAG_HAS_RSSIND;
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
@@ -747,13 +747,14 @@
}
int
-hn_rndis_query_rsscaps(struct hn_softc *sc, int *rxr_cnt)
+hn_rndis_query_rsscaps(struct hn_softc *sc, int *rxr_cnt0)
{
struct ndis_rss_caps in, caps;
size_t caps_len;
- int error;
+ int error, indsz, rxr_cnt, hash_fnidx;
+ uint32_t hash_func = 0, hash_types = 0;
- *rxr_cnt = 0;
+ *rxr_cnt0 = 0;
if (sc->hn_ndis_ver < HN_NDIS_VERSION_6_20)
return (EOPNOTSUPP);
@@ -792,18 +793,73 @@
return (EINVAL);
}
+ /*
+ * Save information for later RSS configuration.
+ */
if (caps.ndis_nrxr == 0) {
if_printf(sc->hn_ifp, "0 RX rings!?\n");
return (EINVAL);
}
- *rxr_cnt = caps.ndis_nrxr;
+ if (bootverbose)
+ if_printf(sc->hn_ifp, "%u RX rings\n", caps.ndis_nrxr);
+ rxr_cnt = caps.ndis_nrxr;
+
+ if (caps.ndis_hdr.ndis_size == NDIS_RSS_CAPS_SIZE &&
+ caps.ndis_hdr.ndis_rev >= NDIS_RSS_CAPS_REV_2) {
+ if (caps.ndis_nind > NDIS_HASH_INDCNT) {
+ if_printf(sc->hn_ifp,
+ "too many RSS indirect table entries %u\n",
+ caps.ndis_nind);
+ return (EOPNOTSUPP);
+ }
+ if (!powerof2(caps.ndis_nind)) {
+ if_printf(sc->hn_ifp, "RSS indirect table size is not "
+ "power-of-2 %u\n", caps.ndis_nind);
+ }
- if (caps.ndis_hdr.ndis_size == NDIS_RSS_CAPS_SIZE) {
if (bootverbose) {
if_printf(sc->hn_ifp, "RSS indirect table size %u\n",
caps.ndis_nind);
}
+ indsz = caps.ndis_nind;
+ } else {
+ indsz = NDIS_HASH_INDCNT;
+ }
+ if (indsz < rxr_cnt) {
+ if_printf(sc->hn_ifp, "# of RX rings (%d) > "
+ "RSS indirect table size %d\n", rxr_cnt, indsz);
+ rxr_cnt = indsz;
}
+
+ /*
+ * NOTE:
+ * Toeplitz is at the lowest bit, and it is prefered; so ffs(),
+ * instead of fls(), is used here.
+ */
+ hash_fnidx = ffs(caps.ndis_caps & NDIS_RSS_CAP_HASHFUNC_MASK);
+ if (hash_fnidx == 0) {
+ if_printf(sc->hn_ifp, "no hash functions, caps 0x%08x\n",
+ caps.ndis_caps);
+ return (EOPNOTSUPP);
+ }
+ hash_func = 1 << (hash_fnidx - 1); /* ffs is 1-based */
+
+ if (caps.ndis_caps & NDIS_RSS_CAP_IPV4)
+ hash_types |= NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4;
+ if (caps.ndis_caps & NDIS_RSS_CAP_IPV6)
+ hash_types |= NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6;
+ if (caps.ndis_caps & NDIS_RSS_CAP_IPV6_EX)
+ hash_types |= NDIS_HASH_IPV6_EX | NDIS_HASH_TCP_IPV6_EX;
+ if (hash_types == 0) {
+ if_printf(sc->hn_ifp, "no hash types, caps 0x%08x\n",
+ caps.ndis_caps);
+ return (EOPNOTSUPP);
+ }
+
+ /* Commit! */
+ sc->hn_rss_ind_size = indsz;
+ sc->hn_rss_hash = hash_func | hash_types;
+ *rxr_cnt0 = rxr_cnt;
return (0);
}
@@ -1033,7 +1089,7 @@
{
struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
struct ndis_rss_params *prm = &rss->rss_params;
- int error;
+ int error, rss_size;
/*
* Only NDIS 6.20+ is supported:
@@ -1043,21 +1099,29 @@
KASSERT(sc->hn_ndis_ver >= HN_NDIS_VERSION_6_20,
("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_ind_size > 0, ("no indirect table size"));
+
+ if (bootverbose) {
+ if_printf(sc->hn_ifp, "RSS indirect table size %d, "
+ "hash 0x%08x\n", sc->hn_rss_ind_size, sc->hn_rss_hash);
+ }
+
/*
* NOTE:
* DO NOT whack rss_key and rss_ind, which are setup by the caller.
*/
memset(prm, 0, sizeof(*prm));
+ rss_size = NDIS_RSSPRM_TOEPLITZ_SIZE(sc->hn_rss_ind_size);
prm->ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_PARAMS;
prm->ndis_hdr.ndis_rev = NDIS_RSS_PARAMS_REV_2;
- prm->ndis_hdr.ndis_size = sizeof(*rss);
+ prm->ndis_hdr.ndis_size = rss_size;
prm->ndis_flags = flags;
- prm->ndis_hash = NDIS_HASH_FUNCTION_TOEPLITZ |
- NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 |
- NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6;
- /* TODO: Take ndis_rss_caps.ndis_nind into account */
- prm->ndis_indsize = sizeof(rss->rss_ind);
+ prm->ndis_hash = sc->hn_rss_hash;
+ prm->ndis_indsize = sizeof(rss->rss_ind[0]) * sc->hn_rss_ind_size;
prm->ndis_indoffset =
__offsetof(struct ndis_rssprm_toeplitz, rss_ind[0]);
prm->ndis_keysize = sizeof(rss->rss_key);
@@ -1065,7 +1129,7 @@
__offsetof(struct ndis_rssprm_toeplitz, rss_key[0]);
error = hn_rndis_set(sc, OID_GEN_RECEIVE_SCALE_PARAMETERS,
- rss, sizeof(*rss));
+ rss, rss_size);
if (error) {
if_printf(sc->hn_ifp, "RSS config failed: %d\n", error);
} else {
Index: head/sys/dev/hyperv/netvsc/ndis.h
===================================================================
--- head/sys/dev/hyperv/netvsc/ndis.h
+++ head/sys/dev/hyperv/netvsc/ndis.h
@@ -57,6 +57,10 @@
#define NDIS_HASH_TCP_IPV6 0x00001000
#define NDIS_HASH_TCP_IPV6_EX 0x00002000
+/* Hash description for use with printf(9) %b identifier. */
+#define NDIS_HASH_BITS \
+ "\20\1TOEPLITZ\11IP4\12TCP4\13IP6\14IP6EX\15TCP6\16TCP6EX"
+
#define NDIS_HASH_KEYSIZE_TOEPLITZ 40
#define NDIS_HASH_INDCNT 128
@@ -142,7 +146,7 @@
*/
struct ndis_rss_caps {
struct ndis_object_hdr ndis_hdr;
- uint32_t ndis_flags; /* NDIS_RSS_CAP_ */
+ uint32_t ndis_caps; /* NDIS_RSS_CAP_ */
uint32_t ndis_nmsi; /* # of MSIs */
uint32_t ndis_nrxr; /* # of RX rings */
/* NDIS >= 6.30 */
@@ -165,7 +169,8 @@
#define NDIS_RSS_CAP_IPV4 0x00000100
#define NDIS_RSS_CAP_IPV6 0x00000200
#define NDIS_RSS_CAP_IPV6_EX 0x00000400
-#define NDIS_RSS_CAP_HASH_TOEPLITZ 0x00000001
+#define NDIS_RSS_CAP_HASH_TOEPLITZ NDIS_HASH_FUNCTION_TOEPLITZ
+#define NDIS_RSS_CAP_HASHFUNC_MASK NDIS_HASH_FUNCTION_MASK
/*
* OID_GEN_RECEIVE_SCALE_PARAMETERS
@@ -209,6 +214,9 @@
uint32_t rss_ind[NDIS_HASH_INDCNT];
};
+#define NDIS_RSSPRM_TOEPLITZ_SIZE(nind) \
+ __offsetof(struct ndis_rssprm_toeplitz, rss_ind[nind])
+
/*
* OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES
* ndis_type: NDIS_OBJTYPE_OFFLOAD
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Dec 21, 8:11 PM (20 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15542744
Default Alt Text
D8338.id21718.diff (8 KB)
Attached To
Mode
D8338: hyperv/hn: Properly configure RSS according to RSS capabilities
Attached
Detach File
Event Timeline
Log In to Comment