RECEIVING PACKETS FROM THE NIC

HI All
i am writing a ndis protocol driver.
I have to receive packets in the kernel and have to do some processing for
the received packet if the packet is mine (to be decided based on the ether
type field in the mac header)
before discarding it or doing something else with it.
The packets received inside the kernel are not to be passed to the user
mode.
What are the steps required to accomplish this after the adapter has been
opened.
I have only able to make out from the ddk sample code the following:-

—we have to allocate a packet pool using NdisAllocatePacketPool(for
allocate a pool of packet descriptors)
—now to receive packets from the nic NdisAllocatePacket is called to fetch
a packet descriptor from the
descriptor pool. This will be called from the receive handler which is
automatically called by the NIC for each packet.
Now how do i determine whther the packet received is of interest to me and
how do i copy the packet into the kernel buffer.
Also for each packet descriptor obtained from the descriptor pool how do i
associate buffers with it. Are MDLs required
when i dont need to copy the packet to user mode.

Please Help
Thanks
Mayank

First, a bit of terminology: Here I use “packet” to mean the payload
(ethernet/MAC header + IP header + TCP datagram, assuming a packet is
TCP) sent over the network, and I use “packet descriptor” to mean an
NDIS_PACKET and “buffer descriptor” to mean an NDIS_BUFFER.

  1. Figuring out which incoming packets are “yours” is a programming
    issue. That is, it’s up to you to devise a solution. Your idea of an
    indicative type field value in the MAC header might work. But I’d be
    careful about the possibility that intermediate systems in the internet
    might drop your packets if they didn’t like the field value. I incline
    toward a VPN-like solution: If we can assume that “your” packets were
    produced by other instances of “your” driver in other hosts, let’s
    consider that the TCP data begin with “your” header, which effectively
    encapsulates the actual payload. Then the steps are a) Is the packet big
    enough to be “my” header plus some original payload of length greater
    than 0?; b) If yes, is the IP protocol type TCP? c) If yes, is the TCP
    data big enough to be “my” header plus some original payload of length
    greater than 0?; d) If yes, Do the TCP data begin with my header? (Bear
    in mind you are looking for a signature, and you don’t want to mistake a
    random string for your signature, so you might put a checksum or hash
    value into your signature to minimize the chance of a mistake.)

  2. Once you’ve decided the current incoming packet is yours, in the
    callback ProtocolReceive() (and don’t forget that packets can arrive in
    ProtocolReceivePacket(), if one was supplied), you would do: a)
    NdisAllocateMemoryWithTag() to get storage for the copied packet, and
    remember you need space for the MAC header, the IP header and the TCP
    datagram (I’m assuming that packets of interest are TCP), which datagram
    is less the space your remote driver instance used for your
    encapsulating header; b) Calculate any necessary checksums (eg, IP and
    TCP headers); b) NdisAllocateBuffer() to allocate a buffer descriptor
    (which is nothing other than an MDL), for the packet copy you created in
    a); c) NdisDprAllocatePacket() or equivalent to get a packet descriptor;
    d) Set the head of the packet descriptor to the buffer descriptor you
    created, and set the tail to NULL; e) NdisMIndicateReceivePacket() to
    indicate up the new packet descriptor; f) In the right places, recycle
    the packet descriptor, buffer descriptor and storage your driver
    obtained. (If ProtocolReceivePacket() is called, the logic will be
    basically the same.)


If replying by e-mail, please remove “nospam.” from the address.

James Antognini

You also need to worry about fragmentation. (Thanks Michal)

Amit Manocha
“James Antognini” wrote in message
news:xxxxx@ntdev…
>
> First, a bit of terminology: Here I use “packet” to mean the payload
> (ethernet/MAC header + IP header + TCP datagram, assuming a packet is
> TCP) sent over the network, and I use “packet descriptor” to mean an
> NDIS_PACKET and “buffer descriptor” to mean an NDIS_BUFFER.
>
> 1) Figuring out which incoming packets are “yours” is a programming
> issue. That is, it’s up to you to devise a solution. Your idea of an
> indicative type field value in the MAC header might work. But I’d be
> careful about the possibility that intermediate systems in the internet
> might drop your packets if they didn’t like the field value. I incline
> toward a VPN-like solution: If we can assume that “your” packets were
> produced by other instances of “your” driver in other hosts, let’s
> consider that the TCP data begin with “your” header, which effectively
> encapsulates the actual payload. Then the steps are a) Is the packet big
> enough to be “my” header plus some original payload of length greater
> than 0?; b) If yes, is the IP protocol type TCP? c) If yes, is the TCP
> data big enough to be “my” header plus some original payload of length
> greater than 0?; d) If yes, Do the TCP data begin with my header? (Bear
> in mind you are looking for a signature, and you don’t want to mistake a
> random string for your signature, so you might put a checksum or hash
> value into your signature to minimize the chance of a mistake.)
>
> 2) Once you’ve decided the current incoming packet is yours, in the
> callback ProtocolReceive() (and don’t forget that packets can arrive in
> ProtocolReceivePacket(), if one was supplied), you would do: a)
> NdisAllocateMemoryWithTag() to get storage for the copied packet, and
> remember you need space for the MAC header, the IP header and the TCP
> datagram (I’m assuming that packets of interest are TCP), which datagram
> is less the space your remote driver instance used for your
> encapsulating header; b) Calculate any necessary checksums (eg, IP and
> TCP headers); b) NdisAllocateBuffer() to allocate a buffer descriptor
> (which is nothing other than an MDL), for the packet copy you created in
> a); c) NdisDprAllocatePacket() or equivalent to get a packet descriptor;
> d) Set the head of the packet descriptor to the buffer descriptor you
> created, and set the tail to NULL; e) NdisMIndicateReceivePacket() to
> indicate up the new packet descriptor; f) In the right places, recycle
> the packet descriptor, buffer descriptor and storage your driver
> obtained. (If ProtocolReceivePacket() is called, the logic will be
> basically the same.)
>
>
> –
> If replying by e-mail, please remove “nospam.” from the address.
>
> James Antognini
>
>
>
>

The NDIS_PACKET discussion at www.ndis.com could help you understand how to
examine packets. See the URL:

http://www.ndis.com/papers/default.htm

Good luck,

Thomas F. Divine

“Mayank Kumar” wrote in message
news:xxxxx@ntdev…
>
> HI All
> i am writing a ndis protocol driver.
> I have to receive packets in the kernel and have to do some processing for
> the received packet if the packet is mine (to be decided based on the
ether
> type field in the mac header)
> before discarding it or doing something else with it.
> The packets received inside the kernel are not to be passed to the user
> mode.
> What are the steps required to accomplish this after the adapter has been
> opened.
> I have only able to make out from the ddk sample code the following:-
>
> —we have to allocate a packet pool using NdisAllocatePacketPool(for
> allocate a pool of packet descriptors)
> —now to receive packets from the nic NdisAllocatePacket is called to
fetch
> a packet descriptor from the
> descriptor pool. This will be called from the receive handler which is
> automatically called by the NIC for each packet.
> Now how do i determine whther the packet received is of interest to me and
> how do i copy the packet into the kernel buffer.
> Also for each packet descriptor obtained from the descriptor pool how do i
> associate buffers with it. Are MDLs required
> when i dont need to copy the packet to user mode.
>
>
> Please Help
> Thanks
> Mayank
>
>
>
>
>
>
>