hyperv/hn: Switch to new RNDIS set for RX filters.

MFC after:	1 week
Sponsored by:	Microsoft
Differential Revision:	https://reviews.freebsd.org/D7683
This commit is contained in:
Sepherosa Ziehau 2016-08-30 03:40:22 +00:00
parent 1010113dad
commit 05bbfc3062

View File

@ -81,10 +81,7 @@ static void hv_rf_receive_data(struct hn_rx_ring *rxr,
const void *data, int dlen);
static inline int hv_rf_query_device_mac(rndis_device *device);
static inline int hv_rf_query_device_link_status(rndis_device *device);
static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
static int hv_rf_init_device(rndis_device *device);
static int hv_rf_open_device(rndis_device *device);
static int hv_rf_close_device(rndis_device *device);
int
hv_rf_send_offload_request(struct hn_softc *sc,
rndis_offload_params *offloads);
@ -679,72 +676,6 @@ static uint8_t netvsc_hash_key[NDIS_HASH_KEYSIZE_TOEPLITZ] = {
0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
};
/*
* RNDIS filter set packet filter
* Sends an rndis request with the new filter, then waits for a response
* from the host.
* Returns zero on success, non-zero on failure.
*/
static int
hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
{
rndis_request *request;
rndis_set_request *set;
rndis_set_complete *set_complete;
uint32_t status;
int ret;
request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
if (request == NULL) {
ret = -1;
goto cleanup;
}
/* Set up the rndis set */
set = &request->request_msg.msg.set_request;
set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
set->info_buffer_length = sizeof(uint32_t);
set->info_buffer_offset = sizeof(rndis_set_request);
memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
&new_filter, sizeof(uint32_t));
ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
if (ret != 0) {
goto cleanup;
}
/*
* Wait for the response from the host. Another thread will signal
* us when the response has arrived. In the failure case,
* sema_timedwait() returns a non-zero status after waiting 5 seconds.
*/
ret = sema_timedwait(&request->wait_sema, 5 * hz);
if (ret == 0) {
/* Response received, check status */
set_complete = &request->response_msg.msg.set_complete;
status = set_complete->status;
if (status != RNDIS_STATUS_SUCCESS) {
/* Bad response status, return error */
ret = -2;
}
} else {
/*
* We cannot deallocate the request since we may still
* receive a send completion for it.
*/
goto exit;
}
cleanup:
if (request != NULL) {
hv_put_rndis_request(device, request);
}
exit:
return (ret);
}
static const void *
hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t rid,
size_t reqlen, size_t *comp_len0, uint32_t comp_type)
@ -1103,6 +1034,25 @@ hn_rndis_conf_rss(struct hn_softc *sc, int nchan)
return (error);
}
static int
hn_rndis_set_rxfilter(struct hn_softc *sc, uint32_t filter)
{
int error;
error = hn_rndis_set(sc, OID_GEN_CURRENT_PACKET_FILTER,
&filter, sizeof(filter));
if (error) {
if_printf(sc->hn_ifp, "set RX filter 0x%08x failed: %d\n",
filter, error);
} else {
if (bootverbose) {
if_printf(sc->hn_ifp, "set RX filter 0x%08x done\n",
filter);
}
}
return (error);
}
/*
* RNDIS filter init device
*/
@ -1210,55 +1160,6 @@ hv_rf_halt_device(rndis_device *device)
return (0);
}
/*
* RNDIS filter open device
*/
static int
hv_rf_open_device(rndis_device *device)
{
int ret;
if (device->state != RNDIS_DEV_INITIALIZED) {
return (0);
}
if (hv_promisc_mode != 1) {
ret = hv_rf_set_packet_filter(device,
NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_ALL_MULTICAST |
NDIS_PACKET_TYPE_DIRECTED);
} else {
ret = hv_rf_set_packet_filter(device,
NDIS_PACKET_TYPE_PROMISCUOUS);
}
if (ret == 0) {
device->state = RNDIS_DEV_DATAINITIALIZED;
}
return (ret);
}
/*
* RNDIS filter close device
*/
static int
hv_rf_close_device(rndis_device *device)
{
int ret;
if (device->state != RNDIS_DEV_DATAINITIALIZED) {
return (0);
}
ret = hv_rf_set_packet_filter(device, 0);
if (ret == 0) {
device->state = RNDIS_DEV_INITIALIZED;
}
return (ret);
}
/*
* RNDIS filter on device add
*/
@ -1442,8 +1343,17 @@ hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
int
hv_rf_on_open(struct hn_softc *sc)
{
uint32_t filter;
return (hv_rf_open_device(sc->rndis_dev));
/* XXX */
if (hv_promisc_mode != 1) {
filter = NDIS_PACKET_TYPE_BROADCAST |
NDIS_PACKET_TYPE_ALL_MULTICAST |
NDIS_PACKET_TYPE_DIRECTED;
} else {
filter = NDIS_PACKET_TYPE_PROMISCUOUS;
}
return (hn_rndis_set_rxfilter(sc, filter));
}
/*
@ -1453,7 +1363,7 @@ int
hv_rf_on_close(struct hn_softc *sc)
{
return (hv_rf_close_device(sc->rndis_dev));
return (hn_rndis_set_rxfilter(sc, 0));
}
static void