3.1.3.4 Choosing a Receive Function
Miniports choose between two methods of passing incoming packets to upper
layers.
-
Miniports call NdisMIndicateReceivePacket
to pass a pointer to an array containing one or more pointers to one or more
received packets. When a miniport indicates an array of packet pointers,
entire network packet(s) are passed up to the receiving layer. That is, when
the miniport calls NdisMIndicateReceivePacket, it makes the entire
network packet available to upper layers including any OOB data associated
with each packet descriptor. When NdisMIndicateReceivePacket returns,
ownership of the array that contains the pointers to packet descriptors
reverts to the miniport. Actual packet descriptors and the miniport-allocated
resources they describe may or may not be returned. Any upper layer can choose
to keep a packet and return it later, consume the data in the packet and
return it immediately, or return the packet immediately unread because it is
not interested in the data. This means that when NdisMIndicateReceivePacket
returns, the miniport must not reference any of the individual packets whose
status in the OOB data is set to NDIS_STATUS_PENDING.
-
Miniports call a filter-specific NdisMXxxIndicateReceive
with a pointer to a lookahead buffer. An interested protocol can either copy
the packet (if the packet is small and the entire packet is indicated up) or
call NdisTransferData from its
ProtocolReceive function and let the MiniportTransferData function copy the
entire packet.
If a miniport indicates an array of packets by calling NdisMIndicateReceivePacket,
ownership of the packets can pass to the receiving protocol driver. Such a
miniport must provide a MiniportReturnPacket function. MiniportReturnPacket
will be called for each packet passed up to a protocol driver for which the
protocol driver returns NDIS_STATUS_PENDING in order to return ownership of
the packet resources to the miniport after the protocol has consumed the data.
Any miniport that supports multipacket receive indications:
-
Must allocate enough packet descriptors and insure that it has available
buffers while waiting for an upper layer to return previously indicated
packets. Packet descriptors must be allocated from packet pool.
-
Must allocate enough memory to contain one or more complete network packets
and buffer descriptors mapping the memory so that it can pass a packet or
packets to upper layers. Miniports that force an interested protocol to copy
received data only need a buffer to hold the received data or lookahead
buffer, which in some cases is buffer space on the NIC. Buffer descriptors
must be allocated from buffer pool.
If a miniport uses NdisMXxxIndicateReceive to indicate a
receive packet up to an upper-layer, that miniport must provide a
MiniportTransferData function. The miniport retains ownership of the memory
containing the indicated data and MiniportTransferData will be called to move
the received data from the miniport’s buffer to a packet supplied by the
receiving protocol driver. The buffer containing the received data can be
either a staging buffer or can be buffer space on the NIC.
A miniport chooses to indicate an array of packets by calling NdisMIndicateReceivePacket
-
If its NIC is a high performance busmaster DMA device that receives data in a
ring of buffers for which multiple packets can be allocated, filled, and
indicated up
-
Or, the miniport supports passing media-specific information with incoming
packets
In this case, the miniport must pass an entire packet, described by a packet
descriptor with an associated OOB data block, up to an interested protocol(s)
since the media-specific information is stored in the OOB block. A miniport
for a slow NIC that wants to pass media-specific information may choose the
multipacket receive technique but indicate up one-element packet arrays to
avoid queuing receives.