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

📄 hello.c

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