⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setup.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 2 页
字号:
            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 + -