只有当网络适配器在队列上设置的筛选器通过所有字段测试时,才会指示接收到的数据包。 有关筛选器测试的详细信息,请参阅 VMQ 筛选器作。
如果上层协议驱动程序在 NDIS_RECEIVE_QUEUE_PARAMETERS 结构的 Flags 成员中设置了 NDIS_RECEIVE_QUEUE_PARAMETERS_PER_QUEUE_RECEIVE_INDICATION 标志,则微型端口驱动程序不得将其他接收队列的 NET_BUFFER_LIST 结构与此队列的 NET_BUFFER_LIST 结构混合在对 NdisMIndicateReceiveNetBufferLists 函数的单次调用中。 此外,驱动程序必须在 NdisMIndicateReceiveNetBufferLists 函数的 ReceiveFlags 参数中设置NDIS_RECEIVE_FLAGS_SINGLE_QUEUE标志。
如果未设置 NDIS_RECEIVE_QUEUE_PARAMETERS_PER_QUEUE_RECEIVE_INDICATION,则微型端口驱动程序可以将来自不同 VM 队列的帧的 NET_BUFFER_LIST 结构链接在一起,并在一次调用 NdisMIndicateReceiveNetBufferLists 时指示它们。 在这种情况下,不需要按队列编号对 NET_BUFFER_LIST 结构的指示链接列表进行排序。 不需要 将不同队列的NET_BUFFER_LIST结构组合在一起。
当协议驱动程序设置NDIS_RETURN_FLAGS_SINGLE_QUEUE并返回接收缓冲区时,NdisReturnNetBufferLists 函数的 NetBufferLists 参数中的所有NET_BUFFER_LIST结构都必须属于同一 VM 队列。 但是,协议驱动程序在一次调用NdisReturnNetBufferLists函数时,不需要返回在一次调用ProtocolReceiveNetBufferLists函数时指示的所有NET_BUFFER_LIST结构。 此外,返回的列表可以包含多个接收指示中的 NET_BUFFER_LIST 结构,只要它们属于同一 VM 队列。
协议驱动程序在 NdisReturnNetBufferLists 的 ReturnFlags 参数上设置NDIS_RETURN_FLAGS_SINGLE_QUEUE位,以指示返回的所有NET_BUFFER_LIST结构都属于同一 VM 队列。
VMQ 接收指示必须在NET_BUFFER_LIST结构的 NetBufferListInfo 成员中包含以下带外 (OOB) 信息。
在 NetBufferListFilteringInfo 信息中指定队列标识符。
将 NetBufferListFilteringInfo 信息中的筛选器标识符设置为零。
NetBufferListFilteringInfo 信息是在NDIS_NET_BUFFER_LIST_FILTERING_INFO结构中指定的。 若要访问 NET_BUFFER_LIST OOB 数据中的NDIS_NET_BUFFER_LIST_FILTERING_INFO结构,NDIS 驱动程序调用 NET_BUFFER_LIST_INFO 宏并指定 NetBufferListFilteringInfo 信息类型。
若要直接访问筛选器标识符和队列标识符,请使用 NET_BUFFER_LIST_RECEIVE_FILTER_ID 和 NET_BUFFER_LIST_RECEIVE_QUEUE_ID 宏。
VMQ 接收指示必须在NET_BUFFER结构的 SharedMemoryInfo 成员处定义共享内存信息。
注意 在删除 VMQ 时(例如,在 VM 实时迁移期间),微型端口驱动程序可能会接收到包含无效 QueueId 值的 NBL。 如果发生这种情况,微型端口应忽略无效的队列 ID 并使用 0(默认队列)。 QueueId 位于 NBL OOB 数据的 NetBufferListFilteringInfo 部分中,并使用 NET_BUFFER_LIST_RECEIVE_QUEUE_ID 宏进行检索。
若要指示 SharedMemoryInfo 上的NET_BUFFER_SHARED_MEMORY指针有效,微型端口驱动程序必须在 NdisMIndicateReceiveNetBufferLists 函数的 ReceiveFlags 参数中设置NDIS_RECEIVE_FLAGS_SHARED_MEMORY_INFO_VALID标志。 有关 VMQ 接收缓冲区中共享内存缓冲区布局的详细信息,请参阅 接收缓冲区中的共享内存。
接收指示必须在 NET_BUFFER_SHARED_MEMORY 结构中包含以下信息。
NextSharedMemorySegment
指向 NULL 终止链接列表中下一个 NET_BUFFER_SHARED_MEMORY 结构的指针。
SharedMemoryHandle
NdisAllocateSharedMemory 返回的 NDIS 共享内存句柄。
SharedMemoryOffset
从共享内存缓冲区的开头到数据的起始位置的偏移量(以字节为单位)。
SharedMemoryLength
共享内存段的长度(以字节为单位)。
如果过度协议驱动程序在 NDIS_RECEIVE_QUEUE_PARAMETERS 结构的 Flags 成员中设置 NDIS_RECEIVE_QUEUE_PARAMETERS_LOOKAHEAD_SPLIT_REQUIRED 标志,则每个 NET_BUFFER 包括:
两个 MDL 和相应的 SharedMemoryInfo 结构。
带回填空间的后看头缓冲区。
如有必要,协议驱动程序会将 lookahead 缓冲区的内容复制到回填区域。 但是,即使数据包完全位于 lookahead 缓冲区中,回填空间也必须存在。
如果上层驱动程序未设置 NDIS_RECEIVE_QUEUE_PARAMETERS_LOOKAHEAD_SPLIT_REQUIRED 标志,则每个 NET_BUFFER 结构包括单个 MDL 和单个 SharedMemoryInfo 结构。
MDL 中的字节计数和字节偏移量以及NET_BUFFER_DATA结构中的 DataLength 和 DataOffset 成员的设置方式与为不使用 VMQ 的驱动程序设置字节计数和字节偏移量的方式相同。 可以在初始化期间设置 SharedMemoryLength 和 SharedMemoryOffset 成员在 SharedMemoryInfo 结构中。 微型端口驱动程序不需要更新收到的每个数据包的 SharedMemoryLength 和 SharedMemoryOffset 成员,因为过度分配的驱动程序和 NDIS 可以使用 NET_BUFFERDataLength 成员和 MDL 字节计数来确定数据包的开始和大小。
注意 从 NDIS 6.30 和 Windows Server 2012 开始,不再支持将数据包数据拆分为单独的看头缓冲区。 上层协议驱动程序不会设置NDIS_RECEIVE_QUEUE_PARAMETERS_LOOKAHEAD_SPLIT_REQUIRED标志。