다음을 통해 공유


Indicating Receive Packets with NdisM(Co)IndicateReceivePacket (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.

To indicate receive data with NdisM(Co)IndicateReceivePacket, a miniport driver:

  • Allocates and manages an array of packet descriptors (The miniport driver must allocate and set up a packet descriptor for a full network packet rather than a lookahead buffer. For more information, see Allocating Memory.)

  • Fills the chained buffers with the received data

  • Calls NdisM(Co)IndicateReceivePacket, passing a pointer to the array of packet descriptors

Before calling NdisM(Co)IndicateReceivePacket a connection-oriented miniport driver typically sets up and always activates a virtual connection (VC) on which to receive the data. When the remote party terminates the incoming call, the miniport driver deactivates and sometimes deletes the VC on which it received the data. For a description of VC creation activation, deactivation, and deletion, see Creating, Activating, Deactivating, and Deleting Virtual Connections.

The following figure illustrates indicating receive data with NdisM(Co)IndicateReceivePacket.

The miniport driver passes status, such as the time a packet is received or sent, or other media-specific information, to upper layers by setting members in the out-of-band (OOB) data block associated with each packet descriptor. If the miniport driver is willing to let a protocol keep the packet and return it later to the miniport driver's MiniportReturnPacketfunction, the miniport driver must set the Statusmember of the OOB block to NDIS_STATUS_SUCCESS. If the miniport driver is running short of free packet descriptors or buffers and wants to force any interested upper layer driver to copy the packet data before NdisM(Co)IndicateReceivePacket returns, the miniport driver must set the Statusmember to NDIS_STATUS_RESOURCES. For more information, see Packet Out-of-Band Data.

A serialized miniport driver must always check the Statusmember in the OOB block that is associated with each packet descriptor when NdisM(Co)IndicateReceivePacket returns:

  • If the Status member is anything except NDIS_STATUS_PENDING, the packet descriptor and all the resources it describes are returned to the miniport driver.

  • If the Status member is NDIS_STATUS_PENDING, ownership of the miniport-allocated packet resources transfers to the protocol driver or to the intermediate protocol driver until the packet descriptor is returned to the miniport's MiniportReturnPacket function.

  • If the miniport driver sets the Status member for any packet in the array to NDIS_STATUS_RESOURCES before calling NdisM(Co)IndicateReceivePacket, that packet will be returned to the miniport driver after higher level drivers have copied the data in the indicated packets. The Status member for all such packets will be set to NDIS_STATUS_SUCCESS.

A deserialized miniport driver must not examine the Statusof indicated packets on return of NdisM(Co)IndicateReceivePacket. Instead, a deserialized miniport driver must save a packet's Statusin a local variable before indicating up the packet descriptor. When NdisM(Co)IndicateReceivePacket returns, the miniport driver should check the saved packet Status. If the miniport driver set the packet's Statusto NDIS_STATUS_RESOURCES before indicating up the packet descriptor, it should reclaim the packet descriptor immediately after NdisM(Co)IndicateReceivePacket returns, preferably by calling its own MiniportReturnPacketfunction. In this case, NDIS does not call the miniport driver's MiniportReturnPacketfunction to return the packet descriptor. If the miniport driver set the packet's Statusto NDIS_STATUS_SUCCESS before indicating up the packet descriptor, the miniport driver must not reclaim the packet descriptor until NDIS subsequently returns the packet descriptor to the miniport driver's MiniportReturnPacketfunction.

A miniport driver that manages a bus-master DMA NIC typically indicates packets by calling NdisM(Co)IndicateReceivePacket because its NIC usually has sufficient ring buffer space to receive multiple packets. The miniport driver improves performance by processing several packets at a time.

Usually, a miniport driver for any other type of network interface card (NIC), such as a programmed I/O (PIO) NIC or an adapter-shared-memory NIC, calls NdisM(Co)IndicateReceivePacket only if it needs to pass priority, media-specific information, or the receive time. A non-DMA NIC typically receives only one packet at a time and must be reset between single receives. The miniport driver for such a device can indicate up only one packet at a time with NdisM(Co)IndicateReceivePacket.

Because the miniport driver passes ownership of the packets up when it calls NdisM(Co)IndicateReceivePacket, it must manage its receive buffers well to ensure that buffers are available when new data arrives on the network. Typically, the miniport driver preallocates, in its MiniportInitializefunction, a few more buffers than required for the ring buffer and allocates sufficient buffer descriptors to map these buffers and a few packet descriptors for making receive indications.

Handling a Resource Problem (NDIS 5.1)

If a miniport driver determines that it is running low on receive buffer space, it can use either of the following strategies:

  • When it calls NdisM(Co)IndicateReceivePacket, the miniport driver should set the Status member of the OOB block to NDIS_STATUS_RESOURCES for each packet descriptor that it does not want the protocol to keep. This tells NDIS that the miniport driver will not give up ownership of the packet's resources to the protocol driver to which the packet is indicated. NDIS ensures that the packet is copied by the protocol driver rather than passed to the protocol driver. If the miniport driver is serialized, NDIS calls the ProtocolReceive function rather than ProtocolReceivePacket function, forcing the protocol driver to copy the packet. If the miniport driver is a deserialized, NDIS calls the protocol driver's Protocol(Co)ReceivePacket function. When the protocol determines that the Status member of the OOB block is set to NDIS_STATUS_RESOURCES, it copies the packet. Because the miniport driver does not have to provide a MiniportTransferData function if it supports the multipacket receive paradigm described here, NDIS intercepts the protocol driver's transfer request and performs the transfer.

  • The miniport driver maintains a high-water mark and low-water mark for its set of free buffers. When the number of buffers approaches the low-water mark, the miniport driver calls NdisMAllocateSharedMemoryAsync to allocate more buffers, and then it calls NdisAllocateBuffer to allocate buffer descriptors to map these buffers. Unlike NdisMAllocateSharedMemory, which can be called only at IRQL < DISPATCH_LEVEL, NdisMAllocateSharedMemoryAsync can be called at IRQL = DISPATCH_LEVEL, even in the MiniportHandleInterrupt function. When the set of free buffers exceeds the high-water mark, the miniport driver calls NdisMFreeSharedMemory to free excess buffers, and then it calls NdisFreeBuffer to free the buffer descriptors that map these buffers.

If a miniport driver that is running on a Microsoft Windows XP or Windows 2000 system indicates packets that consist of multiple chained NDIS_BUFFER structures, the driver must do one of the following to ensure that the host stack properly processes such packets:

  • When responding to a query of OID_GEN_MAC_OPTIONS shortly after driver initialization, the driver must not set the NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA flag.

  • Before calling NdisM(Co)IndicateReceivePacket, the driver must set the Status member of the NDIS_PACKET_OOB_DATA structure that is associated with the packet descriptor to NDIS_STATUS_RESOURCES.

A miniport driver that is running on a Windows Server 2003 or later system does not have to handle the preceding situation.

 

 

Send comments about this topic to Microsoft