Windows Vista Tips

Windows Vista Tips > Newsgroups > Windows Vista Drivers > Problems with received packets and NDIS_STATUS_RESOURCES

Reply
Thread Tools Display Modes

Problems with received packets and NDIS_STATUS_RESOURCES

 
 
Gilad
Guest
Posts: n/a

 
      11-06-2003
I have a problem when I receive packets in my intermediate
driver. I have previously posted a related question in the
newsgroup, unfortunately, no solution was found.
Therefore, I decided to post a sample code based on the
passthru example in order to better explain the problem,
and eventually find its cause.



I wrote a NDIS intermediate driver that changes the
contents of the packet. Some of the data it changes is the
IP address in some of the received packets. Since the data
received from the lower layer should be considered as read
only, I must copy it to a new packet. Furthermore, I know
there are some issues that are related to incoming
packets. Therefore, I have decided that my new packet will
consist of a single NDIS_BUFFER. However, I have noticed a
major problem when I receive a packet that its status is
NDIS_STATUS_RESOURCES, this usually occurs when there is
high traffic.



My problem has 2 symptoms, which I believe are related.



1. Whenever QoS packet scheduling is enabled on the same
network card that my intermediate driver is attached,
packets with status NDIS_STATUS_RESOURCES do not reach
user mode (I cannot see it in the socket). If I run
Ethereal on the same computer, it sees the original packet
rather than the altered packet. In addition if I
run "netstat -s" I see under the IPv4 statistics that the
number of received header errors increases according to
the number of received packets with NDIS_STATUS_RESOURCES.
Packets whose status is NDIS_STATUS_SUCCESS pass correctly.

2. If QoS is disabled, the packet reaches user mode and
Ethereal catches the altered packet. However, "netstat -s"
still reports received header errors that increase
according to the number of received packet with
NDIS_STATUS_RESOURCES.



I do not believe that there is a problem with the contents
of the altered packet (for example, the checksum), since
packets with NDIS_STATUS_SUCCESS pass correctly, and
disabling QoS seems to have a positive effect. However, I
still believe there is some kind of problem, maybe with
the way the packet was created, since netstat should not
report such errors.



I would greatly appreciate ideas and comments on this
issue.



In the following code, I tried to simulate packets with
NDIS_STATUS_RESOURCES - I changed the new packet status to
be always NDIS_STATUS_RESOURCES. This change causes the
same effect as in the case that the status is copied from
the original packet (assuming the original packet's status
was NDIS_STATUS_RESOURCES).



The altered code in PtReceive and PtReceivePacket changes
all received ICMP to the address 172.15.10.10. Therefore,
it assumes it is the local address of the computer. A
remote computer can add another address (say 172.15.10.11)
in the ARP table to the MAC address that has the address
172.15.10.10. If it will ping 172.15.10.11 and the packet
passes through, it will get a reply from 172.15.10.10.

Note that the code in PtReceive and PtReceivePacket is
almost a copy paste. As a result, if one changes the code
in one function, usually the other function will have to
be changed as well.



Thanks.



To change the passthru example:

In passthru.h add the following line in the ADAPT
structure:

NDIS_HANDLE BufferPoolHandle;



In protocol.c, add to PtBindAdapter initialization of
BufferPoolHandle after the initialization of
SendPacketPoolHandle, use the follwing code:

// Allocate a buffer pool messages



//



NdisAllocateBufferPool(Status, &pAdapt->BufferPoolHandle,
65535);

if (*Status != NDIS_STATUS_SUCCESS)

{

break;

}



And after the deinitilization of SendPacketPoolHandle (in
case of error), add the following code



if (pAdapt->BufferPoolHandle != NULL)

{

NdisFreeBufferPool(pAdapt-
>BufferPoolHandle);


}



replace PtReceive and PtReceivePacket with the following
functions:



NDIS_STATUS



