Author: cgutman Date: Sun Sep 20 23:07:45 2009 New Revision: 43099
URL: http://svn.reactos.org/svn/reactos?rev=43099&view=rev Log: - Simplify and fix a few bugs in datagram reassembly - Implement reassembly timeout
Modified: trunk/reactos/drivers/network/tcpip/include/receive.h trunk/reactos/lib/drivers/ip/network/receive.c
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 Sep 20 23:07:45 2009 @@ -9,6 +9,8 @@
#include <ip.h>
+/* Number of timeout ticks before destroying the IPDR */ +#define MAX_TIMEOUT_COUNT 10
/* IP datagram fragment descriptor. Used to store IP datagram fragments */ typedef struct IP_FRAGMENT { @@ -38,6 +40,7 @@ UINT HeaderSize; /* Length of IP header */ LIST_ENTRY FragmentListHead; /* IP fragment list */ LIST_ENTRY HoleListHead; /* IP datagram hole list */ + UINT TimeoutCount; /* Timeout counter */ } IPDATAGRAM_REASSEMBLY, *PIPDATAGRAM_REASSEMBLY;
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 Sep 20 23:07:45 2009 @@ -17,12 +17,6 @@ NPAGED_LOOKASIDE_LIST IPDRList; NPAGED_LOOKASIDE_LIST IPFragmentList; NPAGED_LOOKASIDE_LIST IPHoleList; - -VOID ReflectPacketComplete( - PVOID Context, - PNDIS_PACKET Packet, - NDIS_STATUS Status ) { -}
PIPDATAGRAM_HOLE CreateHoleDescriptor( ULONG First, @@ -299,8 +293,6 @@ TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n")); /* We have a reassembly structure */ TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql); - CurrentEntry = IPDR->HoleListHead.Flink; - Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry); } else { TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n"));
@@ -323,10 +315,10 @@ AddrInitIPv4(&IPDR->DstAddr, IPv4Header->DstAddr); IPDR->Id = IPv4Header->Id; IPDR->Protocol = IPv4Header->Protocol; + IPDR->TimeoutCount = 0; InitializeListHead(&IPDR->FragmentListHead); InitializeListHead(&IPDR->HoleListHead); InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry); - CurrentEntry = IPDR->HoleListHead.Flink;
TcpipInitializeSpinLock(&IPDR->Lock);
@@ -343,10 +335,12 @@ FragLast = FragFirst + WN2H(IPv4Header->TotalLength); MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0;
+ CurrentEntry = IPDR->HoleListHead.Flink; for (;;) { if (CurrentEntry == &IPDR->HoleListHead) - /* No more entries */ - break; + break; + + Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
TI_DbgPrint(DEBUG_IP, ("Comparing Fragment (%d,%d) to Hole (%d,%d).\n", FragFirst, FragLast, Hole->First, Hole->Last)); @@ -357,8 +351,6 @@ descriptor in the list */
CurrentEntry = CurrentEntry->Flink; - if (CurrentEntry != &IPDR->HoleListHead) - Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry); continue; }
@@ -366,7 +358,7 @@ RemoveEntryList(CurrentEntry);
if (FragFirst > Hole->First) { - NewHole = CreateHoleDescriptor(Hole->First, FragLast - 1); + NewHole = CreateHoleDescriptor(Hole->First, FragFirst - 1); if (!NewHole) { /* We don't have the resources to process this packet, discard it */ exFreeToNPagedLookasideList(&IPHoleList, Hole); @@ -378,14 +370,20 @@ InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry); }
- if ((FragLast < Hole->Last) && (MoreFragments)) { - /* We can reuse the descriptor for the new hole */ - Hole->First = FragLast + 1; + if ((FragLast < Hole->Last) && MoreFragments) { + NewHole = CreateHoleDescriptor(FragLast + 1, Hole->Last); + if (!NewHole) { + /* We don't have the resources to process this packet, discard it */ + exFreeToNPagedLookasideList(&IPHoleList, Hole); + Cleanup(&IPDR->Lock, OldIrql, IPDR); + return; + }
/* Put the new hole descriptor in the list */ - InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry); - } else - exFreeToNPagedLookasideList(&IPHoleList, Hole); + InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry); + } + + exFreeToNPagedLookasideList(&IPHoleList, Hole);
/* If this is the first fragment, save the IP header */ if (FragFirst == 0) { @@ -424,7 +422,7 @@ /* Copy datagram data into fragment buffer */ CopyPacketToBuffer(Fragment->Data, IPPacket->NdisPacket, - IPPacket->Position, + IPPacket->HeaderSize, Fragment->Size); Fragment->Offset = FragFirst;
@@ -434,7 +432,7 @@
/* Put the fragment in the list */ InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry); - break; + break; }
TI_DbgPrint(DEBUG_IP, ("Done searching for hole descriptor.\n")); @@ -512,6 +510,36 @@ * to hold IP fragments that have taken too long to reassemble */ { + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry, NextEntry; + PIPDATAGRAM_REASSEMBLY CurrentIPDR; + + TcpipAcquireSpinLock(&ReassemblyListLock, &OldIrql); + + CurrentEntry = ReassemblyListHead.Flink; + while (CurrentEntry != &ReassemblyListHead) + { + NextEntry = CurrentEntry->Flink; + CurrentIPDR = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_REASSEMBLY, ListEntry); + + TcpipAcquireSpinLockAtDpcLevel(&CurrentIPDR->Lock); + + if (++CurrentIPDR->TimeoutCount == MAX_TIMEOUT_COUNT) + { + TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock); + RemoveEntryList(CurrentEntry); + FreeIPDR(CurrentIPDR); + } + else + { + ASSERT(CurrentIPDR->TimeoutCount < MAX_TIMEOUT_COUNT); + TcpipReleaseSpinLockFromDpcLevel(&CurrentIPDR->Lock); + } + + CurrentEntry = NextEntry; + } + + TcpipReleaseSpinLock(&ReassemblyListLock, OldIrql); }
VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)