NDIS_PACKET_OOB_DATA

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.

Members

TimeToSend

Specifies the time, in system time units, at which a given packet should be transmitted over the network.

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.

TimeSent

Specifies the time, in system time units, at which a received packet was transmitted over the network from a remote node.

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.

TimeReceived

Specifies the time, in system time units, at which a given packet from a remote node on the network was received on the NIC.

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.

HeaderSize

Specifies the size in bytes of the medium-specific header contained in the buffer mapped by the initial buffer descriptor chained to the packet descriptor.

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.

SizeMediaSpecificInfo

Specifies the size in bytes of the buffer at MediaSpecificInformation.

A driver must set this member if it supplies out-of-band information with a packet to be sent or indicated.

MediaSpecificInformation

Specifies the address of a driver-allocated buffer. This buffer contains any out-of-band data, such as packet priority, that accompanies the net packet specified with the packet descriptor. The out-of-band data has been set up either by the allocating protocol for a send or by the allocating miniport for a receive indication.

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.

Status

Specifies the current status of the packet descriptor and the ownership of all driver-allocated resources specified with the packet descriptor.

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.

Comments

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.

Using Timestamps

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.

Supplying Out-of-Band Information with Packets

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:

NextEntryOffset

Specifies the byte offset to this member in the next record, if any. Zero indicates this is the last record in the buffer; the values of all remaining members in the last record are also zero. The value of this member must be quad-aligned.

ClassId

Specifies the type of the record. Possible values are one of the following:

NdisClass802_3Priority

The underlying NIC's medium requires that drivers specify per-packet priority, while its driver uses Ethernet emulation to communicate with bound protocols.

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.

NdisClassWirelessWanMbxMailbox

The underlying NIC driver examines the ULONG-sized record at ClassInformation to determine whether the mailbox flag should be set for the associated packet. (1 = set mailbox flag, 0 = do not set mailbox flag)

Size

Specifies the number of bytes in the ClassInformation array, including any padding necessary to align the NextEntryOffset of the next record on a four-byte boundary.

ClassInformation

Specifies the out-of-band information for this record.

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.

Setting Status Before Making Receive Indications

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:

NDIS_STATUS_SUCCESS

Tells NDIS that the driver is relinquishing ownership of the packet about to be indicated with NdisMIndicateReceivePacket until the packet descriptor is returned to its MiniportReturnPacket function.

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_STATUS_RESOURCES

Tells NDIS that the driver is retaining ownership of the packet about to be indicated with NdisMIndicateReceivePacket and of all subsequent packets in the packet array. All these packets will be indicated, one at a time, to the ProtocolReceive functions of bound protocols.

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.

Getting Status on Return from NdisMIndicateReceivePacket

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_STATUS_SUCCESS

If this is set on return from a miniport's call to NdisMIndicateReceivePacket, the miniport regains ownership of the following:

·The packet descriptor

·The associated out-of-band data block associated with the packet descriptor and of any media-specific information buffer specified in this block

·All buffers mapped by buffer descriptors chained to the packet descriptor

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.

NDIS_STATUS_PENDING

If this is set on return from NdisMIndicateReceivePacket, protocols retain ownership of the packet descriptor, of its associated out-of-band data block and of any buffer specified in this block, and of all buffers mapped by buffer descriptors chained to the packet descriptor until the packet descriptor is returned to the indicating driver's MiniportReturnPacket function.

Setting Status in MiniportSendPackets

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:

·If the driver will complete the send operation asynchronously, MiniportSendPackets sets NDIS_STATUS_PENDING in the Status member for the given packet descriptor.

·If the driver cannot process all sends in a given packet array due to current resource constraints, MiniportSendPackets sets NDIS_STATUS_RESOURCES in the Status member for one packet descriptor.

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.

·If MiniportSendPackets will complete a given send request before it returns control, it must set the Status member for the given packet descriptor to a driver-determined status value so that NDIS can reflect this status back to the protocol that initiated the send.

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.

See Also

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