📄 hello.c
字号:
// Store the number of hellos the neighbor received from us during ETX interval.
//
Adj->MetricInfo.Wcett.Etx.FwdDeliv = RtlUshortByteSwap(PHNCE->Rcvd);
break;
}
}
//
// Snapshot QoS data from NCE.
//
Hop1bps = NCE->BitsPerSec;
{
WCETTMetric *wcett = (WCETTMetric *)&NCE->AdjOut.Metric;
Hop1LossProb = wcett->LossProb / 4096;
}
//
// State transitions of our NCE for source of the VrrHello.
// Main case is state of our NCE for the sender of the VrrHello;
// in each branch we consider our own state as shown in the VrrHello.
//
// Some state transitions depend upon QoS thresholds.
//
NCEStateOld = NCE->State;
FSMInput = SelfHNCEState;
QoSInput = QoSToNCEStateTransition(VA,NCE);
switch(NCE->State) {
//
// We have the link (self,sender) in state FAILED.
//
case VRR_NCE_STATE_FAILED:
switch (FSMInput) {
case VRR_NCE_STATE_MISSING:
case VRR_NCE_STATE_FAILED:
case VRR_NCE_STATE_PENDING:
//
// Peer agrees that link has failed. Start recovery.
//
NCE->Timeout = 0;
NCE->State = VRR_NCE_STATE_PENDING;
break;
default:
break; // no change.
}
break;
//
// We have the link (self,sender) in state PENDING.
//
case VRR_NCE_STATE_PENDING:
switch (FSMInput) {
case VRR_NCE_STATE_MISSING:
case VRR_NCE_STATE_FAILED:
break;
case VRR_NCE_STATE_PENDING:
case VRR_NCE_STATE_LINKED:
case VRR_NCE_STATE_ACTIVE:
//
// Both counter-parties are satisfied with link.
//
NCE->State = VRR_NCE_STATE_LINKED;
break;
default:
VrrKdPrint("RcvHello: error - orphan NCE(s)",NCE->VAddress,NULL);
VRRASSERT(FALSE); // Should never get here.
}
break;
//
// We have the link (self,sender) in state LINKED or ACTIVE.
//
case VRR_NCE_STATE_LINKED:
case VRR_NCE_STATE_ACTIVE:
switch (FSMInput) {
case VRR_NCE_STATE_MISSING:
case VRR_NCE_STATE_FAILED:
//
// Neighbor has failed the link. Do likewise.
//
NCE->CountFailHelloFail++;
FailNCE(NCE, Now);
break;
case VRR_NCE_STATE_PENDING:
case VRR_NCE_STATE_LINKED:
case VRR_NCE_STATE_ACTIVE:
//
// Both counter-parties are satisfied with QoS.
//
NCE->State = VRR_NCE_STATE_LINKED;
break;
default:
VrrKdPrint("RcvHello: error - orphan NCE(s)",NCE->VAddress,NULL);
VRRASSERT(FALSE); // Should never get here.
}
break;
//
// Special cases. Should never get here.
//
case VRR_NCE_STATE_ORPHAN:
//
// The NCE is dettached from the Neighbor Cache.
//
VrrKdPrint("RcvHello: error - orphan NCE(s)",NCE->VAddress,NULL);
VRRASSERT(FALSE); // Should never get here.
break;
default:
VrrKdPrint("RcvHello: Invalid state NCE(s)",NCE->VAddress,NULL);
VRRASSERT(FALSE); // Invalid NCE State.
}
SenderIsLinked = (VRR_NCE_STATE_LINKED & NCE->State) ? TRUE : FALSE;
SenderIsActive = SenderIsLinked && (VRR_NTE_STATE_ACTIVE & srp->VrrHello->Opt.State);
if (SenderIsActive)
NCE->State |= VRR_NCE_STATE_ACTIVE;
//
// Fail the link if QoS drops below threshold.
//
if (NCE->State == VRR_NCE_STATE_LINKED ||
NCE->State == VRR_NCE_STATE_ACTIVE)
if (QoSInput == VRR_NCE_INPUT_QoS_EVICT) {
FailNCE(NCE, Now);
NCE->CountFailQoSEvict++;
}
//
// Link may exit FAILED state only if the FAILED timeout
// has expired and QoS is above admission threshold.
//
if (NCEStateOld == VRR_NCE_STATE_FAILED)
if (NCE->State != VRR_NCE_STATE_FAILED)
if (NCE->Timeout != 0)
NCE->State = VRR_NCE_STATE_FAILED;
else if (QoSInput != VRR_NCE_INPUT_QoS_ADMIT)
NCE->State = VRR_NCE_STATE_FAILED;
#if DBG
if (NCEStateOld != NCE->State) {
uchar *s = *source;
uchar *LinkState;
switch(NCE->State) {
case VRR_NCE_STATE_FAILED: LinkState = "LinkFail"; break;
case VRR_NCE_STATE_PENDING: LinkState = "LinkPending"; break;
case VRR_NCE_STATE_LINKED: LinkState = "LinkLinked"; break;
case VRR_NCE_STATE_ACTIVE: LinkState = "LinkActive"; break;
default: LinkState="ShouldNeverGetHere"; break;
}
VrrTrace(VA,4,"HI:HI=Rcv_",*source,*source,NULL,LinkState,NCE->State,NULL,0);
}
#endif
//
// If we just lost our link to the sender, then
// drop routes via that link.
//
if (NCEStateOld & VRR_NCE_STATE_LINKED)
if (!(NCE->State & VRR_NCE_STATE_LINKED))
RouteFailLink(VA,NCE);
//
// Queue a small probe on an 802.11 link that just came up.
//
if (VA->TxDropAllButHello == FALSE)
if ((NCE->State & VRR_NCE_STATE_LINKED) &&
!(NCEStateOld & VRR_NCE_STATE_LINKED))
PktPairCreateProbePacket(VA, &NCE->AdjOut, 0, &Probe,
0, TRUE, METRIC_TYPE_INVALID);
//
// Release locks.
//
NCEStateNew = NCE->State;
NCE = NULL;
KeReleaseSpinLock(&VA->NC.Lock, OldIrql);
//
// Send the small probe, if created one.
//
if (Probe != NULL) {
if (PC(Probe)->PA == NULL)
PktPairSendProbeComplete(VA, Probe, NDIS_STATUS_FAILURE);
else
ProtocolTransmit(PC(Probe)->PA, Probe);
}
//
// If the source of the hello is linked then ensure we have a Hops1 Route
// Table entry for the sender.
//
// Note the supplied (EndpointA, PathId) combo on the FindOrCreateRTE() call
// allows creation of a new PathId.
//
// NCE timeout handles the case where sender ceases to be (linked,active).
//
if (SenderIsLinked) {
RouteTableEntry *RTE;
RTEFlags Flags;
Flags.Flags = 0;
Flags.Hops1 = 1;
KeAcquireSpinLock(&VA->RT.Lock, &OldIrql);
RTE = FindOrCreateRTE(VA,
VA->Address, //const VirtualAddress EndpointA,
*source, //const VirtualAddress EndpointB,
VRR_PATHID_UNSPECIFIED, //PathId,
VRR_ADDRESS_UNSPECIFIED, //const VirtualAddress NextA,
VRR_IFID_UNSPECIFIED, //VRRIf LocIFa,
VRR_IFID_UNSPECIFIED, //VRRIf RemIFa,
*source, //const VirtualAddress NextB,
LocIF, //VRRIf LocIFb,
SentFromIF, //VRRIf RemIFb,
NullAddress, //NextNextA.
Flags);
if (NULL != RTE) {
//
// Maintenance of QoS member in the RTE.
//
VRRASSERT(RTE->Flags.Hops2 != 1);
VRRASSERT(RTE->Flags.VSet != 1);
VRRASSERT(RTE->Flags.Zero != 1);
RTE->ETT = VrrComputeQoS(Hop1bps, Hop1LossProb, 0, 0);
}
KeReleaseSpinLock(&VA->RT.Lock, OldIrql);
}
//
// If we are initializing and just heard from an active neighbor
// then try to join the virtual ring by sending a SetupReq to
// the active neighbor.
//
KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
SelfState = VA->NT.Self->State;
SelfTimeout = VA->NT.Self->Timeout;
if (SenderIsActive &&
NCEStateNew == VRR_NCE_STATE_ACTIVE &&
IsDriverInitialized(VA) == FALSE) {
//
// We must attempt to join the ring.
//
ProbeListEntry *PLE;
if ((PLE=FindPLE(&VA->PL, VA->NT.Self->Address))!=NULL) {
//
// We are already probing in an attempt to join.
//
}
else {
//
// Start probing in an attempt to join.
//
FindOrCreatePLE(VA,VA->NT.Self->Address);
VA->NT.Self->ReconnectAttempts++;
VA->NT.Self->Timeout = Now + MIN_NTE_TIMOUT_INTERVAL;
AttemptJoin = TRUE;
}
}
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
//
// If attempting to join allow proxy to see that we're LINKED
// ahead of receiving our SetupReq.
//
if (AttemptJoin)
SendHellos(VA,Now);
//
// If both sides are active we should have routes for 2-hop neighbors.
//
if (SenderIsActive && IsDriverActive(VA)) {
RouteTableEntry *RTE;
KeAcquireSpinLock(&VA->RT.Lock, &OldIrql);
//
// Install a Hops2 route for each PHNCE.
//
for (i = 0; i < CountHNCE; i++) {
RTEFlags Flags;
Flags.Flags = 0;
Flags.Hops2 = 1;
PHNCE = &FirstHNCE[i];
if (VirtualAddressEqual(VA->Address,PHNCE->addr))
continue;
if (VirtualAddressEqual(*source,PHNCE->addr))
continue;
if (VRR_NCE_STATE_ACTIVE != PHNCE->State)
continue;
RTE = FindOrCreateRTE(VA,
VA->Address, //const VirtualAddress EndpointA,
PHNCE->addr, //const VirtualAddress EndpointB,
VRR_PATHID_UNSPECIFIED, //PathId,
VRR_ADDRESS_UNSPECIFIED, //const VirtualAddress NextA,
VRR_IFID_UNSPECIFIED, //VRRIf LocIFa,
VRR_IFID_UNSPECIFIED, //VRRIf RemIFa,
*source, //const VirtualAddress NextB,
LocIF, //VRRIf LocIFb,
SentFromIF, //VRRIf RemIFb,
NullAddress, //NextNextA.
Flags); //RTEFlags
if (NULL != RTE) {
VRRASSERT(RTE->Flags.Hops1 != 1);
VRRASSERT(RTE->Flags.VSet != 1);
VRRASSERT(RTE->Flags.Zero != 1);
VRRASSERT(RTE->Flags.Hops2 == 1);
//
// Maintain QoS metric on Hops2 routes.
//
RTE->ETT = VrrComputeQoS(Hop1bps,
Hop1LossProb,
MBPS_TO_BPS(PHNCE->Mbps),
PHNCE->LossProb << 4);
//
// RcvHello will explicitly remove old Hops2
// routes once the Hops1 neighbor ceases to
// advertise them. But just in case...
//
RTE->Timeout = Now + HELLO_LIFETIME;
}
}
//
// Done installing Hops2 routes.
// Remove any Hops2 routes no longer being advertised by neighbor.
//
KeAcquireSpinLockAtDpcLevel(&VA->NC.Lock);
for (RTE = VA->RT.FirstRTE; RTE != SentinelRTE(&VA->RT); RTE = RTE->Next) {
if (RTE->State == VRR_RTE_STATE_ACTIVE)
if (RTE->B.Next != NULL)
if (VirtualAddressEqual(RTE->B.Next->VAddress, *source))
if (LocIF == RTE->B.Next->LocIF)
if (SentFromIF == RTE->B.Next->RemIF)
if (RTE->Flags.Hops2 == 1) {
//
// The endpoint must also be ACTIVE in the PHNCE set
// else it has ceased to be a Hops2 neighbor.
//
uint Remove = TRUE;
for (i = 0; i < CountHNCE; i++) {
PHNCE = &FirstHNCE[i];
if (VirtualAddressEqual(PHNCE->addr,RTE->B.Address))
if (VRR_NCE_STATE_ACTIVE == PHNCE->State) {
Remove = FALSE;
break;
}
}
if (Remove == TRUE) {
//
// Retire this RTE.
// We leave the housekeeping for RouteTableTimeout.
//
RTE->State = VRR_RTE_STATE_RETIRED;
RTE->Timeout = RTERetireTimeout(RTE->Flags);
}
}
}
//
// Done removing old Hops2 routes.
//
KeReleaseSpinLockFromDpcLevel(&VA->NC.Lock);
KeReleaseSpinLock(&VA->RT.Lock, OldIrql);
}
//
// Update our Zero List from this Hello message.
//
ReceiveHelloZeroList(VA,
(VrrHello *)&srp->VrrHello->Opt,
srp->VrrHello->Opt.source,
LocIF,
Now);
//VrrKdPrint("RcvHello exit",*source,NULL);
return;
UnlockNCEAndReturn:
KeReleaseSpinLock(&VA->NC.Lock, OldIrql);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -