svn commit: r304834 - in head/sys: dev/hyperv/netvsc net

Sepherosa Ziehau sephe at FreeBSD.org
Fri Aug 26 05:18:29 UTC 2016


Author: sephe
Date: Fri Aug 26 05:18:27 2016
New Revision: 304834
URL: https://svnweb.freebsd.org/changeset/base/304834

Log:
  hyperv/hn: Use vmbus xact for RNDIS set.
  
  And use new RNDIS set to configure NDIS offloading parameters.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D7641

Added:
  head/sys/dev/hyperv/netvsc/ndis.h   (contents, props changed)
Modified:
  head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
  head/sys/net/rndis.h

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Fri Aug 26 05:15:08 2016	(r304833)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c	Fri Aug 26 05:18:27 2016	(r304834)
@@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/hyperv/netvsc/hv_rndis.h>
 #include <dev/hyperv/netvsc/hv_rndis_filter.h>
 #include <dev/hyperv/netvsc/if_hnreg.h>
+#include <dev/hyperv/netvsc/ndis.h>
 
 #define HV_RF_RECVINFO_VLAN	0x1
 #define HV_RF_RECVINFO_CSUM	0x2
@@ -98,6 +99,9 @@ static void hn_rndis_sent_cb(struct hn_s
     const void *data, int dlen);
 static int hn_rndis_query(struct hn_softc *sc, uint32_t oid,
     const void *idata, size_t idlen, void *odata, size_t *odlen0);
+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 __inline uint32_t
 hn_rndis_rid(struct hn_softc *sc)
@@ -1002,7 +1006,7 @@ hn_rndis_query(struct hn_softc *sc, uint
 	reqlen = sizeof(*req) + idlen;
 	xact = vmbus_xact_get(sc->hn_xact, reqlen);
 	if (xact == NULL) {
-		if_printf(sc->hn_ifp, "no xact for RNDIS query\n");
+		if_printf(sc->hn_ifp, "no xact for RNDIS query 0x%08x\n", oid);
 		return (ENXIO);
 	}
 	rid = hn_rndis_rid(sc);
@@ -1078,6 +1082,96 @@ done:
 	return (error);
 }
 
+static int
+hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, size_t dlen)
+{
+	struct rndis_set_req *req;
+	const struct rndis_set_comp *comp;
+	struct vmbus_xact *xact;
+	size_t reqlen, comp_len;
+	uint32_t rid;
+	int error;
+
+	KASSERT(dlen > 0, ("invalid dlen %zu", dlen));
+
+	reqlen = sizeof(*req) + dlen;
+	xact = vmbus_xact_get(sc->hn_xact, reqlen);
+	if (xact == NULL) {
+		if_printf(sc->hn_ifp, "no xact for RNDIS set 0x%08x\n", oid);
+		return (ENXIO);
+	}
+	rid = hn_rndis_rid(sc);
+	req = vmbus_xact_req_data(xact);
+	req->rm_type = REMOTE_NDIS_SET_MSG;
+	req->rm_len = reqlen;
+	req->rm_rid = rid;
+	req->rm_oid = oid;
+	req->rm_infobuflen = dlen;
+	req->rm_infobufoffset = RNDIS_SET_REQ_INFOBUFOFFSET;
+	/* Data immediately follows RNDIS set. */
+	memcpy(req + 1, data, dlen);
+
+	comp_len = sizeof(*comp);
+	comp = hn_rndis_xact_execute(sc, xact, rid, reqlen, &comp_len,
+	    REMOTE_NDIS_SET_CMPLT);
+	if (comp == NULL) {
+		if_printf(sc->hn_ifp, "exec RNDIS set 0x%08x failed\n", oid);
+		error = EIO;
+		goto done;
+	}
+
+	if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
+		if_printf(sc->hn_ifp, "RNDIS set 0x%08x failed: "
+		    "status 0x%08x\n", oid, comp->rm_status);
+		error = EIO;
+		goto done;
+	}
+	error = 0;
+done:
+	vmbus_xact_put(xact);
+	return (error);
+}
+
+static int
+hn_rndis_conf_offload(struct hn_softc *sc)
+{
+	struct ndis_offload_params params;
+	size_t paramsz;
+	int error;
+
+	/* NOTE: 0 means "no change" */
+	memset(&params, 0, sizeof(params));
+
+	params.ndis_hdr.ndis_type = NDIS_OBJTYPE_DEFAULT;
+	if (sc->hn_ndis_ver < NDIS_VERSION_6_30) {
+		params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_2;
+		paramsz = NDIS_OFFLOAD_PARAMS_SIZE_6_1;
+	} else {
+		params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_3;
+		paramsz = NDIS_OFFLOAD_PARAMS_SIZE;
+	}
+	params.ndis_hdr.ndis_size = paramsz;
+
+	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 >= NDIS_VERSION_6_30) {
+		params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX;
+		params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX;
+	}
+	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);
+}
+
 /*
  * RNDIS filter init device
  */
