svn commit: r307591 - stable/11/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Wed Oct 19 01:55:52 UTC 2016
Author: sephe
Date: Wed Oct 19 01:55:50 2016
New Revision: 307591
URL: https://svnweb.freebsd.org/changeset/base/307591
Log:
MFC 305962,305964-305967
305962
hyperv/hn: Don't allow NVS and NDIS version change upon reinitailization
NVS and NDIS version change would break too much assumption and static
configuration.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7919
305964
hyperv/hn: Save capabilities for later use.
And don't allow capability changes during reinitialization, which
breaks too much static configuration.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7922
305965
hyperv/hn: Don't allow MTU change, if it is not supported by the NVS.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7923
305966
hyperv/hn: Stringent RSS sysctl checks
- Don't change RNDIS RSS configuration for RSS key sysctl, if the
interface is not capable of RSS yet.
- Don't change RSS indirect table (both cached one and RNDIS RSS
configuration), if the interface is not capable of RSS yet.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7924
305967
hyperv/hn: Allow RSS capability flipping upon attach/reinit.
Sponsored by: Microsoft
Differential Revision: https://reviews.freebsd.org/D7927
Modified:
stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c Wed Oct 19 01:38:23 2016 (r307590)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.c Wed Oct 19 01:55:50 2016 (r307591)
@@ -467,9 +467,15 @@ hn_nvs_conf_ndis(struct hn_softc *sc, in
/* NOTE: No response. */
error = hn_nvs_req_send(sc, &conf, sizeof(conf));
- if (error)
+ if (error) {
if_printf(sc->hn_ifp, "send nvs ndis conf failed: %d\n", error);
- return (error);
+ return (error);
+ }
+
+ if (bootverbose)
+ if_printf(sc->hn_ifp, "nvs ndis conf done\n");
+ sc->hn_caps |= HN_CAP_MTU | HN_CAP_VLAN;
+ return (0);
}
static int
@@ -495,6 +501,22 @@ hn_nvs_init(struct hn_softc *sc)
{
int i;
+ if (device_is_attached(sc->hn_dev)) {
+ /*
+ * NVS version and NDIS version MUST NOT be changed.
+ */
+ if (bootverbose) {
+ if_printf(sc->hn_ifp, "reinit NVS version 0x%x, "
+ "NDIS version %u.%u\n", sc->hn_nvs_ver,
+ HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver),
+ HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver));
+ }
+ return (hn_nvs_doinit(sc, sc->hn_nvs_ver));
+ }
+
+ /*
+ * Find the supported NVS version and set NDIS version accordingly.
+ */
for (i = 0; i < nitems(hn_nvs_version); ++i) {
int error;
Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h Wed Oct 19 01:38:23 2016 (r307590)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h Wed Oct 19 01:55:50 2016 (r307591)
@@ -228,7 +228,8 @@ struct hn_softc {
struct vmbus_xact_ctx *hn_xact;
uint32_t hn_nvs_ver;
- uint32_t hn_flags;
+ uint32_t hn_caps; /* HN_CAP_ */
+ uint32_t hn_flags; /* HN_FLAG_ */
void *hn_rxbuf;
uint32_t hn_rxbuf_gpadl;
struct hyperv_dma hn_rxbuf_dma;
@@ -244,6 +245,18 @@ struct hn_softc {
#define HN_FLAG_RXBUF_CONNECTED 0x0001
#define HN_FLAG_CHIM_CONNECTED 0x0002
+#define HN_FLAG_HAS_RSSKEY 0x0004
+#define HN_FLAG_HAS_RSSIND 0x0008
+
+#define HN_CAP_VLAN 0x0001
+#define HN_CAP_MTU 0x0002
+#define HN_CAP_IPCS 0x0004
+#define HN_CAP_TCP4CS 0x0008
+#define HN_CAP_TCP6CS 0x0010
+#define HN_CAP_UDP4CS 0x0020
+#define HN_CAP_UDP6CS 0x0040
+#define HN_CAP_TSO4 0x0080
+#define HN_CAP_TSO6 0x0100
/*
* Externs
Modified: stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Wed Oct 19 01:38:23 2016 (r307590)
+++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Wed Oct 19 01:55:50 2016 (r307591)
@@ -325,6 +325,7 @@ static int hn_rx_stat_ulong_sysctl(SYSCT
static int hn_tx_stat_ulong_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS);
static int hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS);
+static int hn_caps_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_check_iplen(const struct mbuf *, int);
@@ -434,6 +435,8 @@ hn_rss_ind_fixup(struct hn_softc *sc, in
struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
int i;
+ KASSERT(nchan > 1, ("invalid # of channels %d", nchan));
+
/*
* Check indirect table to make sure that all channels in it
* can be used.
@@ -641,6 +644,9 @@ netvsc_attach(device_t dev)
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "ndis_version",
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
hn_ndis_version_sysctl, "A", "NDIS version");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "caps",
+ CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0,
+ hn_caps_sysctl, "A", "capabilities");
SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rss_key",
CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0,
hn_rss_key_sysctl, "IU", "RSS key");
@@ -1568,6 +1574,13 @@ hn_ioctl(struct ifnet *ifp, u_long cmd,
HN_LOCK(sc);
+ if ((sc->hn_caps & HN_CAP_MTU) == 0) {
+ /* Can't change MTU */
+ HN_UNLOCK(sc);
+ error = EOPNOTSUPP;
+ break;
+ }
+
if (ifp->if_mtu == ifr->ifr_mtu) {
HN_UNLOCK(sc);
break;
@@ -2095,6 +2108,30 @@ hn_ndis_version_sysctl(SYSCTL_HANDLER_AR
}
static int
+hn_caps_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ struct hn_softc *sc = arg1;
+ char caps_str[128];
+ uint32_t caps;
+
+ HN_LOCK(sc);
+ caps = sc->hn_caps;
+ HN_UNLOCK(sc);
+ snprintf(caps_str, sizeof(caps_str), "%b", caps,
+ "\020"
+ "\001VLAN"
+ "\002MTU"
+ "\003IPCS"
+ "\004TCP4CS"
+ "\005TCP6CS"
+ "\006UDP4CS"
+ "\007UDP6CS"
+ "\010TSO4"
+ "\011TSO6");
+ return sysctl_handle_string(oidp, caps_str, sizeof(caps_str), req);
+}
+
+static int
hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS)
{
struct hn_softc *sc = arg1;
@@ -2109,8 +2146,14 @@ hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS)
error = SYSCTL_IN(req, sc->hn_rss.rss_key, sizeof(sc->hn_rss.rss_key));
if (error)
goto back;
+ sc->hn_flags |= HN_FLAG_HAS_RSSKEY;
- error = hn_rss_reconfig(sc);
+ if (sc->hn_rx_ring_inuse > 1) {
+ error = hn_rss_reconfig(sc);
+ } else {
+ /* Not RSS capable, at least for now; just save the RSS key. */
+ error = 0;
+ }
back:
HN_UNLOCK(sc);
return (error);
@@ -2128,9 +2171,19 @@ hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS)
if (error || req->newptr == NULL)
goto back;
+ /*
+ * Don't allow RSS indirect table change, if this interface is not
+ * RSS capable currently.
+ */
+ if (sc->hn_rx_ring_inuse == 1) {
+ error = EOPNOTSUPP;
+ goto back;
+ }
+
error = SYSCTL_IN(req, sc->hn_rss.rss_ind, sizeof(sc->hn_rss.rss_ind));
if (error)
goto back;
+ sc->hn_flags |= HN_FLAG_HAS_RSSIND;
hn_rss_ind_fixup(sc, sc->hn_rx_ring_inuse);
error = hn_rss_reconfig(sc);
@@ -3223,6 +3276,11 @@ hn_synth_attach(struct hn_softc *sc, int
{
struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
int error, nsubch, nchan, i;
+ uint32_t old_caps;
+
+ /* Save capabilities for later verification. */
+ old_caps = sc->hn_caps;
+ sc->hn_caps = 0;
/*
* Attach the primary channel _before_ attaching NVS and RNDIS.
@@ -3246,6 +3304,17 @@ hn_synth_attach(struct hn_softc *sc, int
return (error);
/*
+ * Make sure capabilities are not changed.
+ */
+ if (device_is_attached(sc->hn_dev) && old_caps != sc->hn_caps) {
+ if_printf(sc->hn_ifp, "caps mismatch old 0x%08x, new 0x%08x\n",
+ old_caps, sc->hn_caps);
+ /* Restore old capabilities and abort. */
+ sc->hn_caps = old_caps;
+ return ENXIO;
+ }
+
+ /*
* Allocate sub-channels for multi-TX/RX rings.
*
* NOTE:
@@ -3268,24 +3337,29 @@ hn_synth_attach(struct hn_softc *sc, int
* are allocated.
*/
- if (!device_is_attached(sc->hn_dev)) {
+ if ((sc->hn_flags & HN_FLAG_HAS_RSSKEY) == 0) {
/*
- * Setup default RSS key and indirect table for the
- * attach DEVMETHOD. They can be altered later on,
- * so don't mess them up once this interface is attached.
+ * RSS key is not set yet; set it to the default RSS key.
*/
- if (bootverbose) {
- if_printf(sc->hn_ifp, "setup default RSS key and "
- "indirect table\n");
- }
-
- /* Setup default RSS key. */
+ if (bootverbose)
+ if_printf(sc->hn_ifp, "setup default RSS key\n");
memcpy(rss->rss_key, hn_rss_key_default, sizeof(rss->rss_key));
+ sc->hn_flags |= HN_FLAG_HAS_RSSKEY;
+ }
- /* Setup default RSS indirect table. */
+ if ((sc->hn_flags & HN_FLAG_HAS_RSSIND) == 0) {
+ /*
+ * RSS indirect table is not set yet; set it up in round-
+ * robin fashion.
+ */
+ if (bootverbose) {
+ 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;
} else {
/*
* # of usable channels may be changed, so we have to
Modified: stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c Wed Oct 19 01:38:23 2016 (r307590)
+++ stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c Wed Oct 19 01:55:50 2016 (r307591)
@@ -800,6 +800,7 @@ static int
hn_rndis_conf_offload(struct hn_softc *sc)
{
struct ndis_offload_params params;
+ uint32_t caps;
size_t paramsz;
int error;
@@ -816,24 +817,29 @@ hn_rndis_conf_offload(struct hn_softc *s
}
params.ndis_hdr.ndis_size = paramsz;
+ caps = HN_CAP_IPCS | HN_CAP_TCP4CS | HN_CAP_TCP6CS;
params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX;
params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX;
params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX;
if (sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30) {
+ caps |= HN_CAP_UDP4CS | HN_CAP_UDP6CS;
params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX;
params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX;
}
+ caps |= HN_CAP_TSO4;
params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_ON;
/* XXX ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_ON */
error = hn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, ¶ms, paramsz);
if (error) {
if_printf(sc->hn_ifp, "offload config failed: %d\n", error);
- } else {
- if (bootverbose)
- if_printf(sc->hn_ifp, "offload config done\n");
+ return (error);
}
- return (error);
+
+ if (bootverbose)
+ if_printf(sc->hn_ifp, "offload config done\n");
+ sc->hn_caps |= caps;
+ return (0);
}
int
More information about the svn-src-stable-11
mailing list