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

📄 setupreq.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 3 页
字号:
            goto ReleaseAndReturn;
        }
    }
    
    //
    // Optimistic Lightweight Transaction (like) rules ex C# SetupProbeEvent::Deliver
    //    ref "don't know how to route message or message looped; drop it but send an ack"
    //
    RtlZeroMemory(&Token, sizeof(TxToken));
    Result = FindNextHop(VA,
                         SetupReq->Dest,
                         VRR_IFID_UNSPECIFIED,
                         VRR_IFID_UNSPECIFIED,
                         &Token,
                         SRcAntiRoute,
                         SR_DIRECTION_BITS(SetupReq->Type));

    //
    // We are acting as a proxy and are closest(originator).
    // Ref C# "(nextB == node.nodeid && !passedProxy && dest != node.nodeid)"
    //
    if (Result == SuccessRcvSelf)
    if (! (SetupReq->Flags & VRR_MSG_FLAG_PASTPROXY))
    if (!VirtualAddressEqual(SetupReq->Dest,VA->Address)) {
        VrrTrace(VA,2,"SR:SR=Drop(BadFwd1)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
        goto ReleaseAndReturn;
    }

    //
    // Do not fwd SR straight back to the node that created it.
    // Ref C# "sender == nextB // subsumed by next but removes one message"
    //
    if (VirtualAddressEqual(Token.NextVAddress, srp->Source)) {
        VrrTrace(VA,2,"SR:SR=Drop(BadFwd2)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
        goto ReleaseAndReturn;
    }

    //
    // Ref C# "nextB == node.nodeid && !node.Active && dest != node.nodeid"
    // where "!node.Active" is true if left or right wing of vset is empty.
    //
    if (Result == SuccessRcvSelf)
    if (!VirtualAddressEqual(SetupReq->Dest,VA->Address))
    if (InterlockedCompareExchange(&VA->NT.CountLeft,0,0) == 0 ||
        InterlockedCompareExchange(&VA->NT.CountRight,0,0) == 0) {
            VrrTrace(VA,2,"SR:SR=Drop(BadFwd3)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
        goto ReleaseAndReturn;
    }

    //
    // Done with Optimistic Lightweight Transaction (like) rules ex C# SetupProbeEvent::Deliver
    //
    
    //
    // Special case when acting as proxy for a node attempting to join ring.
    // We insist that the joining node be (known to be) LINKED (or ACTIVE).
    //
    if (VirtualAddressEqual(VA->Address, SetupReq->Dest))
    if (SetupReq->Flags & VRR_MSG_FLAG_JOIN_ATTEMPT)
    if (! (SetupReq->Flags & VRR_MSG_FLAG_PASTPROXY)) {
        //
        // We are the proxy in a join attempt.
        // Check the originator's NCE.
        //
        NeighborCacheEntry *NCE;

        KeAcquireSpinLock(&VA->NC.Lock, &OldIrql);
        NCE = FindNCE(&VA->NC,
                      SetupReq->Source,
                      VRR_IFID_UNSPECIFIED,
                      VRR_IFID_UNSPECIFIED,
                      VRR_NCE_STATE_LINKED);
                
        if (NULL == NCE) {
            VrrTrace(VA,2,"SR:SR=Drop(BadProxy)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
            KeReleaseSpinLock(&VA->NC.Lock, OldIrql);
            goto ReleaseAndReturn;
        }
        KeReleaseSpinLock(&VA->NC.Lock, OldIrql);
    }
    
    //
    // Forward the message if we are not the destination node.
    // Actions that we must perform if acting as a proxy are done at this point.
    // This includes swapping (Dest,Proxy) addresses.
    //
    if (ForwardSR(VA, (InternalOption*)InternalSetupReq, SRcAntiRoute)) {
        InterlockedIncrement((PLONG)&VA->CountFwdSetupReq);
        goto ReleaseAndReturn;
    }

    //
    // The message is ours to receive.
    //
    // Deal with SetupReq of type VRR_SR_TYPE_NACK.
    // Basically these indicate that the sender is rejecting
    // a SetupReq of type VRR_SR_TYPE_REQUEST that we
    // sent earlier. We add the sender to the SRcAntiRoute for
    // the address we're probing and receive the sender's
    // vset in case it tells us a closer neighbour.
    //
    if (SetupReq->Type & VRR_SR_TYPE_NACK) {
        ProbeListEntry *PLE;
        uint CountPLESRcAntiRoute;

        KeAcquireSpinLock(&VA->NT.Lock,&OldIrql);
        if ((PLE=FindPLE(&VA->PL,SetupReq->Target)) == NULL) {
            //
            // We have no PLE for target.
            //
            VrrTrace(VA,2,"SR:SR=Drop(NoPLE)",SetupReq->Source,SetupReq->Source,SetupReq->Target,
                   NULL,0,"SeqNo",FrameSeqNo);
        } 
        else if (PLE->FrameSeqNo != FrameSeqNo) {
            VrrTrace(VA,2,"SR:SR=Drop(BadSeqNo)",SetupReq->Source,SetupReq->Source,SetupReq->Target,
                   NULL,0,"SeqNo",FrameSeqNo);
        }
        else if (VirtualAddressEqual(SetupReq->Source,SetupReq->Target)) {
            //
            // If we knew no better and sent to a node that knows we're not in
            // its VSet then it will Nack us, but its VSet will tell us a better
            // destination(s) for later attempts, and restrictions on probe list
            // length will stop us probing that node again.
            //
            // However, during periods of instability, such as initialization, we
            // may get a Nack from a node that has made an incorrect decision
            // about whether we should be admitted to its VSet. This most often
            // happens when we are advertizing a wrapped VSet, and a later retry
            // with an evolved VSet will succeed. Therefore allow retries iff the
            // sender is the target of original SR.
            //
            InterlockedIncrement(&VA->CountSRNackSeqT);
            VrrTrace(VA,2,"SR:SR=noop(Sender=target)",SetupReq->Source,SetupReq->Target,SetupReq->Dest,
                   NULL,0,"SeqNo",FrameSeqNo);

        }
        else if ((CountPLESRcAntiRoute=AddressListCount(PLE->SRcAntiRoute)) <= PLE_MAX_REXMITS) {
            //
            // Our SR was routed along a path leading to a node that has closer
            // nodes than us in its vset. This can happen when routing state and
            // vset membership is inconsistent e.g. during initialization. Add 
            // sender to SRcAntiRoute so that next attempt gets routed elsewhere.
            //
            if (! VirtualAddressEqual(SetupReq->Target, SetupReq->Source))
                PLE->SRcAntiRoute = AddressListAdd(PLE->SRcAntiRoute,SetupReq->Source);
            PLE->SRcAntiRoute = AddressListTrim(PLE->SRcAntiRoute,MAX_SRCANTIROUTE_SIZE);

            if (++CountPLESRcAntiRoute > (uint)InterlockedCompareExchange((PLONG)&VA->MaxPLESRcAntiRoute,0,0))
                VA->MaxPLESRcAntiRoute = CountPLESRcAntiRoute;
            VrrTrace(VA,2,"SR:SR=Rcv_(NackTgt)",SetupReq->Source,SetupReq->Source,SetupReq->Target,
                   "CountPLESRcAntiRoute",CountPLESRcAntiRoute, "SeqNo",FrameSeqNo);
        }
        KeReleaseSpinLock(&VA->NT.Lock,OldIrql);

        ReceiveVSet(VA,CountVSet,MsgVSet);
        goto ReleaseAndReturn;
    }

    //
    // Handle a SetupReq of type VRR_SR_TYPE_REQUEST.
    //
    
    //
    // We are going to reply with Setup(A=self,B,PathId).
    // First we send TearDown for, and remove, any old routes RTE=(A,B,*).
    // Ref C# "// There should be at most one fte except in rare cases"
    //
    while (TRUE) { 
        RouteTableEntry *RTE;
        InternalVrrTearDown *TDO;
        VrrGlobalPathId PId;
        uint PathId = VRR_PATHID_UNSPECIFIED;
        RTEFlags Flags;
            
        Flags.Flags = 0;
        Flags.VSet = 1;

        KeAcquireSpinLock(&VA->RT.Lock, &OldIrql);
        RTE = FindRTE(VA,
                      VA->Address,              //const VirtualAddress EndpointA,
                      SetupReq->Source,         //const VirtualAddress EndpointB,
                      VRR_PATHID_UNSPECIFIED,   //PathId,
                      VRR_ADDRESS_UNSPECIFIED,  //const VirtualAddress NextA,
                      VRR_IFID_UNSPECIFIED,     //VRRIf LocIFa,
                      VRR_IFID_UNSPECIFIED,     //VRRIf RemIFa,
                      VRR_ADDRESS_UNSPECIFIED,  //const VirtualAddress NextB,
                      VRR_IFID_UNSPECIFIED,     //VRRIf LocIFb,
                      VRR_IFID_UNSPECIFIED,     //VRRIf RemIFb,
                      Flags);
        if (RTE != NULL) {
            PId.PathId = RtlUlongByteSwap(RTE->PathId);
            AddRefRTE(RTE);
        }
        KeReleaseSpinLock(&VA->RT.Lock, OldIrql);

        //
        // Finished tearing down old routes?
        //
        if (RTE == NULL)
            break;
        
        //
        // An old RTE for this (A,B) pair exists and must be torn down.
        //
        // Construct and send a TearDown message for the old RTE to the
        // NextHop in direction of endpoint B per the old RTE.
        //
        VRRASSERT(RTE->B.Next != NULL);
        RtlCopyMemory(&PId.Address, VA->Address, sizeof(VirtualAddress));

        TDO=CreateTearDownOpt(VA, RTE->B.Next->VAddress, 1, sizeof(PId), &PId, TRUE, FALSE);
        MsgQueueMessage(VA, RTE->B.Next->VAddress, (InternalOption *) TDO, VRR_IFID_UNSPECIFIED,VRR_IFID_UNSPECIFIED,TDOWN_DELAY,NULL);
        VrrKdPrint("RcvSR: send Teardown old RTE(self,s=B) to d",RTE->B.Address,RTE->B.Next->VAddress);

        //
        // Retire the old RTE.
        //
        KeAcquireSpinLock(&VA->RT.Lock, &OldIrql);
        RTE->State = VRR_RTE_STATE_RETIRED;
        RTE->Timeout = RTERetireTimeout(RTE->Flags);
        VrrKdPrint("RcvSR: retired old RTE(s=A,d=B,*)",VA->Address,SetupReq->Source);
        KeReleaseSpinLock(&VA->RT.Lock, OldIrql);
        ReleaseRTE(RTE);
    }

    //
    // Consider whether sender is a candidate for our virtual neighbor set.
    //
    if (IsCandidateNeighbor(VA,*source,CountVSet,MsgVSet)) {
        //
        // The sender should be admitted to our virtual neighbor set, but
        // not until we have constructed a Setup featuring our vset
        // as it stands prior to admitting the new neighbor.
        //
        RouteTableEntry *RTE;
        uint PathId = 0;
        TxToken Tok;
        RTEFlags Flags;
            
        Flags.Flags = 0;
        Flags.VSet = 1;

        //
        // Create setup message before updating our VSet,
        // obtaining snapshot of current state of VSet.
        //
        Setup = CreateSetupOpt(VA,
                    SetupReq->Proxy,   // Dest.
                    VA->Address,       // Endpoint A.
                    *source,           // Endpoint B.
                    0,                 // PathId: inserted later.
                    *source,           // Proxy.
                    NullAddress,       // Prev wrt NextNextA local path repair. 
                    SetupReq->Target); // Enable RemovePLE() when SR->Target==AddressDec!=A
        if (Setup == NULL) {
            VrrKdPrint("RcvSetup: ERROR! NULL==CreateSetupOpt()",NULL, SetupReq->Proxy);
            goto ReleaseAndReturn;
        }

        //
        // ForwardInternal option has adjusted SR addresses wrt proxy handling.
        //
        // Find the next hop towards the new neighbor. May bypass proxy.
        //
        if (VirtualAddressEqual(VA->NT.Self->Address, SetupReq->Proxy) ||
            GetPhysNeighborTxToken(VA, SetupReq->Source, VRR_IFID_UNSPECIFIED,
                                   VRR_IFID_UNSPECIFIED,&Tok, VRR_NCE_STATE_LINKED)) {
            //
            // We are the proxy, or we can bypass the proxy because joiner is a linked 
            // physical neighbor. Get next hop info from the physical neighbor set.
            //
            if (GetPhysNeighborTxToken(VA,SetupReq->Source,VRR_IFID_UNSPECIFIED,
                                       VRR_IFID_UNSPECIFIED,&Tok,VRR_NCE_STATE_LINKED)==FALSE) {
                VrrTrace(VA,2,"SR:SR=Drop(BadPhysNCE)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
                goto ReleaseAndReturn;
            }
            IsProxy = TRUE;
                
        } 
        else {
            //
            // Use the proxy as the next hop towards the sender. Get next hop info
            // from RT state.
            //
            Result = FindNextHop(VA,
                                 SetupReq->Proxy,
                                 VRR_IFID_UNSPECIFIED,
                                 VRR_IFID_UNSPECIFIED,
                                 &Tok,
                                 NULL,
                                 NULL_SR_FLAGS);
                                 
            if (SuccessFwd != Result) {
                VrrTrace(VA,2,"SR:SR=Drop(BadFNHProxy)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
                goto ReleaseAndReturn;
            }
        }
            
        //
        // Add a route for the sender to our Route Table.
        //
        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,
                  Tok.NextVAddress,         //const VirtualAddress NextB,
                  Tok.LocIF,                //VRRIf LocIFb,
                  Tok.RemIF,                //VRRIf RemIFb,
                  NullAddress,              //NextNextA.
                  Flags);

        if (NULL != RTE)
            PathId = RTE->PathId;

        KeReleaseSpinLock(&VA->RT.Lock, OldIrql);

        //
        // We must have an RTE in order to proceed.
        //
        if (RTE == NULL) {
            VrrKdPrint("RcvSetup: ERROR! cannot send Setup - FindRTE(d)==NULL",NULL, *source);
            goto ReleaseAndReturn;
        }

        //
        // Update PathId in our Setup option.
        //
        Setup->Opt.PathId = RtlUlongByteSwap(PathId);
                                
        //                    

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -