这些都是很好的问题。
是否可以加载驱动程序但仅在特定接口上运行过滤器
是的。你在这里有三个选择。
- 在用户模式下静态禁用绑定;或者
- 在运行时拒绝绑定。
- 动态绕过并重新启用数据路径。(这里不会详细介绍,因为它已经在 MSDN 上进行了概述。)
要静态禁用绑定,您可以使用INetCfg API查找过滤器驱动程序和 NIC 之间的绑定,然后禁用它。这可能看起来像:
INetCfg::Initialize
myFilter = INetCfg::FindComponent
myFilter->QueryInterface(INetCfgComponentBindings)
for each binding in bindings
if binding is to undesirable NIC
INetCfgBindingPath::Enable(FALSE)
安装驱动程序后,您可以随时执行此操作。因此,例如,您的用户模式应用程序可能决定仅在其 GUI 运行时启用与某些 NIC 的绑定。
但是运行用户模式代码并不总是很方便,而且如果您的驱动程序还没有用户模式存在,那么创建一个只是为了禁用一些绑定可能有点矫枉过正。这是第二种技术派上用场的地方。您可以在用户模式下静态启用绑定,但在运行时拒绝绑定。
你如何拒绝在运行时绑定?在许多情况下,您所要做的就是从FilterAttach
处理程序返回失败状态。这足以让 NDIS 相信您的过滤器不能(或不会)连接到 NIC。但是 — 如果您的过滤器被标记为强制(即 INF 的 FilterRunType 为 1),那么您的过滤器失败FilterAttach
将导致 NIC 无法运行。(毕竟,这就是强制要求的全部意义。如果您的过滤器不存在,那么数据路径一定不能运行。)但是如果您想让 NIC 开始运行,请在您的过滤器之前的字段中设置NDIS_FILTER_ATTACH_FLAGS_IGNORE_MANDATORY
标志NDIS_FILTER_ATTACH_PARAMETERS::Flags
从其返回失败代码FilterAttach
。
如果我不对特定接口执行任何操作,那么不必使用 FilterReceiveNetBufferLists 回调似乎会更有效。
你的直觉是正确的。在数据路径中有一个过滤器是有开销的,如果过滤器什么都不做,那就是浪费了 CPU 周期。但是暂时不要取消这个选项。在某些情况下,此选项的简单性超过了其(相对较小的)CPU 成本。也就是说,除非您的目标市场正在计算每个 CPU 周期,否则使用这个简单的选项可能就足够了。
我不想在 DriverEntry 期间使用注册表,因为我仍然需要能够根据需要动态重新分配任务。
如上所述,您可以使用用户模式代码重新分配任务。每次用户模式调用 INetCfg::Apply 时,NDIS 都会调用任何FilterAttach
或FilterDetach
需要进行正确的更改。
当您使用第二种技术时,实际上不可能重新分配任务。如果您确实需要重新分配特定 NIC 的任务,那么您应该使用第一种或第三种技术。
当过滤器模块暂停时,整个堆栈是否会暂停或 NDIS 是否围绕暂停的模块路由?
整个堆栈被暂停。NDIS 不会“绕过”过滤器。(如果您的过滤器是可选的,那么当您的过滤器未运行时,流量将绕过您的过滤器。但只要您的过滤器连接到 NIC,NBL 和 OID 就会通过您的过滤器。)