From owner-svn-src-stable-10@freebsd.org Fri Nov 11 03:03:56 2016 Return-Path: Delivered-To: svn-src-stable-10@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 F28F6C3823A; Fri, 11 Nov 2016 03:03:55 +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 B4B9799D; Fri, 11 Nov 2016 03:03:55 +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 uAB33txM082767; Fri, 11 Nov 2016 03:03:55 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id uAB33sA0082759; Fri, 11 Nov 2016 03:03:54 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201611110303.uAB33sA0082759@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Fri, 11 Nov 2016 03:03:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r308494 - in stable/10/sys: dev/hyperv/netvsc net X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Nov 2016 03:03:56 -0000 Author: sephe Date: Fri Nov 11 03:03:54 2016 New Revision: 308494 URL: https://svnweb.freebsd.org/changeset/base/308494 Log: MFC 307710-307712,307714 307710 hyperv/hn: Always query RSS capabilities. - This avoid distributing NDIS version check. - Only NDIS 6.20 required (earlier NDIS uses different indirect table format). Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8291 307711 hyperv/hn: Check NVS version for HASHVAL pktinfo on sending path. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8293 307712 hyperv/hn: Add network change support. Currently the network change is simulated by link status changes. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8295 307714 hyperv/hn: Function renaming; consistent w/ hardware capabilities query. Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8296 Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c stable/10/sys/dev/hyperv/netvsc/if_hnreg.h stable/10/sys/dev/hyperv/netvsc/if_hnvar.h stable/10/sys/dev/hyperv/netvsc/ndis.h stable/10/sys/net/rndis.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c Fri Nov 11 02:42:53 2016 (r308493) +++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.c Fri Nov 11 03:03:54 2016 (r308494) @@ -543,8 +543,9 @@ hn_nvs_init(struct hn_softc *sc) if (error) { if_printf(sc->hn_ifp, "reinit NVS version 0x%x " "failed: %d\n", sc->hn_nvs_ver, error); + return (error); } - return (error); + goto done; } /* @@ -566,11 +567,16 @@ hn_nvs_init(struct hn_softc *sc) HN_NDIS_VERSION_MAJOR(sc->hn_ndis_ver), HN_NDIS_VERSION_MINOR(sc->hn_ndis_ver)); } - return (0); + goto done; } } if_printf(sc->hn_ifp, "no NVS available\n"); return (ENXIO); + +done: + if (sc->hn_nvs_ver >= HN_NVS_VERSION_5) + sc->hn_caps |= HN_CAP_HASHVAL; + return (0); } int Modified: stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Fri Nov 11 02:42:53 2016 (r308493) +++ stable/10/sys/dev/hyperv/netvsc/hv_net_vsc.h Fri Nov 11 03:03:54 2016 (r308494) @@ -208,7 +208,6 @@ struct hn_softc { struct arpcom arpcom; struct ifmedia hn_media; device_t hn_dev; - int hn_carrier; int hn_if_flags; struct sx hn_lock; struct vmbus_channel *hn_prichan; @@ -237,6 +236,9 @@ struct hn_softc { struct taskqueue *hn_mgmt_taskq; struct taskqueue *hn_mgmt_taskq0; struct task hn_link_task; + struct task hn_netchg_init; + struct timeout_task hn_netchg_status; + uint32_t hn_link_flags; /* HN_LINK_FLAG_ */ uint32_t hn_caps; /* HN_CAP_ */ uint32_t hn_flags; /* HN_FLAG_ */ @@ -270,6 +272,10 @@ struct hn_softc { #define HN_CAP_UDP6CS 0x0040 #define HN_CAP_TSO4 0x0080 #define HN_CAP_TSO6 0x0100 +#define HN_CAP_HASHVAL 0x0200 + +#define HN_LINK_FLAG_LINKUP 0x0001 +#define HN_LINK_FLAG_NETCHG 0x0002 /* * Externs Modified: stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Fri Nov 11 02:42:53 2016 (r308493) +++ stable/10/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Fri Nov 11 03:03:54 2016 (r308494) @@ -337,6 +337,8 @@ static void hn_destroy_tx_data(struct hn static void hn_start_taskfunc(void *, int); static void hn_start_txeof_taskfunc(void *, int); static void hn_link_taskfunc(void *, int); +static void hn_netchg_init_taskfunc(void *, int); +static void hn_netchg_status_taskfunc(void *, int); static void hn_suspend_mgmt_taskfunc(void *, int); static int hn_encap(struct hn_tx_ring *, struct hn_txdesc *, struct mbuf **); static int hn_create_rx_data(struct hn_softc *sc, int); @@ -362,6 +364,7 @@ static void hn_rx_drain(struct vmbus_cha static void hn_tx_resume(struct hn_softc *, int); static void hn_tx_ring_qflush(struct hn_tx_ring *); static int netvsc_detach(device_t dev); +static void hn_link_status(struct hn_softc *); static void hn_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt); @@ -484,7 +487,7 @@ hn_ifmedia_sts(struct ifnet *ifp, struct ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; - if (!sc->hn_carrier) { + if ((sc->hn_link_flags & HN_LINK_FLAG_LINKUP) == 0) { ifmr->ifm_active |= IFM_NONE; return; } @@ -579,6 +582,9 @@ netvsc_attach(device_t dev) taskqueue_start_threads(&sc->hn_mgmt_taskq0, 1, PI_NET, "%s mgmt", device_get_nameunit(dev)); TASK_INIT(&sc->hn_link_task, 0, hn_link_taskfunc, sc); + TASK_INIT(&sc->hn_netchg_init, 0, hn_netchg_init_taskfunc, sc); + TIMEOUT_TASK_INIT(sc->hn_mgmt_taskq0, &sc->hn_netchg_status, 0, + hn_netchg_status_taskfunc, sc); /* * Allocate ifnet and setup its name earlier, so that if_printf @@ -824,10 +830,8 @@ netvsc_shutdown(device_t dev) } static void -hn_link_taskfunc(void *xsc, int pending __unused) +hn_link_status(struct hn_softc *sc) { - struct hn_softc *sc = xsc; - struct ifnet *ifp = sc->hn_ifp; uint32_t link_status; int error; @@ -838,11 +842,51 @@ hn_link_taskfunc(void *xsc, int pending } if (link_status == NDIS_MEDIA_STATE_CONNECTED) - sc->hn_carrier = 1; + sc->hn_link_flags |= HN_LINK_FLAG_LINKUP; else - sc->hn_carrier = 0; - if_link_state_change(ifp, - sc->hn_carrier ? LINK_STATE_UP : LINK_STATE_DOWN); + sc->hn_link_flags &= ~HN_LINK_FLAG_LINKUP; + if_link_state_change(sc->hn_ifp, + (sc->hn_link_flags & HN_LINK_FLAG_LINKUP) ? + LINK_STATE_UP : LINK_STATE_DOWN); +} + +static void +hn_link_taskfunc(void *xsc, int pending __unused) +{ + struct hn_softc *sc = xsc; + + if (sc->hn_link_flags & HN_LINK_FLAG_NETCHG) + return; + hn_link_status(sc); +} + +static void +hn_netchg_init_taskfunc(void *xsc, int pending __unused) +{ + struct hn_softc *sc = xsc; + + /* Prevent any link status checks from running. */ + sc->hn_link_flags |= HN_LINK_FLAG_NETCHG; + + /* + * Fake up a [link down --> link up] state change; 5 seconds + * delay is used, which closely simulates miibus reaction + * upon link down event. + */ + sc->hn_link_flags &= ~HN_LINK_FLAG_LINKUP; + if_link_state_change(sc->hn_ifp, LINK_STATE_DOWN); + taskqueue_enqueue_timeout(sc->hn_mgmt_taskq0, + &sc->hn_netchg_status, 5 * hz); +} + +static void +hn_netchg_status_taskfunc(void *xsc, int pending __unused) +{ + struct hn_softc *sc = xsc; + + /* Re-allow link status checks. */ + sc->hn_link_flags &= ~HN_LINK_FLAG_NETCHG; + hn_link_status(sc); } void @@ -853,6 +897,14 @@ hn_link_status_update(struct hn_softc *s taskqueue_enqueue(sc->hn_mgmt_taskq, &sc->hn_link_task); } +void +hn_network_change(struct hn_softc *sc) +{ + + if (sc->hn_mgmt_taskq != NULL) + taskqueue_enqueue(sc->hn_mgmt_taskq, &sc->hn_netchg_init); +} + static __inline int hn_txdesc_dmamap_load(struct hn_tx_ring *txr, struct hn_txdesc *txd, struct mbuf **m_head, bus_dma_segment_t *segs, int *nsegs) @@ -2253,7 +2305,8 @@ hn_caps_sysctl(SYSCTL_HANDLER_ARGS) "\006UDP4CS" "\007UDP6CS" "\010TSO4" - "\011TSO6"); + "\011TSO6" + "\012HASHVAL"); return sysctl_handle_string(oidp, caps_str, sizeof(caps_str), req); } @@ -3028,12 +3081,15 @@ hn_fixup_tx_data(struct hn_softc *sc) if (sc->hn_caps & HN_CAP_UDP6CS) csum_assist |= CSUM_IP6_UDP; #endif - for (i = 0; i < sc->hn_tx_ring_cnt; ++i) sc->hn_tx_ring[i].hn_csum_assist = csum_assist; - if (sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30) { - /* Support HASHVAL pktinfo on TX path. */ + if (sc->hn_caps & HN_CAP_HASHVAL) { + /* + * Support HASHVAL pktinfo on TX path. + */ + if (bootverbose) + if_printf(sc->hn_ifp, "support HASHVAL pktinfo\n"); for (i = 0; i < sc->hn_tx_ring_cnt; ++i) sc->hn_tx_ring[i].hn_tx_flags |= HN_TX_FLAG_HASHVAL; } @@ -3428,20 +3484,19 @@ hn_synth_alloc_subchans(struct hn_softc int nchan, rxr_cnt, error; nchan = *nsubch + 1; - if (sc->hn_ndis_ver < HN_NDIS_VERSION_6_30 || nchan == 1) { + if (nchan == 1) { /* - * Either RSS is not supported, or multiple RX/TX rings - * are not requested. + * Multiple RX/TX rings are not requested. */ *nsubch = 0; return (0); } /* - * Get RSS capabilities, e.g. # of RX rings, and # of indirect + * Query RSS capabilities, e.g. # of RX rings, and # of indirect * table entries. */ - error = hn_rndis_get_rsscaps(sc, &rxr_cnt); + error = hn_rndis_query_rsscaps(sc, &rxr_cnt); if (error) { /* No RSS; this is benign. */ *nsubch = 0; @@ -3736,6 +3791,8 @@ hn_suspend_mgmt(struct hn_softc *sc) /* * Make sure that all pending management tasks are completed. */ + taskqueue_drain(sc->hn_mgmt_taskq0, &sc->hn_netchg_init); + taskqueue_drain_timeout(sc->hn_mgmt_taskq0, &sc->hn_netchg_status); taskqueue_drain_all(sc->hn_mgmt_taskq0); } @@ -3813,10 +3870,11 @@ hn_resume_mgmt(struct hn_softc *sc) { /* - * Kick off link status check. + * Kick off network change detection, which will + * do link status check too. */ sc->hn_mgmt_taskq = sc->hn_mgmt_taskq0; - hn_link_status_update(sc); + hn_network_change(sc); } static void Modified: stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c Fri Nov 11 02:42:53 2016 (r308493) +++ stable/10/sys/dev/hyperv/netvsc/hv_rndis_filter.c Fri Nov 11 03:03:54 2016 (r308494) @@ -159,6 +159,7 @@ 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"); @@ -177,8 +178,19 @@ hv_rf_receive_indicate_status(struct hn_ break; case RNDIS_STATUS_NETWORK_CHANGE: - /* TODO */ - if_printf(sc->hn_ifp, "network changed\n"); + 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: @@ -737,7 +749,7 @@ done: } int -hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt) +hn_rndis_query_rsscaps(struct hn_softc *sc, int *rxr_cnt) { struct ndis_rss_caps in, caps; size_t caps_len; @@ -745,15 +757,13 @@ hn_rndis_get_rsscaps(struct hn_softc *sc *rxr_cnt = 0; + if (sc->hn_ndis_ver < HN_NDIS_VERSION_6_20) + return (EOPNOTSUPP); + memset(&in, 0, sizeof(in)); in.ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_CAPS; - if (sc->hn_ndis_ver < HN_NDIS_VERSION_6_30) { - in.ndis_hdr.ndis_rev = NDIS_RSS_CAPS_REV_1; - in.ndis_hdr.ndis_size = NDIS_RSS_CAPS_SIZE_6_0; - } else { - in.ndis_hdr.ndis_rev = NDIS_RSS_CAPS_REV_2; - in.ndis_hdr.ndis_size = NDIS_RSS_CAPS_SIZE; - } + in.ndis_hdr.ndis_rev = NDIS_RSS_CAPS_REV_2; + in.ndis_hdr.ndis_size = NDIS_RSS_CAPS_SIZE; caps_len = NDIS_RSS_CAPS_SIZE; error = hn_rndis_query2(sc, OID_GEN_RECEIVE_SCALE_CAPABILITIES, @@ -1028,10 +1038,12 @@ hn_rndis_conf_rss(struct hn_softc *sc, u int error; /* - * Only NDIS 6.30+ is supported. + * Only NDIS 6.20+ is supported: + * We only support 4bytes element in indirect table, which has been + * adopted since NDIS 6.20. */ - KASSERT(sc->hn_ndis_ver >= HN_NDIS_VERSION_6_30, - ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver)); + KASSERT(sc->hn_ndis_ver >= HN_NDIS_VERSION_6_20, + ("NDIS 6.20+ is required, NDIS version 0x%08x", sc->hn_ndis_ver)); /* * NOTE: Modified: stable/10/sys/dev/hyperv/netvsc/if_hnreg.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/if_hnreg.h Fri Nov 11 02:42:53 2016 (r308493) +++ stable/10/sys/dev/hyperv/netvsc/if_hnreg.h Fri Nov 11 03:03:54 2016 (r308494) @@ -36,6 +36,7 @@ * NDIS protocol version numbers */ #define HN_NDIS_VERSION_6_1 0x00060001 +#define HN_NDIS_VERSION_6_20 0x00060014 #define HN_NDIS_VERSION_6_30 0x0006001e #define HN_NDIS_VERSION_MAJOR(ver) (((ver) & 0xffff0000) >> 16) #define HN_NDIS_VERSION_MINOR(ver) ((ver) & 0xffff) Modified: stable/10/sys/dev/hyperv/netvsc/if_hnvar.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/if_hnvar.h Fri Nov 11 02:42:53 2016 (r308493) +++ stable/10/sys/dev/hyperv/netvsc/if_hnvar.h Fri Nov 11 03:03:54 2016 (r308494) @@ -122,7 +122,7 @@ void hn_rndis_detach(struct hn_softc *s int hn_rndis_conf_rss(struct hn_softc *sc, uint16_t flags); void *hn_rndis_pktinfo_append(struct rndis_packet_msg *, size_t pktsize, size_t pi_dlen, uint32_t pi_type); -int hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt); +int hn_rndis_query_rsscaps(struct hn_softc *sc, int *rxr_cnt); int hn_rndis_get_eaddr(struct hn_softc *sc, uint8_t *eaddr); int hn_rndis_get_linkstatus(struct hn_softc *sc, uint32_t *link_status); @@ -139,6 +139,7 @@ int hn_rxpkt(struct hn_rx_ring *rxr, co const struct hn_recvinfo *info); void hn_chan_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr); void hn_link_status_update(struct hn_softc *sc); +void hn_network_change(struct hn_softc *sc); extern struct hn_send_ctx hn_send_ctx_none; Modified: stable/10/sys/dev/hyperv/netvsc/ndis.h ============================================================================== --- stable/10/sys/dev/hyperv/netvsc/ndis.h Fri Nov 11 02:42:53 2016 (r308493) +++ stable/10/sys/dev/hyperv/netvsc/ndis.h Fri Nov 11 03:03:54 2016 (r308494) @@ -32,6 +32,10 @@ #define NDIS_MEDIA_STATE_CONNECTED 0 #define NDIS_MEDIA_STATE_DISCONNECTED 1 +#define NDIS_NETCHANGE_TYPE_POSSIBLE 1 +#define NDIS_NETCHANGE_TYPE_DEFINITE 2 +#define NDIS_NETCHANGE_TYPE_FROMMEDIA 3 + #define NDIS_OFFLOAD_SET_NOCHG 0 #define NDIS_OFFLOAD_SET_ON 1 #define NDIS_OFFLOAD_SET_OFF 2 Modified: stable/10/sys/net/rndis.h ============================================================================== --- stable/10/sys/net/rndis.h Fri Nov 11 02:42:53 2016 (r308493) +++ stable/10/sys/net/rndis.h Fri Nov 11 03:03:54 2016 (r308494) @@ -320,6 +320,10 @@ struct rndis_status_msg { /* rndis_diag_info */ }; +/* stbuf offset from the beginning of rndis_status_msg. */ +#define RNDIS_STBUFOFFSET_ABS(ofs) \ + ((ofs) + __offsetof(struct rndis_status_msg, rm_status)) + /* * Immediately after rndis_status_msg.rm_stbufoffset, if a control * message is malformatted, or a packet message contains inappropriate