- Avoid an extra copy operation when receiving packets
- Optimize loopback code a bit
- Make IP receive independent of the location of the data and continuity of buffers in the NDIS packet for ProtocolReceivePacket support (part 1 of x)

svn path=/trunk/; revision=54593
This commit is contained in:
Cameron Gutman 2011-12-04 22:31:49 +00:00
parent 37dc00b136
commit 3b2e97595e
5 changed files with 60 additions and 73 deletions

View file

@ -278,22 +278,21 @@ VOID LanReceiveWorker( PVOID Context ) {
("Ether Type = %x ContigSize = %d Total = %d\n", ("Ether Type = %x ContigSize = %d Total = %d\n",
PacketType, IPPacket.ContigSize, IPPacket.TotalSize)); PacketType, IPPacket.ContigSize, IPPacket.TotalSize));
/* NDIS packet is freed in all of these cases */
switch (PacketType) { switch (PacketType) {
case ETYPE_IPv4: case ETYPE_IPv4:
case ETYPE_IPv6: case ETYPE_IPv6:
TI_DbgPrint(MID_TRACE,("Received IP Packet\n")); TI_DbgPrint(MID_TRACE,("Received IP Packet\n"));
IPReceive(Adapter->Context, &IPPacket); IPReceive(Adapter->Context, &IPPacket);
break; break;
case ETYPE_ARP: case ETYPE_ARP:
TI_DbgPrint(MID_TRACE,("Received ARP Packet\n")); TI_DbgPrint(MID_TRACE,("Received ARP Packet\n"));
ARPReceive(Adapter->Context, &IPPacket); ARPReceive(Adapter->Context, &IPPacket);
break; break;
default: default:
IPPacket.Free(&IPPacket); IPPacket.Free(&IPPacket);
break; break;
} }
FreeNdisPacket( Packet );
} }
VOID LanSubmitReceiveWork( VOID LanSubmitReceiveWork(

View file

@ -15,7 +15,8 @@
/* IP datagram fragment descriptor. Used to store IP datagram fragments */ /* IP datagram fragment descriptor. Used to store IP datagram fragments */
typedef struct IP_FRAGMENT { typedef struct IP_FRAGMENT {
LIST_ENTRY ListEntry; /* Entry on list */ LIST_ENTRY ListEntry; /* Entry on list */
PVOID Data; /* Pointer to fragment data */ PNDIS_PACKET Packet; /* NDIS packet containing fragment data */
UINT PacketOffset; /* Offset into NDIS packet where data is */
UINT Offset; /* Offset into datagram where this fragment is */ UINT Offset; /* Offset into datagram where this fragment is */
UINT Size; /* Size of this fragment */ UINT Size; /* Size of this fragment */
} IP_FRAGMENT, *PIP_FRAGMENT; } IP_FRAGMENT, *PIP_FRAGMENT;

View file

@ -30,14 +30,22 @@ TCPRegisterInterface(PIP_INTERFACE IF);
VOID VOID
TCPUnregisterInterface(PIP_INTERFACE IF); TCPUnregisterInterface(PIP_INTERFACE IF);
VOID DontFreePacket( VOID DeinitializePacket(
PVOID Object) PVOID Object)
/* /*
* FUNCTION: Do nothing for when the IPPacket struct is part of another * FUNCTION: Frees buffers attached to the packet
* ARGUMENTS: * ARGUMENTS:
* Object = Pointer to an IP packet structure * Object = Pointer to an IP packet structure
*/ */
{ {
PIP_PACKET IPPacket = Object;
/* Detect double free */
ASSERT(IPPacket->Type != 0xFF);
IPPacket->Type = 0xFF;
if (IPPacket->NdisPacket != NULL)
FreeNdisPacket(IPPacket->NdisPacket);
} }
VOID FreeIF( VOID FreeIF(
@ -62,10 +70,9 @@ PIP_PACKET IPInitializePacket(
* Pointer to the created IP packet. NULL if there was not enough free resources. * Pointer to the created IP packet. NULL if there was not enough free resources.
*/ */
{ {
/* FIXME: Is this needed? */
RtlZeroMemory(IPPacket, sizeof(IP_PACKET)); RtlZeroMemory(IPPacket, sizeof(IP_PACKET));
IPPacket->Free = DontFreePacket; IPPacket->Free = DeinitializePacket;
IPPacket->Type = Type; IPPacket->Type = Type;
return IPPacket; return IPPacket;

View file

@ -17,10 +17,10 @@ VOID LoopPassiveWorker(
{ {
PIP_PACKET IPPacket = Context; PIP_PACKET IPPacket = Context;
/* IPReceive() takes care of the NDIS packet */
IPReceive(Loopback, IPPacket); IPReceive(Loopback, IPPacket);
FreeNdisPacket(IPPacket->NdisPacket);
ExFreePool(Context); ExFreePool(IPPacket);
} }
VOID LoopTransmit( VOID LoopTransmit(
@ -43,9 +43,8 @@ VOID LoopTransmit(
UINT PacketLength; UINT PacketLength;
PNDIS_PACKET XmitPacket; PNDIS_PACKET XmitPacket;
NDIS_STATUS NdisStatus; NDIS_STATUS NdisStatus;
IP_PACKET IPPacket; PIP_PACKET IPPacket;
PNDIS_BUFFER NdisBuffer; PNDIS_BUFFER NdisBuffer;
PVOID WorkerBuffer;
ASSERT_KM_POINTER(NdisPacket); ASSERT_KM_POINTER(NdisPacket);
ASSERT_KM_POINTER(PC(NdisPacket)); ASSERT_KM_POINTER(PC(NdisPacket));
@ -59,24 +58,23 @@ VOID LoopTransmit(
( &XmitPacket, PacketBuffer, PacketLength ); ( &XmitPacket, PacketBuffer, PacketLength );
if( NT_SUCCESS(NdisStatus) ) { if( NT_SUCCESS(NdisStatus) ) {
IPInitializePacket(&IPPacket, 0); IPPacket = ExAllocatePool(NonPagedPool, sizeof(IP_PACKET));
if (IPPacket)
IPPacket.NdisPacket = XmitPacket;
NdisGetFirstBufferFromPacket(XmitPacket,
&NdisBuffer,
&IPPacket.Header,
&IPPacket.ContigSize,
&IPPacket.TotalSize);
WorkerBuffer = ExAllocatePool(NonPagedPool, sizeof(IPPacket));
if (WorkerBuffer)
{ {
RtlCopyMemory(WorkerBuffer, &IPPacket, sizeof(IPPacket)); IPInitializePacket(IPPacket, 0);
if (!ChewCreate(LoopPassiveWorker, WorkerBuffer))
IPPacket->NdisPacket = XmitPacket;
NdisGetFirstBufferFromPacket(XmitPacket,
&NdisBuffer,
&IPPacket->Header,
&IPPacket->ContigSize,
&IPPacket->TotalSize);
if (!ChewCreate(LoopPassiveWorker, IPPacket))
{ {
ExFreePool(WorkerBuffer); IPPacket->Free(IPPacket);
ExFreePool(IPPacket);
NdisStatus = NDIS_STATUS_RESOURCES; NdisStatus = NDIS_STATUS_RESOURCES;
} }
} }

View file

@ -89,10 +89,10 @@ VOID FreeIPDR(
/* Unlink it from the list */ /* Unlink it from the list */
RemoveEntryList(CurrentEntry); RemoveEntryList(CurrentEntry);
TI_DbgPrint(DEBUG_IP, ("Freeing fragment data at (0x%X).\n", CurrentF->Data)); TI_DbgPrint(DEBUG_IP, ("Freeing fragment packet at (0x%X).\n", CurrentF->Packet));
/* Free the fragment data buffer */ /* Free the fragment data buffer */
ExFreePoolWithTag(CurrentF->Data, FRAGMENT_DATA_TAG); FreeNdisPacket(CurrentF->Packet);
TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF)); TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF));
@ -186,20 +186,16 @@ ReassembleDatagram(
*/ */
{ {
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
PIP_FRAGMENT Current; PIP_FRAGMENT Fragment;
PVOID Data; PCHAR Data;
TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR)); TI_DbgPrint(DEBUG_IP, ("Reassembling datagram from IPDR at (0x%X).\n", IPDR));
TI_DbgPrint(DEBUG_IP, ("IPDR->HeaderSize = %d\n", IPDR->HeaderSize)); TI_DbgPrint(DEBUG_IP, ("IPDR->HeaderSize = %d\n", IPDR->HeaderSize));
TI_DbgPrint(DEBUG_IP, ("IPDR->DataSize = %d\n", IPDR->DataSize)); TI_DbgPrint(DEBUG_IP, ("IPDR->DataSize = %d\n", IPDR->DataSize));
TI_DbgPrint(DEBUG_IP, ("Fragment header:\n"));
//OskitDumpBuffer((PCHAR)IPDR->IPv4Header, IPDR->HeaderSize);
IPPacket->TotalSize = IPDR->HeaderSize + IPDR->DataSize; IPPacket->TotalSize = IPDR->HeaderSize + IPDR->DataSize;
IPPacket->ContigSize = IPPacket->TotalSize; IPPacket->ContigSize = IPPacket->TotalSize;
IPPacket->HeaderSize = IPDR->HeaderSize; IPPacket->HeaderSize = IPDR->HeaderSize;
/*IPPacket->Position = IPDR->HeaderSize;*/
RtlCopyMemory(&IPPacket->SrcAddr, &IPDR->SrcAddr, sizeof(IP_ADDRESS)); RtlCopyMemory(&IPPacket->SrcAddr, &IPDR->SrcAddr, sizeof(IP_ADDRESS));
RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS)); RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS));
@ -221,15 +217,14 @@ ReassembleDatagram(
/* Copy data from all fragments into buffer */ /* Copy data from all fragments into buffer */
CurrentEntry = IPDR->FragmentListHead.Flink; CurrentEntry = IPDR->FragmentListHead.Flink;
while (CurrentEntry != &IPDR->FragmentListHead) { while (CurrentEntry != &IPDR->FragmentListHead) {
Current = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry); Fragment = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry);
/* Copy fragment data into datagram buffer */
CopyPacketToBuffer(Data + Fragment->Offset,
Fragment->Packet,
Fragment->PacketOffset,
Fragment->Size);
TI_DbgPrint(DEBUG_IP, ("Copying (%d) bytes of fragment data from (0x%X) to offset (%d).\n",
Current->Size, Data, Current->Offset));
/* Copy fragment data to the destination buffer at the correct offset */
RtlCopyMemory((PVOID)((ULONG_PTR)Data + Current->Offset),
Current->Data,
Current->Size);
//OskitDumpBuffer( Data, Current->Offset + Current->Size );
CurrentEntry = CurrentEntry->Flink; CurrentEntry = CurrentEntry->Flink;
} }
@ -410,25 +405,13 @@ VOID ProcessFragment(
TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment)); TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));
Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize; Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize;
Fragment->Data = ExAllocatePoolWithTag(NonPagedPool, Fragment->Size, FRAGMENT_DATA_TAG); Fragment->Packet = IPPacket->NdisPacket;
if (!Fragment->Data) { Fragment->PacketOffset = IPPacket->Position + IPPacket->HeaderSize;
/* We don't have the resources to process this packet, discard it */
ExFreeToNPagedLookasideList(&IPFragmentList, Fragment);
Cleanup(&IPDR->Lock, OldIrql, IPDR);
return;
}
/* Position here is an offset from the NdisPacket start, not the header */
TI_DbgPrint(DEBUG_IP, ("Fragment data buffer allocated at (0x%X) Size (%d) Pos (%d).\n",
Fragment->Data, Fragment->Size, IPPacket->Position));
/* Copy datagram data into fragment buffer */
CopyPacketToBuffer(Fragment->Data,
IPPacket->NdisPacket,
IPPacket->HeaderSize,
Fragment->Size);
Fragment->Offset = FragFirst; Fragment->Offset = FragFirst;
/* Disassociate the NDIS packet so it isn't freed upon return from IPReceive() */
IPPacket->NdisPacket = NULL;
/* If this is the last fragment, compute and save the datagram data size */ /* If this is the last fragment, compute and save the datagram data size */
if (!MoreFragments) if (!MoreFragments)
IPDR->DataSize = FragFirst + Fragment->Size; IPDR->DataSize = FragFirst + Fragment->Size;
@ -581,7 +564,6 @@ VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr); AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr);
AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr); AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
IPPacket->Position += IPPacket->HeaderSize;
IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPPacket->HeaderSize); IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPPacket->HeaderSize);
TI_DbgPrint(MID_TRACE,("IPPacket->Position = %d\n", TI_DbgPrint(MID_TRACE,("IPPacket->Position = %d\n",