PtReceive(

IN NDIS_HANDLE ProtocolBindingContext,

IN NDIS_HANDLE MacReceiveContext,

IN PVOID HeaderBuffer,

IN UINT HeaderBufferSize,

IN PVOID LookAheadBuffer,

IN UINT LookAheadBufferSize,

IN UINT PacketSize

)



/*++





Routine Description:

Handle receive data indicated up by the miniport below.
We pass

it along to the protocol above us.



If the miniport below indicates packets, NDIS would more

likely call us at our ReceivePacket handler. However we

might be called here in certain situations even though

the miniport below has indicated a receive packet, e.g.

if the miniport had set packet status to
NDIS_STATUS_RESOURCES.



Arguments:

<see DDK ref page for ProtocolReceive>



Return Value:

NDIS_STATUS_SUCCESS if we processed the receive
successfully,

NDIS_STATUS_XXX error code if we discarded it.



--*/

{

PADAPT pAdapt = (PADAPT)
ProtocolBindingContext;

PNDIS_PACKET MyPacket, Packet;

NDIS_STATUS Status = NDIS_STATUS_SUCCESS;



if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState
> NdisDeviceStateD0))


{

Status = NDIS_STATUS_FAILURE;

}

else do

{

//

// Get at the packet, if any, indicated up by the
miniport below.

//

Packet = NdisGetReceivedPacket(pAdapt->BindingHandle,
MacReceiveContext);

if (Packet != NULL)

{

//

// The miniport below did indicate up a packet. Use
information

// from that packet to construct a new packet to
indicate up.

//



#ifdef NDIS51

//

// NDIS 5.1 NOTE: Do not reuse the original packet
in indicating

// up a receive, even if there is sufficient packet
stack space.

// If we had to do so, we would have had to
overwrite the

// status field in the original packet to
NDIS_STATUS_RESOURCES,

// and it is not allowed for protocols to overwrite
this field

// in received packets.

//

#endif // NDIS51

//

// Get a packet off the pool and indicate that up

//

NdisDprAllocatePacket(&Status,

&MyPacket,

pAdapt->RecvPacketPoolHandle);



if (Status == NDIS_STATUS_SUCCESS)

{

UINT nLength;

PVOID pAddress;

PNDIS_BUFFER MyBuffer;



MyPacket->Private.Head = NULL;

MyPacket->Private.Tail = NULL;



//

// Get the original packet (it could be the same
packet as the

// one received or a different one based on the
number of layered

// miniports below) and set it on the indicated
packet so the OOB

// data is visible correctly at protocols above.

//

NDIS_SET_ORIGINAL_PACKET(MyPacket,
NDIS_GET_ORIGINAL_PACKET(Packet));

NDIS_SET_PACKET_HEADER_SIZE(MyPacket,
HeaderBufferSize);



//

// Copy packet flags.

//

NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags
(Packet);



//

// Force protocols above to make a copy if they
want to hang

// on to data in this packet. This is because we
are in our

// Receive handler (not ReceivePacket) and we
can't return a

// ref count from here.

//

NDIS_SET_PACKET_STATUS(MyPacket,
NDIS_STATUS_RESOURCES);



//

// By setting NDIS_STATUS_RESOURCES, we also know
that we can reclaim

// this packet as soon as the call to
NdisMIndicateReceivePacket

// returns.

//



NdisQueryPacketLength(Packet, &nLength);

Status = NdisAllocateMemoryWithTag(&pAddress,
nLength, 'VCER');



if (Status == NDIS_STATUS_SUCCESS)

{

NdisAllocateBuffer(&Status, &MyBuffer, pAdapt-
>BufferPoolHandle, pAddress, nLength);




if (Status == NDIS_STATUS_SUCCESS)

{

unsigned char* pCurrPacket;

UINT nCopied;

const unsigned char DestIP[4] = {172, 15, 10,
10};

NdisChainBufferAtFront(MyPacket, MyBuffer);

NdisCopyFromPacketToPacketSafe(MyPacket, 0,
nLength, Packet, 0, &nCopied, NormalPagePriority);



ASSERT(nCopied == nLength);



pCurrPacket = pAddress;



DBGPRINT(("Current Packet type %X %X - %X",
pCurrPacket[12], pCurrPacket[13], pCurrPacket[23]));

// If current packet is IP

if ((pCurrPacket[12] == 0x08) && (pCurrPacket
[13] == 0x00) &&

(pCurrPacket[23] == 1))

{

DBGPRINT(("Current Dest %X %X %X %X",
pCurrPacket[30], pCurrPacket[31], pCurrPacket[32],
pCurrPacket[33]));

HandleReceivedPacket(&(pCurrPacket[24]), &
(pCurrPacket[30]), DestIP);

//HandleReceivedPacket(&(pCurrPacket[36]), &
(pCurrPacket[30]), DestIP);

NdisMoveMemory(&(pCurrPacket[30]), DestIP,
4);

DBGPRINT(("New Dest %X %X %X %X", pCurrPacket
[30], pCurrPacket[31], pCurrPacket[32], pCurrPacket[33]));

}



NdisMIndicateReceivePacket(pAdapt-
>MiniportHandle, &MyPacket, 1);




NdisFreeBuffer(MyBuffer);

}



NdisFreeMemory(pAddress, 0, 0);

}



//

// Reclaim the indicated packet. Since we had set
its status

// to NDIS_STATUS_RESOURCES, we are guaranteed
that protocols

// above are done with it.

//

NdisDprFreePacket(MyPacket);



break;

}

}

