From 4d2e0e023f13dc352467edb27f1c6998c67b3527 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 20 Sep 2009 21:07:45 +0000 Subject: [PATCH] - Simplify and fix a few bugs in datagram reassembly - Implement reassembly timeout svn path=/trunk/; revision=43099 --- .../drivers/network/tcpip/include/receive.h | 3 + reactos/lib/drivers/ip/network/receive.c | 72 +++++++++++++------ 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/reactos/drivers/network/tcpip/include/receive.h b/reactos/drivers/network/tcpip/include/receive.h index 52e520f6c39..2681732bf23 100644 --- a/reactos/drivers/network/tcpip/include/receive.h +++ b/reactos/drivers/network/tcpip/include/receive.h @@ -9,6 +9,8 @@ #include +/* 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 @@ typedef struct IPDATAGRAM_REASSEMBLY { 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; diff --git a/reactos/lib/drivers/ip/network/receive.c b/reactos/lib/drivers/ip/network/receive.c index aff556b297a..174b647abfd 100644 --- a/reactos/lib/drivers/ip/network/receive.c +++ b/reactos/lib/drivers/ip/network/receive.c @@ -18,12 +18,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, ULONG Last) @@ -299,8 +293,6 @@ VOID ProcessFragment( 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 @@ VOID ProcessFragment( 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 @@ VOID ProcessFragment( 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 @@ VOID ProcessFragment( descriptor in the list */ CurrentEntry = CurrentEntry->Flink; - if (CurrentEntry != &IPDR->HoleListHead) - Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry); continue; } @@ -366,7 +358,7 @@ VOID ProcessFragment( 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 @@ VOID ProcessFragment( 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 @@ VOID ProcessFragment( /* Copy datagram data into fragment buffer */ CopyPacketToBuffer(Fragment->Data, IPPacket->NdisPacket, - IPPacket->Position, + IPPacket->HeaderSize, Fragment->Size); Fragment->Offset = FragFirst; @@ -434,7 +432,7 @@ VOID ProcessFragment( /* 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 @@ VOID IPDatagramReassemblyTimeout( * 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) -- 2.17.1