mirror of
https://github.com/reactos/reactos.git
synced 2024-10-21 00:18:26 +00:00
- Simplify and fix a few bugs in datagram reassembly
- Implement reassembly timeout svn path=/trunk/; revision=43099
This commit is contained in:
parent
5ec7ec1632
commit
4d2e0e023f
|
@ -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 @@ 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;
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue