Author: cgutman Date: Sun Dec 4 22:31:49 2011 New Revision: 54593
URL: http://svn.reactos.org/svn/reactos?rev=54593&view=rev Log: [TCPIP] - 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)
Modified: trunk/reactos/drivers/network/tcpip/datalink/lan.c trunk/reactos/drivers/network/tcpip/include/receive.h trunk/reactos/lib/drivers/ip/network/ip.c trunk/reactos/lib/drivers/ip/network/loopback.c trunk/reactos/lib/drivers/ip/network/receive.c
Modified: trunk/reactos/drivers/network/tcpip/datalink/lan.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/datal... ============================================================================== --- trunk/reactos/drivers/network/tcpip/datalink/lan.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/datalink/lan.c [iso-8859-1] Sun Dec 4 22:31:49 2011 @@ -278,22 +278,21 @@ ("Ether Type = %x ContigSize = %d Total = %d\n", PacketType, IPPacket.ContigSize, IPPacket.TotalSize));
+ /* NDIS packet is freed in all of these cases */ switch (PacketType) { - case ETYPE_IPv4: - case ETYPE_IPv6: - TI_DbgPrint(MID_TRACE,("Received IP Packet\n")); - IPReceive(Adapter->Context, &IPPacket); - break; - case ETYPE_ARP: - TI_DbgPrint(MID_TRACE,("Received ARP Packet\n")); - ARPReceive(Adapter->Context, &IPPacket); - break; - default: - IPPacket.Free(&IPPacket); - break; - } - - FreeNdisPacket( Packet ); + case ETYPE_IPv4: + case ETYPE_IPv6: + TI_DbgPrint(MID_TRACE,("Received IP Packet\n")); + IPReceive(Adapter->Context, &IPPacket); + break; + case ETYPE_ARP: + TI_DbgPrint(MID_TRACE,("Received ARP Packet\n")); + ARPReceive(Adapter->Context, &IPPacket); + break; + default: + IPPacket.Free(&IPPacket); + break; + } }
VOID LanSubmitReceiveWork(
Modified: trunk/reactos/drivers/network/tcpip/include/receive.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/tcpip/inclu... ============================================================================== --- trunk/reactos/drivers/network/tcpip/include/receive.h [iso-8859-1] (original) +++ trunk/reactos/drivers/network/tcpip/include/receive.h [iso-8859-1] Sun Dec 4 22:31:49 2011 @@ -15,7 +15,8 @@ /* IP datagram fragment descriptor. Used to store IP datagram fragments */ typedef struct IP_FRAGMENT { 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 Size; /* Size of this fragment */ } IP_FRAGMENT, *PIP_FRAGMENT;
Modified: trunk/reactos/lib/drivers/ip/network/ip.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/ip.c... ============================================================================== --- trunk/reactos/lib/drivers/ip/network/ip.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/network/ip.c [iso-8859-1] Sun Dec 4 22:31:49 2011 @@ -30,14 +30,22 @@ VOID TCPUnregisterInterface(PIP_INTERFACE IF);
-VOID DontFreePacket( +VOID DeinitializePacket( PVOID Object) /* - * FUNCTION: Do nothing for when the IPPacket struct is part of another + * FUNCTION: Frees buffers attached to the packet * ARGUMENTS: * 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( @@ -62,10 +70,9 @@ * Pointer to the created IP packet. NULL if there was not enough free resources. */ { - /* FIXME: Is this needed? */ RtlZeroMemory(IPPacket, sizeof(IP_PACKET));
- IPPacket->Free = DontFreePacket; + IPPacket->Free = DeinitializePacket; IPPacket->Type = Type;
return IPPacket;
Modified: trunk/reactos/lib/drivers/ip/network/loopback.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/loop... ============================================================================== --- trunk/reactos/lib/drivers/ip/network/loopback.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/network/loopback.c [iso-8859-1] Sun Dec 4 22:31:49 2011 @@ -17,10 +17,10 @@ { PIP_PACKET IPPacket = Context;
+ /* IPReceive() takes care of the NDIS packet */ IPReceive(Loopback, IPPacket); - FreeNdisPacket(IPPacket->NdisPacket);
- ExFreePool(Context); + ExFreePool(IPPacket); }
VOID LoopTransmit( @@ -43,9 +43,8 @@ UINT PacketLength; PNDIS_PACKET XmitPacket; NDIS_STATUS NdisStatus; - IP_PACKET IPPacket; + PIP_PACKET IPPacket; PNDIS_BUFFER NdisBuffer; - PVOID WorkerBuffer;
ASSERT_KM_POINTER(NdisPacket); ASSERT_KM_POINTER(PC(NdisPacket)); @@ -59,24 +58,23 @@ ( &XmitPacket, PacketBuffer, PacketLength );
if( NT_SUCCESS(NdisStatus) ) { - IPInitializePacket(&IPPacket, 0); - - IPPacket.NdisPacket = XmitPacket; - - NdisGetFirstBufferFromPacket(XmitPacket, - &NdisBuffer, - &IPPacket.Header, - &IPPacket.ContigSize, - &IPPacket.TotalSize); + IPPacket = ExAllocatePool(NonPagedPool, sizeof(IP_PACKET)); + if (IPPacket) + { + IPInitializePacket(IPPacket, 0);
- - WorkerBuffer = ExAllocatePool(NonPagedPool, sizeof(IPPacket)); - if (WorkerBuffer) - { - RtlCopyMemory(WorkerBuffer, &IPPacket, sizeof(IPPacket)); - 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; } }
Modified: trunk/reactos/lib/drivers/ip/network/receive.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/ip/network/rece... ============================================================================== --- trunk/reactos/lib/drivers/ip/network/receive.c [iso-8859-1] (original) +++ trunk/reactos/lib/drivers/ip/network/receive.c [iso-8859-1] Sun Dec 4 22:31:49 2011 @@ -89,10 +89,10 @@ /* Unlink it from the list */ 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 */ - ExFreePoolWithTag(CurrentF->Data, FRAGMENT_DATA_TAG); + FreeNdisPacket(CurrentF->Packet);
TI_DbgPrint(DEBUG_IP, ("Freeing fragment at (0x%X).\n", CurrentF));
@@ -186,20 +186,16 @@ */ { PLIST_ENTRY CurrentEntry; - PIP_FRAGMENT Current; - PVOID Data; + PIP_FRAGMENT Fragment; + PCHAR Data;
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->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->ContigSize = IPPacket->TotalSize; IPPacket->HeaderSize = IPDR->HeaderSize; - /*IPPacket->Position = IPDR->HeaderSize;*/
RtlCopyMemory(&IPPacket->SrcAddr, &IPDR->SrcAddr, sizeof(IP_ADDRESS)); RtlCopyMemory(&IPPacket->DstAddr, &IPDR->DstAddr, sizeof(IP_ADDRESS)); @@ -221,15 +217,14 @@ /* Copy data from all fragments into buffer */ CurrentEntry = IPDR->FragmentListHead.Flink; while (CurrentEntry != &IPDR->FragmentListHead) { - Current = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry); - - 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 ); + Fragment = CONTAINING_RECORD(CurrentEntry, IP_FRAGMENT, ListEntry); + + /* Copy fragment data into datagram buffer */ + CopyPacketToBuffer(Data + Fragment->Offset, + Fragment->Packet, + Fragment->PacketOffset, + Fragment->Size); + CurrentEntry = CurrentEntry->Flink; }
@@ -410,24 +405,12 @@ TI_DbgPrint(DEBUG_IP, ("Fragment descriptor allocated at (0x%X).\n", Fragment));
Fragment->Size = IPPacket->TotalSize - IPPacket->HeaderSize; - Fragment->Data = ExAllocatePoolWithTag(NonPagedPool, Fragment->Size, FRAGMENT_DATA_TAG); - if (!Fragment->Data) { - /* 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->Packet = IPPacket->NdisPacket; + Fragment->PacketOffset = IPPacket->Position + IPPacket->HeaderSize; 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 (!MoreFragments) @@ -581,7 +564,6 @@ AddrInitIPv4(&IPPacket->SrcAddr, ((PIPv4_HEADER)IPPacket->Header)->SrcAddr); AddrInitIPv4(&IPPacket->DstAddr, ((PIPv4_HEADER)IPPacket->Header)->DstAddr);
- IPPacket->Position += IPPacket->HeaderSize; IPPacket->Data = (PVOID)((ULONG_PTR)IPPacket->Header + IPPacket->HeaderSize);
TI_DbgPrint(MID_TRACE,("IPPacket->Position = %d\n",