- Changed some behavior from the last neighbor cache rewrite

- NCEs are no longer destroyed when they become stale so the hardware address can be saved for direct communication
 - The route selection code has been changed to choose against stale NCEs if possible

svn path=/trunk/; revision=43077
This commit is contained in:
Cameron Gutman 2009-09-19 01:39:16 +00:00
parent 3db65819eb
commit 9ccce3d818
5 changed files with 20 additions and 26 deletions

View file

@ -41,11 +41,8 @@ typedef struct NEIGHBOR_CACHE_ENTRY {
/* NCE states */ /* NCE states */
#define NUD_INCOMPLETE 0x01 #define NUD_INCOMPLETE 0x01
#define NUD_REACHABLE 0x02 #define NUD_PERMANENT 0x02
#define NUD_PERMANENT 0x04 #define NUD_STALE 0x04
#define NUD_BROADCAST (NUD_PERMANENT | NUD_REACHABLE)
#define NUD_LOCAL (NUD_PERMANENT | NUD_REACHABLE)
/* Number of seconds before the NCE times out */ /* Number of seconds before the NCE times out */
#define ARP_TIMEOUT 30 #define ARP_TIMEOUT 30

View file

@ -215,13 +215,13 @@ VOID ARPReceive(
if (NCE) { if (NCE) {
/* We know the sender. Update the hardware address /* We know the sender. Update the hardware address
and state in our neighbor address cache */ and state in our neighbor address cache */
NBUpdateNeighbor(NCE, SenderHWAddress, NUD_REACHABLE); NBUpdateNeighbor(NCE, SenderHWAddress, 0);
} else { } else {
/* The packet had our protocol address as target. The sender /* The packet had our protocol address as target. The sender
may want to communicate with us soon, so add his address may want to communicate with us soon, so add his address
to our address cache */ to our address cache */
NCE = NBAddNeighbor(Interface, &Address, SenderHWAddress, NCE = NBAddNeighbor(Interface, &Address, SenderHWAddress,
Header->HWAddrLen, NUD_REACHABLE, ARP_TIMEOUT); Header->HWAddrLen, 0, ARP_TIMEOUT);
} }
if (Header->Opcode != ARP_OPCODE_REQUEST) if (Header->Opcode != ARP_OPCODE_REQUEST)

View file

@ -212,7 +212,7 @@ VOID IPAddInterfaceRoute( PIP_INTERFACE IF ) {
/* Add a permanent neighbor for this NTE */ /* Add a permanent neighbor for this NTE */
NCE = NBAddNeighbor(IF, &IF->Unicast, NCE = NBAddNeighbor(IF, &IF->Unicast,
IF->Address, IF->AddressLength, IF->Address, IF->AddressLength,
NUD_LOCAL, 0); NUD_PERMANENT, 0);
if (!NCE) { if (!NCE) {
TI_DbgPrint(MIN_TRACE, ("Could not create NCE.\n")); TI_DbgPrint(MIN_TRACE, ("Could not create NCE.\n"));
return; return;

View file

@ -30,7 +30,7 @@ VOID NBSendPackets( PNEIGHBOR_CACHE_ENTRY NCE ) {
PNEIGHBOR_PACKET Packet; PNEIGHBOR_PACKET Packet;
UINT HashValue; UINT HashValue;
ASSERT(NCE->State & NUD_REACHABLE); ASSERT(!(NCE->State & NUD_INCOMPLETE));
HashValue = *(PULONG)(&NCE->Address.Address); HashValue = *(PULONG)(&NCE->Address.Address);
HashValue ^= HashValue >> 16; HashValue ^= HashValue >> 16;
@ -105,26 +105,22 @@ VOID NBTimeout(VOID)
TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql); TcpipAcquireSpinLock(&NeighborCache[i].Lock, &OldIrql);
for (PrevNCE = &NeighborCache[i].Cache; for (PrevNCE = &NeighborCache[i].Cache;
(NCE = *PrevNCE) != NULL;) { (NCE = *PrevNCE) != NULL;
PrevNCE = &NCE->Next) {
/* Check if event timer is running */ /* Check if event timer is running */
if (NCE->EventTimer > 0) { if (NCE->EventTimer > 0) {
ASSERT(!(NCE->State & NUD_PERMANENT));
NCE->EventCount++; NCE->EventCount++;
if (NCE->EventCount % ARP_RATE == 0) if (NCE->EventCount % ARP_RATE == 0)
NBSendSolicit(NCE); NBSendSolicit(NCE);
if (NCE->EventTimer - NCE->EventCount == 0) { if (NCE->EventTimer - NCE->EventCount == 0) {
ASSERT(!(NCE->State & NUD_PERMANENT)); DbgPrint("Marking NCE stale: %s\n", A2S(&NCE->Address));
/* Flush packet queue */ NCE->State |= NUD_STALE;
NBFlushPacketQueue( NCE, NDIS_STATUS_REQUEST_ABORTED );
*PrevNCE = NCE->Next; NCE->EventCount = 0;
exFreePool(NCE);
continue;
} }
} }
PrevNCE = &NCE->Next;
} }
TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql); TcpipReleaseSpinLock(&NeighborCache[i].Lock, OldIrql);
@ -304,7 +300,7 @@ VOID NBUpdateNeighbor(
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql); TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
if( NCE->State & NUD_REACHABLE ) if( !(NCE->State & NUD_INCOMPLETE) )
NBSendPackets( NCE ); NBSendPackets( NCE );
} }
@ -376,7 +372,7 @@ PNEIGHBOR_CACHE_ENTRY NBFindOrCreateNeighbor(
AddrIsUnspecified(Address) ) { AddrIsUnspecified(Address) ) {
TI_DbgPrint(MID_TRACE,("Packet targeted at broadcast addr\n")); TI_DbgPrint(MID_TRACE,("Packet targeted at broadcast addr\n"));
NCE = NBAddNeighbor(Interface, Address, NULL, NCE = NBAddNeighbor(Interface, Address, NULL,
Interface->AddressLength, NUD_BROADCAST, 0); Interface->AddressLength, NUD_PERMANENT, 0);
} else { } else {
NCE = NBAddNeighbor(Interface, Address, NULL, NCE = NBAddNeighbor(Interface, Address, NULL,
Interface->AddressLength, NUD_INCOMPLETE, ARP_TIMEOUT); Interface->AddressLength, NUD_INCOMPLETE, ARP_TIMEOUT);
@ -430,7 +426,7 @@ BOOLEAN NBQueuePacket(
TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql); TcpipReleaseSpinLock(&NeighborCache[HashValue].Lock, OldIrql);
if( NCE->State & NUD_REACHABLE ) if( !(NCE->State & NUD_INCOMPLETE) )
NBSendPackets( NCE ); NBSendPackets( NCE );
return TRUE; return TRUE;
@ -505,10 +501,10 @@ ULONG NBCopyNeighbors
ArpTable[Size].LogAddr = CurNCE->Address.Address.IPv4Address; ArpTable[Size].LogAddr = CurNCE->Address.Address.IPv4Address;
if( CurNCE->State & NUD_PERMANENT ) if( CurNCE->State & NUD_PERMANENT )
ArpTable[Size].Type = ARP_ENTRY_STATIC; ArpTable[Size].Type = ARP_ENTRY_STATIC;
else if( CurNCE->State & NUD_REACHABLE ) else if( CurNCE->State & NUD_INCOMPLETE )
ArpTable[Size].Type = ARP_ENTRY_DYNAMIC; ArpTable[Size].Type = ARP_ENTRY_INVALID;
else else
ArpTable[Size].Type = ARP_ENTRY_OTHER; ArpTable[Size].Type = ARP_ENTRY_DYNAMIC;
} }
Size++; Size++;
} }

View file

@ -274,7 +274,8 @@ PNEIGHBOR_CACHE_ENTRY RouterGetRoute(PIP_ADDRESS Destination)
TI_DbgPrint(DEBUG_ROUTER,("This-Route: %s (Sharing %d bits)\n", TI_DbgPrint(DEBUG_ROUTER,("This-Route: %s (Sharing %d bits)\n",
A2S(&NCE->Address), Length)); A2S(&NCE->Address), Length));
if(Length >= MaskLength && (Length > BestLength || !BestLength)) { if(Length >= MaskLength && (Length > BestLength || !BestLength) &&
(!(State & NUD_STALE) || !BestState)) {
/* This seems to be a better router */ /* This seems to be a better router */
BestNCE = NCE; BestNCE = NCE;
BestLength = Length; BestLength = Length;