diff --git a/adapter.cpp b/adapter.cpp index bb1b9b2..da9da38 100644 --- a/adapter.cpp +++ b/adapter.cpp @@ -59,41 +59,28 @@ Return Value: static void EvtSetReceiveFilter( _In_ NETADAPTER netAdapter, - _In_ NETRECEIVEFILTER receiveFilter) + _In_ NETRECEIVEFILTER Handle) { TraceEntryNetAdapter(netAdapter); RT_ADAPTER* adapter = RtGetAdapterContext(netAdapter); - // PASSIVE_LEVEL, nonpaged (resume path) - NET_PACKET_FILTER_FLAGS flags = NetReceiveFilterGetPacketFilter(receiveFilter); - size_t mcastCount = (flags & NetPacketFilterFlagMulticast) - ? NetReceiveFilterGetMulticastAddressCount(receiveFilter) - : 0; - const NET_ADAPTER_LINK_LAYER_ADDRESS* mcast = mcastCount > 0 ? - NetReceiveFilterGetMulticastAddressList(receiveFilter) - : nullptr; - - /*MacPacketFilter_t filter = {}; - if (flags & NetPacketFilterFlagPromiscuous) + adapter->PacketFilterFlags = NetReceiveFilterGetPacketFilter(Handle); + + adapter->MCAddressCount = (UINT)NetReceiveFilterGetMulticastAddressCount(Handle); + RtlZeroMemory( + adapter->MCList, + sizeof(NET_ADAPTER_LINK_LAYER_ADDRESS) * RT_MAX_MCAST_LIST); + + if (adapter->MCAddressCount != 0U) { - filter.PromiscuousMode = true; + NET_ADAPTER_LINK_LAYER_ADDRESS const* MulticastAddressList = NetReceiveFilterGetMulticastAddressList(Handle); + RtlCopyMemory( + adapter->MCList, + MulticastAddressList, + sizeof(NET_ADAPTER_LINK_LAYER_ADDRESS) * adapter->MCAddressCount); } - else - { - filter.PassAllMulticast = 0 != (flags & NetPacketFilterFlagAllMulticast); - filter.DisableBroadcast = 0 == (flags & NetPacketFilterFlagBroadcast); - SetOneMacAddress(context->regs, 0, context->currentMacAddress, - 0 != (flags & NetPacketFilterFlagDirected)); // Address[0] can't really be disabled... - // Could also use hash-based filtering for additional mcast support, but this seems okay. - auto const macAddrCount = context->feature0.MacAddrCount; - for (unsigned i = 1; i < macAddrCount; i += 1) - { - static constexpr UINT8 zero[ETHERNET_LENGTH_OF_ADDRESS] = {}; - bool const enable = mcastCount > i - 1 && mcast[i - 1].Length >= ETHERNET_LENGTH_OF_ADDRESS; - auto const addr = enable ? mcast[i - 1].Address : zero; - SetOneMacAddress(context->regs, i, addr, enable); - } - }*/ + + re_set_rx_packet_filter(&adapter->bsdData); TraceExit(); } @@ -105,13 +92,8 @@ RtAdapterSetReceiveFilterCapabilities( { NET_ADAPTER_RECEIVE_FILTER_CAPABILITIES rxFilterCaps; NET_ADAPTER_RECEIVE_FILTER_CAPABILITIES_INIT(&rxFilterCaps, EvtSetReceiveFilter); - rxFilterCaps.SupportedPacketFilters = - NetPacketFilterFlagDirected | - NetPacketFilterFlagMulticast | - NetPacketFilterFlagAllMulticast | - NetPacketFilterFlagBroadcast | - NetPacketFilterFlagPromiscuous; - rxFilterCaps.MaximumMulticastAddresses = 1; // TODO: Packet filter. + rxFilterCaps.SupportedPacketFilters = RT_SUPPORTED_FILTERS; + rxFilterCaps.MaximumMulticastAddresses = RT_MAX_MCAST_LIST; NetAdapterSetReceiveFilterCapabilities(adapter->NetAdapter, &rxFilterCaps); } diff --git a/adapter.h b/adapter.h index 3660abf..503ab75 100644 --- a/adapter.h +++ b/adapter.h @@ -3,6 +3,17 @@ #include "if_re_bsd.h" #include "bsdexport.h" +// multicast list size +#define RT_MAX_MCAST_LIST 32 + +// supported filters +#define RT_SUPPORTED_FILTERS ( \ + NetPacketFilterFlagDirected | \ + NetPacketFilterFlagMulticast | \ + NetPacketFilterFlagBroadcast | \ + NetPacketFilterFlagPromiscuous | \ + NetPacketFilterFlagAllMulticast) + #define RT_MAX_TX_QUEUES (2) #define RT_MAX_RX_QUEUES (4) #define RT_MAX_QUEUES RT_MAX_RX_QUEUES @@ -70,6 +81,11 @@ typedef struct _RT_ADAPTER // Pointer to interrupt object RT_INTERRUPT* Interrupt; + // Multicast list + NET_PACKET_FILTER_FLAGS PacketFilterFlags; + UINT MCAddressCount; + NET_ADAPTER_LINK_LAYER_ADDRESS MCList[RT_MAX_MCAST_LIST]; + // Configuration REG_SPEED_SETTING SpeedDuplex; NET_ADAPTER_LINK_LAYER_ADDRESS PermanentAddress; @@ -114,4 +130,11 @@ UINT16 ConfigRead16(_In_ RT_ADAPTER* adapter, UINT32 reg); void ConfigWrite8(_In_ RT_ADAPTER* adapter, UINT32 reg, UINT8 val); void ConfigWrite16(_In_ RT_ADAPTER* adapter, UINT32 reg, UINT16 val); -void RtResetQueues(_In_ RT_ADAPTER* adapter); \ No newline at end of file +void RtResetQueues(_In_ RT_ADAPTER* adapter); + +void +GetMulticastBit( + _In_ NET_ADAPTER_LINK_LAYER_ADDRESS const* address, + _Out_ _Post_satisfies_(*byte < MAX_NIC_MULTICAST_REG) UCHAR* byte, + _Out_ UCHAR* value +); \ No newline at end of file diff --git a/bsdexport.h b/bsdexport.h index d713b1f..73f77b1 100644 --- a/bsdexport.h +++ b/bsdexport.h @@ -24,4 +24,5 @@ void re_hw_d3_para(struct re_softc* sc); int re_ifmedia_upd(struct re_softc* sc); int re_ifmedia_upd_8125(struct re_softc* sc); -void re_rar_set(struct re_softc* sc, u_int8_t* eaddr); \ No newline at end of file +void re_rar_set(struct re_softc* sc, u_int8_t* eaddr); +void re_set_rx_packet_filter(struct re_softc* sc); \ No newline at end of file diff --git a/if_re.vcxproj b/if_re.vcxproj index 8c40c33..7e5146b 100644 --- a/if_re.vcxproj +++ b/if_re.vcxproj @@ -223,6 +223,7 @@ + diff --git a/if_re.vcxproj.Filters b/if_re.vcxproj.Filters index 641a191..dcf853e 100644 --- a/if_re.vcxproj.Filters +++ b/if_re.vcxproj.Filters @@ -71,6 +71,9 @@ Source Files + + Source Files + diff --git a/mcast.cpp b/mcast.cpp new file mode 100644 index 0000000..a55be06 --- /dev/null +++ b/mcast.cpp @@ -0,0 +1,54 @@ +#include "precomp.h" +#include "adapter.h" + +ULONG +ComputeCrc( + _In_reads_(length) UCHAR const* buffer, + UINT length +) +{ + ULONG crc = 0xffffffff; + + for (UINT i = 0; i < length; i++) + { + UCHAR curByte = buffer[i]; + + for (UINT j = 0; j < 8; j++) + { + ULONG carry = ((crc & 0x80000000) ? 1 : 0) ^ (curByte & 0x01); + crc <<= 1; + curByte >>= 1; + + if (carry) + { + crc = (crc ^ 0x04c11db6) | carry; + } + } + } + + return crc; +} + +void +GetMulticastBit( + _In_ NET_ADAPTER_LINK_LAYER_ADDRESS const* address, + _Out_ _Post_satisfies_(*byte < MAX_NIC_MULTICAST_REG) UCHAR* byte, + _Out_ UCHAR* value +) +/*++ + +Routine Description: + + For a given multicast address, returns the byte and bit in + the card multicast registers that it hashes to. Calls + ComputeCrc() to determine the CRC value. + +--*/ +{ + ULONG crc = ComputeCrc(address->Address, address->Length); + + // The bit number is now in the 6 most significant bits of CRC. + UINT bitNumber = (UINT)((crc >> 26) & 0x3f); + *byte = (UCHAR)(bitNumber / 8); + *value = (UCHAR)((UCHAR)1 << (bitNumber % 8)); +} \ No newline at end of file diff --git a/rtlhw.cpp b/rtlhw.cpp index dfc756e..2c7096b 100644 --- a/rtlhw.cpp +++ b/rtlhw.cpp @@ -98,7 +98,7 @@ static void re_clrwol __P((struct re_softc*)); static void re_set_wol_linkspeed __P((struct re_softc*)); #endif -static void re_set_rx_packet_filter __P((struct re_softc*)); +void re_set_rx_packet_filter __P((struct re_softc*)); static void re_eeprom_ShiftOutBits __P((struct re_softc*, int, int)); static u_int16_t re_eeprom_ShiftInBits __P((struct re_softc*)); @@ -5650,20 +5650,55 @@ void re_stop(struct re_softc* sc) { re_reset(sc); } -static void re_set_rx_packet_filter(struct re_softc* sc) { +void re_set_rx_packet_filter(struct re_softc* sc) { u_int32_t rxfilt; - + rxfilt = CSR_READ_4(sc, RE_RXCFG); - rxfilt |= RE_RXCFG_RX_INDIV; + rxfilt &= ~(RE_RXCFG_RX_ALLPHYS | RE_RXCFG_RX_INDIV | + RE_RXCFG_RX_MULTI | RE_RXCFG_RX_BROAD | + RE_RXCFG_RX_RUNT | RE_RXCFG_RX_ERRPKT); + + NET_PACKET_FILTER_FLAGS flags = sc->dev->PacketFilterFlags; - rxfilt |= (RE_RXCFG_RX_ALLPHYS | RE_RXCFG_RX_MULTI); - rxfilt |= RE_RXCFG_RX_BROAD; + if (flags & NetPacketFilterFlagPromiscuous) { + rxfilt |= ( + RE_RXCFG_RX_ALLPHYS | RE_RXCFG_RX_INDIV | + RE_RXCFG_RX_MULTI | RE_RXCFG_RX_BROAD | + RE_RXCFG_RX_RUNT | RE_RXCFG_RX_ERRPKT + ); + } + else { + rxfilt |= ((flags & NetPacketFilterFlagAllMulticast) ? (RE_RXCFG_RX_ALLPHYS | RE_RXCFG_RX_MULTI) : 0); + rxfilt |= ((flags & NetPacketFilterFlagMulticast) ? (RE_RXCFG_RX_ALLPHYS | RE_RXCFG_RX_MULTI) : 0); + rxfilt |= ((flags & NetPacketFilterFlagBroadcast) ? RE_RXCFG_RX_BROAD : 0); + rxfilt |= ((flags & NetPacketFilterFlagDirected) ? RE_RXCFG_RX_INDIV : 0); + } CSR_WRITE_4(sc, RE_RXCFG, rxfilt); - u_int32_t mask0 = 0xffffffff; - u_int32_t mask4 = 0xffffffff; + typedef union { + struct { + uint32_t mask0; + uint32_t mask4; + }; + uint8_t bytes[32]; + } MarRegs; + + MarRegs regs = { 0 }; + + if (flags & (NetPacketFilterFlagPromiscuous | NetPacketFilterFlagAllMulticast)) { + regs.mask0 = 0xffffffff; + regs.mask4 = 0xffffffff; + } + else { + for (UINT i = 0; i < sc->dev->MCAddressCount; i++) { + UCHAR byte, bit; + NET_ADAPTER_LINK_LAYER_ADDRESS address = sc->dev->MCList[i]; + GetMulticastBit(&sc->dev->MCList[i], &byte, &bit); + regs.bytes[byte] |= bit; + } + } u_int8_t enable_cfg_reg_write = 0; @@ -5672,8 +5707,10 @@ static void re_set_rx_packet_filter(struct re_softc* sc) { if (enable_cfg_reg_write) re_enable_cfg9346_write(sc); - CSR_WRITE_4(sc, RE_MAR0, mask0); - CSR_WRITE_4(sc, RE_MAR4, mask4); + + CSR_WRITE_4(sc, RE_MAR0, regs.mask0); + CSR_WRITE_4(sc, RE_MAR4, regs.mask4); + if (enable_cfg_reg_write) re_disable_cfg9346_write(sc); }