Author: sephe
Date: Fri Oct 14 02:19:47 2016
New Revision: 307245
URL: https://svnweb.freebsd.org/changeset/base/307245

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/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
  stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c        Fri Oct 14 02:03:53 
2016        (r307244)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c        Fri Oct 14 02:19:47 
2016        (r307245)
@@ -466,9 +466,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
@@ -494,6 +500,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/10/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h        Fri Oct 14 02:03:53 
2016        (r307244)
+++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h        Fri Oct 14 02:19:47 
2016        (r307245)
@@ -229,7 +229,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;
@@ -245,6 +246,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/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Fri Oct 14 
02:03:53 2016        (r307244)
+++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c     Fri Oct 14 
02:19:47 2016        (r307245)
@@ -327,6 +327,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);
@@ -436,6 +437,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.
@@ -657,6 +660,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");
@@ -1588,6 +1594,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;
@@ -2115,6 +2128,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;
@@ -2129,8 +2166,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);
@@ -2148,9 +2191,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);
@@ -3243,6 +3296,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.
@@ -3266,6 +3324,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:
@@ -3288,24 +3357,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/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c   Fri Oct 14 02:03:53 
2016        (r307244)
+++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c   Fri Oct 14 02:19:47 
2016        (r307245)
@@ -801,6 +801,7 @@ static int
 hn_rndis_conf_offload(struct hn_softc *sc)
 {
        struct ndis_offload_params params;
+       uint32_t caps;
        size_t paramsz;
        int error;
 
@@ -817,24 +818,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, &params, 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
_______________________________________________
svn-src-stable-10@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-stable-10
To unsubscribe, send any mail to "svn-src-stable-10-unsubscr...@freebsd.org"

Reply via email to