Re: Duplicating NDIS_PACKET
- From: "Peter Schmitz" <PeterSchmitz@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Wed, 26 Oct 2005 10:02:11 -0700
Thanks for replying! According to your suggestions I rewrote the function to
create a real independent copy of any NDIS_PACKET:
PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT Adapter,
BOOLEAN tosend)
{
PNDIS_PACKET OurPacket = NULL;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNDIS_BUFFER pNdisBuffer,pOurBuffer;
ULONG PacketLength = 0;
ULONG bytescopied = 0;
PVOID virtualaddr = NULL;
PRECV_RSVD RecvRsvd;
PSEND_RSVD SendRsvd;
if(tosend == FALSE)
{
NdisAllocatePacket(&Status, &OurPacket, Adapter->RecvPacketPoolHandle);
}
else
{
NdisAllocatePacket(&Status,&OurPacket,Adapter->SendPacketPoolHandle);
}
NdisQueryPacket(OriginalPacket, NULL, NULL,&pNdisBuffer,&PacketLength );
NdisAllocateMemoryWithTag(&virtualaddr,PacketLength,'DMSA');
NdisAllocateBuffer(&Status,&pOurBuffer,Adapter->BufferPool,
virtualaddr,PacketLength);
NdisChainBufferAtFront(OurPacket,pOurBuffer);
NdisCopyFromPacketToPacket(OurPacket,0,PacketLength,OriginalPacket,0,
&bytescopied);
OurPacket->Private.Head = OriginalPacket->Private.Head;
OurPacket->Private.Tail = OriginalPacket->Private.Tail;
if(tosend == FALSE)
{
RecvRsvd = (PRECV_RSVD)(OurPacket->MiniportReserved);
RecvRsvd->OriginalPkt = NULL;
}
else
{
SendRsvd = (PSEND_RSVD)(OurPacket->ProtocolReserved);
SendRsvd->OriginalPkt = NULL;
}
NdisSetPacketFlags(OurPacket, NdisGetPacketFlags(OriginalPacket));
NdisFreeMemory(virtualaddr,PacketLength,0);
NDIS_SET_PACKET_STATUS(OurPacket, Status);
NDIS_SET_PACKET_HEADER_SIZE(OurPacket,
NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket));
return OurPacket;
}
Now, the NULL pointer to OriginalPkt in my ProtocolReserved area is
necessary for me to distinguish between real packets - and my own copies (as
I need to kill the buffers etc. for them).
So, I just test Pkt for being NULL in my PtCompleteSend handler, and if so
(my own copy as packet) delete the buffers.
Or...would, as a BAD_POOL_CALLER appears at NdisFreeBuffer saying that the
memory was already freed....but how?
Thanks in advance,
Peter
"Stephan Wolf [MVP]" wrote:
> Several things to consider here:
>
> - Calling NdisDprAllocatePacket() from any IRQL below DISPATCH_LEVEL is
> a programming fault and can cause unpredictable results. So please use
> the non-DPR variant NdisAllocatePacket() if you are not 100% sure. Same
> is true for the free function.
>
> - Your local packet uses the same NDIS_BUFFER chain as the original
> packet. Thus, the lifetime of your local packet cannot be any longer
> than that of the original. That is, as soon as you "kill" the original
> packet (i.e. return it back to NDIS), your should also "kill" your
> local packet.
>
> - NDIS_SET_ORIGINAL_PACKET() sets a reference (back-link) in your local
> packet to the "original" packet of the packet you are making a copy of.
> (Usually, the packet returned by NDIS_GET_ORIGINAL_PACKET() is just the
> same as the one passed to the macro but can be different in some
> cases.)
> Since you "kill" the original packet, this reference also becomes
> invalid. So better set as follows:
>
> NDIS_SET_ORIGINAL_PACKET(MyPacket, MyPacket);
>
> ...which IIRC is the default anyway.
>
> - I guess you should set the status of your local packet to
> NDIS_STATUS_SUCCESS rather than that of the original packet via
> NDIS_SET_PACKET_STATUS().
>
> - Umm, I have difficulties trying to understand your PtSendComplete().
> First you get 'Pkt' from 'Packet->ProtocolReserved'. So this means
> 'Packet' must be one of your own local packets. But if the pool handle
> of 'Packet' is not your own - which is is contradictory - you return
> this packet to NdisMSendComplete().
>
> Stephan
> ---
> Peter Schmitz wrote:
> > Hi,
> >
> > I'm currently trying to develop a NDIS IM driver, that duplicates every
> > packet it ought to send/receive, kills the original one - and (after some
> > short period) sends/receives the duplicate instead.
> > Therefore, I created a function, that shall duplicate the NDIS_PACKETs, but
> > which, unfortunately, seems to create some memory leaks (I have no idea
> > why).
> >
> > So, here goes some source code:
> >
> > PNDIS_PACKET DuplicatePacket(PNDIS_PACKET OriginalPacket,PADAPT Adapter,
> > BOOLEAN tosend)
> > {
> > NDIS_STATUS Status;
> > PNDIS_PACKET MyPacket;
> > PRECV_RSVD RecvRsvd;
> > PSEND_RSVD SendRsvd;
> >
> > //tosend == FALSE -> packet is going to be received
> > if(tosend == FALSE)
> > {
> > NdisDprAllocatePacket(&Status, &MyPacket, Adapter->RecvPacketPoolHandle);
> > RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);
> > RecvRsvd->OriginalPkt = OriginalPacket;
> > }
> > else
> > {
> > NdisDprAllocatePacket(&Status, &MyPacket, Adapter->SendPacketPoolHandle);
> > SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved);
> > SendRsvd->OriginalPkt = NULL;//marking packet as crafted
> > }
> >
> > MyPacket->Private.Head = OriginalPacket->Private.Head;
> > MyPacket->Private.Tail = OriginalPacket->Private.Tail;
> >
> > NDIS_SET_ORIGINAL_PACKET(MyPacket,NDIS_GET_ORIGINAL_PACKET(OriginalPacket));
> >
> > NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(OriginalPacket);
> >
> > Status = NDIS_GET_PACKET_STATUS(OriginalPacket);
> >
> > NDIS_SET_PACKET_STATUS(MyPacket, Status);
> > NDIS_SET_PACKET_HEADER_SIZE(MyPacket,
> > NDIS_GET_PACKET_HEADER_SIZE(OriginalPacket));
> > return (MyPacket);
> > }
> >
> > Now, I'm not quite satisfied with this function (although it seems to work)
> > as it seems to me that I don't really copy any packet data...
> > Additionally, if I mark any packet that shall be received later on with a
> > NULL pointer at OriginalPkt, MPReturnPackets crashes, if I enter a pointer
> > to the real original packet, everything works fine.
> >
> > Anyway, the PtSendComplete handler looks as follows:
> >
> > VOID
> > PtSendComplete(
> > IN NDIS_HANDLE ProtocolBindingContext,
> > IN PNDIS_PACKET Packet,
> > IN NDIS_STATUS Status
> > )
> > {
> > PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
> > PNDIS_PACKET Pkt;
> > NDIS_HANDLE PoolHandle;
> >
> >
> > PSEND_RSVD SendRsvd;
> >
> >
> > SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
> > Pkt = SendRsvd->OriginalPkt;
> >
> > if( Pkt )
> > {
> >
> > PoolHandle = NdisGetPoolFromPacket(Packet);
> > if (PoolHandle != pAdapt->SendPacketPoolHandle)
> > {
> > NdisMSendComplete(pAdapt->MiniportHandle, Packet, Status);
> > }
> > else
> > {
> > NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
> > NdisDprFreePacket(Packet);
> > NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status);
> > }
> > }
> > else
> > {
> > //packet was crafted, just free it
> > NdisDprFreePacket(Packet);
> > }
> > }
> >
> > Any ideas, what could cause the memory leaks? Do you have any comments on
> > the DuplicatePacket function? Could this code really work as expected
> > (although it seems to do so)?
> >
> > There's a second problem: When I additionally start ethereal on the testing
> > machine, the NdisSend call I make to send the packet fails with
> > DRIVER_IRQL_NOT_LESS_OR_EQUAL. Any ideas on that?
> >
> >
> > Greetings,
> > Peter
>
>
.
- References:
- Duplicating NDIS_PACKET
- From: Peter Schmitz
- Re: Duplicating NDIS_PACKET
- From: Stephan Wolf [MVP]
- Duplicating NDIS_PACKET
- Prev by Date: Re: Duplicating NDIS_PACKET
- Next by Date: Re: ASR - while no tape drive support ion OS CD
- Previous by thread: Re: Duplicating NDIS_PACKET
- Next by thread: Re: Duplicating NDIS_PACKET
- Index(es):
Relevant Pages
|
Loading