Page MenuHomeFreeBSD

D8088.diff
No OneTemporary

D8088.diff

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(&params, 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, &params, 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

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)

Event Timeline