From owner-svn-src-head@freebsd.org Mon Aug 29 05:35:37 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 25320BC5EC3; Mon, 29 Aug 2016 05:35:37 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C9F8E164; Mon, 29 Aug 2016 05:35:36 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u7T5Zaoa054163; Mon, 29 Aug 2016 05:35:36 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u7T5ZZ6g054159; Mon, 29 Aug 2016 05:35:35 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201608290535.u7T5ZZ6g054159@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Mon, 29 Aug 2016 05:35:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r304979 - head/sys/dev/hyperv/netvsc X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Aug 2016 05:35:37 -0000 Author: sephe Date: Mon Aug 29 05:35:35 2016 New Revision: 304979 URL: https://svnweb.freebsd.org/changeset/base/304979 Log: hyperv/hn: Switch to new RNDIS set for RSS parameters. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D7658 Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h head/sys/dev/hyperv/netvsc/hv_rndis.h head/sys/dev/hyperv/netvsc/hv_rndis_filter.c head/sys/dev/hyperv/netvsc/ndis.h Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- head/sys/dev/hyperv/netvsc/hv_net_vsc.h Mon Aug 29 05:17:44 2016 (r304978) +++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h Mon Aug 29 05:35:35 2016 (r304979) @@ -62,6 +62,8 @@ #include #include +#include + #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: head/sys/dev/hyperv/netvsc/hv_rndis.h ============================================================================== --- head/sys/dev/hyperv/netvsc/hv_rndis.h Mon Aug 29 05:17:44 2016 (r304978) +++ head/sys/dev/hyperv/netvsc/hv_rndis.h Mon Aug 29 05:35:35 2016 (r304979) @@ -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 { Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c ============================================================================== --- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c Mon Aug 29 05:17:44 2016 (r304978) +++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c Mon Aug 29 05:35:35 2016 (r304979) @@ -101,6 +101,7 @@ static int hn_rndis_set(struct hn_softc 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) @@ -670,7 +671,7 @@ hv_rf_query_device_link_status(rndis_dev 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, @@ -679,106 +680,6 @@ static uint8_t netvsc_hash_key[HASH_KEYL }; /* - * 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. @@ -1155,6 +1056,52 @@ 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_RSS_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); +} + /* * RNDIS filter init device */ @@ -1456,8 +1403,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); Modified: head/sys/dev/hyperv/netvsc/ndis.h ============================================================================== --- head/sys/dev/hyperv/netvsc/ndis.h Mon Aug 29 05:17:44 2016 (r304978) +++ head/sys/dev/hyperv/netvsc/ndis.h Mon Aug 29 05:35:35 2016 (r304979) @@ -33,10 +33,12 @@ #define NDIS_MEDIA_STATE_DISCONNECTED 1 #define OID_GEN_RSS_CAPABILITIES 0x00010203 +#define OID_GEN_RSS_PARAMETERS 0x00010204 #define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C #define NDIS_OBJTYPE_DEFAULT 0x80 #define NDIS_OBJTYPE_RSS_CAPS 0x88 +#define NDIS_OBJTYPE_RSS_PARAMS 0x89 /* common_set */ #define NDIS_OFFLOAD_SET_NOCHG 0 @@ -46,6 +48,23 @@ /* a.k.a GRE MAC */ #define NDIS_ENCAP_TYPE_NVGRE 0x00000001 +#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 + +#define NDIS_HASH_KEYSIZE_TOEPLITZ 40 +#define NDIS_HASH_INDCNT 128 + struct ndis_object_hdr { uint8_t ndis_type; /* NDIS_OBJTYPE_ */ uint8_t ndis_rev; /* type specific */ @@ -154,4 +173,45 @@ struct ndis_rss_caps { #define NDIS_RSS_CAP_IPV6_EX 0x00000400 #define NDIS_RSS_CAP_HASH_TOEPLITZ 0x00000001 +/* + * OID_GEN_RSS_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_ */