Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Nov 2016 08:57:52 +0000 (UTC)
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r308521 - in stable/11/sys: dev/hyperv/netvsc net
Message-ID:  <201611110857.uAB8vqG0024276@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sephe
Date: Fri Nov 11 08:57:52 2016
New Revision: 308521
URL: https://svnweb.freebsd.org/changeset/base/308521

Log:
  MFC 307843
  
      hyperv/hn: Fix RX filter settings.
  
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8313

Modified:
  stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
  stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  stable/11/sys/net/rndis.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h	Fri Nov 11 08:55:45 2016	(r308520)
+++ stable/11/sys/dev/hyperv/netvsc/hv_net_vsc.h	Fri Nov 11 08:57:52 2016	(r308521)
@@ -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: stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Nov 11 08:55:45 2016	(r308520)
+++ stable/11/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Fri Nov 11 08:57:52 2016	(r308521)
@@ -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: stable/11/sys/net/rndis.h
==============================================================================
--- stable/11/sys/net/rndis.h	Fri Nov 11 08:55:45 2016	(r308520)
+++ stable/11/sys/net/rndis.h	Fri Nov 11 08:57:52 2016	(r308521)
@@ -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	\



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201611110857.uAB8vqG0024276>