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>
|
#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 */
|
/* IP datagram fragment descriptor. Used to store IP datagram fragments */
|
||||||
typedef struct IP_FRAGMENT {
|
typedef struct IP_FRAGMENT {
|
||||||
|
@ -38,6 +40,7 @@ typedef struct IPDATAGRAM_REASSEMBLY {
|
||||||
UINT HeaderSize; /* Length of IP header */
|
UINT HeaderSize; /* Length of IP header */
|
||||||
LIST_ENTRY FragmentListHead; /* IP fragment list */
|
LIST_ENTRY FragmentListHead; /* IP fragment list */
|
||||||
LIST_ENTRY HoleListHead; /* IP datagram hole list */
|
LIST_ENTRY HoleListHead; /* IP datagram hole list */
|
||||||
|
UINT TimeoutCount; /* Timeout counter */
|
||||||
} IPDATAGRAM_REASSEMBLY, *PIPDATAGRAM_REASSEMBLY;
|
} IPDATAGRAM_REASSEMBLY, *PIPDATAGRAM_REASSEMBLY;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,6 @@ NPAGED_LOOKASIDE_LIST IPDRList;
|
||||||
NPAGED_LOOKASIDE_LIST IPFragmentList;
|
NPAGED_LOOKASIDE_LIST IPFragmentList;
|
||||||
NPAGED_LOOKASIDE_LIST IPHoleList;
|
NPAGED_LOOKASIDE_LIST IPHoleList;
|
||||||
|
|
||||||
VOID ReflectPacketComplete(
|
|
||||||
PVOID Context,
|
|
||||||
PNDIS_PACKET Packet,
|
|
||||||
NDIS_STATUS Status ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
PIPDATAGRAM_HOLE CreateHoleDescriptor(
|
PIPDATAGRAM_HOLE CreateHoleDescriptor(
|
||||||
ULONG First,
|
ULONG First,
|
||||||
ULONG Last)
|
ULONG Last)
|
||||||
|
@ -299,8 +293,6 @@ VOID ProcessFragment(
|
||||||
TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n"));
|
TI_DbgPrint(DEBUG_IP, ("Continueing assembly.\n"));
|
||||||
/* We have a reassembly structure */
|
/* We have a reassembly structure */
|
||||||
TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);
|
TcpipAcquireSpinLock(&IPDR->Lock, &OldIrql);
|
||||||
CurrentEntry = IPDR->HoleListHead.Flink;
|
|
||||||
Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
|
|
||||||
} else {
|
} else {
|
||||||
TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n"));
|
TI_DbgPrint(DEBUG_IP, ("Starting new assembly.\n"));
|
||||||
|
|
||||||
|
@ -323,10 +315,10 @@ VOID ProcessFragment(
|
||||||
AddrInitIPv4(&IPDR->DstAddr, IPv4Header->DstAddr);
|
AddrInitIPv4(&IPDR->DstAddr, IPv4Header->DstAddr);
|
||||||
IPDR->Id = IPv4Header->Id;
|
IPDR->Id = IPv4Header->Id;
|
||||||
IPDR->Protocol = IPv4Header->Protocol;
|
IPDR->Protocol = IPv4Header->Protocol;
|
||||||
|
IPDR->TimeoutCount = 0;
|
||||||
InitializeListHead(&IPDR->FragmentListHead);
|
InitializeListHead(&IPDR->FragmentListHead);
|
||||||
InitializeListHead(&IPDR->HoleListHead);
|
InitializeListHead(&IPDR->HoleListHead);
|
||||||
InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry);
|
InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry);
|
||||||
CurrentEntry = IPDR->HoleListHead.Flink;
|
|
||||||
|
|
||||||
TcpipInitializeSpinLock(&IPDR->Lock);
|
TcpipInitializeSpinLock(&IPDR->Lock);
|
||||||
|
|
||||||
|
@ -343,10 +335,12 @@ VOID ProcessFragment(
|
||||||
FragLast = FragFirst + WN2H(IPv4Header->TotalLength);
|
FragLast = FragFirst + WN2H(IPv4Header->TotalLength);
|
||||||
MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0;
|
MoreFragments = (WN2H(IPv4Header->FlagsFragOfs) & IPv4_MF_MASK) > 0;
|
||||||
|
|
||||||
|
CurrentEntry = IPDR->HoleListHead.Flink;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (CurrentEntry == &IPDR->HoleListHead)
|
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",
|
TI_DbgPrint(DEBUG_IP, ("Comparing Fragment (%d,%d) to Hole (%d,%d).\n",
|
||||||
FragFirst, FragLast, Hole->First, Hole->Last));
|
FragFirst, FragLast, Hole->First, Hole->Last));
|
||||||
|
@ -357,8 +351,6 @@ VOID ProcessFragment(
|
||||||
descriptor in the list */
|
descriptor in the list */
|
||||||
|
|
||||||
CurrentEntry = CurrentEntry->Flink;
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
if (CurrentEntry != &IPDR->HoleListHead)
|
|
||||||
Hole = CONTAINING_RECORD(CurrentEntry, IPDATAGRAM_HOLE, ListEntry);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +358,7 @@ VOID ProcessFragment(
|
||||||
RemoveEntryList(CurrentEntry);
|
RemoveEntryList(CurrentEntry);
|
||||||
|
|
||||||
if (FragFirst > Hole->First) {
|
if (FragFirst > Hole->First) {
|
||||||
NewHole = CreateHoleDescriptor(Hole->First, FragLast - 1);
|
NewHole = CreateHoleDescriptor(Hole->First, FragFirst - 1);
|
||||||
if (!NewHole) {
|
if (!NewHole) {
|
||||||
/* We don't have the resources to process this packet, discard it */
|
/* We don't have the resources to process this packet, discard it */
|
||||||
exFreeToNPagedLookasideList(&IPHoleList, Hole);
|
exFreeToNPagedLookasideList(&IPHoleList, Hole);
|
||||||
|
@ -378,14 +370,20 @@ VOID ProcessFragment(
|
||||||
InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
|
InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((FragLast < Hole->Last) && (MoreFragments)) {
|
if ((FragLast < Hole->Last) && MoreFragments) {
|
||||||
/* We can reuse the descriptor for the new hole */
|
NewHole = CreateHoleDescriptor(FragLast + 1, Hole->Last);
|
||||||
Hole->First = FragLast + 1;
|
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 */
|
/* Put the new hole descriptor in the list */
|
||||||
InsertTailList(&IPDR->HoleListHead, &Hole->ListEntry);
|
InsertTailList(&IPDR->HoleListHead, &NewHole->ListEntry);
|
||||||
} else
|
}
|
||||||
exFreeToNPagedLookasideList(&IPHoleList, Hole);
|
|
||||||
|
exFreeToNPagedLookasideList(&IPHoleList, Hole);
|
||||||
|
|
||||||
/* If this is the first fragment, save the IP header */
|
/* If this is the first fragment, save the IP header */
|
||||||
if (FragFirst == 0) {
|
if (FragFirst == 0) {
|
||||||
|
@ -424,7 +422,7 @@ VOID ProcessFragment(
|
||||||
/* Copy datagram data into fragment buffer */
|
/* Copy datagram data into fragment buffer */
|
||||||
CopyPacketToBuffer(Fragment->Data,
|
CopyPacketToBuffer(Fragment->Data,
|
||||||
IPPacket->NdisPacket,
|
IPPacket->NdisPacket,
|
||||||
IPPacket->Position,
|
IPPacket->HeaderSize,
|
||||||
Fragment->Size);
|
Fragment->Size);
|
||||||
Fragment->Offset = FragFirst;
|
Fragment->Offset = FragFirst;
|
||||||
|
|
||||||
|
@ -434,7 +432,7 @@ VOID ProcessFragment(
|
||||||
|
|
||||||
/* Put the fragment in the list */
|
/* Put the fragment in the list */
|
||||||
InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry);
|
InsertTailList(&IPDR->FragmentListHead, &Fragment->ListEntry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TI_DbgPrint(DEBUG_IP, ("Done searching for hole descriptor.\n"));
|
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
|
* 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)
|
VOID IPv4Receive(PIP_INTERFACE IF, PIP_PACKET IPPacket)
|
||||||
|
|
Loading…
Reference in a new issue