Skip to content

Commit

Permalink
[rndis] Clear receive filter when closing the device
Browse files Browse the repository at this point in the history
On Windows Server 2012 R2, closing and reopening the device will
sometimes result in a non-functional RX datapath.  The root cause is
unknown.  Clearing the receive filter before closing the device seems
to fix the problem.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Dec 20, 2014
1 parent cd68d93 commit 6729146
Showing 1 changed file with 30 additions and 11 deletions.
41 changes: 30 additions & 11 deletions src/net/rndis.c
Expand Up @@ -828,6 +828,28 @@ void rndis_rx ( struct rndis_device *rndis, struct io_buffer *iobuf ) {
netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}

/**
* Set receive filter
*
* @v rndis RNDIS device
* @v filter Receive filter
* @ret rc Return status code
*/
static int rndis_filter ( struct rndis_device *rndis, unsigned int filter ) {
uint32_t value = cpu_to_le32 ( filter );
int rc;

/* Set receive filter */
if ( ( rc = rndis_oid ( rndis, RNDIS_OID_GEN_CURRENT_PACKET_FILTER,
&value, sizeof ( value ) ) ) != 0 ) {
DBGC ( rndis, "RNDIS %s could not set receive filter to %#08x: "
"%s\n", rndis->name, filter, strerror ( rc ) );
return rc;
}

return 0;
}

/**
* Open network device
*
Expand All @@ -836,7 +858,6 @@ void rndis_rx ( struct rndis_device *rndis, struct io_buffer *iobuf ) {
*/
static int rndis_open ( struct net_device *netdev ) {
struct rndis_device *rndis = netdev->priv;
uint32_t filter;
int rc;

/* Open RNDIS device */
Expand All @@ -851,17 +872,12 @@ static int rndis_open ( struct net_device *netdev ) {
goto err_initialise;

/* Set receive filter */
filter = cpu_to_le32 ( RNDIS_FILTER_UNICAST |
RNDIS_FILTER_MULTICAST |
RNDIS_FILTER_ALL_MULTICAST |
RNDIS_FILTER_BROADCAST |
RNDIS_FILTER_PROMISCUOUS );
if ( ( rc = rndis_oid ( rndis, RNDIS_OID_GEN_CURRENT_PACKET_FILTER,
&filter, sizeof ( filter ) ) ) != 0 ) {
DBGC ( rndis, "RNDIS %s could not set receive filter: %s\n",
rndis->name, strerror ( rc ) );
if ( ( rc = rndis_filter ( rndis, ( RNDIS_FILTER_UNICAST |
RNDIS_FILTER_MULTICAST |
RNDIS_FILTER_ALL_MULTICAST |
RNDIS_FILTER_BROADCAST |
RNDIS_FILTER_PROMISCUOUS ) ) ) != 0)
goto err_set_filter;
}

/* Update link status */
if ( ( rc = rndis_oid ( rndis, RNDIS_OID_GEN_MEDIA_CONNECT_STATUS,
Expand All @@ -887,6 +903,9 @@ static int rndis_open ( struct net_device *netdev ) {
static void rndis_close ( struct net_device *netdev ) {
struct rndis_device *rndis = netdev->priv;

/* Clear receive filter */
rndis_filter ( rndis, 0 );

/* Halt RNDIS device */
rndis_halt ( rndis );

Expand Down

0 comments on commit 6729146

Please sign in to comment.