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/incl…
==============================================================================
--- 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/rec…
==============================================================================
--- 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)