📄 setup.c
字号:
VirtualAddressEqual(VA->NT.Self->Address, Setup->B)) {
//
// Setup is consistently addressed to us.
//
RtlZeroMemory(&TokB, sizeof(TxToken));
Forwarding = FALSE;
}
else {
//
// Setup has been misrouted.
//
// Optimistic Lightweight Transaction Stage 5.
// ref "message was delivered to the wrong node, teardown path", see below.
//
// "Teardowns are also generated when setup messages are
// delivered to the wrong node..."
//
VrrTrace(VA,1,"SU:SU=FAIL=delivered to the wrong node",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort = TRUE;
InterlockedIncrement((PLONG)&VA->CountMisroutedSetup);
goto ReleaseAndReturn;
}
}
else if (VirtualAddressEqual(Setup->B, VA->Address)) {
//
// Setup has not passed the proxy but we are the final destination
// so we might as well receive the Setup.
//
RtlZeroMemory(&TokB, sizeof(TxToken));
Forwarding = FALSE;
}
else if (GetPhysNeighborTxToken(VA,Setup->Proxy,VRR_IFID_UNSPECIFIED,
VRR_IFID_UNSPECIFIED,&TokB,VRR_NCE_STATE_LINKED)) {
//
// Setup has not passed the proxy and we are not the final destination.
// Whether or not we are the intended proxy the final destination
// is a physical neighbor which we can reach in one hop.
//
// Note: cannot exploit Hops2 because these don't exist for new joiners.
//
RTEFlags FlagsHops1;
VirtualAddress Swap;
LastHop = TRUE;
FlagsHops1.Flags = 0;
FlagsHops1.Hops1 = 1;
//
// Swap (Dest,Proxy) addresses and change proxy flag in message.
//
VrrTrace(VA,2,"SU:SU=perform proxy (Dest,Proxy) swap",Setup->A,Setup->B,Setup->Proxy,NULL,0,NULL,0);
RtlCopyMemory(Swap, Setup->Dest, sizeof(VirtualAddress));
RtlCopyMemory(Setup->Dest, Setup->Proxy, sizeof(VirtualAddress));
RtlCopyMemory(Setup->Proxy, Swap, sizeof(VirtualAddress));
Setup->Flags |= VRR_MSG_FLAG_PASTPROXY;
//
// We are unlocked but assume NCE(dest) remains LINKED.
// Ensure we also have a Hops1 RTE from self to final destination.
// This must be present before we attempt to set up an new
// RTE(A,B) so that FNH can resolve the NextHop(B).
//
KeAcquireSpinLock(&VA->RT.Lock, &OldIrql);
RTE = FindOrCreateRTE(VA,
VA->Address, //const VirtualAddress EndpointA,
TokB.NextVAddress, //const VirtualAddress EndpointB,
VRR_PATHID_UNSPECIFIED, //PathId,
VRR_ADDRESS_UNSPECIFIED, //const VirtualAddress NextA,
VRR_IFID_UNSPECIFIED, //VRRIf LocIFa,
VRR_IFID_UNSPECIFIED, //VRRIf RemIFa,
TokB.NextVAddress, //const VirtualAddress NextB,
TokB.LocIF, //VRRIf LocIFb,
TokB.RemIF, //VRRIf RemIFb,
NullAddress, //NextNextA.
FlagsHops1);
KeReleaseSpinLock(&VA->RT.Lock, OldIrql);
if (NULL == RTE) {
VrrTrace(VA,1,"SU:SU=FAIL: failed to create local RTE for joining node",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort = TRUE;
goto ReleaseAndReturn;
}
}
else if (VirtualAddressEqual(VA->NT.Self->Address, Setup->Dest)) {
//
// Bad news. The Setup is not past its proxy and is meant for us.
// This means we are the proxy, but we did not find the final
// destination in our set of one-hop neighbors (above).
// This can happen if physical neighbor sets change while the
// SetupReq and Setup are in flight.
//
VrrTrace(VA,1,"SU:SU=FAIL: join fail: am proxy with no NCE(LINKED) for dest",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort = TRUE;
goto ReleaseAndReturn;
}
else if ((Result=FindNextHop(VA,
Setup->Dest,
VRR_IFID_UNSPECIFIED,
VRR_IFID_UNSPECIFIED,
&TokB,
NULL,
NULL_SR_FLAGS)) == Error) {
//
// Setup not past proxy and we fail to forward it to proxy.
// Note: dest is typically proxy, rather than EndpointB, on all but last hop.
//
VrrTrace(VA,1,"SU:SU=FAIL: Err==FNH(proxy)",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort = TRUE;
goto ReleaseAndReturn;
}
else if (Result == SuccessRcvNearest) {
//
// Setup not past proxy and we fail to forward it to proxy.
// Optimistic Lightweight Transaction Stage 5.
// ref "message was delivered to the wrong node, teardown path", see below.
//
// "Teardowns are also generated when setup messages are
// delivered to the wrong node..."
//
VrrTrace(VA,1,"SU:SU=FAIL:Setup(A=s,B=d);B!=self;RcvNearest==FNH(B) - send Teardown",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort = TRUE;
goto ReleaseAndReturn;
}
else if (Result == SuccessRcvSelf) {
//
// Setup not past proxy and and decided (above) that we are not the proxy.
// But FNH() thinks we are the proxy.
// Should be unreachable.
//
VrrTrace(VA,1,"SU:SU=FAIL:decided not proxy but FNH() disagrees (Proxy=s,Dest=d)",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
VRRASSERT("FALSE");
TransactionAbort = TRUE;
goto ReleaseAndReturn;
}
//
// At this point we have NextHop info for both A and B.
// Due to changes in pset and latency in signalling
// Hops2 neighbor state to sender it is possible that
// we will receive a Setup from a sender who believes
// we still have a Hops1 route to B but that route has
// gone and our current route state yields FNH(B)=sender.
// Returning a Setup creates a loop: instead we tear it down.
//
if (VirtualAddressEqual(TokA.NextVAddress, TokB.NextVAddress)) {
VrrTrace(VA,1,"SU:SU=FAIL:FNH(A)=FNH(B): avoid fwd setup back to sender(s)",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort = TRUE;
goto ReleaseAndReturn;
}
//
// Add a route for the sender to our Route Table.
//
KeAcquireSpinLock(&VA->RT.Lock, &OldIrql);
RTE = FindOrCreateRTE(VA,
Setup->A, // EndpointA,
Setup->B, // EndpointB,
PathId, // PathId,
TokA.NextVAddress, // NextA,
TokA.LocIF, // LocIFa,
TokA.RemIF, // RemIFa,
TokB.NextVAddress, // NextB,
TokB.LocIF, // LocIFb,
TokB.RemIF, // RemIFb,
Setup->Prev, // NextNextA.
Flags);
if (RTE == NULL) {
VrrTrace(VA,1,"SU:SU=FAIL: failed to create AtoB RTE - abort",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort = TRUE;
}
else if (RTE->B.Next != NULL &&
VirtualAddressEqual(srp->Source,RTE->B.Next->VAddress)) {
//
// Optimistic Lightweight Transaction Stage 3.
// ref "forward setup on"
//
VrrTrace(VA,1,"SU:SU=FAIL: OLT(3)=FAIL: RTE->BNext==Setup->Source",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort=TRUE;
}
KeReleaseSpinLock(&VA->RT.Lock, OldIrql);
if (TransactionAbort)
goto ReleaseAndReturn;
VrrTrace(VA,1,"SU:SU=Exec",Setup->Source,Setup->A,Setup->B,"Pid",PathId,NULL,0);
//
// Create an NTE representing the source of the Setup.
// The source of the message could be a new virtual neighbor.
// Note that this may update our vset.
//
VSetAddNode(VA,Setup->A,CountVSet,MsgVSet);
//
// If the Setup is for and about us, and we are joining, then
// transition self NTE to state INITIALIZED.
//
if (VirtualAddressEqual(VA->Address,Setup->Dest))
if (VirtualAddressEqual(VA->Address,Setup->B)) {
KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
if (IsDriverInitialized(VA) == FALSE) {
SetSelfInitialized(VA);
FindAndDeletePLE(VA, VA->Address);
}
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
}
//
// If we were probing the sender, stop doing so.
// Leave elapsed PLE: PLETimeout will handle it.
//
KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
{
ProbeListEntry *PLE;
if ((PLE=FindPLE(&VA->PL, Setup->A)) != NULL) {
PLE->Timeout = KeQueryInterruptTime() - 1;
PLE->RexmitCount = PLE_MAX_REXMITS + 1;
}
//
// If we were sending directed SR, to AddressDec or
// AddressInc, then the Setup is almost certain to
// originate at an address different to the one in
// the PLE. In such cases the SRTarget field allows
// us to find and remove the appropriate PLE.
//
if ((PLE=FindPLE(&VA->PL, Setup->SRTarget)) != NULL) {
PLE->Timeout = KeQueryInterruptTime() - 1;
PLE->RexmitCount = PLE_MAX_REXMITS + 1;
}
}
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
//
// Receipt of a setup may warrant immediate transition of NT->Self state.
//
NodeTableTimeout(VA, KeQueryInterruptTime());
//
// Process the vset from the Setup message.
//
ReceiveVSet(VA,CountVSet,MsgVSet);
//
// Forward setup if we are not its final destination.
//
if (Forwarding) {
//
// We must take care to forward using the NextB info
// created above in order to ensure that the trail
// of RTEs left by passage of a Setup is unbroken.
//
// Setup->Dest must be (proxy or B) so that Setup is
// routed towards proxy and eventually to Endpoint B.
//
// PO->Dest must be the NextB computed for the new
// RTE=(EndpointA,PathId) created above.
//
InternalOption *NewOpt = NULL;
InternalVrrSetup *SetupNew;
//
// Update the Setup->Prev field with address of node that sent to us.
//
RtlCopyMemory(InternalSetup->Opt.Prev,
InternalSetup->Opt.Source,
sizeof(VirtualAddress));
//
// Make a copy of the Setup message.
//
NewOpt=CopyInternalOption(VA,(InternalOption *)InternalSetup);
if (NewOpt == NULL) {
VrrTrace(VA,1,"SU:SU=FAIL: CopyInternalOption()==NULL",Setup->Source,Setup->A,Setup->B,NULL,0,NULL,0);
TransactionAbort = TRUE;
goto ReleaseAndReturn;
}
//
// Signal LocIF and RemIF in Setup message.
//
SetupNew = (InternalVrrSetup *)NewOpt;
SetupNew->Opt.LocIF = TokB.LocIF;
SetupNew->Opt.RemIF = TokB.RemIF;
//
// Forward the Setup message using reliable transmission.
//
VrrTrace(VA,2,"SU:SU=Fwd_",Setup->A,TokB.NextVAddress,Setup->B,"Pid",PathId,NULL,0);
MsgQueueMessage(VA, TokB.NextVAddress, NewOpt, SetupNew->Opt.LocIF,SetupNew->Opt.RemIF,FWD_DELAY,NULL);
InterlockedIncrement((PLONG)&VA->CountFwdSetup);
}
ReleaseAndReturn:
//
// Issue TearDowns if the Setup failed.
//
if (TransactionAbort) {
VrrTrace(VA,1,"SU,SU=Rjct",Setup->Source,Setup->A,Setup->A,"Pid",PathId,NULL,0);
SetupTransactAbort(VA,Setup->A,PathId,Setup->Source);
}
}
//* CreateSetupOpt
//
// Creates an SRP Opt encoding a Setup.
//
// Caller must not hold the NT->Lock.
//
InternalVrrSetup *
CreateSetupOpt(
MiniportAdapter *VA,
VirtualAddress Dest,
VirtualAddress EndpointA,
VirtualAddress EndpointB,
uint PathId,
VirtualAddress Proxy,
const VirtualAddress Prev,
VirtualAddress SRTarget)
{
uint OptSize;
NodeTableEntry *NTE;
KIRQL OldIrql;
uint NTECount = 0;
uint i;
InternalVrrSetup *VS;
uint FrameSeqNo = 0;
VirtualAddress FlatVSet[VRR_MAX_VSET_SIZE];
InterlockedIncrement((PLONG)&VA->CountSendSetup);
//
// Lock the Node Table during our traversals.
//
KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
//
// Obtain memory for VrrSetup option. Include as many neighbours
// as a single packet can accommodate.
//
NTECount = VSetToFlatBuffer(VA,FlatVSet);
OptSize = sizeof *VS // Internal option linkage.
+ sizeof(VrrSetup) // Preamble.
+ (NTECount * sizeof(VirtualAddress)); // vset.
VS = ExAllocatePool(NonPagedPool, OptSize);
if (VS == NULL) {
goto UnlockReleaseAndReturn;
}
VrrTrace(VA,3,"gregos:CreateSetupOpt (A,B)",EndpointA,EndpointB,NULL,NULL,0,"*ptr=",(uint)VS);
//
// Format the Setup header.
//
RtlZeroMemory(VS, OptSize);
VS->Opt.OptionType = VRR_OPTION_TYPE_SETUP;
VS->Opt.OptDataLen = VRRSETUP_LEN(NTECount);
RtlCopyMemory(VS->Opt.Source, VA->NT.Self->Address, sizeof(VirtualAddress));
RtlCopyMemory(VS->Opt.Dest, Dest, sizeof(VirtualAddress));
RtlCopyMemory(VS->Opt.Proxy, Proxy, sizeof(VirtualAddress));
RtlCopyMemory(VS->Opt.A, EndpointA, sizeof(VirtualAddress));
RtlCopyMemory(VS->Opt.B, EndpointB, sizeof(VirtualAddress));
FrameSeqNo = InterlockedIncrement((unsigned long *)&VrrGlobal.NextFrameSeqNo);
VS->Opt.FrameSeqNo = RtlUlongByteSwap(FrameSeqNo);
VS->Opt.PathId = RtlUlongByteSwap(PathId);
RtlCopyMemory(VS->Opt.Prev, Prev, sizeof(VirtualAddress));
RtlCopyMemory(VS->Opt.SRTarget, SRTarget, sizeof(VirtualAddress));
//
// Append list of VSet addresses.
//
RtlCopyMemory(VS->Opt.vset,FlatVSet,NTECount*sizeof(VirtualAddress));
VrrTrace(VA,3,"SU:SU=New_",EndpointA,Dest,EndpointB,"Pid",PathId,NULL,0);
UnlockReleaseAndReturn:
//
// Finished with Node Table. Release its lock.
//
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
return VS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -