Author: sephe
Date: Mon Oct 17 07:27:16 2016
New Revision: 307490
URL: https://svnweb.freebsd.org/changeset/base/307490

Log:
  MFC 304973,304975,304976,304979,305044-305048
  
  304973
      hyperv/hn: Switch to new RNDIS query for link status extraction.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7654
  
  304975
      hyperv/hn: Switch to new RNDIS query for RSS capabilities extraction.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7656
  
  304976
      hyperv/hn: Fix # of channels setting, if RSS is not available.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7657
  
  304979
      hyperv/hn: Switch to new RNDIS set for RSS parameters.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7658
  
  305044
      hyperv/hn: Move OIDs to net/rndis.h; they are standard NDIS OIDs.
  
      Actually all OIDs defined in net/rndis.h are standard NDIS OIDs.
      While I'm here, use the verbose macro name as in NDIS spec.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7679
  
  305045
      hyperv/hn: Indentation and field comment fixup for ndis.h.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7680
  
  305046
      net/rndis: Packet types are defined by NDIS; not RNDIS specific.
  
      Reviewed by:    hps
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7681
  
  305047
      hyperv/hn: Switch to new RNDIS set for RX filters.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7683
  
  305048
      hyperv/hn: Remove unused function
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D7684

Modified:
  stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/11/sys/dev/hyperv/netvsc/hv_rndis.h
  stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  stable/11/sys/dev/hyperv/netvsc/ndis.h
  stable/11/sys/dev/usb/net/if_urndis.c
  stable/11/sys/net/rndis.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h        Mon Oct 17 07:25:46 
2016        (r307489)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h        Mon Oct 17 07:27:16 
2016        (r307490)
@@ -62,6 +62,8 @@
 #include <dev/hyperv/include/hyperv_busdma.h>
 #include <dev/hyperv/include/vmbus.h>
 
+#include <dev/hyperv/netvsc/ndis.h>
+
 #define HN_USE_TXDESC_BUFRING
 
 MALLOC_DECLARE(M_NETVSC);
@@ -383,6 +385,8 @@ typedef struct hn_softc {
 
        uint32_t                hn_rndis_rid;
        uint32_t                hn_ndis_ver;
+
+       struct ndis_rssprm_toeplitz hn_rss;
 } hn_softc_t;
 
 #define HN_FLAG_RXBUF_CONNECTED                0x0001

Modified: stable/11/sys/dev/hyperv/netvsc/hv_rndis.h
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_rndis.h  Mon Oct 17 07:25:46 2016        
(r307489)
+++ stable/11/sys/dev/hyperv/netvsc/hv_rndis.h  Mon Oct 17 07:27:16 2016        
(r307490)
@@ -536,20 +536,6 @@ struct rndis_hash_info {
        uint32_t        hash_info;
 } __packed;
 
-#define NDIS_HASH_FUNCTION_MASK                0x000000FF      /* see hash 
function */
-#define NDIS_HASH_TYPE_MASK            0x00FFFF00      /* see hash type */
-
-/* hash function */
-#define NDIS_HASH_FUNCTION_TOEPLITZ    0x00000001
-
-/* hash type */
-#define NDIS_HASH_IPV4                 0x00000100
-#define NDIS_HASH_TCP_IPV4             0x00000200
-#define NDIS_HASH_IPV6                 0x00000400
-#define NDIS_HASH_IPV6_EX              0x00000800
-#define NDIS_HASH_TCP_IPV6             0x00001000
-#define NDIS_HASH_TCP_IPV6_EX          0x00002000
-
 typedef struct rndis_tcp_tso_info_ {
        union {
                struct {
@@ -903,19 +889,6 @@ typedef struct rndismp_rx_bufs_info_ {
 
 #define RNDIS_HEADER_SIZE (sizeof(rndis_msg) - sizeof(rndis_msg_container))
 
-#define NDIS_PACKET_TYPE_DIRECTED      0x00000001
-#define NDIS_PACKET_TYPE_MULTICAST     0x00000002
-#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004
-#define NDIS_PACKET_TYPE_BROADCAST     0x00000008
-#define NDIS_PACKET_TYPE_SOURCE_ROUTING        0x00000010
-#define NDIS_PACKET_TYPE_PROMISCUOUS   0x00000020
-#define NDIS_PACKET_TYPE_SMT           0x00000040
-#define NDIS_PACKET_TYPE_ALL_LOCAL     0x00000080
-#define NDIS_PACKET_TYPE_GROUP         0x00000100
-#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL        0x00000200
-#define NDIS_PACKET_TYPE_FUNCTIONAL    0x00000400
-#define NDIS_PACKET_TYPE_MAC_FRAME     0x00000800
-
 /*
  * Externs
  */

Modified: stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c   Mon Oct 17 07:25:46 
2016        (r307489)
+++ stable/11/sys/dev/hyperv/netvsc/hv_rndis_filter.c   Mon Oct 17 07:27:16 
2016        (r307490)
@@ -79,17 +79,9 @@ static void hv_rf_receive_indicate_statu
     const rndis_msg *response);
 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
     const void *data, int dlen);
-static int  hv_rf_query_device(rndis_device *device, uint32_t oid,
-                              void *result, uint32_t *result_size);
 static inline int hv_rf_query_device_mac(rndis_device *device);
 static inline int hv_rf_query_device_link_status(rndis_device *device);
-static int  hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
 static int  hv_rf_init_device(rndis_device *device);
-static int  hv_rf_open_device(rndis_device *device);
-static int  hv_rf_close_device(rndis_device *device);
-int
-hv_rf_send_offload_request(struct hn_softc *sc,
-    rndis_offload_params *offloads);
 
 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
     struct hn_softc *sc, struct vmbus_channel *chan,
@@ -102,6 +94,8 @@ static int hn_rndis_query(struct hn_soft
 static int hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data,
     size_t dlen);
 static int hn_rndis_conf_offload(struct hn_softc *sc);
+static int hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt);
+static int hn_rndis_conf_rss(struct hn_softc *sc, int nchan);
 
 static __inline uint32_t
 hn_rndis_rid(struct hn_softc *sc)
@@ -355,78 +349,6 @@ hv_rf_receive_response(rndis_device *dev
        }
 }
 
-int
-hv_rf_send_offload_request(struct hn_softc *sc,
-    rndis_offload_params *offloads)
-{
-       rndis_request *request;
-       rndis_set_request *set;
-       rndis_offload_params *offload_req;
-       rndis_set_complete *set_complete;       
-       rndis_device *rndis_dev = sc->rndis_dev;
-       device_t dev = sc->hn_dev;
-       uint32_t extlen = sizeof(rndis_offload_params);
-       int ret;
-
-       if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) {
-               extlen = VERSION_4_OFFLOAD_SIZE;
-               /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
-                * UDP checksum offload.
-                */
-               offloads->udp_ipv4_csum = 0;
-               offloads->udp_ipv6_csum = 0;
-       }
-
-       request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
-           RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
-       if (!request)
-               return (ENOMEM);
-
-       set = &request->request_msg.msg.set_request;
-       set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
-       set->info_buffer_length = extlen;
-       set->info_buffer_offset = sizeof(rndis_set_request);
-       set->device_vc_handle = 0;
-
-       offload_req = (rndis_offload_params *)((unsigned long)set +
-           set->info_buffer_offset);
-       *offload_req = *offloads;
-       offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
-       offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
-       offload_req->header.size = extlen;
-
-       ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
-       if (ret != 0) {
-               device_printf(dev, "hv send offload request failed, ret=%d!\n",
-                   ret);
-               goto cleanup;
-       }
-
-       ret = sema_timedwait(&request->wait_sema, 5 * hz);
-       if (ret != 0) {
-               device_printf(dev, "hv send offload request timeout\n");
-               goto cleanup;
-       }
-
-       set_complete = &request->response_msg.msg.set_complete;
-       if (set_complete->status == RNDIS_STATUS_SUCCESS) {
-               device_printf(dev, "hv send offload request succeeded\n");
-               ret = 0;
-       } else {
-               if (set_complete->status == RNDIS_STATUS_NOT_SUPPORTED) {
-                       device_printf(dev, "HV Not support offload\n");
-                       ret = 0;
-               } else {
-                       ret = set_complete->status;
-               }
-       }
-
-cleanup:
-       hv_put_rndis_request(rndis_dev, request);
-
-       return (ret);
-}
-
 /*
  * RNDIS filter receive indicate status
  */
@@ -628,77 +550,6 @@ hv_rf_on_receive(struct hn_softc *sc, st
 }
 
 /*
- * RNDIS filter query device
- */
-static int
-hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
-                  uint32_t *result_size)
-{
-       rndis_request *request;
-       uint32_t in_result_size = *result_size;
-       rndis_query_request *query;
-       rndis_query_complete *query_complete;
-       int ret = 0;
-
-       *result_size = 0;
-       request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
-           RNDIS_MESSAGE_SIZE(rndis_query_request));
-       if (request == NULL) {
-               ret = -1;
-               goto cleanup;
-       }
-
-       /* Set up the rndis query */
-       query = &request->request_msg.msg.query_request;
-       query->oid = oid;
-       query->info_buffer_offset = sizeof(rndis_query_request); 
-       query->info_buffer_length = 0;
-       query->device_vc_handle = 0;
-
-       if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
-               struct rndis_recv_scale_cap *cap;
-
-               request->request_msg.msg_len += 
-                       sizeof(struct rndis_recv_scale_cap);
-               query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
-               cap = (struct rndis_recv_scale_cap *)((unsigned long)query + 
-                                               query->info_buffer_offset);
-               cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
-               cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
-               cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
-       }
-
-       ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
-       if (ret != 0) {
-               /* Fixme:  printf added */
-               printf("RNDISFILTER request failed to Send!\n");
-               goto cleanup;
-       }
-
-       sema_wait(&request->wait_sema);
-
-       /* Copy the response back */
-       query_complete = &request->response_msg.msg.query_complete;
-       
-       if (query_complete->info_buffer_length > in_result_size) {
-               ret = EINVAL;
-               goto cleanup;
-       }
-
-       memcpy(result, (void *)((unsigned long)query_complete +
-           query_complete->info_buffer_offset),
-           query_complete->info_buffer_length);
-
-       *result_size = query_complete->info_buffer_length;
-
-cleanup:
-       if (request != NULL)
-               hv_put_rndis_request(device, request);
-
-       return (ret);
-}
-
-/*
  * RNDIS filter query device MAC address
  */
 static int
@@ -712,12 +563,12 @@ hv_rf_query_device_mac(rndis_device *dev
        error = hn_rndis_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
            device->hw_mac_addr, &hwaddr_len);
        if (error)
-               return error;
+               return (error);
        if (hwaddr_len != ETHER_ADDR_LEN) {
                if_printf(sc->hn_ifp, "invalid hwaddr len %zu\n", hwaddr_len);
-               return EINVAL;
+               return (EINVAL);
        }
-       return 0;
+       return (0);
 }
 
 /*
@@ -726,13 +577,23 @@ hv_rf_query_device_mac(rndis_device *dev
 static inline int
 hv_rf_query_device_link_status(rndis_device *device)
 {
-       uint32_t size = sizeof(uint32_t);
+       struct hn_softc *sc = device->sc;
+       size_t size;
+       int error;
 
-       return (hv_rf_query_device(device,
-           RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
+       size = sizeof(uint32_t);
+       error = hn_rndis_query(sc, OID_GEN_MEDIA_CONNECT_STATUS, NULL, 0,
+           &device->link_status, &size);
+       if (error)
+               return (error);
+       if (size != sizeof(uint32_t)) {
+               if_printf(sc->hn_ifp, "invalid link status len %zu\n", size);
+               return (EINVAL);
+       }
+       return (0);
 }
 
-static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
+static uint8_t netvsc_hash_key[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
        0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
        0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
        0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
@@ -740,172 +601,6 @@ static uint8_t netvsc_hash_key[HASH_KEYL
        0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
 };
 
-/*
- * RNDIS set vRSS parameters
- */
-static int
-hv_rf_set_rss_param(rndis_device *device, int num_queue)
-{
-       rndis_request *request;
-       rndis_set_request *set;
-       rndis_set_complete *set_complete;
-       rndis_recv_scale_param *rssp;
-       uint32_t extlen = sizeof(rndis_recv_scale_param) +
-           (4 * ITAB_NUM) + HASH_KEYLEN;
-       uint32_t *itab, status;
-       uint8_t *keyp;
-       int i, ret;
-
-
-       request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
-           RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
-       if (request == NULL) {
-               if (bootverbose)
-                       printf("Netvsc: No memory to set vRSS parameters.\n");
-               ret = -1;
-               goto cleanup;
-       }
-
-       set = &request->request_msg.msg.set_request;
-       set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
-       set->info_buffer_length = extlen;
-       set->info_buffer_offset = sizeof(rndis_set_request);
-       set->device_vc_handle = 0;
-
-       /* Fill out the rssp parameter structure */
-       rssp = (rndis_recv_scale_param *)(set + 1);
-       rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
-       rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
-       rssp->hdr.size = sizeof(rndis_recv_scale_param);
-       rssp->flag = 0;
-       rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
-           RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
-       rssp->indirect_tabsize = 4 * ITAB_NUM;
-       rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
-       rssp->hashkey_size = HASH_KEYLEN;
-       rssp->hashkey_offset = rssp->indirect_taboffset +
-           rssp->indirect_tabsize;
-
-       /* Set indirection table entries */
-       itab = (uint32_t *)(rssp + 1);
-       for (i = 0; i < ITAB_NUM; i++)
-               itab[i] = i % num_queue;
-
-       /* Set hash key values */
-       keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
-       for (i = 0; i < HASH_KEYLEN; i++)
-               keyp[i] = netvsc_hash_key[i];
-
-       ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
-       if (ret != 0) {
-               goto cleanup;
-       }
-
-       /*
-        * Wait for the response from the host.  Another thread will signal
-        * us when the response has arrived.  In the failure case,
-        * sema_timedwait() returns a non-zero status after waiting 5 seconds.
-        */
-       ret = sema_timedwait(&request->wait_sema, 5 * hz);
-       if (ret == 0) {
-               /* Response received, check status */
-               set_complete = &request->response_msg.msg.set_complete;
-               status = set_complete->status;
-               if (status != RNDIS_STATUS_SUCCESS) {
-                       /* Bad response status, return error */
-                       if (bootverbose)
-                               printf("Netvsc: Failed to set vRSS "
-                                   "parameters.\n");
-                       ret = -2;
-               } else {
-                       if (bootverbose)
-                               printf("Netvsc: Successfully set vRSS "
-                                   "parameters.\n");
-               }
-       } else {
-               /*
-                * We cannot deallocate the request since we may still
-                * receive a send completion for it.
-                */
-               printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
-                   request->request_msg.msg.init_request.request_id, ret);
-               goto exit;
-       }
-
-cleanup:
-       if (request != NULL) {
-               hv_put_rndis_request(device, request);
-       }
-exit:
-       return (ret);
-}
-
-/*
- * RNDIS filter set packet filter
- * Sends an rndis request with the new filter, then waits for a response
- * from the host.
- * Returns zero on success, non-zero on failure.
- */
-static int
-hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
-{
-       rndis_request *request;
-       rndis_set_request *set;
-       rndis_set_complete *set_complete;
-       uint32_t status;
-       int ret;
-
-       request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
-           RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
-       if (request == NULL) {
-               ret = -1;
-               goto cleanup;
-       }
-
-       /* Set up the rndis set */
-       set = &request->request_msg.msg.set_request;
-       set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
-       set->info_buffer_length = sizeof(uint32_t);
-       set->info_buffer_offset = sizeof(rndis_set_request); 
-
-       memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
-           &new_filter, sizeof(uint32_t));
-
-       ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
-       if (ret != 0) {
-               goto cleanup;
-       }
-
-       /*
-        * Wait for the response from the host.  Another thread will signal
-        * us when the response has arrived.  In the failure case,
-        * sema_timedwait() returns a non-zero status after waiting 5 seconds.
-        */
-       ret = sema_timedwait(&request->wait_sema, 5 * hz);
-       if (ret == 0) {
-               /* Response received, check status */
-               set_complete = &request->response_msg.msg.set_complete;
-               status = set_complete->status;
-               if (status != RNDIS_STATUS_SUCCESS) {
-                       /* Bad response status, return error */
-                       ret = -2;
-               }
-       } else {
-               /*
-                * We cannot deallocate the request since we may still
-                * receive a send completion for it.
-                */
-               goto exit;
-       }
-
-cleanup:
-       if (request != NULL) {
-               hv_put_rndis_request(device, request);
-       }
-exit:
-       return (ret);
-}
-
 static const void *
 hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t 
