Date: Fri, 28 Oct 2016 08:08:46 +0000 (UTC) From: Sepherosa Ziehau <sephe@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r308014 - head/sys/dev/hyperv/netvsc Message-ID: <201610280808.u9S88kpv023116@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: sephe Date: Fri Oct 28 08:08:46 2016 New Revision: 308014 URL: https://svnweb.freebsd.org/changeset/base/308014 Log: hyperv/hn: Reorganize RX path; mainly pull non-control code path up MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8356 Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c head/sys/dev/hyperv/netvsc/hv_rndis_filter.c head/sys/dev/hyperv/netvsc/hv_rndis_filter.h head/sys/dev/hyperv/netvsc/if_hnvar.h Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Fri Oct 28 07:59:02 2016 (r308013) +++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Fri Oct 28 08:08:46 2016 (r308014) @@ -166,6 +166,16 @@ __FBSDID("$FreeBSD$"); #define HN_EARLY_TXEOF_THRESH 8 +#define HN_RXINFO_VLAN 0x0001 +#define HN_RXINFO_CSUM 0x0002 +#define HN_RXINFO_HASHINF 0x0004 +#define HN_RXINFO_HASHVAL 0x0008 +#define HN_RXINFO_ALL \ + (HN_RXINFO_VLAN | \ + HN_RXINFO_CSUM | \ + HN_RXINFO_HASHINF | \ + HN_RXINFO_HASHVAL) + struct hn_txdesc { #ifndef HN_USE_TXDESC_BUFRING SLIST_ENTRY(hn_txdesc) link; @@ -188,6 +198,17 @@ struct hn_txdesc { #define HN_TXD_FLAG_ONLIST 0x1 #define HN_TXD_FLAG_DMAMAP 0x2 +#define HN_NDIS_VLAN_INFO_INVALID 0xffffffff +#define HN_NDIS_RXCSUM_INFO_INVALID 0 +#define HN_NDIS_HASH_INFO_INVALID 0 + +struct hn_rxinfo { + uint32_t vlan_info; + uint32_t csum_info; + uint32_t hash_info; + uint32_t hash_value; +}; + #define HN_LRO_LENLIM_MULTIRX_DEF (12 * ETHERMTU) #define HN_LRO_LENLIM_DEF (25 * ETHERMTU) /* YYY 2*MTU is a bit rough, but should be good enough. */ @@ -377,12 +398,18 @@ static void hn_link_status(struct hn_sof static int hn_sendpkt_rndis_sglist(struct hn_tx_ring *, struct hn_txdesc *); static int hn_sendpkt_rndis_chim(struct hn_tx_ring *, struct hn_txdesc *); static int hn_set_rxfilter(struct hn_softc *); +static void hn_link_status_update(struct hn_softc *); +static void hn_network_change(struct hn_softc *); + +static int hn_rndis_rxinfo(const void *, int, struct hn_rxinfo *); +static void hn_rndis_rx_data(struct hn_rx_ring *, const void *, int); +static void hn_rndis_rx_status(struct hn_softc *, const void *, int); static void hn_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt); static void hn_nvs_handle_comp(struct hn_softc *sc, struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkt); -static void hn_nvs_handle_rxbuf(struct hn_softc *sc, struct hn_rx_ring *rxr, +static void hn_nvs_handle_rxbuf(struct hn_rx_ring *rxr, struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr); static void hn_nvs_ack_rxbuf(struct vmbus_channel *chan, uint64_t tid); @@ -1006,7 +1033,7 @@ hn_netchg_status_taskfunc(void *xsc, int hn_link_status(sc); } -void +static void hn_link_status_update(struct hn_softc *sc) { @@ -1014,7 +1041,7 @@ hn_link_status_update(struct hn_softc *s taskqueue_enqueue(sc->hn_mgmt_taskq, &sc->hn_link_task); } -void +static void hn_network_change(struct hn_softc *sc) { @@ -1615,15 +1642,9 @@ hn_lro_rx(struct lro_ctrl *lc, struct mb } #endif -/* - * Called when we receive a data packet from the "wire" on the - * specified device - * - * Note: This is no longer used as a callback - */ -int +static int hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen, - const struct hn_recvinfo *info) + const struct hn_rxinfo *info) { struct ifnet *ifp = rxr->hn_ifp; struct mbuf *m_new; @@ -4025,6 +4046,325 @@ hn_resume(struct hn_softc *sc) hn_resume_mgmt(sc); } +static void +hn_rndis_rx_status(struct hn_softc *sc, const void *data, int dlen) +{ + const struct rndis_status_msg *msg; + int ofs; + + if (dlen < sizeof(*msg)) { + if_printf(sc->hn_ifp, "invalid RNDIS status\n"); + return; + } + msg = data; + + switch (msg->rm_status) { + case RNDIS_STATUS_MEDIA_CONNECT: + case RNDIS_STATUS_MEDIA_DISCONNECT: + hn_link_status_update(sc); + break; + + case RNDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG: + /* Not really useful; ignore. */ + break; + + case RNDIS_STATUS_NETWORK_CHANGE: + ofs = RNDIS_STBUFOFFSET_ABS(msg->rm_stbufoffset); + if (dlen < ofs + msg->rm_stbuflen || + msg->rm_stbuflen < sizeof(uint32_t)) { + if_printf(sc->hn_ifp, "network changed\n"); + } else { + uint32_t change; + + memcpy(&change, ((const uint8_t *)msg) + ofs, + sizeof(change)); + if_printf(sc->hn_ifp, "network changed, change %u\n", + change); + } + hn_network_change(sc); + break; + + default: + if_printf(sc->hn_ifp, "unknown RNDIS status 0x%08x\n", + msg->rm_status); + break; + } +} + +static int +hn_rndis_rxinfo(const void *info_data, int info_dlen, struct hn_rxinfo *info) +{ + const struct rndis_pktinfo *pi = info_data; + uint32_t mask = 0; + + while (info_dlen != 0) { + const void *data; + uint32_t dlen; + + if (__predict_false(info_dlen < sizeof(*pi))) + return (EINVAL); + if (__predict_false(info_dlen < pi->rm_size)) + return (EINVAL); + info_dlen -= pi->rm_size; + + if (__predict_false(pi->rm_size & RNDIS_PKTINFO_SIZE_ALIGNMASK)) + return (EINVAL); + if (__predict_false(pi->rm_size < pi->rm_pktinfooffset)) + return (EINVAL); + dlen = pi->rm_size - pi->rm_pktinfooffset; + data = pi->rm_data; + + switch (pi->rm_type) { + case NDIS_PKTINFO_TYPE_VLAN: + if (__predict_false(dlen < NDIS_VLAN_INFO_SIZE)) + return (EINVAL); + info->vlan_info = *((const uint32_t *)data); + mask |= HN_RXINFO_VLAN; + break; + + case NDIS_PKTINFO_TYPE_CSUM: + if (__predict_false(dlen < NDIS_RXCSUM_INFO_SIZE)) + return (EINVAL); + info->csum_info = *((const uint32_t *)data); + mask |= HN_RXINFO_CSUM; + break; + + case HN_NDIS_PKTINFO_TYPE_HASHVAL: + if (__predict_false(dlen < HN_NDIS_HASH_VALUE_SIZE)) + return (EINVAL); + info->hash_value = *((const uint32_t *)data); + mask |= HN_RXINFO_HASHVAL; + break; + + case HN_NDIS_PKTINFO_TYPE_HASHINF: + if (__predict_false(dlen < HN_NDIS_HASH_INFO_SIZE)) + return (EINVAL); + info->hash_info = *((const uint32_t *)data); + mask |= HN_RXINFO_HASHINF; + break; + + default: + goto next; + } + + if (mask == HN_RXINFO_ALL) { + /* All found; done */ + break; + } +next: + pi = (const struct rndis_pktinfo *) + ((const uint8_t *)pi + pi->rm_size); + } + + /* + * Final fixup. + * - If there is no hash value, invalidate the hash info. + */ + if ((mask & HN_RXINFO_HASHVAL) == 0) + info->hash_info = HN_NDIS_HASH_INFO_INVALID; + return (0); +} + +static __inline bool +hn_rndis_check_overlap(int off, int len, int check_off, int check_len) +{ + + if (off < check_off) { + if (__predict_true(off + len <= check_off)) + return (false); + } else if (off > check_off) { + if (__predict_true(check_off + check_len <= off)) + return (false); + } + return (true); +} + +static void +hn_rndis_rx_data(struct hn_rx_ring *rxr, const void *data, int dlen) +{ + const struct rndis_packet_msg *pkt; + struct hn_rxinfo info; + int data_off, pktinfo_off, data_len, pktinfo_len; + + /* + * Check length. + */ + if (__predict_false(dlen < sizeof(*pkt))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg\n"); + return; + } + pkt = data; + + if (__predict_false(dlen < pkt->rm_len)) { + if_printf(rxr->hn_ifp, "truncated RNDIS packet msg, " + "dlen %d, msglen %u\n", dlen, pkt->rm_len); + return; + } + if (__predict_false(pkt->rm_len < + pkt->rm_datalen + pkt->rm_oobdatalen + pkt->rm_pktinfolen)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msglen, " + "msglen %u, data %u, oob %u, pktinfo %u\n", + pkt->rm_len, pkt->rm_datalen, pkt->rm_oobdatalen, + pkt->rm_pktinfolen); + return; + } + if (__predict_false(pkt->rm_datalen == 0)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, no data\n"); + return; + } + + /* + * Check offests. + */ +#define IS_OFFSET_INVALID(ofs) \ + ((ofs) < RNDIS_PACKET_MSG_OFFSET_MIN || \ + ((ofs) & RNDIS_PACKET_MSG_OFFSET_ALIGNMASK)) + + /* XXX Hyper-V does not meet data offset alignment requirement */ + if (__predict_false(pkt->rm_dataoffset < RNDIS_PACKET_MSG_OFFSET_MIN)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "data offset %u\n", pkt->rm_dataoffset); + return; + } + if (__predict_false(pkt->rm_oobdataoffset > 0 && + IS_OFFSET_INVALID(pkt->rm_oobdataoffset))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob offset %u\n", pkt->rm_oobdataoffset); + return; + } + if (__predict_true(pkt->rm_pktinfooffset > 0) && + __predict_false(IS_OFFSET_INVALID(pkt->rm_pktinfooffset))) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo offset %u\n", pkt->rm_pktinfooffset); + return; + } + +#undef IS_OFFSET_INVALID + + data_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_dataoffset); + data_len = pkt->rm_datalen; + pktinfo_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_pktinfooffset); + pktinfo_len = pkt->rm_pktinfolen; + + /* + * Check OOB coverage. + */ + if (__predict_false(pkt->rm_oobdatalen != 0)) { + int oob_off, oob_len; + + if_printf(rxr->hn_ifp, "got oobdata\n"); + oob_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_oobdataoffset); + oob_len = pkt->rm_oobdatalen; + + if (__predict_false(oob_off + oob_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overflow, msglen %u, oob abs %d len %d\n", + pkt->rm_len, oob_off, oob_len); + return; + } + + /* + * Check against data. + */ + if (hn_rndis_check_overlap(oob_off, oob_len, + data_off, data_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overlaps data, oob abs %d len %d, " + "data abs %d len %d\n", + oob_off, oob_len, data_off, data_len); + return; + } + + /* + * Check against pktinfo. + */ + if (pktinfo_len != 0 && + hn_rndis_check_overlap(oob_off, oob_len, + pktinfo_off, pktinfo_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "oob overlaps pktinfo, oob abs %d len %d, " + "pktinfo abs %d len %d\n", + oob_off, oob_len, pktinfo_off, pktinfo_len); + return; + } + } + + /* + * Check per-packet-info coverage and find useful per-packet-info. + */ + info.vlan_info = HN_NDIS_VLAN_INFO_INVALID; + info.csum_info = HN_NDIS_RXCSUM_INFO_INVALID; + info.hash_info = HN_NDIS_HASH_INFO_INVALID; + if (__predict_true(pktinfo_len != 0)) { + bool overlap; + int error; + + if (__predict_false(pktinfo_off + pktinfo_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo overflow, msglen %u, " + "pktinfo abs %d len %d\n", + pkt->rm_len, pktinfo_off, pktinfo_len); + return; + } + + /* + * Check packet info coverage. + */ + overlap = hn_rndis_check_overlap(pktinfo_off, pktinfo_len, + data_off, data_len); + if (__predict_false(overlap)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "pktinfo overlap data, pktinfo abs %d len %d, " + "data abs %d len %d\n", + pktinfo_off, pktinfo_len, data_off, data_len); + return; + } + + /* + * Find useful per-packet-info. + */ + error = hn_rndis_rxinfo(((const uint8_t *)pkt) + pktinfo_off, + pktinfo_len, &info); + if (__predict_false(error)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg " + "pktinfo\n"); + return; + } + } + + if (__predict_false(data_off + data_len > pkt->rm_len)) { + if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " + "data overflow, msglen %u, data abs %d len %d\n", + pkt->rm_len, data_off, data_len); + return; + } + hn_rxpkt(rxr, ((const uint8_t *)pkt) + data_off, data_len, &info); +} + +static __inline void +hn_rndis_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen) +{ + const struct rndis_msghdr *hdr; + + if (__predict_false(dlen < sizeof(*hdr))) { + if_printf(rxr->hn_ifp, "invalid RNDIS msg\n"); + return; + } + hdr = data; + + if (__predict_true(hdr->rm_type == REMOTE_NDIS_PACKET_MSG)) { + /* Hot data path. */ + hn_rndis_rx_data(rxr, data, dlen); + /* Done! */ + return; + } + + if (hdr->rm_type == REMOTE_NDIS_INDICATE_STATUS_MSG) + hn_rndis_rx_status(rxr->hn_ifp->if_softc, data, dlen); + else + hn_rndis_rx_ctrl(rxr->hn_ifp->if_softc, data, dlen); +} + static void hn_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt) { @@ -4060,8 +4400,8 @@ hn_nvs_handle_comp(struct hn_softc *sc, } static void -hn_nvs_handle_rxbuf(struct hn_softc *sc, struct hn_rx_ring *rxr, - struct vmbus_channel *chan, const struct vmbus_chanpkt_hdr *pkthdr) +hn_nvs_handle_rxbuf(struct hn_rx_ring *rxr, struct vmbus_channel *chan, + const struct vmbus_chanpkt_hdr *pkthdr) { const struct vmbus_chanpkt_rxbuf *pkt; const struct hn_nvs_hdr *nvs_hdr; @@ -4111,9 +4451,9 @@ hn_nvs_handle_rxbuf(struct hn_softc *sc, "ofs %d, len %d\n", i, ofs, len); continue; } - hv_rf_on_receive(sc, rxr, rxr->hn_rxbuf + ofs, len); + hn_rndis_rxpkt(rxr, rxr->hn_rxbuf + ofs, len); } - + /* * Moved completion call back here so that all received * messages (not just data messages) will trigger a response @@ -4177,7 +4517,7 @@ hn_chan_callback(struct vmbus_channel *c hn_nvs_handle_comp(sc, chan, pkt); break; case VMBUS_CHANPKT_TYPE_RXBUF: - hn_nvs_handle_rxbuf(sc, rxr, chan, pkt); + hn_nvs_handle_rxbuf(rxr, chan, pkt); break; case VMBUS_CHANPKT_TYPE_INBAND: hn_nvs_handle_notify(sc, pkt); Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c ============================================================================== --- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c Fri Oct 28 07:59:02 2016 (r308013) +++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c Fri Oct 28 08:08:46 2016 (r308014) @@ -59,16 +59,6 @@ __FBSDID("$FreeBSD$"); #include <dev/hyperv/netvsc/hn_nvs.h> #include <dev/hyperv/netvsc/hv_rndis_filter.h> -#define HV_RF_RECVINFO_VLAN 0x1 -#define HV_RF_RECVINFO_CSUM 0x2 -#define HV_RF_RECVINFO_HASHINF 0x4 -#define HV_RF_RECVINFO_HASHVAL 0x8 -#define HV_RF_RECVINFO_ALL \ - (HV_RF_RECVINFO_VLAN | \ - HV_RF_RECVINFO_CSUM | \ - HV_RF_RECVINFO_HASHINF | \ - HV_RF_RECVINFO_HASHVAL) - #define HN_RNDIS_RID_COMPAT_MASK 0xffff #define HN_RNDIS_RID_COMPAT_MAX HN_RNDIS_RID_COMPAT_MASK @@ -89,11 +79,6 @@ __FBSDID("$FreeBSD$"); /* * Forward declarations */ -static void hv_rf_receive_indicate_status(struct hn_softc *sc, - const void *data, int dlen); -static void hv_rf_receive_data(struct hn_rx_ring *rxr, - 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_query2(struct hn_softc *sc, uint32_t oid, @@ -155,335 +140,22 @@ hn_rndis_pktinfo_append(struct rndis_pac return (pi->rm_data); } -/* - * RNDIS filter receive indicate status - */ -static void -hv_rf_receive_indicate_status(struct hn_softc *sc, const void *data, int dlen) -{ - const struct rndis_status_msg *msg; - int ofs; - - if (dlen < sizeof(*msg)) { - if_printf(sc->hn_ifp, "invalid RNDIS status\n"); - return; - } - msg = data; - - switch (msg->rm_status) { - case RNDIS_STATUS_MEDIA_CONNECT: - case RNDIS_STATUS_MEDIA_DISCONNECT: - hn_link_status_update(sc); - break; - - case RNDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG: - /* Not really useful; ignore. */ - break; - - case RNDIS_STATUS_NETWORK_CHANGE: - ofs = RNDIS_STBUFOFFSET_ABS(msg->rm_stbufoffset); - if (dlen < ofs + msg->rm_stbuflen || - msg->rm_stbuflen < sizeof(uint32_t)) { - if_printf(sc->hn_ifp, "network changed\n"); - } else { - uint32_t change; - - memcpy(&change, ((const uint8_t *)msg) + ofs, - sizeof(change)); - if_printf(sc->hn_ifp, "network changed, change %u\n", - change); - } - hn_network_change(sc); - break; - - default: - /* TODO: */ - if_printf(sc->hn_ifp, "unknown RNDIS status 0x%08x\n", - msg->rm_status); - break; - } -} - -static int -hn_rndis_rxinfo(const void *info_data, int info_dlen, struct hn_recvinfo *info) -{ - const struct rndis_pktinfo *pi = info_data; - uint32_t mask = 0; - - while (info_dlen != 0) { - const void *data; - uint32_t dlen; - - if (__predict_false(info_dlen < sizeof(*pi))) - return (EINVAL); - if (__predict_false(info_dlen < pi->rm_size)) - return (EINVAL); - info_dlen -= pi->rm_size; - - if (__predict_false(pi->rm_size & RNDIS_PKTINFO_SIZE_ALIGNMASK)) - return (EINVAL); - if (__predict_false(pi->rm_size < pi->rm_pktinfooffset)) - return (EINVAL); - dlen = pi->rm_size - pi->rm_pktinfooffset; - data = pi->rm_data; - - switch (pi->rm_type) { - case NDIS_PKTINFO_TYPE_VLAN: - if (__predict_false(dlen < NDIS_VLAN_INFO_SIZE)) - return (EINVAL); - info->vlan_info = *((const uint32_t *)data); - mask |= HV_RF_RECVINFO_VLAN; - break; - - case NDIS_PKTINFO_TYPE_CSUM: - if (__predict_false(dlen < NDIS_RXCSUM_INFO_SIZE)) - return (EINVAL); - info->csum_info = *((const uint32_t *)data); - mask |= HV_RF_RECVINFO_CSUM; - break; - - case HN_NDIS_PKTINFO_TYPE_HASHVAL: - if (__predict_false(dlen < HN_NDIS_HASH_VALUE_SIZE)) - return (EINVAL); - info->hash_value = *((const uint32_t *)data); - mask |= HV_RF_RECVINFO_HASHVAL; - break; - - case HN_NDIS_PKTINFO_TYPE_HASHINF: - if (__predict_false(dlen < HN_NDIS_HASH_INFO_SIZE)) - return (EINVAL); - info->hash_info = *((const uint32_t *)data); - mask |= HV_RF_RECVINFO_HASHINF; - break; - - default: - goto next; - } - - if (mask == HV_RF_RECVINFO_ALL) { - /* All found; done */ - break; - } -next: - pi = (const struct rndis_pktinfo *) - ((const uint8_t *)pi + pi->rm_size); - } - - /* - * Final fixup. - * - If there is no hash value, invalidate the hash info. - */ - if ((mask & HV_RF_RECVINFO_HASHVAL) == 0) - info->hash_info = HN_NDIS_HASH_INFO_INVALID; - return (0); -} - -static __inline bool -hn_rndis_check_overlap(int off, int len, int check_off, int check_len) -{ - - if (off < check_off) { - if (__predict_true(off + len <= check_off)) - return (false); - } else if (off > check_off) { - if (__predict_true(check_off + check_len <= off)) - return (false); - } - return (true); -} - -/* - * RNDIS filter receive data - */ -static void -hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen) -{ - const struct rndis_packet_msg *pkt; - struct hn_recvinfo info; - int data_off, pktinfo_off, data_len, pktinfo_len; - - /* - * Check length. - */ - if (__predict_false(dlen < sizeof(*pkt))) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg\n"); - return; - } - pkt = data; - - if (__predict_false(dlen < pkt->rm_len)) { - if_printf(rxr->hn_ifp, "truncated RNDIS packet msg, " - "dlen %d, msglen %u\n", dlen, pkt->rm_len); - return; - } - if (__predict_false(pkt->rm_len < - pkt->rm_datalen + pkt->rm_oobdatalen + pkt->rm_pktinfolen)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msglen, " - "msglen %u, data %u, oob %u, pktinfo %u\n", - pkt->rm_len, pkt->rm_datalen, pkt->rm_oobdatalen, - pkt->rm_pktinfolen); - return; - } - if (__predict_false(pkt->rm_datalen == 0)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, no data\n"); - return; - } - - /* - * Check offests. - */ -#define IS_OFFSET_INVALID(ofs) \ - ((ofs) < RNDIS_PACKET_MSG_OFFSET_MIN || \ - ((ofs) & RNDIS_PACKET_MSG_OFFSET_ALIGNMASK)) - - /* XXX Hyper-V does not meet data offset alignment requirement */ - if (__predict_false(pkt->rm_dataoffset < RNDIS_PACKET_MSG_OFFSET_MIN)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "data offset %u\n", pkt->rm_dataoffset); - return; - } - if (__predict_false(pkt->rm_oobdataoffset > 0 && - IS_OFFSET_INVALID(pkt->rm_oobdataoffset))) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "oob offset %u\n", pkt->rm_oobdataoffset); - return; - } - if (__predict_true(pkt->rm_pktinfooffset > 0) && - __predict_false(IS_OFFSET_INVALID(pkt->rm_pktinfooffset))) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "pktinfo offset %u\n", pkt->rm_pktinfooffset); - return; - } - -#undef IS_OFFSET_INVALID - - data_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_dataoffset); - data_len = pkt->rm_datalen; - pktinfo_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_pktinfooffset); - pktinfo_len = pkt->rm_pktinfolen; - - /* - * Check OOB coverage. - */ - if (__predict_false(pkt->rm_oobdatalen != 0)) { - int oob_off, oob_len; - - if_printf(rxr->hn_ifp, "got oobdata\n"); - oob_off = RNDIS_PACKET_MSG_OFFSET_ABS(pkt->rm_oobdataoffset); - oob_len = pkt->rm_oobdatalen; - - if (__predict_false(oob_off + oob_len > pkt->rm_len)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "oob overflow, msglen %u, oob abs %d len %d\n", - pkt->rm_len, oob_off, oob_len); - return; - } - - /* - * Check against data. - */ - if (hn_rndis_check_overlap(oob_off, oob_len, - data_off, data_len)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "oob overlaps data, oob abs %d len %d, " - "data abs %d len %d\n", - oob_off, oob_len, data_off, data_len); - return; - } - - /* - * Check against pktinfo. - */ - if (pktinfo_len != 0 && - hn_rndis_check_overlap(oob_off, oob_len, - pktinfo_off, pktinfo_len)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "oob overlaps pktinfo, oob abs %d len %d, " - "pktinfo abs %d len %d\n", - oob_off, oob_len, pktinfo_off, pktinfo_len); - return; - } - } - - /* - * Check per-packet-info coverage and find useful per-packet-info. - */ - info.vlan_info = HN_NDIS_VLAN_INFO_INVALID; - info.csum_info = HN_NDIS_RXCSUM_INFO_INVALID; - info.hash_info = HN_NDIS_HASH_INFO_INVALID; - if (__predict_true(pktinfo_len != 0)) { - bool overlap; - int error; - - if (__predict_false(pktinfo_off + pktinfo_len > pkt->rm_len)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "pktinfo overflow, msglen %u, " - "pktinfo abs %d len %d\n", - pkt->rm_len, pktinfo_off, pktinfo_len); - return; - } - - /* - * Check packet info coverage. - */ - overlap = hn_rndis_check_overlap(pktinfo_off, pktinfo_len, - data_off, data_len); - if (__predict_false(overlap)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "pktinfo overlap data, pktinfo abs %d len %d, " - "data abs %d len %d\n", - pktinfo_off, pktinfo_len, data_off, data_len); - return; - } - - /* - * Find useful per-packet-info. - */ - error = hn_rndis_rxinfo(((const uint8_t *)pkt) + pktinfo_off, - pktinfo_len, &info); - if (__predict_false(error)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg " - "pktinfo\n"); - return; - } - } - - if (__predict_false(data_off + data_len > pkt->rm_len)) { - if_printf(rxr->hn_ifp, "invalid RNDIS packet msg, " - "data overflow, msglen %u, data abs %d len %d\n", - pkt->rm_len, data_off, data_len); - return; - } - hn_rxpkt(rxr, ((const uint8_t *)pkt) + data_off, data_len, &info); -} - -/* - * RNDIS filter on receive - */ void -hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, - const void *data, int dlen) +hn_rndis_rx_ctrl(struct hn_softc *sc, const void *data, int dlen) { const struct rndis_comp_hdr *comp; const struct rndis_msghdr *hdr; - if (__predict_false(dlen < sizeof(*hdr))) { - if_printf(rxr->hn_ifp, "invalid RNDIS msg\n"); - return; - } + KASSERT(dlen >= sizeof(*hdr), ("invalid RNDIS msg\n")); hdr = data; switch (hdr->rm_type) { - case REMOTE_NDIS_PACKET_MSG: - hv_rf_receive_data(rxr, data, dlen); - break; - case REMOTE_NDIS_INITIALIZE_CMPLT: case REMOTE_NDIS_QUERY_CMPLT: case REMOTE_NDIS_SET_CMPLT: case REMOTE_NDIS_KEEPALIVE_CMPLT: /* unused */ if (dlen < sizeof(*comp)) { - if_printf(rxr->hn_ifp, "invalid RNDIS cmplt\n"); + if_printf(sc->hn_ifp, "invalid RNDIS cmplt\n"); return; } comp = data; @@ -493,10 +165,6 @@ hv_rf_on_receive(struct hn_softc *sc, st vmbus_xact_ctx_wakeup(sc->hn_xact, comp, dlen); break; - case REMOTE_NDIS_INDICATE_STATUS_MSG: - hv_rf_receive_indicate_status(sc, data, dlen); - break; - case REMOTE_NDIS_RESET_CMPLT: /* * Reset completed, no rid. @@ -505,11 +173,11 @@ hv_rf_on_receive(struct hn_softc *sc, st * RESET is not issued by hn(4), so this message should * _not_ be observed. */ - if_printf(rxr->hn_ifp, "RESET cmplt received\n"); + if_printf(sc->hn_ifp, "RESET cmplt received\n"); break; default: - if_printf(rxr->hn_ifp, "unknown RNDIS msg 0x%x\n", + if_printf(sc->hn_ifp, "unknown RNDIS msg 0x%x\n", hdr->rm_type); break; } Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.h ============================================================================== --- head/sys/dev/hyperv/netvsc/hv_rndis_filter.h Fri Oct 28 07:59:02 2016 (r308013) +++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.h Fri Oct 28 08:08:46 2016 (r308014) @@ -31,16 +31,9 @@ #ifndef __HV_RNDIS_FILTER_H__ #define __HV_RNDIS_FILTER_H__ -#include <sys/param.h> -#include <net/ethernet.h> -#include <dev/hyperv/netvsc/if_hnvar.h> +struct hn_softc; -/* - * Externs - */ -struct hn_rx_ring; - -void hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr, - const void *data, int dlen); +void hn_rndis_rx_ctrl(struct hn_softc *sc, const void *data, + int dlen); #endif /* __HV_RNDIS_FILTER_H__ */ Modified: head/sys/dev/hyperv/netvsc/if_hnvar.h ============================================================================== --- head/sys/dev/hyperv/netvsc/if_hnvar.h Fri Oct 28 07:59:02 2016 (r308013) +++ head/sys/dev/hyperv/netvsc/if_hnvar.h Fri Oct 28 08:08:46 2016 (r308014) @@ -51,17 +51,6 @@ #define HN_GPACNT_MAX 32 -#define HN_NDIS_VLAN_INFO_INVALID 0xffffffff -#define HN_NDIS_RXCSUM_INFO_INVALID 0 -#define HN_NDIS_HASH_INFO_INVALID 0 - -struct hn_recvinfo { - uint32_t vlan_info; - uint32_t csum_info; - uint32_t hash_info; - uint32_t hash_value; -}; - struct hn_txdesc; #ifndef HN_USE_TXDESC_BUFRING SLIST_HEAD(hn_txdesc_list, hn_txdesc); @@ -256,9 +245,4 @@ int hn_rndis_get_linkstatus(struct hn_s /* filter: NDIS_PACKET_TYPE_. */ int hn_rndis_set_rxfilter(struct hn_softc *sc, uint32_t filter); -int hn_rxpkt(struct hn_rx_ring *rxr, const void *data, int dlen, - const struct hn_recvinfo *info); -void hn_link_status_update(struct hn_softc *sc); -void hn_network_change(struct hn_softc *sc); - #endif /* !_IF_HNVAR_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201610280808.u9S88kpv023116>