From owner-svn-src-all@freebsd.org Mon Oct 24 05:10:36 2016 Return-Path: Delivered-To: svn-src-all@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 BEAD6C1F4DB; Mon, 24 Oct 2016 05:10:36 +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 7FA889BB; Mon, 24 Oct 2016 05:10:36 +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 u9O5AZZN045436; Mon, 24 Oct 2016 05:10:35 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u9O5AZkX045433; Mon, 24 Oct 2016 05:10:35 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201610240510.u9O5AZkX045433@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Mon, 24 Oct 2016 05:10:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r307843 - in head/sys: dev/hyperv/netvsc net X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Oct 2016 05:10:36 -0000 Author: sephe Date: Mon Oct 24 05:10:35 2016 New Revision: 307843 URL: https://svnweb.freebsd.org/changeset/base/307843 Log: hyperv/hn: Fix RX filter settings. MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8313 Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c head/sys/net/rndis.h Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h ============================================================================== --- head/sys/dev/hyperv/netvsc/hv_net_vsc.h Mon Oct 24 05:01:34 2016 (r307842) +++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h Mon Oct 24 05:10:35 2016 (r307843) @@ -232,6 +232,7 @@ struct hn_softc { struct sysctl_oid *hn_rx_sysctl_tree; struct vmbus_xact_ctx *hn_xact; uint32_t hn_nvs_ver; + uint32_t hn_rx_filter; struct taskqueue *hn_mgmt_taskq; struct taskqueue *hn_mgmt_taskq0; Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c ============================================================================== --- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Oct 24 05:01:34 2016 (r307842) +++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon Oct 24 05:10:35 2016 (r307843) @@ -326,6 +326,7 @@ static int hn_tx_conf_int_sysctl(SYSCTL_ static int hn_ndis_version_sysctl(SYSCTL_HANDLER_ARGS); static int hn_caps_sysctl(SYSCTL_HANDLER_ARGS); static int hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS); +static int hn_rxfilter_sysctl(SYSCTL_HANDLER_ARGS); static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS); static int hn_rss_ind_sysctl(SYSCTL_HANDLER_ARGS); static int hn_check_iplen(const struct mbuf *, int); @@ -367,6 +368,7 @@ static int netvsc_detach(device_t dev); static void hn_link_status(struct hn_softc *); 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_nvs_handle_notify(struct hn_softc *sc, const struct vmbus_chanpkt_hdr *pkt); @@ -455,6 +457,43 @@ hn_sendpkt_rndis_chim(struct hn_tx_ring } static int +hn_set_rxfilter(struct hn_softc *sc) +{ + struct ifnet *ifp = sc->hn_ifp; + uint32_t filter; + int error = 0; + + HN_LOCK_ASSERT(sc); + + if (ifp->if_flags & IFF_PROMISC) { + filter = NDIS_PACKET_TYPE_PROMISCUOUS; + } else { + filter = NDIS_PACKET_TYPE_DIRECTED; + if (ifp->if_flags & IFF_BROADCAST) + filter |= NDIS_PACKET_TYPE_BROADCAST; +#ifdef notyet + /* + * See the comment in SIOCADDMULTI/SIOCDELMULTI. + */ + /* TODO: support multicast list */ + if ((ifp->if_flags & IFF_ALLMULTI) || + !TAILQ_EMPTY(&ifp->if_multiaddrs)) + filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; +#else + /* Always enable ALLMULTI */ + filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; +#endif + } + + if (sc->hn_rx_filter != filter) { + error = hn_rndis_set_rxfilter(sc, filter); + if (!error) + sc->hn_rx_filter = filter; + } + return (error); +} + +static int hn_get_txswq_depth(const struct hn_tx_ring *txr) { @@ -728,6 +767,9 @@ netvsc_attach(device_t dev) SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "hwassist", CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0, hn_hwassist_sysctl, "A", "hwassist"); + SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxfilter", + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, 0, + hn_rxfilter_sysctl, "A", "rxfilter"); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rss_key", CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, 0, hn_rss_key_sysctl, "IU", "RSS key"); @@ -1840,31 +1882,13 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, } if (ifp->if_flags & IFF_UP) { - /* - * If only the state of the PROMISC flag changed, - * then just use the 'set promisc mode' command - * instead of reinitializing the entire NIC. Doing - * a full re-init means reloading the firmware and - * waiting for it to start up, which may take a - * second or two. - */ -#ifdef notyet - /* Fixme: Promiscuous mode? */ - if (ifp->if_drv_flags & IFF_DRV_RUNNING && - ifp->if_flags & IFF_PROMISC && - !(sc->hn_if_flags & IFF_PROMISC)) { - /* do something here for Hyper-V */ - } else if (ifp->if_drv_flags & IFF_DRV_RUNNING && - !(ifp->if_flags & IFF_PROMISC) && - sc->hn_if_flags & IFF_PROMISC) { - /* do something here for Hyper-V */ - } else -#endif + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + hn_set_rxfilter(sc); + else hn_init_locked(sc); } else { - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + if (ifp->if_drv_flags & IFF_DRV_RUNNING) hn_stop(sc); - } } sc->hn_if_flags = ifp->if_flags; @@ -1922,12 +1946,27 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, case SIOCADDMULTI: case SIOCDELMULTI: - /* Always all-multi */ +#ifdef notyet /* - * TODO: - * Enable/disable all-multi according to the emptiness of - * the mcast address list. + * XXX + * Multicast uses mutex, while RNDIS RX filter setting + * sleeps. We workaround this by always enabling + * ALLMULTI. ALLMULTI would actually always be on, even + * if we supported the SIOCADDMULTI/SIOCDELMULTI, since + * we don't support multicast address list configuration + * for this driver. */ + HN_LOCK(sc); + + if ((sc->hn_flags & HN_FLAG_SYNTH_ATTACHED) == 0) { + HN_UNLOCK(sc); + break; + } + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + hn_set_rxfilter(sc); + + HN_UNLOCK(sc); +#endif break; case SIOCSIFMEDIA: @@ -2035,8 +2074,8 @@ hn_init_locked(struct hn_softc *sc) if (ifp->if_drv_flags & IFF_DRV_RUNNING) return; - /* TODO: add hn_rx_filter */ - hn_rndis_set_rxfilter(sc, NDIS_PACKET_TYPE_PROMISCUOUS); + /* Configure RX filter */ + hn_set_rxfilter(sc); /* Clear OACTIVE bit. */ atomic_clear_int(&ifp->if_drv_flags, IFF_DRV_OACTIVE); @@ -2363,6 +2402,21 @@ hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS) } static int +hn_rxfilter_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct hn_softc *sc = arg1; + char filter_str[128]; + uint32_t filter; + + HN_LOCK(sc); + filter = sc->hn_rx_filter; + HN_UNLOCK(sc); + snprintf(filter_str, sizeof(filter_str), "%b", filter, + NDIS_PACKET_TYPES); + return sysctl_handle_string(oidp, filter_str, sizeof(filter_str), req); +} + +static int hn_rss_key_sysctl(SYSCTL_HANDLER_ARGS) { struct hn_softc *sc = arg1; @@ -3783,6 +3837,7 @@ hn_suspend_data(struct hn_softc *sc) * Disable RX by clearing RX filter. */ hn_rndis_set_rxfilter(sc, 0); + sc->hn_rx_filter = 0; /* * Give RNDIS enough time to flush all pending data packets. @@ -3870,9 +3925,8 @@ hn_resume_data(struct hn_softc *sc) /* * Re-enable RX. - * TODO: add hn_rx_filter. */ - hn_rndis_set_rxfilter(sc, NDIS_PACKET_TYPE_PROMISCUOUS); + hn_set_rxfilter(sc); /* * Make sure to clear suspend status on "all" TX rings, Modified: head/sys/net/rndis.h ============================================================================== --- head/sys/net/rndis.h Mon Oct 24 05:01:34 2016 (r307842) +++ head/sys/net/rndis.h Mon Oct 24 05:10:35 2016 (r307843) @@ -351,7 +351,7 @@ struct rndis_keepalive_comp { uint32_t rm_status; }; -/* packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */ +/* Packet filter bits used by OID_GEN_CURRENT_PACKET_FILTER */ #define NDIS_PACKET_TYPE_DIRECTED 0x00000001 #define NDIS_PACKET_TYPE_MULTICAST 0x00000002 #define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 @@ -365,6 +365,14 @@ struct rndis_keepalive_comp { #define NDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 #define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000 +/* + * Packet filter description for use with printf(9) %b identifier. + */ +#define NDIS_PACKET_TYPES \ + "\20\1DIRECT\2MULTICAST\3ALLMULTI\4BROADCAST" \ + "\5SRCROUTE\6PROMISC\7SMT\10ALLLOCAL" \ + "\11GROUP\12ALLFUNC\13FUNC\14MACFRAME" + /* RNDIS offsets */ #define RNDIS_HEADER_OFFSET ((uint32_t)sizeof(struct rndis_msghdr)) #define RNDIS_DATA_OFFSET \