VMQ 接收路径

仅当网络适配器通过针对该队列上设置的筛选器的所有筛选器字段测试时,网络适配器才会指示队列上收到的数据包。 有关筛选器测试的详细信息,请参阅 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 队列)。

协议驱动程序在 NdisReturnNetBufferListsReturnFlags 参数上设置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_IDNET_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 结构。

NET_BUFFER_DATA结构中 MDL 中的字节计数和字节偏移量和 DataLength 和 DataOffset 成员的设置方式与为不使用 VMQ 的驱动程序设置的字节计数和字节偏移量相同。 可以在初始化期间设置 SharedMemoryInfo 结构中的 SharedMemoryLengthSharedMemoryOffset 成员。 微型端口驱动程序不需要更新收到的每个数据包的 SharedMemoryLength 和 SharedMemoryOffset 成员,因为过度分配的驱动程序和 NDIS 可以使用 NET_BUFFER DataLength 成员和 MDL 字节计数来确定数据包的开始和大小。

请注意 ,从 NDIS 6.30 和 Windows Server 2012 开始,不再支持将数据包数据拆分为单独的看头缓冲区。 过度的协议驱动程序不会设置 NDIS_RECEIVE_QUEUE_PARAMETERS_LOOKAHEAD_SPLIT_REQUIRED 标志。