diff options
author | Michael Brown <mcb30@ipxe.org> | 2014-12-20 12:06:35 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2014-12-20 12:06:35 +0000 |
commit | 67291465ead5d227d1caf28b8a863fca1ad9e952 (patch) | |
tree | 505afece90cb9ed881d9ae8aa275944a346e128b /src | |
parent | cd68d93b6edacb4903b81f3d94af6c3d9aaff6fe (diff) | |
download | ipxe-67291465ead5d227d1caf28b8a863fca1ad9e952.zip ipxe-67291465ead5d227d1caf28b8a863fca1ad9e952.tar.gz ipxe-67291465ead5d227d1caf28b8a863fca1ad9e952.tar.bz2 |
[rndis] Clear receive filter when closing the device
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/net/rndis.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/src/net/rndis.c b/src/net/rndis.c index 62a26ad..e21dd19 100644 --- a/src/net/rndis.c +++ b/src/net/rndis.c @@ -829,6 +829,28 @@ void rndis_rx ( struct rndis_device *rndis, struct io_buffer *iobuf ) { } /** + * 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 * * @v netdev Network device @@ -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 */ @@ -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, @@ -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 ); |