包过滤
你的理解是正确的。 NIC 会在硬件中进行大量过滤,以使 CPU 免受过度过滤的影响。通常,典型的以太网 NIC 会有一个可编程的数据包过滤器,它只允许满足特定条件的数据包,例如:
- 目标 MAC 地址与一组可编程目标地址中的一个匹配(通常您会将自己的单播地址以及多个多播地址放入目标集中)。
- 目标地址是广播地址(对于以太网,即
ff-ff-ff-ff-ff-ff)。
- 目标地址是任意多播地址(对于以太网,第一个字节设置了 LSB)
在典型操作中,Windows 将对 NIC 进行编程,以接受发往 NIC 的单播地址、广播地址和少量多播地址(例如,用于 IPv6 邻居发现和 UPnP)的流量。
硬件包过滤器的唯一目的是减少主机的 CPU 使用率。 Windows 不依赖硬件包过滤器来保证功能的正确性。如果表现不佳的 NIC 始终指示所有数据包未过滤,Windows 将自动退回到软件过滤。
更新包过滤器
Windows may modify the packet filter on the hardware。例如,如果您运行 Netmon 或 Wireshark 并启用它们的“混杂模式”,NDIS 将指示 NIC 指示所有流量,即使目标是非本地单播地址。
如果您想进行有趣的实验室实验,请打开 PowerShell 并运行以下命令来查询当前的数据包过滤器:
Get-WmiObject -Namespace root\wmi -Class MSNdis_CurrentPacketFilter |
Format-List InstanceName, NdisCurrentPacketFilter
您可以将它传递给另一个命令以使输出更具可读性:
% { @{ $_.InstanceName = "{0:X8}" -f $_.NdisCurrentPacketFilter } }
包过滤器以整数形式呈现,它是 SDK/WDK 头文件 ntddndis.h 中NDIS_PACKET_TYPE_XXX 常量的位掩码。现在,如果您在 Netmon 或 Wireshark 中启用混杂模式,您应该会看到数据包过滤器更改为包含 NDIS_PACKET_TYPE_PROMISCUOUS 标志 (0x20)。禁用 Netmon 或 Wireshark 将恢复预先存在的数据包过滤器。
其他过滤类型
我刚刚描述了几乎所有以太网 NIC 都支持的最基本级别的数据包过滤。 (Microsoft 需要这种最低级别的支持以及“Device.Network.LAN.Base.PacketFiltering”徽标要求。)更复杂的硬件可以做很酷的事情。
例如,支持多个接收队列的硬件具有多个接收过滤器。 NIC 在不同的 CPU 上分别指示与每个过滤器匹配的数据包,以使管理程序更容易将流量分配到虚拟化来宾操作系统。
免责声明
您的问题同时提到了 OS X 和 NDIS,这是一种 Windows 技术。我的言论仅适用于 NDIS 和 Windows,因为我在 Microsoft 工作。