Tech Support > Microsoft Windows > Drivers > The relationship between NdisSend() and NdisMSendComplete()
The relationship between NdisSend() and NdisMSendComplete()
Posted by Liang Chen on August 17th, 2005


Hi all,

I learnd from the passthru sample than it is required in NDIS to acknowledge
the successful sending operations by NdisMSendComplete(). However, I need
the futhurmore expertise to cover my trick modified from the original
passthru sample.

It is supposed that there are 2 adapters binding to the passthru, NIC1 and
NIC2. In my design, I expecte every downlink packet, either from the NIC1 or
NIC2, will be forwarded to the NIC2's miniport.

For example, if a packet is sent from the NIC1 to passthru via
MPSendPackets(), the passthru transfers the packet to NIC2 by calling
NdisSend(). When the packet is sent successfully, NDIS will call the
PtSendComplete() to indicate the success to the upper layer.

In my scenario, which adapter shall I acknowledge in PtSendComplete(), NIC1
or NIC2?

Does NDIS return the packet with the same address to PtSendComplete() as the
packet sending by NdisSend()?

Thanks!

-Liang

Posted by Stephan Wolf [MVP] on August 17th, 2005


Simply follow this rule: Each NDIS_PACKET has a current owner. An owner
(aka "module"/"driver") can temporarily pass ownership of an
NDIS_PACKET to some other driver. Finally, a temporary owner must pass
ownership back to the originator of the NDIS_PACKET.

In your case, there is some protocol like TCP/IP that allocates and
thus owns an NDIS_PACKET. The protocol sets up the NDIS_PACKET with one
or more NDIS_BUFFERs and passes ownership to the miniport of an
underlying NIC by calling NdisSend().

Since you are a Filter intermediate driver, the NIC miniport does not
get the NDIS_PACKET but instead your IM's MiniportSend() routine gets
it. Thus your IM now temporarily owns the NDIS_PACKET. The IM is
responsible for passing ownership back to the protocol by *later*
calling NdisMSendComplete().

Since you want to actually send the packet, you allocate a new
NDIS_PACKET and attach to it the same NDIS_BUFFER(s) from the original
NDIS_PACKET (unless you use packet stacking). Then you pass this new
NDIS_PACKET to NdisSend() with the miniport handle of e.g. NIC1.

The NIC1 miniport now temporarily owns your NDIS_PACKET until it calls
NdisMSendComplete(). This is when the NDIS_PACKET gets passed back to
your ProtocolSendComplete() routine. You are now again the owner of the
NDIS_PACKET that you allocated. (You can free this NDIS_PACKET.)

But you still own the original NDIS_PACKET from the protocol. Thus you
now pass the original NDIS_PACKET back to the protocol by also calling
NdisMSendComplete() with the same miniport handle that was passed to
MiniportSend() earlier.

Note that an NDIS_PACKET is uniquely identified by its address (i.e.
the pointer to it). All routines that handle the same NDIS_PACKET thus
use the same pointer value.

Also note that what you are doing is not actually what a Filter IM is
supposed to do. You are rather implementing a MUX IM. See the MUX
sample in the DDK.

Stephan
---
Liang Chen wrote:


Similar Posts