else

{

//

// The miniport below us uses the old-style (not
packet)

// receive indication. Fall through.

//

}



//

// Fall through if the miniport below us has either not

// indicated a packet or we could not allocate one

//

pAdapt->IndicateRcvComplete = TRUE;

switch (pAdapt->Medium)

{

case NdisMedium802_3:

case NdisMediumWan:

NdisMEthIndicateReceive(pAdapt->MiniportHandle,

MacReceiveContext,

HeaderBuffer,

HeaderBufferSize,

LookAheadBuffer,

LookAheadBufferSize,

PacketSize);

break;



case NdisMedium802_5:

NdisMTrIndicateReceive(pAdapt->MiniportHandle,

MacReceiveContext,

HeaderBuffer,

HeaderBufferSize,

LookAheadBuffer,

LookAheadBufferSize,

PacketSize);

break;



case NdisMediumFddi:

NdisMFddiIndicateReceive(pAdapt-
>MiniportHandle,



MacReceiveContext,


HeaderBuffer,


HeaderBufferSize,


LookAheadBuffer,


LookAheadBufferSize,


PacketSize);

break;



default:

ASSERT(FALSE);

break;

}



} while(FALSE);



return Status;

}





INT

PtReceivePacket(

IN NDIS_HANDLE ProtocolBindingContext,

IN PNDIS_PACKET Packet

)

/*++



Routine Description:



ReceivePacket handler. Called by NDIS if the miniport
below supports

NDIS 4.0 style receives. Re-package the buffer chain in
a new packet

and indicate the new packet to protocols above us. Any
context for

packets indicated up must be kept in the
MiniportReserved field.



NDIS 5.1 - packet stacking - if there is
sufficient "stack space" in

the packet passed to us, we can use the same packet in a
receive

indication.



Arguments:



ProtocolBindingContext - Pointer to our adapter
structure.

Packet - Pointer to the packet



Return Value:



== 0 -> We are done with the packet

!= 0 -> We will keep the packet and call
NdisReturnPackets() this

many times when done.

--*/

{

PADAPT pAdapt =(PADAPT)
ProtocolBindingContext;

NDIS_STATUS Status;

PNDIS_PACKET MyPacket;

BOOLEAN Remaining;



//

// Drop the packet silently if the upper miniport edge
isn't initialized or

// the miniport edge is in low power state

//

if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState
> NdisDeviceStateD0))


{

return 0;

}



