You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1403 lines
29 KiB
1403 lines
29 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
timeouts.c - Timeout handlers.
|
|
|
|
Abstract:
|
|
|
|
All timeout handlers for the ATMARP client.
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----------------------------------------------
|
|
arvindm 08-01-96 Created
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
#include <precomp.h>
|
|
|
|
#define _FILENUMBER 'EMIT'
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpServerConnectTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This timeout indicates that enough time has passed since a previous
|
|
failed attempt at connecting to the ARP server. Try again now.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP interface structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc; // Ref Count
|
|
|
|
pInterface = (PATMARP_INTERFACE)Context;
|
|
AA_STRUCT_ASSERT(pInterface, aai);
|
|
|
|
AA_ACQUIRE_IF_LOCK(pInterface);
|
|
rc = AtmArpDereferenceInterface(pInterface); // Timer ref
|
|
|
|
//
|
|
// Continue only if the Interface is still alive
|
|
//
|
|
if (rc > 0)
|
|
{
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
AADEBUGP(AAD_INFO, ("Server Connect timeout on IF 0x%x\n", pInterface));
|
|
|
|
//
|
|
// Restart registration
|
|
//
|
|
AtmArpStartRegistration(pInterface);
|
|
//
|
|
// IF lock is released by the above routine.
|
|
}
|
|
else
|
|
{
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
}
|
|
}
|
|
// else the Interface is gone!
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpRegistrationTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is called if we timed out waiting for registration to a server
|
|
to complete. If we have retries left for this server, we send another
|
|
ARP Request to register ourselves. Otherwise, we close all VCs to this
|
|
server, move to the next server in the server list, and wait for a while
|
|
before initiating registration to this new server.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP interface structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc; // Ref Count
|
|
|
|
pInterface = (PATMARP_INTERFACE)Context;
|
|
AA_STRUCT_ASSERT(pInterface, aai);
|
|
|
|
AADEBUGP(AAD_INFO, ("Registration timeout: pIf 0x%x, IF Flags 0x%x\n",
|
|
pInterface, pInterface->Flags));
|
|
|
|
AA_ACQUIRE_IF_LOCK(pInterface);
|
|
rc = AtmArpDereferenceInterface(pInterface); // Timer ref
|
|
|
|
//
|
|
// Continue only if the Interface is still alive
|
|
//
|
|
if (rc > 0)
|
|
{
|
|
AtmArpRetryServerRegistration(pInterface);
|
|
//
|
|
// The IF lock is released within the above.
|
|
//
|
|
}
|
|
//
|
|
// else the Interface is gone.
|
|
//
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpServerRefreshTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is periodically invoked so that we can refresh our
|
|
IP address+ATM address info with the ARP server. We do so by registering
|
|
the first of our local IP addresses. We mark all the other IP addresses
|
|
configured on this interface as "not registered", so that, when the first
|
|
one completes, we register all the rest.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP interface structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_INTERFACE pInterface;
|
|
PIP_ADDRESS_ENTRY pIPAddressEntry;
|
|
ULONG rc; // Ref Count
|
|
|
|
pInterface = (PATMARP_INTERFACE)Context;
|
|
AA_STRUCT_ASSERT(pInterface, aai);
|
|
|
|
AADEBUGP(AAD_INFO, ("Server Refresh timeout: IF 0x%x\n", pInterface));
|
|
|
|
//
|
|
// We also use this opportunity to clean out orphan entries in the
|
|
// Arp Table.
|
|
//
|
|
AtmArpCleanupArpTable(pInterface);
|
|
|
|
AA_ACQUIRE_IF_LOCK(pInterface);
|
|
rc = AtmArpDereferenceInterface(pInterface); // Timer ref
|
|
|
|
//
|
|
// Continue only if the Interface is still alive
|
|
//
|
|
if (rc > 0)
|
|
{
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
//
|
|
// Mark all local addresses as not registered.
|
|
//
|
|
pIPAddressEntry = &(pInterface->LocalIPAddress);
|
|
while (pIPAddressEntry != (PIP_ADDRESS_ENTRY)NULL)
|
|
{
|
|
pIPAddressEntry->IsRegistered = FALSE;
|
|
pIPAddressEntry = pIPAddressEntry->pNext;
|
|
}
|
|
|
|
//
|
|
// Start registering the first one.
|
|
//
|
|
pInterface->RetriesLeft = pInterface->MaxRegistrationAttempts - 1;
|
|
|
|
AA_SET_FLAG(
|
|
pInterface->Flags,
|
|
AA_IF_SERVER_STATE_MASK,
|
|
AA_IF_SERVER_NO_CONTACT);
|
|
|
|
AtmArpStartRegistration(pInterface);
|
|
//
|
|
// The IF lock is released in the above routine.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
}
|
|
}
|
|
//
|
|
// else the Interface is gone!
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpAddressResolutionTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is called when we time out waiting for a response to an ARP Request
|
|
we had sent ages ago in order to resolve/refresh an IP entry.
|
|
|
|
First, check if the IP address got resolved anyway (e.g. an InARP Reply
|
|
on a PVC). If so, we don't have to do anything. Otherwise, check if we
|
|
have tried enough times. If we have retries left, send another ARP
|
|
Request.
|
|
|
|
If we have run out of retries, delete the IP entry, and any VCs going to it.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP IP Entry structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_IP_ENTRY pIpEntry; // IP Entry being ARP'ed for.
|
|
ULONG Flags; // On IP Entry
|
|
PATMARP_VC pVc; // VC to this IP destination
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc; // Ref Count on IP Entry
|
|
IP_ADDRESS DstIPAddress; // Address being resolved
|
|
IP_ADDRESS UNALIGNED * pSrcIPAddress; // Our IP address
|
|
#ifdef IPMCAST
|
|
BOOLEAN IsMARSProblem;
|
|
#endif
|
|
|
|
#ifdef IPMCAST
|
|
IsMARSProblem = FALSE;
|
|
#endif
|
|
|
|
pIpEntry = (PATMARP_IP_ENTRY)Context;
|
|
AA_STRUCT_ASSERT(pIpEntry, aip);
|
|
|
|
AA_ACQUIRE_IE_LOCK(pIpEntry);
|
|
AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
|
|
Flags = pIpEntry->Flags;
|
|
|
|
rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer reference
|
|
|
|
//
|
|
// Continue only if the IP Entry still exists
|
|
//
|
|
if (rc > 0)
|
|
{
|
|
AADEBUGP(AAD_INFO,
|
|
("Addr Resolution timeout: pIpEntry 0x%x, Flags 0x%x, IP Addr: %d.%d.%d.%d\n",
|
|
pIpEntry,
|
|
pIpEntry->Flags,
|
|
((PUCHAR)&(pIpEntry->IPAddress))[0],
|
|
((PUCHAR)&(pIpEntry->IPAddress))[1],
|
|
((PUCHAR)&(pIpEntry->IPAddress))[2],
|
|
((PUCHAR)&(pIpEntry->IPAddress))[3]
|
|
));
|
|
|
|
//
|
|
// Check if the entry got resolved somehow.
|
|
//
|
|
if (!AA_IS_FLAG_SET(
|
|
Flags,
|
|
AA_IP_ENTRY_STATE_MASK,
|
|
AA_IP_ENTRY_RESOLVED))
|
|
{
|
|
//
|
|
// We are still trying to resolve this. See if we have
|
|
// retries left.
|
|
//
|
|
pInterface = pIpEntry->pInterface;
|
|
|
|
if (pIpEntry->RetriesLeft != 0)
|
|
{
|
|
pIpEntry->RetriesLeft--;
|
|
|
|
//
|
|
// Try again: start addr resolution timer, send ARP Request.
|
|
//
|
|
pSrcIPAddress = &(pInterface->LocalIPAddress.IPAddress);
|
|
DstIPAddress = pIpEntry->IPAddress;
|
|
|
|
AtmArpStartTimer(
|
|
pInterface,
|
|
&(pIpEntry->Timer),
|
|
AtmArpAddressResolutionTimeout,
|
|
pInterface->AddressResolutionTimeout,
|
|
(PVOID)pIpEntry
|
|
);
|
|
|
|
AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer reference
|
|
|
|
AA_RELEASE_IE_LOCK(pIpEntry);
|
|
|
|
#ifdef IPMCAST
|
|
if (AA_IS_FLAG_SET(Flags,
|
|
AA_IP_ENTRY_ADDR_TYPE_MASK,
|
|
AA_IP_ENTRY_ADDR_TYPE_UCAST))
|
|
{
|
|
AtmArpSendARPRequest(
|
|
pInterface,
|
|
pSrcIPAddress,
|
|
&DstIPAddress
|
|
);
|
|
}
|
|
else
|
|
{
|
|
AtmArpMcSendRequest(
|
|
pInterface,
|
|
&DstIPAddress
|
|
);
|
|
}
|
|
#else
|
|
AtmArpSendARPRequest(
|
|
pInterface,
|
|
pSrcIPAddress,
|
|
&DstIPAddress
|
|
);
|
|
#endif // IPMCAST
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We are out of retries. Check if we were REvalidating
|
|
// an entry that was aged out. If so, try revalidating
|
|
// using InARP on a VC attached to it -- if no such VC
|
|
// exists, delete the IP Entry.
|
|
//
|
|
if ((pIpEntry->pAtmEntry != NULL_PATMARP_ATM_ENTRY) &&
|
|
#ifdef IPMCAST
|
|
(AA_IS_FLAG_SET(Flags,
|
|
AA_IP_ENTRY_ADDR_TYPE_MASK,
|
|
AA_IP_ENTRY_ADDR_TYPE_UCAST)) &&
|
|
#endif // IPMCAST
|
|
(pIpEntry->pAtmEntry->pVcList != NULL_PATMARP_VC))
|
|
{
|
|
pVc = pIpEntry->pAtmEntry->pVcList;
|
|
|
|
//
|
|
// Try revalidating now via InARP.
|
|
//
|
|
AA_SET_FLAG(
|
|
pIpEntry->Flags,
|
|
AA_IP_ENTRY_STATE_MASK,
|
|
AA_IP_ENTRY_INARPING
|
|
);
|
|
|
|
AtmArpStartTimer(
|
|
pInterface,
|
|
&(pIpEntry->Timer),
|
|
AtmArpIPEntryInARPWaitTimeout,
|
|
pInterface->InARPWaitTimeout,
|
|
(PVOID)pIpEntry
|
|
);
|
|
|
|
AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer reference
|
|
|
|
AA_RELEASE_IE_LOCK(pIpEntry);
|
|
#ifdef VC_REFS_ON_SENDS
|
|
AA_ACQUIRE_VC_LOCK(pVc);
|
|
#endif // VC_REFS_ON_SENDS
|
|
AtmArpSendInARPRequest(pVc);
|
|
}
|
|
else
|
|
{
|
|
AtmArpAbortIPEntry(pIpEntry);
|
|
//
|
|
// The IP Entry lock is released in the above routine.
|
|
//
|
|
#ifdef IPMCAST
|
|
IsMARSProblem = AA_IS_FLAG_SET(Flags,
|
|
AA_IP_ENTRY_ADDR_TYPE_MASK,
|
|
AA_IP_ENTRY_ADDR_TYPE_NUCAST);
|
|
#endif // IPMCAST
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The IP Entry must have got resolved.
|
|
// Nothing more to be done.
|
|
//
|
|
AA_RELEASE_IE_LOCK(pIpEntry);
|
|
}
|
|
}
|
|
// else the IP Entry is gone
|
|
|
|
#ifdef IPMCAST
|
|
if (IsMARSProblem)
|
|
{
|
|
AtmArpMcHandleMARSFailure(pInterface, FALSE);
|
|
}
|
|
#endif // IPMCAST
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpIPEntryInARPWaitTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This timeout happens if we don't receive an InARP Reply in response
|
|
to an InARP Request sent in order to revalidate an IP Entry. Delete
|
|
the entry.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP IP Entry structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_IP_ENTRY pIpEntry;
|
|
ULONG rc; // Ref Count on IP Entry
|
|
|
|
pIpEntry = (PATMARP_IP_ENTRY)Context;
|
|
AA_STRUCT_ASSERT(pIpEntry, aip);
|
|
|
|
AA_ACQUIRE_IE_LOCK(pIpEntry);
|
|
AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
|
|
rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER);
|
|
|
|
if (rc > 0)
|
|
{
|
|
AtmArpAbortIPEntry(pIpEntry);
|
|
//
|
|
// The IP Entry lock is released in the above routine.
|
|
//
|
|
}
|
|
//
|
|
// else the entry is gone.
|
|
//
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpPVCInARPWaitTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This timeout happens if we don't receive a reply to an InARP Request
|
|
we had sent in order to resolve a PVC. We send another InARP Request,
|
|
and restart this timer, but to fire after a longer delay.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP VC structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_VC pVc;
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc; // Ref Count on VC
|
|
|
|
pVc = (PATMARP_VC)Context;
|
|
AA_STRUCT_ASSERT(pVc, avc);
|
|
|
|
AA_ACQUIRE_VC_LOCK(pVc);
|
|
rc = AtmArpDereferenceVc(pVc); // Timer ref
|
|
|
|
if (rc > 0)
|
|
{
|
|
AA_ASSERT(AA_IS_FLAG_SET(
|
|
pVc->Flags,
|
|
AA_VC_ARP_STATE_MASK,
|
|
AA_VC_INARP_IN_PROGRESS));
|
|
|
|
pInterface = pVc->pInterface;
|
|
|
|
|
|
AtmArpStartTimer(
|
|
pInterface,
|
|
&(pVc->Timer),
|
|
AtmArpPVCInARPWaitTimeout,
|
|
(2 * pInterface->InARPWaitTimeout),
|
|
(PVOID)pVc
|
|
);
|
|
|
|
|
|
AtmArpReferenceVc(pVc); // Timer ref
|
|
|
|
#ifndef VC_REFS_ON_SENDS
|
|
AA_RELEASE_VC_LOCK(pVc);
|
|
#endif // VC_REFS_ON_SENDS
|
|
|
|
//
|
|
// Send another InARP Request on the PVC
|
|
//
|
|
AtmArpSendInARPRequest(pVc);
|
|
}
|
|
//
|
|
// else the VC is gone
|
|
//
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpIPEntryAgingTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called if some time has passed (~15 minutes) since an
|
|
IP entry was last resolved/refreshed.
|
|
|
|
If there is no VC attached to this IP entry, we delete it. Otherwise,
|
|
revalidate the entry:
|
|
- Mark this entry so that packets are temporarily queued rather
|
|
than sent.
|
|
- If "the VC attached to this entry" is a PVC, send an InARP Request
|
|
to validate the entry, otherwise, send an ARP Request to the server
|
|
to validate.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP IP Entry structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_IP_ENTRY pIpEntry; // IP Entry that has aged out
|
|
ULONG rc; // Ref count on IP Entry
|
|
PATMARP_VC pVc; // VC going to this IP Entry
|
|
ULONG VcFlags; // Flags on above VC
|
|
PATMARP_INTERFACE pInterface;
|
|
IP_ADDRESS DstIPAddress; // IP Address on this Entry
|
|
|
|
|
|
pIpEntry = (PATMARP_IP_ENTRY)Context;
|
|
AA_STRUCT_ASSERT(pIpEntry, aip);
|
|
VcFlags = 0;
|
|
|
|
AA_ACQUIRE_IE_LOCK(pIpEntry);
|
|
AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
|
|
|
|
rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
|
|
|
|
//
|
|
// Continue only if the entry hasn't gone away.
|
|
//
|
|
if (rc != 0)
|
|
{
|
|
//
|
|
// Continue only if the Interface is not going down
|
|
//
|
|
pInterface = pIpEntry->pInterface;
|
|
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
PATMARP_ATM_ENTRY pAtmEntry;
|
|
|
|
pAtmEntry = pIpEntry->pAtmEntry;
|
|
if (pAtmEntry != NULL_PATMARP_ATM_ENTRY)
|
|
{
|
|
AA_ACQUIRE_AE_LOCK_DPC(pAtmEntry);
|
|
pVc = pAtmEntry->pVcList;
|
|
if (pVc != NULL_PATMARP_VC)
|
|
{
|
|
VcFlags = pVc->Flags;
|
|
}
|
|
AA_RELEASE_AE_LOCK_DPC(pAtmEntry);
|
|
}
|
|
else
|
|
{
|
|
pVc = NULL_PATMARP_VC;
|
|
}
|
|
|
|
AADEBUGP(AAD_INFO,
|
|
("Aged out IP Entry 0x%x, Flags 0x%x, IP Addr: %d.%d.%d.%d, VC: 0x%x\n",
|
|
pIpEntry,
|
|
pIpEntry->Flags,
|
|
((PUCHAR)(&(pIpEntry->IPAddress)))[0],
|
|
((PUCHAR)(&(pIpEntry->IPAddress)))[1],
|
|
((PUCHAR)(&(pIpEntry->IPAddress)))[2],
|
|
((PUCHAR)(&(pIpEntry->IPAddress)))[3],
|
|
pVc
|
|
) );
|
|
|
|
#ifdef IPMCAST
|
|
if ((pVc != NULL_PATMARP_VC) &&
|
|
(AA_IS_FLAG_SET(pIpEntry->Flags,
|
|
AA_IP_ENTRY_ADDR_TYPE_MASK,
|
|
AA_IP_ENTRY_ADDR_TYPE_UCAST)))
|
|
#else
|
|
if (pVc != NULL_PATMARP_VC)
|
|
#endif // IPMCAST
|
|
{
|
|
//
|
|
// There is atleast one VC going to this IP Address.
|
|
// So we try to revalidate this IP entry: use InARP
|
|
// if the VC is a PVC, otherwise use ARP.
|
|
//
|
|
|
|
//
|
|
// First mark this entry so that we don't send packets
|
|
// to this destination till it is revalidated.
|
|
//
|
|
pIpEntry->Flags |= AA_IP_ENTRY_AGED_OUT;
|
|
|
|
if (AA_IS_FLAG_SET(VcFlags, AA_VC_TYPE_MASK, AA_VC_TYPE_PVC))
|
|
{
|
|
//
|
|
// PVC; send InARP Request: actually, we fire off a timer
|
|
// at whose expiry we send the InARP Request.
|
|
//
|
|
AtmArpStartTimer(
|
|
pInterface,
|
|
&(pIpEntry->Timer),
|
|
AtmArpIPEntryInARPWaitTimeout,
|
|
pInterface->InARPWaitTimeout,
|
|
(PVOID)pIpEntry
|
|
);
|
|
|
|
AA_SET_FLAG(pIpEntry->Flags, AA_IP_ENTRY_STATE_MASK, AA_IP_ENTRY_INARPING);
|
|
AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
|
|
AA_RELEASE_IE_LOCK(pIpEntry);
|
|
|
|
#ifdef VC_REFS_ON_SENDS
|
|
AA_ACQUIRE_VC_LOCK(pVc);
|
|
#endif // VC_REFS_ON_SENDS
|
|
AtmArpSendInARPRequest(pVc);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// SVC; send ARP Request
|
|
//
|
|
|
|
AtmArpStartTimer(
|
|
pInterface,
|
|
&(pIpEntry->Timer),
|
|
AtmArpAddressResolutionTimeout,
|
|
pInterface->AddressResolutionTimeout,
|
|
(PVOID)pIpEntry
|
|
);
|
|
|
|
pIpEntry->RetriesLeft = 0;
|
|
AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
|
|
AA_SET_FLAG(pIpEntry->Flags, AA_IP_ENTRY_STATE_MASK, AA_IP_ENTRY_ARPING);
|
|
DstIPAddress = pIpEntry->IPAddress;
|
|
|
|
AA_RELEASE_IE_LOCK(pIpEntry);
|
|
|
|
AtmArpSendARPRequest(
|
|
pInterface,
|
|
&(pInterface->LocalIPAddress.IPAddress),
|
|
&DstIPAddress
|
|
);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No VCs attached to this IP Entry; Delete it.
|
|
//
|
|
|
|
AtmArpAbortIPEntry(pIpEntry);
|
|
//
|
|
// The IP Entry lock is released in the above routine.
|
|
//
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The Interface is going down.
|
|
//
|
|
AA_RELEASE_IE_LOCK(pIpEntry);
|
|
}
|
|
}
|
|
//
|
|
// else the IP Entry is gone
|
|
//
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpVcAgingTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called if there hasn't been traffic on a VC for
|
|
some time. We should be running this timer on a VC only if it is
|
|
an SVC.
|
|
|
|
Close the VC.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP VC
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_VC pVc; // VC that has aged out
|
|
ULONG rc; // Ref Count on the VC
|
|
PATMARP_INTERFACE pInterface;
|
|
|
|
|
|
pVc = (PATMARP_VC)Context;
|
|
AA_STRUCT_ASSERT(pVc, avc);
|
|
AA_ASSERT(AA_IS_FLAG_SET(pVc->Flags, AA_VC_TYPE_MASK, AA_VC_TYPE_SVC));
|
|
|
|
AADEBUGP(AAD_INFO, ("Aged out VC %x, Flags %x, ATMEntry %x\n",
|
|
pVc, pVc->Flags, pVc->pAtmEntry));
|
|
#if DBG
|
|
if (pVc->pAtmEntry)
|
|
{
|
|
AADEBUGPATMADDR(AAD_INFO, "To ATM Addr:", &pVc->pAtmEntry->ATMAddress);
|
|
}
|
|
#endif
|
|
|
|
AA_ACQUIRE_VC_LOCK(pVc);
|
|
rc = AtmArpDereferenceVc(pVc); // Timer ref
|
|
|
|
//
|
|
// Continue only if the VC hasn't gone away in the meantime.
|
|
//
|
|
if (rc > 0)
|
|
{
|
|
//
|
|
// Continue only if the Interface isn't going down.
|
|
//
|
|
pInterface = pVc->pInterface;
|
|
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
AADEBUGP(AAD_INFO,
|
|
("Aged out VC 0x%x, RefCount %d, Flags 0x%x, pAtmEntry 0x%x\n",
|
|
pVc, pVc->RefCount, pVc->Flags, pVc->pAtmEntry));
|
|
|
|
AtmArpCloseCall(pVc);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The interface is going down.
|
|
//
|
|
AA_RELEASE_VC_LOCK(pVc);
|
|
}
|
|
}
|
|
//
|
|
// else the VC is gone
|
|
//
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpNakDelayTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called if sufficient time has elapsed since we last
|
|
received a NAK for an IP address. This means that we can try again
|
|
(if necessary) to resolve this IP address.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP IP Entry structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_IP_ENTRY pIpEntry;
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc;
|
|
|
|
pIpEntry = (PATMARP_IP_ENTRY)Context;
|
|
AA_STRUCT_ASSERT(pIpEntry, aip);
|
|
AA_ASSERT(AA_IS_FLAG_SET(pIpEntry->Flags,
|
|
AA_IP_ENTRY_STATE_MASK,
|
|
AA_IP_ENTRY_SEEN_NAK));
|
|
|
|
AADEBUGP(AAD_INFO, ("NakDelay timeout: pIpEntry 0x%x, IP Addr: %d.%d.%d.%d\n",
|
|
pIpEntry,
|
|
((PUCHAR)(&(pIpEntry->IPAddress)))[0],
|
|
((PUCHAR)(&(pIpEntry->IPAddress)))[1],
|
|
((PUCHAR)(&(pIpEntry->IPAddress)))[2],
|
|
((PUCHAR)(&(pIpEntry->IPAddress)))[3]
|
|
));
|
|
|
|
pInterface = pIpEntry->pInterface;
|
|
AA_STRUCT_ASSERT(pInterface, aai);
|
|
|
|
AA_ACQUIRE_IE_LOCK(pIpEntry);
|
|
AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
|
|
|
|
rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER);
|
|
if (rc > 0)
|
|
{
|
|
AA_SET_FLAG(pIpEntry->Flags,
|
|
AA_IP_ENTRY_STATE_MASK,
|
|
AA_IP_ENTRY_IDLE2);
|
|
|
|
AtmArpStartTimer(
|
|
pInterface,
|
|
&(pIpEntry->Timer),
|
|
AtmArpIPEntryAgingTimeout,
|
|
pInterface->ARPEntryAgingTimeout,
|
|
(PVOID)pIpEntry
|
|
);
|
|
|
|
AA_REF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
|
|
AA_RELEASE_IE_LOCK(pIpEntry);
|
|
}
|
|
//
|
|
// else the IP Entry is gone.
|
|
//
|
|
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
#ifdef IPMCAST
|
|
|
|
VOID
|
|
AtmArpMcMARSRegistrationTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We haven't received acknowledgement of registering with the MARS.
|
|
If we have retries left for this, try registering again. Otherwise,
|
|
process this as a MARS failure.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our ATMARP Interface structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc;
|
|
|
|
pInterface = (PATMARP_INTERFACE)Context;
|
|
AA_STRUCT_ASSERT(pInterface, aai);
|
|
|
|
AADEBUGP(AAD_INFO, ("MARS Registration timeout: pIf 0x%x, IF Flags 0x%x\n",
|
|
pInterface, pInterface->Flags));
|
|
|
|
AA_ACQUIRE_IF_LOCK(pInterface);
|
|
rc = AtmArpDereferenceInterface(pInterface); // Timer ref
|
|
|
|
//
|
|
// Continue only if the Interface is still alive
|
|
//
|
|
if (rc != 0)
|
|
{
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
if (pInterface->McRetriesLeft != 0)
|
|
{
|
|
pInterface->McRetriesLeft--;
|
|
|
|
AAMC_SET_IF_STATE(pInterface, AAMC_IF_STATE_NOT_REGISTERED);
|
|
|
|
AtmArpMcStartRegistration(pInterface);
|
|
//
|
|
// IF Lock is released within the above.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Out of retries: problems with this MARS
|
|
//
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
AtmArpMcHandleMARSFailure(pInterface, TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpMcMARSReconnectTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the end of a delay before we retry registering with MARS.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our Interface structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc;
|
|
|
|
pInterface = (PATMARP_INTERFACE)Context;
|
|
AA_STRUCT_ASSERT(pInterface, aai);
|
|
|
|
AA_ACQUIRE_IF_LOCK(pInterface);
|
|
rc = AtmArpDereferenceInterface(pInterface); // MARS Reconnect timer deref
|
|
if (rc != 0)
|
|
{
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
AAMCDEBUGP(AAD_INFO, ("MARS Reconnect timeout: pIf 0x%x, Flags 0x%x\n",
|
|
pInterface, pInterface->Flags));
|
|
|
|
AAMC_SET_IF_STATE(pInterface, AAMC_IF_STATE_NOT_REGISTERED);
|
|
|
|
AA_SET_FLAG(pInterface->Flags,
|
|
AAMC_IF_MARS_FAILURE_MASK,
|
|
AAMC_IF_MARS_FAILURE_NONE);
|
|
|
|
AtmArpMcStartRegistration(pInterface);
|
|
//
|
|
// IF Lock is released within the above.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
}
|
|
}
|
|
//
|
|
// else the IF is gone.
|
|
//
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpMcMARSKeepAliveTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is called if "MARSKeepAliveTimeout" seconds have passed since
|
|
we last received a MARS_REDIRECT message.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our Interface structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc;
|
|
|
|
pInterface = (PATMARP_INTERFACE)Context;
|
|
AA_STRUCT_ASSERT(pInterface, aai);
|
|
|
|
AA_ACQUIRE_IF_LOCK(pInterface);
|
|
rc = AtmArpDereferenceInterface(pInterface); // MARS Keepalive timer deref
|
|
if (rc != 0)
|
|
{
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
AAMCDEBUGP(AAD_INFO, ("MARS Keepalive timeout: pIf 0x%x, Flags 0x%x\n",
|
|
pInterface, pInterface->Flags));
|
|
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
|
|
AtmArpMcHandleMARSFailure(pInterface, FALSE);
|
|
}
|
|
else
|
|
{
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpMcJoinOrLeaveTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
We timed out waiting for an acknowledgement for a MARS_JOIN/MARS_LEAVE.
|
|
|
|
If we have retries left for this JOIN/LEAVE, resend the JOIN. Otherwise,
|
|
declare a MARS failure.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our JOIN Entry structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_IPMC_JOIN_ENTRY pJoinEntry;
|
|
PATMARP_INTERFACE pInterface;
|
|
PIP_ADDRESS pIpAddress;
|
|
IP_MASK IpMask;
|
|
USHORT OpType;
|
|
|
|
pJoinEntry = (PATMARP_IPMC_JOIN_ENTRY)Context;
|
|
AA_STRUCT_ASSERT(pJoinEntry, aamj);
|
|
|
|
pInterface = pJoinEntry->pInterface;
|
|
|
|
AAMCDEBUGP(AAD_VERY_LOUD,
|
|
("McJoinTimeout: pJoinEntry 0x%x, RetriesLeft %d, IP Addr: %d.%d.%d.%d\n",
|
|
pJoinEntry,
|
|
pJoinEntry->RetriesLeft,
|
|
((PUCHAR)&(pJoinEntry->IPAddress))[0],
|
|
((PUCHAR)&(pJoinEntry->IPAddress))[1],
|
|
((PUCHAR)&(pJoinEntry->IPAddress))[2],
|
|
((PUCHAR)&(pJoinEntry->IPAddress))[3]));
|
|
|
|
AA_ACQUIRE_IF_LOCK(pInterface);
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
pJoinEntry->RetriesLeft--;
|
|
if (pJoinEntry->RetriesLeft != 0)
|
|
{
|
|
pIpAddress = &(pJoinEntry->IPAddress);
|
|
IpMask = pJoinEntry->Mask;
|
|
|
|
if (AA_IS_FLAG_SET(pJoinEntry->Flags,
|
|
AA_IPMC_JE_STATE_MASK,
|
|
AA_IPMC_JE_STATE_LEAVING))
|
|
{
|
|
OpType = AA_MARS_OP_TYPE_LEAVE;
|
|
}
|
|
else
|
|
{
|
|
OpType = AA_MARS_OP_TYPE_JOIN;
|
|
|
|
//
|
|
// State could've been "pending"
|
|
//
|
|
AA_SET_FLAG(pJoinEntry->Flags,
|
|
AA_IPMC_JE_STATE_MASK,
|
|
AA_IPMC_JE_STATE_JOINING);
|
|
}
|
|
|
|
//
|
|
// Restart the "Wait For Join completion" timer.
|
|
//
|
|
AtmArpStartTimer(
|
|
pInterface,
|
|
&(pJoinEntry->Timer),
|
|
AtmArpMcJoinOrLeaveTimeout,
|
|
pInterface->JoinTimeout,
|
|
(PVOID)pJoinEntry
|
|
);
|
|
|
|
//
|
|
// Resend the Join or Leave
|
|
//
|
|
AAMCDEBUGP(AAD_INFO,
|
|
("Resending Join/Leave: pIf 0x%x, pJoinEntry 0x%x, Addr: %d.%d.%d.%d\n",
|
|
pInterface,
|
|
pJoinEntry,
|
|
((PUCHAR)pIpAddress)[0],
|
|
((PUCHAR)pIpAddress)[1],
|
|
((PUCHAR)pIpAddress)[2],
|
|
((PUCHAR)pIpAddress)[3]));
|
|
|
|
AtmArpMcSendJoinOrLeave(
|
|
pInterface,
|
|
OpType,
|
|
pIpAddress,
|
|
IpMask
|
|
);
|
|
//
|
|
// IF Lock is released within the above.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Out of retries: problems with this MARS.
|
|
//
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
AtmArpMcHandleMARSFailure(pInterface, FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AA_RELEASE_IF_LOCK(pInterface);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
AtmArpMcRevalidationDelayTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
It's time to mark an IP Entry representing a Multicast group as
|
|
needing revalidation.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our IP Entry structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_IP_ENTRY pIpEntry;
|
|
PATMARP_INTERFACE pInterface;
|
|
ULONG rc;
|
|
PNDIS_PACKET PacketList;
|
|
|
|
pIpEntry = (PATMARP_IP_ENTRY)Context;
|
|
AA_STRUCT_ASSERT(pIpEntry, aip);
|
|
PacketList = NULL;
|
|
|
|
AA_ACQUIRE_IE_LOCK(pIpEntry);
|
|
AA_ASSERT(AA_IE_IS_ALIVE(pIpEntry));
|
|
|
|
rc = AA_DEREF_IE(pIpEntry, IE_REFTYPE_TIMER); // Timer ref
|
|
|
|
//
|
|
// Continue only if the entry hasn't gone away.
|
|
//
|
|
if (rc != 0)
|
|
{
|
|
//
|
|
// Remove any packets queued on this IP Entry.
|
|
//
|
|
PacketList = pIpEntry->PacketList;
|
|
pIpEntry->PacketList = (PNDIS_PACKET)NULL;
|
|
|
|
//
|
|
// Continue only if the state is OK.
|
|
//
|
|
pInterface = pIpEntry->pInterface;
|
|
|
|
if (pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
AAMCDEBUGP(AAD_LOUD,
|
|
("Marking Revalidate: pIpEntry 0x%x/0x%x, pAtmEntry 0x%x, Addr: %d.%d.%d.%d\n",
|
|
pIpEntry,
|
|
pIpEntry->Flags,
|
|
pIpEntry->pAtmEntry,
|
|
((PUCHAR)&(pIpEntry->IPAddress))[0],
|
|
((PUCHAR)&(pIpEntry->IPAddress))[1],
|
|
((PUCHAR)&(pIpEntry->IPAddress))[2],
|
|
((PUCHAR)&(pIpEntry->IPAddress))[3]));
|
|
|
|
AA_SET_FLAG(pIpEntry->Flags,
|
|
AA_IP_ENTRY_MC_VALIDATE_MASK,
|
|
AA_IP_ENTRY_MC_REVALIDATE);
|
|
}
|
|
|
|
AA_RELEASE_IE_LOCK(pIpEntry);
|
|
}
|
|
//
|
|
// else the IP Entry is gone.
|
|
//
|
|
|
|
if (PacketList != NULL)
|
|
{
|
|
//
|
|
// Free all packets that were queued on the IP Entry.
|
|
//
|
|
AtmArpFreeSendPackets(
|
|
pInterface,
|
|
PacketList,
|
|
FALSE // No LLC/SNAP header on these
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
AtmArpMcPartyRetryDelayTimeout(
|
|
IN PATMARP_TIMER pTimer,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
End of a delay after failing to connect or add-party a member of
|
|
a multicast group. Unmark this member, and attempt to add it.
|
|
|
|
Arguments:
|
|
|
|
pTimer - Pointer to timer that went off
|
|
Context - Actually a pointer to our MC ATM Entry structure
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PATMARP_IPMC_ATM_ENTRY pMcAtmEntry;
|
|
PATMARP_IPMC_ATM_ENTRY * ppMcAtmEntry;
|
|
PATMARP_ATM_ENTRY pAtmEntry;
|
|
PATMARP_IP_ENTRY pIpEntry;
|
|
|
|
pMcAtmEntry = (PATMARP_IPMC_ATM_ENTRY)Context;
|
|
AA_STRUCT_ASSERT(pMcAtmEntry, ame);
|
|
|
|
pAtmEntry = pMcAtmEntry->pAtmEntry;
|
|
AA_STRUCT_ASSERT(pAtmEntry, aae);
|
|
|
|
AAMCDEBUGP(AAD_LOUD,
|
|
("PartyRetryDelay timeout: pMcAtmEntry 0x%x, pAtmEntry 0x%x\n",
|
|
pMcAtmEntry, pAtmEntry));
|
|
|
|
AA_ACQUIRE_AE_LOCK(pAtmEntry);
|
|
AA_ASSERT(pAtmEntry->pIpEntryList != NULL_PATMARP_IP_ENTRY);
|
|
|
|
if (pAtmEntry->pInterface->AdminState == IF_STATUS_UP)
|
|
{
|
|
AA_SET_FLAG(pMcAtmEntry->Flags,
|
|
AA_IPMC_AE_CONN_STATE_MASK,
|
|
AA_IPMC_AE_CONN_DISCONNECTED);
|
|
|
|
//
|
|
// Move this MC ATM Entry to the top of the list it belongs to.
|
|
//
|
|
// Find the predecessor for this MC ATM Entry:
|
|
//
|
|
for (ppMcAtmEntry = &(pAtmEntry->pMcAtmInfo->pMcAtmEntryList);
|
|
*ppMcAtmEntry != pMcAtmEntry;
|
|
ppMcAtmEntry = &((*ppMcAtmEntry)->pNextMcAtmEntry))
|
|
{
|
|
AA_ASSERT(*ppMcAtmEntry != NULL_PATMARP_IPMC_ATM_ENTRY);
|
|
}
|
|
|
|
//
|
|
// Unlink the MC ATM Entry from its current position
|
|
//
|
|
*ppMcAtmEntry = pMcAtmEntry->pNextMcAtmEntry;
|
|
|
|
//
|
|
// And insert at the top of the list.
|
|
//
|
|
pMcAtmEntry->pNextMcAtmEntry = pAtmEntry->pMcAtmInfo->pMcAtmEntryList;
|
|
pAtmEntry->pMcAtmInfo->pMcAtmEntryList = pMcAtmEntry;
|
|
|
|
AtmArpMcUpdateConnection(pAtmEntry);
|
|
//
|
|
// AE Lock is released within the above.
|
|
//
|
|
}
|
|
else
|
|
{
|
|
AA_RELEASE_AE_LOCK(pAtmEntry);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
#endif // IPMCAST
|