@@ -1243,7 +1337,6 @@ hv_rf_on_device_add(struct hn_softc *sc,
 {
 	int ret;
 	rndis_device *rndis_dev;
-	rndis_offload_params offloads;
 	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;
@@ -1293,21 +1386,8 @@ hv_rf_on_device_add(struct hn_softc *sc,
 		/* TODO: shut down rndis device and the channel */
 	}
 
-	/* config csum offload and send request to host */
-	memset(&offloads, 0, sizeof(offloads));
-	offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
-	offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
-	offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
-	offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
-	offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
-	offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
-
-	ret = hv_rf_send_offload_request(sc, &offloads);
-	if (ret != 0) {
-		/* TODO: shut down rndis device and the channel */
-		device_printf(dev,
-		    "hv_rf_send_offload_request failed, ret=%d\n", ret);
-	}
+	/* Configure NDIS offload settings */
+	hn_rndis_conf_offload(sc);
 	
 	memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
 

Added: head/sys/dev/hyperv/netvsc/ndis.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/hyperv/netvsc/ndis.h	Fri Aug 26 05:18:27 2016	(r304834)
@@ -0,0 +1,118 @@
+/*-
+ * Copyright (c) 2016 Microsoft Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NET_NDIS_H_
+#define _NET_NDIS_H_
+
+#define OID_TCP_OFFLOAD_PARAMETERS	0xFC01020C
+
+#define NDIS_OBJTYPE_DEFAULT		0x80
+
+/* common_set */
+#define NDIS_OFFLOAD_SET_NOCHG		0
+#define NDIS_OFFLOAD_SET_ON		1
+#define NDIS_OFFLOAD_SET_OFF		2
+
+/* a.k.a GRE MAC */
+#define NDIS_ENCAP_TYPE_NVGRE		0x00000001
+
+struct ndis_object_hdr {
+	uint8_t			ndis_type;		/* NDIS_OBJTYPE_ */
+	uint8_t			ndis_rev;		/* type specific */
+	uint16_t		ndis_size;		/* incl. this hdr */
+};
+
+/* OID_TCP_OFFLOAD_PARAMETERS */
+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 */
+	/* NDIS >= 6.1 */
+	uint8_t			ndis_ipsecv2;		/* ipsecv2_set */
+	uint8_t			ndis_ipsecv2_ip4;	/* ipsecv2_set */
+	/* 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_ */
+};
+
+#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 */
+
+/* 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
+
+/* lsov1_set */
+/* NDIS_OFFLOAD_PARAM_NOCHG */
+#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
+
+/* lsov2_set */
+/* NDIS_OFFLOAD_PARAM_NOCHG */
+#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
+
+/* rsc_set */
+/* NDIS_OFFLOAD_PARAM_NOCHG */
+#define NDIS_OFFLOAD_RSC_OFF		1
+#define NDIS_OFFLOAD_RSC_ON		2
+
+#endif	/* !_NET_NDIS_H_ */

Modified: head/sys/net/rndis.h
==============================================================================
--- head/sys/net/rndis.h	Fri Aug 26 05:15:08 2016	(r304833)
+++ head/sys/net/rndis.h	Fri Aug 26 05:18:27 2016	(r304834)
@@ -202,6 +202,10 @@ struct rndis_set_req {
 	uint32_t rm_devicevchdl;
 };
 
+#define	RNDIS_SET_REQ_INFOBUFOFFSET		\
+	(sizeof(struct rndis_set_req) -		\
+	 __offsetof(struct rndis_set_req, rm_rid))
+
 struct rndis_set_comp {
 	uint32_t rm_type;
 	uint32_t rm_len;


More information about the svn-src-all mailing list