Transmitting Packets Through an Intermediate Driver (NDIS 5.1)
Note NDIS 5. x has been deprecated and is superseded by NDIS 6. x. For new NDIS driver development, see Network Drivers Starting with Windows Vista. For information about porting NDIS 5. x drivers to NDIS 6. x, see Porting NDIS 5.x Drivers to NDIS 6.0.
As discussed in Registering an Intermediate Driver as a Miniport, an intermediate driver must provide a MiniportSendPacketsfunction when it registers with NdisIMRegisterLayeredMiniport. The MiniportSendPacketsfunction can forward incoming packet arrays by calling NdisSendPacketsif the driver has a connectionless lower edge or NdisCoSendPacketsif the driver has a connection-oriented lower edge. MiniportSendPacketscan send the array of packets it receives with NdisSendPacketswithout regard to the capabilities of the underlying miniport driver. NDIS can, transparently to the intermediate driver, queue the packets in the array and send each individual packet to the underlying connectionless miniport driver's MiniportSendfunction when the miniport driver is able to accept the send request.
An NDIS 4.0 or 5.0 intermediate driver will, at a minimum, replace the packet descriptor for each incoming send with its own. It must retain the original descriptor (and chained buffers if it copies them to new buffers) from the higher-level driver and, when the send completes, the intermediate driver must return the original packet descriptor and the data buffers of the as-sent packet before completing the send back to the higher-level driver.
In most common cases, an NDIS 5.1 intermediate driver that implements packet-stacking will not have to allocate a new packet descriptor. For more information about how to allocate packet resources and copy information from one packet to another, see Intermediate Driver Packet Management.
MiniportSendPacketsreceives an array of packet descriptors arranged in an order determined by the caller of NdisSendPackets. In most cases, the intermediate driver should maintain this ordering as it passes an incoming array of packets on to the underlying miniport driver. An intermediate driver that modifies per-packet information or OOB data in incoming packets before passing them on to the underlying driver might reorder an incoming array.
NDIS always preserves the ordering of packet descriptor pointers as passed as an array to NdisSendPackets. The underlying miniport driver also assumes that an array of packet pointers passed in to its MiniportSendPacketsfunction implies the packets should be transmitted in the same order.
An intermediate driver with a connectionless lower edge can call NdisRequestwith a RequestType of NdisQueryInformation and an OID_GEN_MAXIMUM_SEND_PACKETSto obtain the maximum number of send packets that the underlying driver will accept in a packet array. When an intermediate driver with a connectionless lower edge transmits one or more packets by calling NdisSendPacketsor when an intermediate driver with a connection-oriented lower edge transmits one or more packets by calling NdisCoSendPackets, the send operation is implicitly asynchronous. The caller relinquishes ownership of its packet descriptors and all the resources that they describe until each packet descriptor and the final status of the send for that packet is returned to ProtocolSendCompleteor ProtocolCoSendComplete. Protocol(Co)SendComplete must propagate the status of the send of each packet back to the next higher driver as described in the previous paragraph.
As a consequence, when an intermediate driver sends packets in an array using NdisSendPackets, the intermediate driver should not attempt to read the Statusmembers of the associated OOB blocks on return from NdisSendPackets. This member is in use by NDIS to track the progress of an in-transition send request and is volatile. An intermediate driver can only obtain the status of a transmit request by examining the Statusargument passed to its Protocol(Co)SendComplete function.
If an intermediate driver requests the transmission of an array of packets of different priorities by rearranging the packets that it receives from an overlying driver before transmitting them, it should place the highest priority packets at the beginning of the array. NDIS retains this ordering when it passes the packets to either the MiniportSendor to the Miniport(Co)SendPackets function of the underlying miniport driver, even if NDIS queues some of the packets internally. This ordering is maintained by NDIS for each call to Ndis(Co)SendPackets.
Unless an intermediate driver has special knowledge of the manner in which a miniport driver handles packet priority, it should assume that the miniport driver transmits the packets in the order in which it receives them, preserving the as-received order.
The structure of the Privatemember of an NDIS_PACKET-type descriptor is opaque to an intermediate driver and is accessed to read and, in some cases, to write using NDIS-supplied macros or functions.