Receiving Network Data

The following figure illustrates a basic receive operation, which involves a miniport driver, NDIS, and a protocol driver.

diagram illustrating a basic receive operation

Miniport drivers call the NdisMIndicateReceiveNetBufferLists function to indicated NET_BUFFER structures to higher level drivers. Every NET_BUFFER structure should usually be attached to a separate NET_BUFFER_LIST structure. This allows protocol drivers to create a subset of the original list of NET_BUFFER_LIST structures and forward them to different clients. Some drivers, for example native IEEE 802.11 miniport drivers, might attach more than one NET_BUFFER structure to a NET_BUFFER_LIST structure.

After linking all the NET_BUFFER_LIST structures, a miniport driver passes a pointer to the first NET_BUFFER_LIST structure in the list to the NdisMIndicateReceiveNetBufferLists function. NDIS examines the NET_BUFFER_LIST structures and it calls the ProtocolReceiveNetBufferLists function of each protocol driver that is associated with the NET_BUFFER_LIST structures. NDIS passes a subset of the list that includes only the NET_BUFFER_LIST structures that are associated with the correct binding to each protocol driver. NDIS matches the NetBufferListFrameType value that is specified in the NET_BUFFER_LIST structure to the frame type that each protocol driver registers.

If the NDIS_RECEIVE_FLAGS_RESOURCES flag in the ReceiveFlags parameter that is passed to a protocol driver's ProtocolReceiveNetBufferLists function is set, NDIS regains the ownership of the NET_BUFFER_LIST structures immediately after the ProtocolReceiveNetBufferLists call returns.

Note If the NDIS_RECEIVE_FLAGS_RESOURCES flag is set, the protocol driver must retain the original set of NET_BUFFER_LIST structures in the linked list. For example, when this flag is set the driver might process the structures and indicate them up the stack one at a time but before the function returns it must restore the original linked list.

If the NDIS_RECEIVE_FLAGS_RESOURCES flag in the ReceiveFlags parameter that is passed to a protocol driver's ProtocolReceiveNetBufferLists function is not set, the protocol driver can retain ownership of the NET_BUFFER_LIST structures. In this case, the protocol driver must return the NET_BUFFER_LIST structures by calling the NdisReturnNetBufferLists function.

If a miniport driver is running low on receive resources, it can set the NDIS_RECEIVE_FLAGS_RESOURCES flag in the ReceiveFlags parameter in the call to NdisMIndicateReceiveNetBufferLists. In that case, the driver can reclaim the ownership of all the indicated NET_BUFFER_LIST structures and embedded NET_BUFFER structures as soon as NdisMIndicateReceiveNetBufferLists returns. Indicating NET_BUFFER structures with the NDIS_RECEIVE_FLAGS_RESOURCES flag set forces the protocol drivers to copy the data and therefore should be avoided. A miniport driver should detect when it is about to run out of receive resources and take any steps that are necessary to avoid this situation.

NDIS calls a miniport driver's MiniportReturnNetBufferLists function after the protocol driver calls NdisReturnNetBufferLists.

Note If a miniport driver indicates a NET_BUFFER_LIST structure with the NDIS_RECEIVE_FLAGS_RESOURCES flag set, that does not mean that NDIS will indicate the NET_BUFFER_LIST structure to the protocol driver with the same status. For example, NDIS could copy a NET_BUFFER_LIST structure with the NDIS_RECEIVE_FLAGS_RESOURCES flag set and indicate the copy to the protocol driver with the flag cleared.

NDIS can return NET_BUFFER_LIST structures to the miniport driver in any arbitrary order and in any combination. That is, the linked list of NET_BUFFER_LIST structures returned back to a miniport driver by a call to its MiniportReturnNetBufferLists function, can have NET_BUFFER_LIST structures from different previous calls to NdisMIndicateReceiveNetBufferLists.

Miniport drivers should set the SourceHandle member in the NET_BUFFER_LIST structures to the MiniportAdapterHandle that NDIS provided to the miniport driver in the MiniportInitializeEx function. Filter drivers must set the SourceHandle member of each NET_BUFFER_LIST structure that the filter driver originated to the filter's NdisFilterHandle that NDIS provided to the filter driver in the FilterAttach function. Filter drivers must not modify the SourceHandle member in any NET_BUFFER_LIST structures that were not originated by the filter driver.

Intermediate drivers also set the SourceHandle member in the NET_BUFFER_LIST structure to the MiniportAdapterHandle value that NDIS provided to the intermediate driver in the MiniportInitializeEx function. If an intermediate driver forwards a receive indication, the driver must save the SourceHandle value that the underlying driver provided before it writes to the SourceHandle member. When NDIS returns a forwarded NET_BUFFER_LIST structure to the intermediate driver, the intermediate driver must restore the SourceHandle that it saved.