设置 VMQ 筛选器

分配接收队列后,过分的驱动程序可以在接收队列上设置筛选器。 只有分配了接收队列的驱动程序才能在该队列上设置筛选器。

注意 由于默认接收队列 (NDIS_DEFAULT_RECEIVE_QUEUE_ID) 始终存在,因此,过分的驱动程序始终可以在默认队列上设置接收筛选器。 过度覆盖的驱动程序不拥有默认队列。 因此,绑定到网络适配器的所有协议驱动程序都可以使用默认队列。

对接收队列设置筛选器

若要使用一组初始配置参数对接收队列设置筛选器,则过分驱动程序 (OID) 请求发出 OID_RECEIVE_FILTER_SET_FILTER方法对象 标识符。 NDIS_OID_REQUEST 结构的 InformationBuffer 成员最初包含指向NDIS_RECEIVE_FILTER_PARAMETERS结构的指针。 从 OID 方法请求成功返回后,NDIS_OID_REQUEST 结构的 InformationBuffer 成员包含指向具有新筛选器标识符的 NDIS_RECEIVE_FILTER_PARAMETERS 结构的指针。

覆盖驱动程序使用以下接收队列的筛选器配置参数初始化 NDIS_RECEIVE_FILTER_PARAMETERS 结构:

  • 通过 NDIS_RECEIVE_FILTER_TYPE 枚举值指定的筛选器类型。

    注意 从 NDIS 6.20 开始,虚拟机队列 (VMQ) 接口仅支持 NdisReceiveFilterTypeVMQueue 筛选器类型。

  • 队列标识符。

  • 格式化为 NDIS_RECEIVE_FILTER_FIELD_PARAMETERS 结构的一个或多个字段测试参数。 对于 VMQ,定义了以下字段测试参数。

    • 数据包中的目标媒体访问控制 (MAC) 地址等于指定的 MAC 地址。

    • 数据包中的虚拟 LAN (VLAN) 标识符等于指定的 VLAN 标识符。

NDIS_RECEIVE_FILTER_PARAMETERS 结构与 OID_RECEIVE_FILTER_PARAMETERS OID 和 OID_RECEIVE_FILTER_SET_FILTER OID 一起使用,以指定筛选器的配置参数。

NDIS_RECEIVE_FILTER_PARAMETERS 结构的 FieldParametersArrayOffsetFieldParametersArrayNumElementsFieldParametersArrayElementSize 成员定义NDIS_RECEIVE_FILTER_FIELD_PARAMETERS结构的数组。 数组中的每个 NDIS_RECEIVE_FILTER_FIELD_PARAMETERS 结构为网络标头中的一个字段设置筛选器测试条件。

NDIS_RECEIVE_FILTER_FIELD_PARAMETERS 结构的 Flags 成员指定要对接收筛选器执行的操作。 以下几点适用于 NDIS_RECEIVE_FILTER_FIELD_MAC_HEADER_VLAN_UNTAGGED_OR_ZERO 标志:

  • 如果在 NDIS_RECEIVE_FILTER_FIELD_PARAMETERS 结构的 Flags 成员中设置了 NDIS_RECEIVE_FILTER_FIELD_MAC_HEADER_VLAN_UNTAGGED_OR_ZERO 标志,则网络适配器必须仅指示与以下所有测试条件匹配的已接收数据包:

    • 具有匹配 MAC 地址的数据包。

    • 没有 VLAN 标记或 VLAN 标识符为零的数据包。

    如果设置了 NDIS_RECEIVE_FILTER_FIELD_MAC_HEADER_VLAN_UNTAGGED_OR_ZERO 标志,则网络适配器不得指示具有匹配 MAC 地址和非零 VLAN 标识符的数据包。

    注意 如果 Hyper-V 可扩展交换机设置 MAC 地址筛选器,并且 未在 OID_RECEIVE_FILTER_SET_FILTER 中配置 VLAN 标识符筛选器,则交换机还会设置 NDIS_RECEIVE_FILTER_FIELD_MAC_HEADER_VLAN_UNTAGGED_OR_ZERO 标志。

  • 如果未设置 NDIS_RECEIVE_FILTER_FIELD_MAC_HEADER_VLAN_UNTAGGED_OR_ZERO 标志,并且没有由 OID_RECEIVE_FILTER_SET_FILTER 的 OID 集请求配置的 VLAN 标识符筛选器,微型端口驱动程序必须执行以下操作之一:

    • 如果微型端口驱动程序支持 NDIS 6.20,则必须返回 OID_RECEIVE_FILTER_SET_FILTER的 OID 请求的失败状态。

    • 如果微型端口驱动程序支持 NDIS 6.30 或更高版本的 NDIS,则必须配置网络适配器以检查和筛选指定的 MAC 地址字段。 如果收到的数据包中存在 VLAN 标记,则网络适配器必须将其从数据包数据中删除。 微型端口驱动程序必须将 VLAN 标记放在与数据包 NET_BUFFER_LIST 结构关联的 NDIS_NET_BUFFER_LIST_8021Q_INFO 中。

  • 如果协议驱动程序使用 OID_RECEIVE_FILTER_SET_FILTER OID 设置 MAC 地址筛选器和 VLAN 标识符筛选器,则不会在任一筛选器字段中设置 NDIS_RECEIVE_FILTER_FIELD_MAC_HEADER_VLAN_UNTAGGED_OR_ZERO 标志。 在这种情况下,微型端口驱动程序应指示与指定的 MAC 地址和 VLAN 标识符匹配的数据包。 也就是说,微型端口驱动程序不应指示具有匹配 MAC 地址的数据包,这些数据包具有零 VLAN 标识符或未标记的数据包。

