hyperv/hn: Fix RX filter settings.
MFC after: 1 week Sponsored by: Microsoft Differential Revision: https://reviews.freebsd.org/D8313
This commit is contained in:
parent
951eda704f
commit
5dd046f63c
@ -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;
|
||||
|
@ -326,6 +326,7 @@ static int hn_tx_conf_int_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
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);
|
||||
@ -454,6 +456,43 @@ hn_sendpkt_rndis_chim(struct hn_tx_ring *txr, struct hn_txdesc *txd)
|
||||
&rndis, sizeof(rndis), &txd->send_ctx));
|
||||
}
|
||||
|
||||
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,32 +1882,14 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
HN_UNLOCK(sc);
|
||||
@ -1922,12 +1946,27 @@ hn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
|
||||
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);
|
||||
@ -2362,6 +2401,21 @@ hn_hwassist_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
return sysctl_handle_string(oidp, assist_str, sizeof(assist_str), req);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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,
|
||||
|
@ -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 \
|
||||
|
Loading…
Reference in New Issue
Block a user