rid,
     size_t reqlen, size_t *comp_len0, uint32_t comp_type)
@@ -1083,6 +778,51 @@ done:
 }
 
 static int
+hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt)
+{
+       struct ndis_rss_caps in, caps;
+       size_t caps_len;
+       int error;
+
+       /*
+        * Only NDIS 6.30+ is supported.
+        */
+       KASSERT(sc->hn_ndis_ver >= NDIS_VERSION_6_30,
+           ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver));
+       *rxr_cnt = 0;
+
+       memset(&in, 0, sizeof(in));
+       in.ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_CAPS;
+       in.ndis_hdr.ndis_rev = NDIS_RSS_CAPS_REV_2;
+       in.ndis_hdr.ndis_size = NDIS_RSS_CAPS_SIZE;
+
+       caps_len = NDIS_RSS_CAPS_SIZE;
+       error = hn_rndis_query(sc, OID_GEN_RECEIVE_SCALE_CAPABILITIES,
+           &in, NDIS_RSS_CAPS_SIZE, &caps, &caps_len);
+       if (error)
+               return (error);
+       if (caps_len < NDIS_RSS_CAPS_SIZE_6_0) {
+               if_printf(sc->hn_ifp, "invalid NDIS RSS caps len %zu",
+                   caps_len);
+               return (EINVAL);
+       }
+
+       if (caps.ndis_nrxr == 0) {
+               if_printf(sc->hn_ifp, "0 RX rings!?\n");
+               return (EINVAL);
+       }
+       *rxr_cnt = caps.ndis_nrxr;
+
+       if (caps_len == NDIS_RSS_CAPS_SIZE) {
+               if (bootverbose) {
+                       if_printf(sc->hn_ifp, "RSS indirect table size %u\n",
+                           caps.ndis_nind);
+               }
+       }
+       return (0);
+}
+
+static int
 hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, size_t dlen)
 {
        struct rndis_set_req *req;
@@ -1172,6 +912,72 @@ hn_rndis_conf_offload(struct hn_softc *s
        return (error);
 }
 
+static int
+hn_rndis_conf_rss(struct hn_softc *sc, int nchan)
+{
+       struct ndis_rssprm_toeplitz *rss = &sc->hn_rss;
+       struct ndis_rss_params *prm = &rss->rss_params;
+       int i, error;
+
+       /*
+        * Only NDIS 6.30+ is supported.
+        */
+       KASSERT(sc->hn_ndis_ver >= NDIS_VERSION_6_30,
+           ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver));
+
+       memset(rss, 0, sizeof(*rss));
+       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_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_indoffset =
+           __offsetof(struct ndis_rssprm_toeplitz, rss_ind[0]);
+       prm->ndis_keysize = sizeof(rss->rss_key);
+       prm->ndis_keyoffset =
+           __offsetof(struct ndis_rssprm_toeplitz, rss_key[0]);
+
+       /* Setup RSS key */
+       memcpy(rss->rss_key, netvsc_hash_key, sizeof(rss->rss_key));
+
+       /* Setup RSS indirect table */
+       /* TODO: Take ndis_rss_caps.ndis_nind into account */
+       for (i = 0; i < NDIS_HASH_INDCNT; ++i)
+               rss->rss_ind[i] = i % nchan;
+
+       error = hn_rndis_set(sc, OID_GEN_RECEIVE_SCALE_PARAMETERS,
+           rss, sizeof(*rss));
+       if (error) {
+               if_printf(sc->hn_ifp, "RSS config failed: %d\n", error);
+       } else {
+               if (bootverbose)
+                       if_printf(sc->hn_ifp, "RSS config done\n");
+       }
+       return (error);
+}
+
+static int
+hn_rndis_set_rxfilter(struct hn_softc *sc, uint32_t filter)
+{
+       int error;
+
+       error = hn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
+           &filter, sizeof(filter));
+       if (error) {
+               if_printf(sc->hn_ifp, "set RX filter 0x%08x failed: %d\n",
+                   filter, error);
+       } else {
+               if (bootverbose) {
+                       if_printf(sc->hn_ifp, "set RX filter 0x%08x done\n",
+                           filter);
+               }
+       }
+       return (error);
+}
+
 /*
  * RNDIS filter init device
  */
