VMQ Receive Path

A network adapter indicates a received packet on a queue only if it passes all the filter field tests for a filter that is set on that queue. For more information about filter tests, see VMQ Filter Operations.

If the overlying protocol driver set the NDIS_RECEIVE_QUEUE_PARAMETERS_PER_QUEUE_RECEIVE_INDICATION flag in the Flags member of the NDIS_RECEIVE_QUEUE_PARAMETERS structure, the miniport driver must not mix NET_BUFFER_LIST structures for other receive queues with the NET_BUFFER_LIST structures for this queue in a single call to the NdisMIndicateReceiveNetBufferLists function. Also, the driver must set the NDIS_RECEIVE_FLAGS_SINGLE_QUEUE flag in the ReceiveFlags parameter of the NdisMIndicateReceiveNetBufferLists function.

If NDIS_RECEIVE_QUEUE_PARAMETERS_PER_QUEUE_RECEIVE_INDICATION was not set, miniport drivers can link NET_BUFFER_LIST structures for frames from different VM queues and indicate them in a single call to NdisMIndicateReceiveNetBufferLists. In this case, the indicated linked list of NET_BUFFER_LIST structures is not required to be sorted by queue number. NET_BUFFER_LIST structures for different queues are not required to be grouped together.

When a protocol driver sets NDIS_RETURN_FLAGS_SINGLE_QUEUE and it returns receive buffers, all of the NET_BUFFER_LIST structures in the NetBufferLists parameter of the NdisReturnNetBufferLists function must belong to the same VM queue. However, protocol drivers are not required to return all the NET_BUFFER_LIST structures that were indicated in a single call to the ProtocolReceiveNetBufferLists function in a single call to NdisReturnNetBufferLists. Also, the returned list can include NET_BUFFER_LIST structures from multiple receive indications if they belong to the same VM queue.

Protocol drivers set the NDIS_RETURN_FLAGS_SINGLE_QUEUE bit on the ReturnFlags parameter of NdisReturnNetBufferLists to indicate that all of the returned NET_BUFFER_LIST structures belong to the same VM queue.

VMQ receive indications must include the following out of band (OOB) information in the NetBufferListInfo member of the NET_BUFFER_LIST structures.

  • Specify the queue identifier in the NetBufferListFilteringInfo information.

  • Set the filter identifier in the NetBufferListFilteringInfo information to zero.

The NetBufferListFilteringInfo information is specified in an NDIS_NET_BUFFER_LIST_FILTERING_INFO structure. To access the NDIS_NET_BUFFER_LIST_FILTERING_INFO structure in the NET_BUFFER_LIST OOB data, an NDIS driver calls the NET_BUFFER_LIST_INFO macro and specifies the NetBufferListFilteringInfo information type.

To access the filter identifier and queue identifier directly, use the NET_BUFFER_LIST_RECEIVE_FILTER_ID and NET_BUFFER_LIST_RECEIVE_QUEUE_ID macros.

VMQ receive indications must define shared memory information at the SharedMemoryInfo member of the NET_BUFFER structure.

Note  When a VMQ is deleted (for example, during VM live migration), it is possible for the miniport driver to receive an NBL that contains an invalid QueueId value. If this happens, the miniport should ignore the invalid queue ID and use 0 (the default queue) instead. The QueueId is found in the NetBufferListFilteringInfo portion of the NBL's OOB data, and is retrieved by using the NET_BUFFER_LIST_RECEIVE_QUEUE_ID macro.

To indicate that the NET_BUFFER_SHARED_MEMORY pointer at SharedMemoryInfo is valid, the miniport driver must set the NDIS_RECEIVE_FLAGS_SHARED_MEMORY_INFO_VALID flag in the ReceiveFlags parameter of the NdisMIndicateReceiveNetBufferLists function. For more information about the layout of shared memory buffers in VMQ receive buffers, see Shared Memory in Receive Buffers.

The receive indication must include the following information in the NET_BUFFER_SHARED_MEMORY structure.

NextSharedMemorySegment
A pointer to the next NET_BUFFER_SHARED_MEMORY structure in a NULL-terminated linked list of such structures.

SharedMemoryHandle
An NDIS shared memory handle that NdisAllocateSharedMemory returned.

SharedMemoryOffset
An offset, in bytes, to the start of the data from the beginning of the shared memory buffer.

SharedMemoryLength
The length, in bytes, of the shared memory segment.

If the overlying protocol driver set the NDIS_RECEIVE_QUEUE_PARAMETERS_LOOKAHEAD_SPLIT_REQUIRED flag in the Flags member of the NDIS_RECEIVE_QUEUE_PARAMETERS structure, each NET_BUFFER includes:

  • Two MDLs and corresponding SharedMemoryInfo structures.

  • A post-lookahead buffer with backfill space.

If necessary, the protocol driver copies the contents of the lookahead buffer to the backfill area. However, backfill space must exist even if the packet is entirely in the lookahead buffer.

If the overlying driver does not set the NDIS_RECEIVE_QUEUE_PARAMETERS_LOOKAHEAD_SPLIT_REQUIRED flag, each NET_BUFFER structure includes a single MDL and a single SharedMemoryInfo structure.

The byte count and byte offset in the MDL and the DataLength and DataOffset members in the NET_BUFFER_DATA structure are set in the same way as they are set for drivers that do not use VMQ. The SharedMemoryLength and SharedMemoryOffset members in the SharedMemoryInfo structure can be set once during initialization. The miniport driver is not required to update the SharedMemoryLength and SharedMemoryOffset members for every packet that is received because the overlying drivers and NDIS can use the NET_BUFFER DataLength member and the MDL byte count to determine the packet start and size.

Note  Starting with NDIS 6.30 and Windows Server 2012, splitting packet data into separate lookahead buffers is no longer supported. The overlying protocol driver will not set the NDIS_RECEIVE_QUEUE_PARAMETERS_LOOKAHEAD_SPLIT_REQUIRED flag.