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

📄 partition.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 2 页
字号:
    KeReleaseSpinLock(&VA->ZL.Lock, OldIrql);

    return NextTimeout;
}

//* UpdateLocalZeroListEntry
//
//  Refresh ZLE representing self.
//
void
UpdateLocalZeroListEntry(
    MiniportAdapter *VA)
{
    KIRQL OldIrql;

    KeAcquireSpinLock(&VA->ZL.Lock, &OldIrql);

    UpdateZLE(VA,VA->Address,GetZeroSeqNo());

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

//* EmitHelloZeroList
//
//  Emit list of partition representatives (Zero List) in
//  format expected by Hello message.
//
void
EmitHelloZeroList(
    MiniportAdapter *VA,
    VrrHello *Hello)
{
    KIRQL OldIrql;
    NodeTable *NT = &VA->NT;
    ZeroList *ZL = &VA->ZL;
    NodeTableEntry *NTE;
    ZeroListEntry *ZLE;
    uint AmActive = FALSE;
    uint AmClosestZero = TRUE;

    //
    // Decide if we're the representative node for this partition.
    //
    KeAcquireSpinLock(&NT->Lock, &OldIrql);
    AmActive = IsDriverActive(VA);

    for (NTE = NT->FirstNTE; NTE != SentinelNTE(NT); NTE = NTE->Next) {
        if (VirtualAddressIsCloser(NTE->Address, VA->Address, NullAddress)) {
            AmClosestZero = FALSE;
            break;
        }
    }
    KeReleaseSpinLock(&NT->Lock, OldIrql);

    //
    // If we are representative, refresh our Zero List entry.
    //
    if (AmActive && AmClosestZero)
        UpdateLocalZeroListEntry(VA);

    //
    // Dump first two ACTIVE entries from Zero List to caller's
    // buffer.
    //
    KeAcquireSpinLock(&ZL->Lock, &OldIrql);
    ZLE = ZL->FirstZLE;
    if (ZLE != SentinelZLE(ZL) && ZLE->State == ZLE_STATE_ACTIVE) {
        Hello->ZeroCount++;
        RtlCopyMemory(Hello->Zero1Addr,ZLE->Address,sizeof(VirtualAddress));
        Hello->Zero1SeqNo = RtlUlongByteSwap(ZLE->SeqNo);
        if ((ZLE=ZLE->Next) != SentinelZLE(ZL) && ZLE->State == ZLE_STATE_ACTIVE) {
            Hello->ZeroCount++;
            RtlCopyMemory(Hello->Zero2Addr,ZLE->Address,sizeof(VirtualAddress));
            Hello->Zero2SeqNo = RtlUlongByteSwap(ZLE->SeqNo);
        }
    }
    KeReleaseSpinLock(&ZL->Lock, OldIrql);
}

//* ReceiveHelloZeroList
//
//  Receive the Zero List from an incoming Hello message.
//
//  Caller must not hold ZL->Lock;
//  Caller must not hold NC->Lock;
//  Caller must not hold RT->Lock;
//  Caller must not hold NT->Lock;
//  Caller must not hold PCache->Lock;
//
void
ReceiveHelloZeroList(
    MiniportAdapter *VA,
    VrrHello *Hello,
    VirtualAddress NextHop,
    VRRIf LocIF,
    Time Now)
{
    KIRQL OldIrql;
    ZeroList *ZL = &VA->ZL;
    ZeroListEntry *ZLE;
    NeighborCacheEntry *NCE;
    VRRIf RemIF = Hello->SentFromIF;
    RouteTableEntry *RTE1;
    RTEFlags Flags1;
    Time RTETimeout = Now + HelloLifetime;
    VirtualAddress *ZeroAddress;
    uint Zero2PathId = 0;
    uint i;

    //
    // Sanity test on ZeroCount.
    //
    if (Hello->ZeroCount == 0)
        return;

    if (Hello->ZeroCount > VRRHELLO_MAX_ZERO_LIST_ENTRIES) {
        VrrKdPrint("RcvZList: drop hello from s, ZeroCount too large",
                 Hello->source, NULL);
        return;
    }

    //
    // Update our Zero List with max two hosts per Hello message.
    //
    KeAcquireSpinLock(&ZL->Lock, &OldIrql);
    UpdateZLE(VA,Hello->Zero1Addr,RtlUlongByteSwap(Hello->Zero1SeqNo));
    if (Hello->ZeroCount == VRRHELLO_MAX_ZERO_LIST_ENTRIES)
        UpdateZLE(VA,Hello->Zero2Addr,RtlUlongByteSwap(Hello->Zero2SeqNo));
    KeReleaseSpinLock(&ZL->Lock, OldIrql);

    //
    // Partition repair may be disabled.
    //
    if (IsPartitionRepairEnabled(VA) == FALSE)
        return;

    //
    // There may be some delay before a new NCE becomes LINKED.
    //
    KeAcquireSpinLock(&VA->NC.Lock, &OldIrql);
    NCE = FindNCE(&VA->NC,NextHop,LocIF, RemIF, VRR_NCE_STATE_LINKED);
    KeReleaseSpinLock(&VA->NC.Lock, OldIrql);
    if (NCE == NULL)
        return;

    //
    // Ensure we have routes of type zero for each partition
    // representative via the node that sent us this hello,
    // taking ETT from the corresponding Hops1 route.
    //
    // The Z routes have short lifetimes and are soon garbage 
    // collected by the route module unless frequently renewed.
    //
    Flags1.Flags = 0;
    Flags1.Hops1 = 1;

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

    RTE1 = FindRTE(VA, VA->Address, Hello->source, VRR_PATHID_UNSPECIFIED,
               VRR_ADDRESS_UNSPECIFIED, VRR_IFID_UNSPECIFIED, VRR_IFID_UNSPECIFIED,
               NextHop, LocIF, Hello->SentFromIF, Flags1);

    ZeroAddress = &Hello->Zero1Addr;
    for (i=0; i<Hello->ZeroCount; i++) {
        if (! VirtualAddressEqual(*ZeroAddress, VA->Address)) {
            //
            // Removing old route for ZeroAddress is easier than updating it,
            // as it saves messing with NCE ref counts etc.
            //
            RouteTableEntry *RTE;
            RTEFlags FlagsZ;

            FlagsZ.Flags = 0;
            FlagsZ.Zero = 1;

            RTE = FindRTE(VA, VA->Address, *ZeroAddress, VRR_PATHID_UNSPECIFIED,
                       VRR_ADDRESS_UNSPECIFIED, VRR_IFID_UNSPECIFIED, VRR_IFID_UNSPECIFIED,
                       VRR_ADDRESS_UNSPECIFIED, VRR_IFID_UNSPECIFIED, VRR_IFID_UNSPECIFIED,
                       FlagsZ);

            if (RTE != NULL) {
                RTE->State = VRR_RTE_STATE_RETIRED;
                RTE->Timeout = Now + RTE_RETIRE_IMMEDIATE;
            }

            //
            // Update existing, or create new, route for the zero address.
            //
            RTE = FindOrCreateRTE(VA, VA->Address, *ZeroAddress, VRR_PATHID_UNSPECIFIED,
                       VRR_ADDRESS_UNSPECIFIED, VRR_IFID_UNSPECIFIED, VRR_IFID_UNSPECIFIED,
                       NextHop, LocIF, RemIF, NullAddress, FlagsZ);

            if (RTE != NULL) {
                RTE->Timeout = RTETimeout;
                if (RTE1 != NULL)
                    RTE->ETT = RTE1->ETT;
                if (i != 0)
                    Zero2PathId = RTE->PathId;
            }
        }
        ZeroAddress++;
    }
    KeReleaseSpinLock(&VA->RT.Lock, OldIrql);

    //
    // Assume that the ring breaks into partions A and B,
    // and that we are in A. If A and B meet again then
    // all it takes is one vset message between A and B
    // for vset repair to start, and once started it will
    // ripple throughout both partitions.
    //
    // Assume that A is much larger than B, hence it is
    // likely that closest(zero,A) is closer to zero than
    // closest(zero,B), hence any hello featuring both
    // will have Zero2Addr=closest(zero,B).
    //
    // Assume we are in A, that fresh information about
    // closest(zero,B) reaches us. If closest(zero,B) belongs
    // in our vset then we are the node that will start the
    // process by sending a Setup to closest(zero,B).
    //
    if (Hello->ZeroCount > 1 &&
        IsDriverActive(VA) &&
        IsCandidateNeighbor(VA,Hello->Zero2Addr,1,&Hello->Zero2Addr) &&
        FindVSetRoute(VA, VA->Address, Hello->Zero2Addr) == NULL) {

        NodeTableEntry *NTE = NULL;
        InternalVrrSetup *Setup = NULL;
        RouteTableEntry *RTE = NULL;
        uint PathId;

        KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
        NTE = FindNTE(&VA->NT,Hello->Zero2Addr);
        KeReleaseSpinLock(&VA->NT.Lock, OldIrql);

        //
        // Create setup message before updating our VSet,
        // obtaining snapshot of current state of VSet.
        //
        if (NTE == NULL) {
            Setup = CreateSetupOpt(VA,
                                   Hello->Zero2Addr,   // Dest.
                                   VA->Address,        // Endpoint A.
                                   Hello->Zero2Addr,   // Endpoint B.
                                   0,                  // PathId - inserted later.
                                   Hello->Zero2Addr,   // Proxy.
                                   NullAddress,        // Prev wrt NextNextA local path repair. 
                                   VA->Address);
        }

        //
        // Create an RTE type V for Zero2Addr.
        //
        if (Setup != NULL) {
            RTEFlags FlagsV;
            FlagsV.Flags = 0;
            FlagsV.VSet = 1;

            KeAcquireSpinLock(&VA->RT.Lock, &OldIrql);
            VrrKdPrint("RcvZList: send setup(d)",NULL,Hello->Zero2Addr);
            RTE = FindOrCreateRTE(VA,
                      VA->Address,              // VirtualAddress EndpointA,
                      Hello->Zero2Addr,         // VirtualAddress EndpointB,
                      VRR_PATHID_UNSPECIFIED,   // PathId,
                      VRR_ADDRESS_UNSPECIFIED,  // VirtualAddress NextA,
                      VRR_IFID_UNSPECIFIED,     // LocIFa,
                      VRR_IFID_UNSPECIFIED,     // RemIFa,
                      NextHop,                  // VirtualAddress NextB,
                      LocIF,                    // LocIFb,
                      RemIF,                    // RemIFb,
                      NullAddress,              // NextNextA.
                      FlagsV);

            if (RTE != NULL)
                PathId = RTE->PathId;
            KeReleaseSpinLock(&VA->RT.Lock, OldIrql);
        }

        //
        // Add Zero2Addr to local VSet and send Setup.
        //
        if (RTE != NULL) {
            VirtualAddress *ZeroVSet = &Hello->Zero2Addr;

            VrrKdPrint("RcvZList: VSetAdd(d) & SendSetup(d)",NULL,Hello->Zero2Addr);

            VSetAddNode(VA,Hello->Zero2Addr,1,ZeroVSet);
            Setup->Opt.PathId = RtlUlongByteSwap(PathId);
            Setup->Opt.LocIF = LocIF;
            Setup->Opt.RemIF = RemIF;
            InterlockedIncrement((PLONG)&VA->CountPnRepairSendSetup);
            MsgQueueMessage(VA, NextHop, (InternalOption *) Setup, LocIF, RemIF, SETUP_DELAY, NULL);
            Setup = NULL;
        }

        if (Setup != NULL) {
            //
            // Allocated but never sent message.
            //
            ExFreePool(Setup);
        }
    }
}

⌨️ 快捷键说明

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