/* Cannot use packet stacking since we are setting a new
buffer

#ifdef NDIS51

//

// Check if we can reuse the same packet for indicating
up.

// See also: PtReceive().

//

(VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);

if (Remaining)

{

//

// We can reuse "Packet". Indicate it up and be done
with it.

//

Status = NDIS_GET_PACKET_STATUS(Packet);

NdisMIndicateReceivePacket(pAdapt->MiniportHandle,
&Packet, 1);

return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);

}

#endif // NDIS51

*/

//

// Get a packet off the pool and indicate that up

//

NdisDprAllocatePacket(&Status,

&MyPacket,

pAdapt->RecvPacketPoolHandle);



if (Status == NDIS_STATUS_SUCCESS)

{

PRECV_RSVD RecvRsvd;

UINT nLength;

PVOID pAddress;

PNDIS_BUFFER MyBuffer;

NDIS_STATUS OriginalStatus;



RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);

RecvRsvd->OriginalPkt = Packet;



MyPacket->Private.Head = NULL;

MyPacket->Private.Tail = NULL;



//

// Get the original packet (it could be the same
packet as the one

// received or a different one based on the number of
layered miniports

// below) and set it on the indicated packet so the
OOB data is visible

// correctly to protocols above us.

//

NDIS_SET_ORIGINAL_PACKET(MyPacket,
NDIS_GET_ORIGINAL_PACKET(Packet));



//

// Set Packet Flags

//

NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags
(Packet);



OriginalStatus = NDIS_GET_PACKET_STATUS(Packet);



NDIS_SET_PACKET_STATUS(MyPacket,
NDIS_STATUS_RESOURCES);

NDIS_SET_PACKET_HEADER_SIZE(MyPacket,
NDIS_GET_PACKET_HEADER_SIZE(Packet));



NdisQueryPacketLength(Packet, &nLength);

Status = NdisAllocateMemoryWithTag(&pAddress,
nLength, 'VCER');



if (Status == NDIS_STATUS_SUCCESS)

{

NdisAllocateBuffer(&Status, &MyBuffer, pAdapt-
>BufferPoolHandle, pAddress, nLength);




if (Status == NDIS_STATUS_SUCCESS)

{

unsigned char* pCurrPacket;

const unsigned char DestIP[4] = {172, 15, 10, 10};

UINT nCopied;



NdisChainBufferAtFront(MyPacket, MyBuffer);

NdisCopyFromPacketToPacketSafe(MyPacket, 0,
nLength, Packet, 0, &nCopied, NormalPagePriority);



ASSERT(nCopied == nLength);



pCurrPacket = pAddress;



DBGPRINT(("Current Packet type %X %X - %X",
pCurrPacket[12], pCurrPacket[13], pCurrPacket[23]));

// If current packet is IP

if ((pCurrPacket[12] == 0x08) && (pCurrPacket[13]
== 0x00) &&

(pCurrPacket[23] == 1))

{

DBGPRINT(("Current Dest %X %X %X %X", pCurrPacket
[30], pCurrPacket[31], pCurrPacket[32], pCurrPacket[33]));

HandleReceivedPacket(&(pCurrPacket[24]), &
(pCurrPacket[30]), DestIP);

//HandleReceivedPacket(&(pCurrPacket[36]), &
(pCurrPacket[30]), DestIP);

NdisMoveMemory(&(pCurrPacket[30]), DestIP, 4);

DBGPRINT(("New Dest %X %X %X %X", pCurrPacket
[30], pCurrPacket[31], pCurrPacket[32], pCurrPacket[33]));

}



NdisMIndicateReceivePacket(pAdapt->MiniportHandle,
&MyPacket, 1);



//

// Check if we had indicated up the packet with
NDIS_STATUS_RESOURCES

// NOTE -- do not use NDIS_GET_PACKET_STATUS
(MyPacket) for this since

// it might have changed! Use the value saved in
the local variable.

//



//

// Our ReturnPackets handler will not be called
for this packet.

// We should reclaim it right here.

//

NdisFreeBuffer(MyBuffer);

}