使用筛选器标识符

NDIS 在 NDIS_RECEIVE_FILTER_PARAMETERS 结构的 FilterId 成员中分配筛选器标识符,并将OID_RECEIVE_FILTER_SET_FILTER的 OID 方法请求传递给基础微型端口驱动程序。 在接收队列上设置的每个筛选器都具有网络适配器的唯一筛选器标识符。 也就是说,筛选器标识符不会在网络适配器管理的不同队列上重复。

覆盖驱动程序必须使用 NDIS 在以后的 OID 请求中提供的筛选器标识符;例如,修改筛选器参数或释放筛选器。

当 NDIS 收到 OID 请求以在接收队列上设置筛选器时,它会验证筛选器参数。 NDIS 分配必要的资源和筛选器标识符后,会将 OID 请求提交到基础网络适配器。 如果网络适配器可以成功为筛选器分配必要的软件和硬件资源,则会使用 NDIS_STATUS_SUCCESS完成 OID 请求。

微型端口驱动程序必须保留分配的接收筛选器的筛选器标识符。 NDIS 使用筛选器的筛选器标识符和后面的 OID 请求,以更改接收筛选器参数或清除接收筛选器。 有关如何更改参数和清除筛选器的详细信息,请参阅 获取和更新 VM 队列参数清除 VMQ 筛选器

处理接收队列上的筛选器

微型端口驱动程序按以下方式基于筛选器对网络适配器进行程序设置:

  • 特定筛选器的所有字段测试参数必须匹配,才能将数据包分配给队列。

  • 可以在一个队列上设置多个筛选器。

  • 如果任何筛选器通过,则必须将数据包分配给接收队列。

网络适配器将所有现场测试的结果与逻辑 AND 操作组合在一起。 也就是说,如果 NDIS_RECEIVE_FILTER_FIELD_PARAMETERS 结构数组中包含的任何现场测试失败,则网络数据包不符合指定的筛选条件。

当网络适配器根据这些筛选条件测试收到的数据包时,它必须忽略数据包中未指定测试条件的所有字段。

从接收队列接收数据包

微型端口驱动程序收到 OID_RECEIVE_FILTER_QUEUE_ALLOCATION_COMPLETE 请求并在队列中设置了筛选器后,队列将处于 “正在运行” 状态。 当队列处于此状态时,微型端口驱动程序可以指示队列上的数据包。 有关队列状态的详细信息,请参阅 队列状态和操作

如果微型端口驱动程序已收到 队列OID_RECEIVE_FILTER_QUEUE_ALLOCATION_COMPLETE OID 请求,但没有在队列上设置筛选器,则微型端口驱动程序不得指示该队列上的任何接收数据包。 在这种情况下,当微型端口驱动程序收到 队列的OID_RECEIVE_FILTER_SET_FILTER OID 请求,并且可能在完成 OID 请求之前,它可以指示该队列上的数据包。 如果微型端口驱动程序在处理OID_RECEIVE_FILTER_SET_FILTER OID 请求时指示队列上的数据包,则微型端口驱动程序必须完成具有NDIS_STATUS_SUCCESS返回代码的 OID_RECEIVE_FILTER_SET_FILTER 请求。