Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F109249375
D8088.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D8088.diff
View Options
Index: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
===================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
@@ -68,6 +68,16 @@
#define HN_RNDIS_XFER_SIZE 2048
+#define HN_NDIS_TXCSUM_CAP_IP4 \
+ (NDIS_TXCSUM_CAP_IP4 | NDIS_TXCSUM_CAP_IP4OPT)
+#define HN_NDIS_TXCSUM_CAP_TCP4 \
+ (NDIS_TXCSUM_CAP_TCP4 | NDIS_TXCSUM_CAP_TCP4OPT)
+#define HN_NDIS_TXCSUM_CAP_TCP6 \
+ (NDIS_TXCSUM_CAP_TCP6 | NDIS_TXCSUM_CAP_TCP6OPT | \
+ NDIS_TXCSUM_CAP_IP6EXT)
+#define HN_NDIS_TXCSUM_CAP_UDP6 \
+ (NDIS_TXCSUM_CAP_UDP6 | NDIS_TXCSUM_CAP_IP6EXT)
+
/*
* Forward declarations
*/
@@ -78,9 +88,14 @@
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_query2(struct hn_softc *sc, uint32_t oid,
+ const void *idata, size_t idlen, void *odata, size_t *odlen0,
+ size_t min_odlen);
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_query_hwcaps(struct hn_softc *sc,
+ struct ndis_offload *caps);
static __inline uint32_t
hn_rndis_rid(struct hn_softc *sc)
@@ -624,6 +639,15 @@
hn_rndis_query(struct hn_softc *sc, uint32_t oid,
const void *idata, size_t idlen, void *odata, size_t *odlen0)
{
+
+ return (hn_rndis_query2(sc, oid, idata, idlen, odata, odlen0, *odlen0));
+}
+
+static int
+hn_rndis_query2(struct hn_softc *sc, uint32_t oid,
+ const void *idata, size_t idlen, void *odata, size_t *odlen0,
+ size_t min_odlen)
+{
struct rndis_query_req *req;
const struct rndis_query_comp *comp;
struct vmbus_xact *xact;
@@ -661,7 +685,7 @@
memcpy(req + 1, idata, idlen);
}
- comp_len = sizeof(*comp) + odlen;
+ comp_len = sizeof(*comp) + min_odlen;
comp = hn_rndis_xact_execute(sc, xact, rid, reqlen, &comp_len,
REMOTE_NDIS_QUERY_CMPLT);
if (comp == NULL) {
@@ -808,11 +832,18 @@
static int
hn_rndis_conf_offload(struct hn_softc *sc)
{
+ struct ndis_offload hwcaps;
struct ndis_offload_params params;
- uint32_t caps;
+ uint32_t caps = 0;
size_t paramsz;
int error;
+ error = hn_rndis_query_hwcaps(sc, &hwcaps);
+ if (error) {
+ if_printf(sc->hn_ifp, "hwcaps query failed: %d\n", error);
+ return (error);
+ }
+
/* NOTE: 0 means "no change" */
memset(¶ms, 0, sizeof(params));
@@ -826,18 +857,96 @@
}
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 */
+ /* TSO */
+ if (hwcaps.ndis_lsov2.ndis_ip4_encap & NDIS_OFFLOAD_ENCAP_8023) {
+ caps |= HN_CAP_TSO4;
+ params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_ON;
+ /* TODO: tso_max */
+ }
+ if (hwcaps.ndis_lsov2.ndis_ip6_encap & NDIS_OFFLOAD_ENCAP_8023) {
+#ifdef notyet
+ caps |= HN_CAP_TSO6;
+ params.ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_ON;
+#endif
+ /* TODO: tso_max */
+ }
+
+ /* IPv4 checksum */
+ if ((hwcaps.ndis_csum.ndis_ip4_txcsum & HN_NDIS_TXCSUM_CAP_IP4) ==
+ HN_NDIS_TXCSUM_CAP_IP4) {
+ caps |= HN_CAP_IPCS;
+ params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TX;
+ }
+ if (hwcaps.ndis_csum.ndis_ip4_rxcsum & NDIS_RXCSUM_CAP_IP4) {
+ if (params.ndis_ip4csum == NDIS_OFFLOAD_PARAM_TX)
+ params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX;
+ else
+ params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_RX;
+ }
+
+ /* TCP4 checksum */
+ if ((hwcaps.ndis_csum.ndis_ip4_txcsum & HN_NDIS_TXCSUM_CAP_TCP4) ==
+ HN_NDIS_TXCSUM_CAP_TCP4) {
+ caps |= HN_CAP_TCP4CS;
+ params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TX;
+ }
+ if (hwcaps.ndis_csum.ndis_ip4_rxcsum & NDIS_RXCSUM_CAP_TCP4) {
+ if (params.ndis_tcp4csum == NDIS_OFFLOAD_PARAM_TX)
+ params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX;
+ else
+ params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_RX;
+ }
+
+ /* UDP4 checksum */
+ if (hwcaps.ndis_csum.ndis_ip4_txcsum & NDIS_TXCSUM_CAP_UDP4) {
+ caps |= HN_CAP_UDP4CS;
+ params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TX;
+ }
+ if (hwcaps.ndis_csum.ndis_ip4_rxcsum & NDIS_RXCSUM_CAP_UDP4) {
+ if (params.ndis_udp4csum == NDIS_OFFLOAD_PARAM_TX)
+ params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX;
+ else
+ params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_RX;
+ }
+
+ /* TCP6 checksum */
+ if ((hwcaps.ndis_csum.ndis_ip6_txcsum & HN_NDIS_TXCSUM_CAP_TCP6) ==
+ HN_NDIS_TXCSUM_CAP_TCP6) {
+ caps |= HN_CAP_TCP6CS;
+ params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TX;
+ }
+ if (hwcaps.ndis_csum.ndis_ip6_rxcsum & NDIS_RXCSUM_CAP_TCP6) {
+ if (params.ndis_tcp6csum == NDIS_OFFLOAD_PARAM_TX)
+ params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX;
+ else
+ params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_RX;
+ }
+
+ /* UDP6 checksum */
+ if ((hwcaps.ndis_csum.ndis_ip6_txcsum & HN_NDIS_TXCSUM_CAP_UDP6) ==
+ HN_NDIS_TXCSUM_CAP_UDP6) {
+ caps |= HN_CAP_UDP6CS;
+ params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TX;
+ }
+ if (hwcaps.ndis_csum.ndis_ip6_rxcsum & NDIS_RXCSUM_CAP_UDP6) {
+ if (params.ndis_udp6csum == NDIS_OFFLOAD_PARAM_TX)
+ params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX;
+ else
+ params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_RX;
+ }
+
+ if (bootverbose) {
+ if_printf(sc->hn_ifp, "offload csum: "
+ "ip4 %u, tcp4 %u, udp4 %u, tcp6 %u, udp6 %u\n",
+ params.ndis_ip4csum,
+ params.ndis_tcp4csum,
+ params.ndis_udp4csum,
+ params.ndis_tcp6csum,
+ params.ndis_udp6csum);
+ if_printf(sc->hn_ifp, "offload lsov2: ip4 %u, ip6 %u\n",
+ params.ndis_lsov2_ip4,
+ params.ndis_lsov2_ip6);
+ }
error = hn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, ¶ms, paramsz);
if (error) {
@@ -994,6 +1103,88 @@
return (0);
}
+static int
+hn_rndis_query_hwcaps(struct hn_softc *sc, struct ndis_offload *caps)
+{
+ struct ndis_offload in;
+ size_t caps_len, size;
+ int error;
+
+ memset(&in, 0, sizeof(in));
+ in.ndis_hdr.ndis_type = NDIS_OBJTYPE_OFFLOAD;
+ if (sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30) {
+ in.ndis_hdr.ndis_rev = NDIS_OFFLOAD_REV_3;
+ size = NDIS_OFFLOAD_SIZE;
+ } else if (sc->hn_ndis_ver >= HN_NDIS_VERSION_6_1) {
+ in.ndis_hdr.ndis_rev = NDIS_OFFLOAD_REV_2;
+ size = NDIS_OFFLOAD_SIZE_2;
+ } else {
+ in.ndis_hdr.ndis_rev = NDIS_OFFLOAD_REV_1;
+ size = NDIS_OFFLOAD_SIZE_1;
+ }
+ in.ndis_hdr.ndis_size = size;
+
+ caps_len = NDIS_OFFLOAD_SIZE;
+ error = hn_rndis_query2(sc, OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES,
+ &in, size, caps, &caps_len, NDIS_OFFLOAD_SIZE_1);
+ if (error)
+ return (error);
+
+ /*
+ * Preliminary verification.
+ */
+ if (caps->ndis_hdr.ndis_type != NDIS_OBJTYPE_OFFLOAD) {
+ if_printf(sc->hn_ifp, "invalid NDIS objtype 0x%02x\n",
+ caps->ndis_hdr.ndis_type);
+ return (EINVAL);
+ }
+ if (caps->ndis_hdr.ndis_rev < NDIS_OFFLOAD_REV_1) {
+ if_printf(sc->hn_ifp, "invalid NDIS objrev 0x%02x\n",
+ caps->ndis_hdr.ndis_rev);
+ return (EINVAL);
+ }
+ if (caps->ndis_hdr.ndis_size > caps_len) {
+ if_printf(sc->hn_ifp, "invalid NDIS objsize %u, "
+ "data size %zu\n", caps->ndis_hdr.ndis_size, caps_len);
+ return (EINVAL);
+ } else if (caps->ndis_hdr.ndis_size < NDIS_OFFLOAD_SIZE_1) {
+ if_printf(sc->hn_ifp, "invalid NDIS objsize %u\n",
+ caps->ndis_hdr.ndis_size);
+ return (EINVAL);
+ }
+
+ if (bootverbose) {
+ /*
+ * Fields for NDIS 6.0 are accessable.
+ */
+ if_printf(sc->hn_ifp, "hwcaps rev %u\n",
+ caps->ndis_hdr.ndis_rev);
+
+ if_printf(sc->hn_ifp, "hwcaps csum: "
+ "ip4 tx 0x%x/0x%x rx 0x%x/0x%x, "
+ "ip6 tx 0x%x/0x%x rx 0x%x/0x%x\n",
+ caps->ndis_csum.ndis_ip4_txcsum,
+ caps->ndis_csum.ndis_ip4_txenc,
+ caps->ndis_csum.ndis_ip4_rxcsum,
+ caps->ndis_csum.ndis_ip4_rxenc,
+ caps->ndis_csum.ndis_ip6_txcsum,
+ caps->ndis_csum.ndis_ip6_txenc,
+ caps->ndis_csum.ndis_ip6_rxcsum,
+ caps->ndis_csum.ndis_ip6_rxenc);
+ if_printf(sc->hn_ifp, "hwcaps lsov2: "
+ "ip4 maxsz %u minsg %u encap 0x%x, "
+ "ip6 maxsz %u minsg %u encap 0x%x opts 0x%x\n",
+ caps->ndis_lsov2.ndis_ip4_maxsz,
+ caps->ndis_lsov2.ndis_ip4_minsg,
+ caps->ndis_lsov2.ndis_ip4_encap,
+ caps->ndis_lsov2.ndis_ip6_maxsz,
+ caps->ndis_lsov2.ndis_ip6_minsg,
+ caps->ndis_lsov2.ndis_ip6_encap,
+ caps->ndis_lsov2.ndis_ip6_opts);
+ }
+ return (0);
+}
+
int
hn_rndis_attach(struct hn_softc *sc)
{
Index: head/sys/dev/hyperv/netvsc/ndis.h
===================================================================
--- head/sys/dev/hyperv/netvsc/ndis.h
+++ head/sys/dev/hyperv/netvsc/ndis.h
@@ -59,6 +59,7 @@
#define NDIS_OBJTYPE_DEFAULT 0x80
#define NDIS_OBJTYPE_RSS_CAPS 0x88
#define NDIS_OBJTYPE_RSS_PARAMS 0x89
+#define NDIS_OBJTYPE_OFFLOAD 0xa7
struct ndis_object_hdr {
uint8_t ndis_type; /* NDIS_OBJTYPE_ */
@@ -205,6 +206,129 @@
};
/*
+ * OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES
+ * ndis_type: NDIS_OBJTYPE_OFFLOAD
+ */
+
+#define NDIS_OFFLOAD_ENCAP_NONE 0x0000
+#define NDIS_OFFLOAD_ENCAP_NULL 0x0001
+#define NDIS_OFFLOAD_ENCAP_8023 0x0002
+#define NDIS_OFFLOAD_ENCAP_8023PQ 0x0004
+#define NDIS_OFFLOAD_ENCAP_8023PQ_OOB 0x0008
+#define NDIS_OFFLOAD_ENCAP_RFC1483 0x0010
+
+struct ndis_csum_offload {
+ uint32_t ndis_ip4_txenc; /*NDIS_OFFLOAD_ENCAP_*/
+ uint32_t ndis_ip4_txcsum;
+#define NDIS_TXCSUM_CAP_IP4OPT 0x001
+#define NDIS_TXCSUM_CAP_TCP4OPT 0x004
+#define NDIS_TXCSUM_CAP_TCP4 0x010
+#define NDIS_TXCSUM_CAP_UDP4 0x040
+#define NDIS_TXCSUM_CAP_IP4 0x100
+ uint32_t ndis_ip4_rxenc; /*NDIS_OFFLOAD_ENCAP_*/
+ uint32_t ndis_ip4_rxcsum;
+#define NDIS_RXCSUM_CAP_IP4OPT 0x001
+#define NDIS_RXCSUM_CAP_TCP4OPT 0x004
+#define NDIS_RXCSUM_CAP_TCP4 0x010
+#define NDIS_RXCSUM_CAP_UDP4 0x040
+#define NDIS_RXCSUM_CAP_IP4 0x100
+ uint32_t ndis_ip6_txenc; /*NDIS_OFFLOAD_ENCAP_*/
+ uint32_t ndis_ip6_txcsum;
+#define NDIS_TXCSUM_CAP_IP6EXT 0x001
+#define NDIS_TXCSUM_CAP_TCP6OPT 0x004
+#define NDIS_TXCSUM_CAP_TCP6 0x010
+#define NDIS_TXCSUM_CAP_UDP6 0x040
+ uint32_t ndis_ip6_rxenc; /*NDIS_OFFLOAD_ENCAP_*/
+ uint32_t ndis_ip6_rxcsum;
+#define NDIS_RXCSUM_CAP_IP6EXT 0x001
+#define NDIS_RXCSUM_CAP_TCP6OPT 0x004
+#define NDIS_RXCSUM_CAP_TCP6 0x010
+#define NDIS_RXCSUM_CAP_UDP6 0x040
+};
+
+struct ndis_lsov1_offload {
+ uint32_t ndis_encap; /*NDIS_OFFLOAD_ENCAP_*/
+ uint32_t ndis_maxsize;
+ uint32_t ndis_minsegs;
+ uint32_t ndis_opts;
+};
+
+struct ndis_ipsecv1_offload {
+ uint32_t ndis_encap; /*NDIS_OFFLOAD_ENCAP_*/
+ uint32_t ndis_ah_esp;
+ uint32_t ndis_xport_tun;
+ uint32_t ndis_ip4_opts;
+ uint32_t ndis_flags;
+ uint32_t ndis_ip4_ah;
+ uint32_t ndis_ip4_esp;
+};
+
+struct ndis_lsov2_offload {
+ uint32_t ndis_ip4_encap; /*NDIS_OFFLOAD_ENCAP_*/
+ uint32_t ndis_ip4_maxsz;
+ uint32_t ndis_ip4_minsg;
+ uint32_t ndis_ip6_encap; /*NDIS_OFFLOAD_ENCAP_*/
+ uint32_t ndis_ip6_maxsz;
+ uint32_t ndis_ip6_minsg;
+ uint32_t ndis_ip6_opts;
+#define NDIS_LSOV2_CAP_IP6EXT 0x001
+#define NDIS_LSOV2_CAP_TCP6OPT 0x004
+};
+
+struct ndis_ipsecv2_offload {
+ uint32_t ndis_encap; /*NDIS_OFFLOAD_ENCAP_*/
+ uint16_t ndis_ip6;
+ uint16_t ndis_ip4opt;
+ uint16_t ndis_ip6ext;
+ uint16_t ndis_ah;
+ uint16_t ndis_esp;
+ uint16_t ndis_ah_esp;
+ uint16_t ndis_xport;
+ uint16_t ndis_tun;
+ uint16_t ndis_xport_tun;
+ uint16_t ndis_lso;
+ uint16_t ndis_extseq;
+ uint32_t ndis_udp_esp;
+ uint32_t ndis_auth;
+ uint32_t ndis_crypto;
+ uint32_t ndis_sa_caps;
+};
+
+struct ndis_rsc_offload {
+ uint16_t ndis_ip4;
+ uint16_t ndis_ip6;
+};
+
+struct ndis_encap_offload {
+ uint32_t ndis_flags;
+ uint32_t ndis_maxhdr;
+};
+
+struct ndis_offload {
+ struct ndis_object_hdr ndis_hdr;
+ struct ndis_csum_offload ndis_csum;
+ struct ndis_lsov1_offload ndis_lsov1;
+ struct ndis_ipsecv1_offload ndis_ipsecv1;
+ struct ndis_lsov2_offload ndis_lsov2;
+ uint32_t ndis_flags;
+ /* NDIS >= 6.1 */
+ struct ndis_ipsecv2_offload ndis_ipsecv2;
+ /* NDIS >= 6.30 */
+ struct ndis_rsc_offload ndis_rsc;
+ struct ndis_encap_offload ndis_encap_gre;
+};
+
+#define NDIS_OFFLOAD_SIZE sizeof(struct ndis_offload)
+#define NDIS_OFFLOAD_SIZE_1 \
+ __offsetof(struct ndis_offload, ndis_ipsecv2)
+#define NDIS_OFFLOAD_SIZE_2 \
+ __offsetof(struct ndis_offload, ndis_rsc)
+
+#define NDIS_OFFLOAD_REV_1 1 /* NDIS 6.0 */
+#define NDIS_OFFLOAD_REV_2 2 /* NDIS 6.1 */
+#define NDIS_OFFLOAD_REV_3 3 /* NDIS 6.30 */
+
+/*
* Per-packet-info
*/
Index: head/sys/net/rndis.h
===================================================================
--- head/sys/net/rndis.h
+++ head/sys/net/rndis.h
@@ -87,6 +87,7 @@
#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C
+#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D
#define RNDIS_MEDIUM_802_3 0x00000000
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 3, 2:48 PM (20 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16436292
Default Alt Text
D8088.diff (12 KB)
Attached To
Mode
D8088: hyperv/hn: Fix checksum offload settings
Attached
Detach File
Event Timeline
Log In to Comment