NdisFreeMemory(pAddress, 0, 0);

}



NdisDprFreePacket(MyPacket);



return(0);

}

else

{

//

// We are out of packets. Silently drop it.

//

return(0);

}

}



Also in protocol.c, add the following function before the
implementation of PtReceive



VOID HandleReceivedPacket(unsigned char* pCheckSum,
unsigned char* pIP, const unsigned char nDestIP[4])

{

signed long x, nTemp;



x=pCheckSum[0]*256+pCheckSum[1];

x=~x & 0xFFFF;



nTemp = pIP[0]*256+pIP[1];

x -= nTemp & 0xffff;

if (x<=0) { x--; x&=0xffff; }



nTemp = pIP[2]*256+pIP[3];

x -= nTemp & 0xffff;

if (x<=0) { x--; x&=0xffff; }



nTemp = nDestIP[0]*256+nDestIP[1];

x += nTemp & 0xffff;

if (x & 0x10000) { x++; x&=0xffff; }



nTemp = nDestIP[2]*256+nDestIP[3];

x += nTemp & 0xffff;

if (x & 0x10000) { x++; x&=0xffff; }



x=~x & 0xFFFF;



pCheckSum[0]=(unsigned char)(x/256);

pCheckSum[1]=(unsigned char)(x & 0xff);



}







in miniport.c replace MPFreeAllPacketPools with the
following function:



VOID

MPFreeAllPacketPools(IN PADAPT pAdapt)

/*++



Routine Description:



Free all packet pools on the specified adapter.



Arguments:



pAdapt - pointer to ADAPT structure



Return Value:



None



--*/

{

if (pAdapt->RecvPacketPoolHandle != NULL)

{

//

// Free the packet pool that is used to indicate
receives

//

NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);



pAdapt->RecvPacketPoolHandle = NULL;

}



if (pAdapt->BufferPoolHandle != NULL)

{

NdisFreeBufferPool(pAdapt->BufferPoolHandle);

pAdapt-> BufferPoolHandle = NULL;

}



if (pAdapt->SendPacketPoolHandle != NULL)

{



//

// Free the packet pool that is used to send packets
below

//



NdisFreePacketPool(pAdapt->SendPacketPoolHandle);



pAdapt->SendPacketPoolHandle = NULL;



}

}






 
Reply With Quote
 
 
 
 
Paul Edwards
Guest
Posts: n/a

 
      11-07-2003
Can you reproduce these symptoms using the unmodified passthru sample in
the ddk?
 
Reply With Quote
 
Gilad
Guest
Posts: n/a

 
      11-12-2003
No, because it requires copying the data to new buffers
in order to reproduce it.

>-----Original Message-----
>Can you reproduce these symptoms using the unmodified

passthru sample in
>the ddk?

 
Reply With Quote
 
Bryan S. Burgin [MSFT]
Guest
Posts: n/a

 
      11-12-2003

Gilad,

If you get NDIS_STATUS_RESOURCES, you must consume/use the packet
immediately, including copying the payload to your own buffer. Regarding
psched - are you copying the NDIS_PACKET_EXTENSION information?

Bryan S. Burgin


This posting is provided "AS IS" with no warranties, and confers no rights
 
Reply With Quote
 
 
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
emails received are duplicates of previously received for a month Jimmer Windows Vista Mail 1 08-30-2007 04:17 PM
GetPrinterDataEx packets ferozf Windows Vista Networking 0 12-22-2006 12:00 PM
packets sent/recieved Niklas Olsson Windows Vista Drivers 1 11-08-2003 05:22 AM
NDISUIO and writing raw packets Jon Windows Vista Drivers 8 09-04-2003 06:43 AM
Re: IM drivers not returning packets to miniport ? Stephan Wolf Windows Vista Drivers 3 08-15-2003 08:48 AM



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59