typedef struct _NDIS_PACKET_OOB_DATA { union { ULONGLONG TimeToSend; ULONGLONG TimeSent; }; ULONGLONG TimeReceived; UINT HeaderSize; UINT SizeMediaSpecificInfo; PVOID MediaSpecificInformation; NDIS_STATUS Status; } NDIS_PACKET_OOB_DATA, *PNDIS_PACKET_OOB_DATA;
NDIS_PACKET_OOB_DATA specifies out-of-band information associated with a packet descriptor, used by drivers whose media supplies, requires, or accepts out-of-band information, such as packet priorities, and by drivers that support multipacket receives and/or sends.
Protocols can set this timestamp before passing an array of packet descriptor pointers to NdisSendPackets or a packet descriptor pointer to NdisSend.
The MiniportSendPackets or MiniportSend functions of underlying drivers can
retrieve the value of this timestamp to determine when the given packet(s)
should be transmitted over the network. Usually, only the lowest-level
underlying driver retrieves this timestamp.
NIC drivers and, possibly, intermediate drivers that export only a set of MiniportXxx functions set this timestamp before indicating receive packet(s).
The ProtocolReceivePacket functions of drivers bound above such a miniport can
retrieve the value of this timestamp to determine when any particular packet
was transmitted from the remote node. If the ProtocolReceive function is given
an indication and the underlying driver sets this timestamp, ProtocolReceive
can call NdisQueryReceiveInformation to retrieve this timestamp.
NIC drivers and, possibly, intermediate drivers that export only a set of MiniportXxx functions set this timestamp before calling NdisMIndicateReceivePacket with a packet array, which can have one or more pointers to packet descriptors.
The ProtocolReceivePacket functions of drivers bound above any such miniport
can retrieve the value of this timestamp to determine when the given packet(s)
were received. If the ProtocolReceive function is given an indication and the
underlying driver sets this timestamp, ProtocolReceive can call NdisQueryReceiveInformation
to retrieve this timestamp.
Lower-level drivers set this member for subsequent receive indication(s) according to the medium each driver’s MiniportInitialize function elected to support.
The ProtocolReceivePacket functions of drivers bound above such a miniport can
retrieve the value of this member to determine how to process the
medium-specific net packet.
A driver must set this member if it supplies out-of-band information with a
packet to be sent or indicated.
Either type of driver can retrieve the address of the out-of-band data buffer
and its size to determine how to process or interpret the send or receive
specified with the incoming packet descriptor. If the ProtocolReceive function
is given an indication and the underlying driver supplies this information,
ProtocolReceive can call NdisQueryReceiveInformation to retrieve the
virtual range of this buffer.
Only lower-level drivers and NDIS set this member.
A miniport can set this member before it calls NdisMIndicateReceivePacket to indicate how soon it needs to regain ownership of its allocated resources specified in the associated packet descriptor(s). It can retrieve this value on return from NdisMIndicateReceivePacket to determine whether the resources specified with the packet descriptor for its indication can be prepared for reuse immediately.
A miniport can set this member in its MiniportSendPackets function to complete an incoming send immediately, to notify NDIS that it will complete the request asynchronously, or to request that NDIS requeue some or all of the incoming packet array and resubmit those packet descriptor(s) to MiniportSendPackets later.
A protocol cannot retrieve this value to determine the completion status of a send on return from its call to NdisSendPackets or NdisSend.
Every packet descriptor allocated with NdisAllocatePacket has an associated NDIS_PACKET_OOB_DATA block. Only drivers that support multipacket sends and/or receives and drivers that supply out-of-band information, such as packet priority, with each network packet to be transferred use the OOB block. Nevertheless, every NDIS driver that allocates packet descriptors for transfers between bound drivers must allocate those packet descriptors with NdisAllocatePacket from the packet pool that each such NDIS driver usually allocates when it initializes.
In general, drivers of high-capacity busmaster DMA NICs are most likely to support multipacket receives and sends because such a NIC driver makes the greatest performance gains by supporting multipacket transfers. Any protocol that binds itself to (or above) such an underlying NIC driver also should support multipacket sends and receives for maximum performance.
If such a protocol also binds itself above another NIC driver without multipacket transfer support, NDIS handles multipacket sends and single-packet receives in a manner transparent to both drivers by always calling the protocol’s ProtocolReceive function and by calling that NIC driver’s MiniportSend function with a single packet per call. Similarly, if a protocol that does not support multipacket transfers binds itself above a NIC driver that does, NDIS handles multipacket receive indications and single packet sends in a manner transparent to both drivers, although the MiniportSendPackets function of the underlying NIC driver is given only a single send request per call to NdisSend from such a protocol.
All timestamps set in the NDIS_PACKET_OOB_DATA blocks associated with packet descriptors are expressed in system time units as the number of 100-nanosecond intervals since 12:00 a.m., January 1, 1601.
NDIS drivers can call NdisGetCurrentSystemTime when they set these timestamps with the NDIS_SET_PACKET_TIME_XXX macros. Still higher-level drivers or system components can convert these timestamps into locale-specific values more meaningful to the end user.
Any out-of-band information specified in the SizeMediaSpecificInfo and MediaSpecificInformation members is medium-type-specific. For example, some types of media require protocols to specify a packet priority for each packet they send and require NIC drivers to specify a packet priority with each receive packet they indicate. Such a NIC driver must call NdisMIndicateReceivePacket to fulfill the requirements of these types of media.
While NDIS provides support for a range of priority values from zero through seven, some media support only two levels of priority. For these types of media, NDIS drivers should map values zero through three to the medium-specific normal priority value (usually zero for such media types) and values four through seven to the medium-specific high priority value (usually one for such media types).
The structure of individual records within the buffer at MediaSpecificInformation is defined as follows:
typedef struct MediaSpecificInformation { UINT NextEntryOffset; NDIS_CLASS_ID ClassId; UINT Size; UCHAR ClassInformation[1]; } MEDIA_SPECIFIC_INFORMATION;
The members of this structure contain the following information:
A bound protocol can determine whether the underlying NIC miniport’s native
medium requires prioritized packets with the OID_802_3_MAC_OPTIONS query. If
so, the miniport sets the NDIS_802_3_OPTION_PRIORITY flag.
The NDIS_CLASS_ID type is an NDIS-defined enumeration. Most common classifications for records will be specified as system-defined values. However, a range of values in this enumeration will be available for vendor-defined experimental classes.
Only lower-level NDIS drivers use the Status member of this structure for receive indications. Before such a driver calls NdisMIndicateReceivePacket, it sets the Status with NDIS_SET_PACKET_STATUS for one or more packet descriptors in the array to be indicated to either of the following values:
Protocols that receive the indication can use the packet descriptor, along
with all buffers mapped by buffer descriptors chained to the packet descriptor
and any out-of-band information supplied with the packet, to copy the
indicated net packet data or, possibly, to forward the indicated data to
interested clients.
NDIS assumes that, if this status is set for a packet in an indicated array, it is set for all subsequent packets in that array. Consequently, an indicating driver need not set the status for subsequent packets in an array after it sets this status for one packet descriptor.
Setting this status forces bound protocols to return ownership of each such packet descriptor, of any medium-specific buffer in the out-of-band data block for each packet descriptor, and of the memory mapped by each packet descriptor’s respective chained buffer descriptors to the indicating driver more quickly. The protocols must wait for a call to their ProtocolReceiveComplete functions to begin postprocessing the data they copied from indication(s) and forwarding the data to clients.
An indicating driver can set this status if it is running low on packet pool or buffer pool. An indicating NIC driver can set this status if it is running low on NIC receive buffers due to high network traffic. A busmaster DMA NIC driver might call NdisMAllocateSharedMemoryAsync in these circumstances to get additional NIC receive buffer space.
After such a driver has set the Status for some number of packet descriptors and called NdisMIndicateReceivePacket with the array of pointers to the packet descriptors, it must use the NDIS_GET_PACKET_STATUS macro when NdisMIndicateReceivePacket returns control to retrieve the Status set by NDIS.
The returned Status in the NDIS_PACKET_OOB_DATA block associated with each packet descriptor that the driver indicated with NDIS_STATUS_SUCCESS determines what the indicating driver does next, as follows:
NDIS guarantees that any packet descriptors for which the indicating driver set NDIS_STATUS_RESOURCES, as already described, will be returned from its call to NdisMIndicateReceivePacket with NDIS_STATUS_SUCCESS.
The driver can prepare these descriptors, the out-of-band block, and
media-specific information buffer, if any, for reuse in subsequent receive
indications immediately.
Only underlying NDIS drivers with MiniportSendPackets functions can use the Status member of this structure for packet descriptors specifying sends. Such a driver’s MiniportSendPackets function sets the Status member in the out-of-band data blocks associated with the packet descriptors in the input array as follows:
NDIS assumes that the Status members for all subsequent packet descriptors in the input array are set to the same value. NDIS queues these packet descriptors internally in the same order for resubmission to MiniportSendPackets when the driver calls NdisMSendResourcesAvailable or NdisMSendComplete, whichever occurs first. NDIS reflects this miniport-set status value to protocols as NDIS_STATUS_PENDING.
Otherwise, such a driver supplies the completion status for each packet when it calls NdisMSendComplete with the packet descriptor. Drivers that have MiniportSend instead of MiniportSendPackets functions return the status for each incoming send packet, so such a driver never sets the Status member of the out-of-band data block for a packet descriptor specifying a send.
Protocols cannot determine the completion status for a protocol-allocated packet descriptor from the Status member of the associated OOB block on return from NdisSendPackets or NdisSend. This value can change dynamically as NDIS submits, requeues, and resubmits send packet(s) to underlying drivers’ MiniportSendPackets and/or MiniportSend functions.
A protocol cannot use any NDIS_GET_PACKET_XXX macro nor the NDIS_OOB_DATA_FROM_PACKET macro to access the OOB data block for such a protocol-allocated packet descriptor until its ProtocolSendComplete function is called with the packet descriptor.
MiniportAllocateComplete, MiniportHandleInterrupt, MiniportReturnPacket, MiniportSend, MiniportSendPackets, MiniportTimer, NdisAllocateBuffer, NdisAllocateBufferPool, NdisAllocatePacket, NdisAllocatePacketPool, NdisGetCurrentSystemTime, NDIS_GET_PACKET_HEADER_SIZE, NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO, NDIS_GET_PACKET_STATUS, NDIS_GET_PACKET_TIME_RECEIVED, NDIS_GET_PACKET_TIME_SENT, NDIS_GET_PACKET_TIME_TO_SEND, NdisMIndicateReceivePacket, NdisMSendComplete, NdisMSendResourcesAvailable, NDIS_OOB_DATA_FROM_PACKET, NDIS_PACKET, NdisQueryReceiveInformation, NdisSend, NdisSendPackets, NDIS_SET_PACKET_HEADER_SIZE, NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO, NDIS_SET_PACKET_STATUS, NDIS_SET_PACKET_TIME_RECEIVED, NDIS_SET_PACKET_TIME_SENT, NDIS_SET_PACKET_TIME_TO_SEND, ProtocolReceive, ProtocolReceivePacket, ProtocolSendComplete