@@ -1280,55 +1086,6 @@ hv_rf_halt_device(rndis_device *device)
 }
 
 /*
- * RNDIS filter open device
- */
-static int
-hv_rf_open_device(rndis_device *device)
-{
-       int ret;
-
-       if (device->state != RNDIS_DEV_INITIALIZED) {
-               return (0);
-       }
-
-       if (hv_promisc_mode != 1) {
-               ret = hv_rf_set_packet_filter(device, 
-                   NDIS_PACKET_TYPE_BROADCAST     |
-                   NDIS_PACKET_TYPE_ALL_MULTICAST |
-                   NDIS_PACKET_TYPE_DIRECTED);
-       } else {
-               ret = hv_rf_set_packet_filter(device, 
-                   NDIS_PACKET_TYPE_PROMISCUOUS);
-       }
-
-       if (ret == 0) {
-               device->state = RNDIS_DEV_DATAINITIALIZED;
-       }
-
-       return (ret);
-}
-
-/*
- * RNDIS filter close device
- */
-static int
-hv_rf_close_device(rndis_device *device)
-{
-       int ret;
-
-       if (device->state != RNDIS_DEV_DATAINITIALIZED) {
-               return (0);
-       }
-
-       ret = hv_rf_set_packet_filter(device, 0);
-       if (ret == 0) {
-               device->state = RNDIS_DEV_INITIALIZED;
-       }
-
-       return (ret);
-}
-
-/*
  * RNDIS filter on device add
  */
 int
@@ -1337,8 +1094,6 @@ hv_rf_on_device_add(struct hn_softc *sc,
 {
        int ret;
        rndis_device *rndis_dev;
-       struct rndis_recv_scale_cap rsscaps;
-       uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
        netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
        device_t dev = sc->hn_dev;
        struct hn_nvs_subch_req *req;
@@ -1347,6 +1102,7 @@ hv_rf_on_device_add(struct hn_softc *sc,
        struct vmbus_xact *xact = NULL;
        uint32_t status, nsubch;
        int nchan = *nchan0;
+       int rxr_cnt;
 
        rndis_dev = hv_get_rndis_device();
        if (rndis_dev == NULL) {
@@ -1395,22 +1151,29 @@ hv_rf_on_device_add(struct hn_softc *sc,
        
        dev_info->link_state = rndis_dev->link_status;
 
-       if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
+       if (sc->hn_ndis_ver < NDIS_VERSION_6_30 || nchan == 1) {
+               /*
+                * Either RSS is not supported, or multiple RX/TX rings
+                * are not requested.
+                */
+               *nchan0 = 1;
                return (0);
+       }
 
-       memset(&rsscaps, 0, rsscaps_size);
-       ret = hv_rf_query_device(rndis_dev,
-                       RNDIS_OID_GEN_RSS_CAPABILITIES,
-                       &rsscaps, &rsscaps_size);
-       if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
-               device_printf(dev, "hv_rf_query_device failed or "
-                       "rsscaps.num_recv_que < 2 \n");
-               goto out;
+       /*
+        * Get RSS capabilities, e.g. # of RX rings, and # of indirect
+        * table entries.
+        */
+       ret = hn_rndis_get_rsscaps(sc, &rxr_cnt);
+       if (ret) {
+               /* No RSS; this is benign. */
+               *nchan0 = 1;
+               return (0);
        }
-       device_printf(dev, "channel, offered %u, requested %d\n",
-           rsscaps.num_recv_que, nchan);
-       if (nchan > rsscaps.num_recv_que)
-               nchan = rsscaps.num_recv_que;
+       if (nchan > rxr_cnt)
+               nchan = rxr_cnt;
+       if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n",
+           rxr_cnt, nchan);
 
        if (nchan == 1) {
                device_printf(dev, "only 1 channel is supported, no vRSS\n");
@@ -1467,8 +1230,11 @@ hv_rf_on_device_add(struct hn_softc *sc,
        }
        nchan = nsubch + 1;
 
-       ret = hv_rf_set_rss_param(rndis_dev, nchan);
-       *nchan0 = nchan;
+       ret = hn_rndis_conf_rss(sc, nchan);
+       if (ret != 0)
+               *nchan0 = 1;
+       else
+               *nchan0 = nchan;
 out:
        if (xact != NULL)
                vmbus_xact_put(xact);
@@ -1502,8 +1268,17 @@ hv_rf_on_device_remove(struct hn_softc *
 int
 hv_rf_on_open(struct hn_softc *sc)
 {
+       uint32_t filter;
 
-       return (hv_rf_open_device(sc->rndis_dev));
+       /* XXX */
+       if (hv_promisc_mode != 1) {
+               filter = NDIS_PACKET_TYPE_BROADCAST |
+                   NDIS_PACKET_TYPE_ALL_MULTICAST |
+                   NDIS_PACKET_TYPE_DIRECTED;
+       } else {
+               filter = NDIS_PACKET_TYPE_PROMISCUOUS;
+       }
+       return (hn_rndis_set_rxfilter(sc, filter));
 }
 
 /*
@@ -1513,7 +1288,7 @@ int 
 hv_rf_on_close(struct hn_softc *sc)
 {
 
-       return (hv_rf_close_device(sc->rndis_dev));
+       return (hn_rndis_set_rxfilter(sc, 0));
 }
 
 static void

Modified: stable/11/sys/dev/hyperv/netvsc/ndis.h
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/ndis.h      Mon Oct 17 07:25:46 2016        
(r307489)
+++ stable/11/sys/dev/hyperv/netvsc/ndis.h      Mon Oct 17 07:27:16 2016        
(r307490)
@@ -29,93 +29,178 @@
 #ifndef _NET_NDIS_H_
 #define _NET_NDIS_H_
 
-#define NDIS_MEDIA_STATE_CONNECTED     0
-#define NDIS_MEDIA_STATE_DISCONNECTED  1
+#define        NDIS_MEDIA_STATE_CONNECTED      0
+#define        NDIS_MEDIA_STATE_DISCONNECTED   1
 
-#define OID_TCP_OFFLOAD_PARAMETERS     0xFC01020C
+#define        NDIS_OFFLOAD_SET_NOCHG          0
+#define        NDIS_OFFLOAD_SET_ON             1
+#define        NDIS_OFFLOAD_SET_OFF            2
 
-#define NDIS_OBJTYPE_DEFAULT           0x80
+/* a.k.a GRE MAC */
+#define        NDIS_ENCAP_TYPE_NVGRE           0x00000001
 
-/* common_set */
-#define NDIS_OFFLOAD_SET_NOCHG         0
-#define NDIS_OFFLOAD_SET_ON            1
-#define NDIS_OFFLOAD_SET_OFF           2
+#define        NDIS_HASH_FUNCTION_MASK         0x000000FF      /* see hash 
function */
+#define        NDIS_HASH_TYPE_MASK             0x00FFFF00      /* see hash 
type */
 
-/* a.k.a GRE MAC */
-#define NDIS_ENCAP_TYPE_NVGRE          0x00000001
+/* hash function */
+#define        NDIS_HASH_FUNCTION_TOEPLITZ     0x00000001
+
+/* hash type */
+#define        NDIS_HASH_IPV4                  0x00000100
+#define        NDIS_HASH_TCP_IPV4              0x00000200
+#define        NDIS_HASH_IPV6                  0x00000400
+#define        NDIS_HASH_IPV6_EX               0x00000800
+#define        NDIS_HASH_TCP_IPV6              0x00001000
+#define        NDIS_HASH_TCP_IPV6_EX           0x00002000
+
+#define        NDIS_HASH_KEYSIZE_TOEPLITZ      40
+#define        NDIS_HASH_INDCNT                128
+
+#define        NDIS_OBJTYPE_DEFAULT            0x80
+#define        NDIS_OBJTYPE_RSS_CAPS           0x88
+#define        NDIS_OBJTYPE_RSS_PARAMS         0x89
 
 struct ndis_object_hdr {
-       uint8_t                 ndis_type;              /* NDIS_OBJTYPE_ */
-       uint8_t                 ndis_rev;               /* type specific */
-       uint16_t                ndis_size;              /* incl. this hdr */
+       uint8_t                 ndis_type;      /* NDIS_OBJTYPE_ */
+       uint8_t                 ndis_rev;       /* type specific */
+       uint16_t                ndis_size;      /* incl. this hdr */
 };
 
-/* OID_TCP_OFFLOAD_PARAMETERS */
+/*
+ * OID_TCP_OFFLOAD_PARAMETERS
+ * ndis_type: NDIS_OBJTYPE_DEFAULT
+ */
 struct ndis_offload_params {
        struct ndis_object_hdr  ndis_hdr;
-       uint8_t                 ndis_ip4csum;           /* param_set */
-       uint8_t                 ndis_tcp4csum;          /* param_set */
-       uint8_t                 ndis_udp4csum;          /* param_set */
-       uint8_t                 ndis_tcp6csum;          /* param_set */
-       uint8_t                 ndis_udp6csum;          /* param_set */
-       uint8_t                 ndis_lsov1;             /* lsov1_set */
-       uint8_t                 ndis_ipsecv1;           /* ipsecv1_set */
-       uint8_t                 ndis_lsov2_ip4;         /* lsov2_set */
-       uint8_t                 ndis_lsov2_ip6;         /* lsov2_set */
-       uint8_t                 ndis_tcp4conn;          /* PARAM_NOCHG */
-       uint8_t                 ndis_tcp6conn;          /* PARAM_NOCHG */
-       uint32_t                ndis_flags;             /* 0 */
+       uint8_t                 ndis_ip4csum;   /* NDIS_OFFLOAD_PARAM_ */
+       uint8_t                 ndis_tcp4csum;  /* NDIS_OFFLOAD_PARAM_ */
+       uint8_t                 ndis_udp4csum;  /* NDIS_OFFLOAD_PARAM_ */
+       uint8_t                 ndis_tcp6csum;  /* NDIS_OFFLOAD_PARAM_ */
+       uint8_t                 ndis_udp6csum;  /* NDIS_OFFLOAD_PARAM_ */
+       uint8_t                 ndis_lsov1;     /* NDIS_OFFLOAD_PARAM_ */
+       uint8_t                 ndis_ipsecv1;   /* NDIS_OFFLOAD_IPSECV1_ */
+       uint8_t                 ndis_lsov2_ip4; /* NDIS_OFFLOAD_LSOV2_ */
+       uint8_t                 ndis_lsov2_ip6; /* NDIS_OFFLOAD_LSOV2_ */
+       uint8_t                 ndis_tcp4conn;  /* 0 */
+       uint8_t                 ndis_tcp6conn;  /* 0 */
+       uint32_t                ndis_flags;     /* 0 */
        /* NDIS >= 6.1 */
-       uint8_t                 ndis_ipsecv2;           /* ipsecv2_set */
-       uint8_t                 ndis_ipsecv2_ip4;       /* ipsecv2_set */
+       uint8_t                 ndis_ipsecv2;   /* NDIS_OFFLOAD_IPSECV2_ */
+       uint8_t                 ndis_ipsecv2_ip4;/* NDIS_OFFLOAD_IPSECV2_ */
        /* NDIS >= 6.30 */
-       uint8_t                 ndis_rsc_ip4;           /* rsc_set */
-       uint8_t                 ndis_rsc_ip6;           /* rsc_set */
-       uint8_t                 ndis_encap;             /* common_set */
-       uint8_t                 ndis_encap_types;       /* NDIS_ENCAP_TYPE_ */
+       uint8_t                 ndis_rsc_ip4;   /* NDIS_OFFLOAD_RSC_ */
+       uint8_t                 ndis_rsc_ip6;   /* NDIS_OFFLOAD_RSC_ */
+       uint8_t                 ndis_encap;     /* NDIS_OFFLOAD_SET_ */
+       uint8_t                 ndis_encap_types;/* NDIS_ENCAP_TYPE_ */
 };
 
-#define NDIS_OFFLOAD_PARAMS_SIZE       sizeof(struct ndis_offload_params)
-#define NDIS_OFFLOAD_PARAMS_SIZE_6_1   \
+#define        NDIS_OFFLOAD_PARAMS_SIZE        sizeof(struct 
ndis_offload_params)
+#define        NDIS_OFFLOAD_PARAMS_SIZE_6_1    \
        __offsetof(struct ndis_offload_params, ndis_rsc_ip4)
 
-#define NDIS_OFFLOAD_PARAMS_REV_2      2       /* NDIS 6.1 */
-#define NDIS_OFFLOAD_PARAMS_REV_3      3       /* NDIS 6.30 */
+#define        NDIS_OFFLOAD_PARAMS_REV_2       2       /* NDIS 6.1 */
+#define        NDIS_OFFLOAD_PARAMS_REV_3       3       /* NDIS 6.30 */
 
-/* param_set */
-#define NDIS_OFFLOAD_PARAM_NOCHG       0       /* common to all sets */
-#define NDIS_OFFLOAD_PARAM_OFF         1
-#define NDIS_OFFLOAD_PARAM_TX          2
-#define NDIS_OFFLOAD_PARAM_RX          3
-#define NDIS_OFFLOAD_PARAM_TXRX                4
+#define        NDIS_OFFLOAD_PARAM_NOCHG        0       /* common */
+#define        NDIS_OFFLOAD_PARAM_OFF          1
+#define        NDIS_OFFLOAD_PARAM_TX           2
+#define        NDIS_OFFLOAD_PARAM_RX           3
+#define        NDIS_OFFLOAD_PARAM_TXRX         4
 
-/* lsov1_set */
 /* NDIS_OFFLOAD_PARAM_NOCHG */
-#define NDIS_OFFLOAD_LSOV1_OFF         1
-#define NDIS_OFFLOAD_LSOV1_ON          2
+#define        NDIS_OFFLOAD_LSOV1_OFF          1
+#define        NDIS_OFFLOAD_LSOV1_ON           2
 
-/* ipsecv1_set */
 /* NDIS_OFFLOAD_PARAM_NOCHG */
-#define NDIS_OFFLOAD_IPSECV1_OFF       1
-#define NDIS_OFFLOAD_IPSECV1_AH                2
-#define NDIS_OFFLOAD_IPSECV1_ESP       3
-#define NDIS_OFFLOAD_IPSECV1_AH_ESP    4
+#define        NDIS_OFFLOAD_IPSECV1_OFF        1
+#define        NDIS_OFFLOAD_IPSECV1_AH         2
+#define        NDIS_OFFLOAD_IPSECV1_ESP        3
+#define        NDIS_OFFLOAD_IPSECV1_AH_ESP     4
 
-/* lsov2_set */
 /* NDIS_OFFLOAD_PARAM_NOCHG */
-#define NDIS_OFFLOAD_LSOV2_OFF         1
-#define NDIS_OFFLOAD_LSOV2_ON          2
+#define        NDIS_OFFLOAD_LSOV2_OFF          1
+#define        NDIS_OFFLOAD_LSOV2_ON           2
 
-/* ipsecv2_set */
 /* NDIS_OFFLOAD_PARAM_NOCHG */
-#define NDIS_OFFLOAD_IPSECV2_OFF       1
-#define NDIS_OFFLOAD_IPSECV2_AH                2
-#define NDIS_OFFLOAD_IPSECV2_ESP       3
-#define NDIS_OFFLOAD_IPSECV2_AH_ESP    4
+#define        NDIS_OFFLOAD_IPSECV2_OFF        1
+#define        NDIS_OFFLOAD_IPSECV2_AH         2
+#define        NDIS_OFFLOAD_IPSECV2_ESP        3
+#define        NDIS_OFFLOAD_IPSECV2_AH_ESP     4
 
-/* rsc_set */
 /* NDIS_OFFLOAD_PARAM_NOCHG */
-#define NDIS_OFFLOAD_RSC_OFF           1
-#define NDIS_OFFLOAD_RSC_ON            2
+#define        NDIS_OFFLOAD_RSC_OFF            1
+#define        NDIS_OFFLOAD_RSC_ON             2
+
+/*
+ * OID_GEN_RECEIVE_SCALE_CAPABILITIES
+ * ndis_type: NDIS_OBJTYPE_RSS_CAPS
+ */
+struct ndis_rss_caps {
+       struct ndis_object_hdr          ndis_hdr;
+       uint32_t                        ndis_flags;     /* NDIS_RSS_CAP_ */
+       uint32_t                        ndis_nmsi;      /* # of MSIs */
+       uint32_t                        ndis_nrxr;      /* # of RX rings */
+       /* NDIS >= 6.30 */
+       uint16_t                        ndis_nind;      /* # of indtbl ent. */
+       uint16_t                        ndis_pad;
+};
+
+#define        NDIS_RSS_CAPS_SIZE              \
+       __offsetof(struct ndis_rss_caps, ndis_pad)
+#define        NDIS_RSS_CAPS_SIZE_6_0          \
+       __offsetof(struct ndis_rss_caps, ndis_nind)
+
+#define        NDIS_RSS_CAPS_REV_1             1       /* NDIS 6.{0,1,20} */
+#define        NDIS_RSS_CAPS_REV_2             2       /* NDIS 6.30 */
+
+#define        NDIS_RSS_CAP_MSI                0x01000000
+#define        NDIS_RSS_CAP_CLASSIFY_ISR       0x02000000
+#define        NDIS_RSS_CAP_CLASSIFY_DPC       0x04000000
+#define        NDIS_RSS_CAP_MSIX               0x08000000
+#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
+
+/*
+ * OID_GEN_RECEIVE_SCALE_PARAMETERS
+ * ndis_type: NDIS_OBJTYPE_RSS_PARAMS
+ */
+struct ndis_rss_params {
+       struct ndis_object_hdr          ndis_hdr;
+       uint16_t                        ndis_flags;     /* NDIS_RSS_FLAG_ */
+       uint16_t                        ndis_bcpu;      /* base cpu 0 */
+       uint32_t                        ndis_hash;      /* NDIS_HASH_ */
+       uint16_t                        ndis_indsize;   /* indirect table */
+       uint32_t                        ndis_indoffset;
+       uint16_t                        ndis_keysize;   /* hash key */
+       uint32_t                        ndis_keyoffset;
+       /* NDIS >= 6.20 */
+       uint32_t                        ndis_cpumaskoffset;
+       uint32_t                        ndis_cpumaskcnt;
+       uint32_t                        ndis_cpumaskentsz;
+};
+
+#define        NDIS_RSS_PARAMS_SIZE            sizeof(struct ndis_rss_params)
+#define        NDIS_RSS_PARAMS_SIZE_6_0        \
+       __offsetof(struct ndis_rss_params, ndis_cpumaskoffset)
+
+#define        NDIS_RSS_PARAMS_REV_1           1       /* NDIS 6.0 */
+#define        NDIS_RSS_PARAMS_REV_2           2       /* NDIS 6.20 */
+
+#define        NDIS_RSS_FLAG_BCPU_UNCHG        0x0001
+#define        NDIS_RSS_FLAG_HASH_UNCHG        0x0002
+#define        NDIS_RSS_FLAG_IND_UNCHG         0x0004
+#define        NDIS_RSS_FLAG_KEY_UNCHG         0x0008
+#define        NDIS_RSS_FLAG_DISABLE           0x0010
+
+/* non-standard convenient struct */
+struct ndis_rssprm_toeplitz {
+       struct ndis_rss_params          rss_params;
+       /* Toeplitz hash key */
+       uint8_t                         rss_key[NDIS_HASH_KEYSIZE_TOEPLITZ];
+       /* Indirect table */
+       uint32_t                        rss_ind[NDIS_HASH_INDCNT];
+};
 
 #endif /* !_NET_NDIS_H_ */

Modified: stable/11/sys/dev/usb/net/if_urndis.c
==============================================================================
--- stable/11/sys/dev/usb/net/if_urndis.c       Mon Oct 17 07:25:46 2016        
(r307489)
+++ stable/11/sys/dev/usb/net/if_urndis.c       Mon Oct 17 07:27:16 2016        
(r307490)
@@ -292,8 +292,8 @@ urndis_attach(device_t dev)
        memcpy(&sc->sc_ue.ue_eaddr, buf, ETHER_ADDR_LEN);
 
        /* Initialize packet filter */
-       sc->sc_filter = RNDIS_PACKET_TYPE_BROADCAST |
-           RNDIS_PACKET_TYPE_ALL_MULTICAST;
+       sc->sc_filter = NDIS_PACKET_TYPE_BROADCAST |

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to