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

📄 teardown.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 2 页
字号:
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
//
// (c) Microsoft Corporation. All rights reserved. 
//
// This file is part of the Microsoft Virtual Ring Routing distribution.
// You should have received a copy of the Microsoft Research Shared Source
// license agreement (MSR-SSLA) for this software; see the file "license.txt".
// If not, please see http://research.microsoft.com/vrr/license.htm,
// or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
//

#include "headers.h"

//* TearDownCacheInit
void
TearDownCacheInit(TearDownCache *TDC)
{
    KeInitializeSpinLock(&TDC->Lock);
    TDC->FirstTDCE = TDC->LastTDCE = SentinelTDCE(TDC);
}

//* RemoveTDCE
void
RemoveTDCE(
    TearDownCache *TDC,
    TearDownCacheEntry *TDCE)
{
    //
    // Sanity checks.
    //
    VRRASSERT(TDCE != (TearDownCacheEntry *)TDC);

    //
    // Adjust pointers and free memory.
    //
    TDCE->Next->Prev = TDCE->Prev;
    TDCE->Prev->Next = TDCE->Next;
    ExFreePool(TDCE);
}

//* InsertTDCE
//
//  Insert TDCE into TearDown cache.
//
//  Caller must hold the TDC->Lock.
//
void
InsertTDCE(
    TearDownCache *TDC,
    TearDownCacheEntry *TDCE)
{
    TearDownCacheEntry *NextTDCE;

    VRRASSERT(TDC != NULL);
    VRRASSERT(TDCE != NULL);

    //
    // Find insertion point for new TDCE in the TearDown cache.
    //
    for (NextTDCE = TDC->FirstTDCE; 
         NextTDCE != SentinelTDCE(TDC);
         NextTDCE = NextTDCE->Next) {
         
        if (VirtualAddressLessThan(TDCE->Address, NextTDCE->Address))
            continue;
            
        if (VirtualAddressLessThan(NextTDCE->Address, TDCE->Address))
            break;
        
        if (TDCE->PathId < NextTDCE->PathId)
            continue;
            
        break;
    }

    //
    // Insert the new TDCE immediately prior to NextTDCE.
    //
    TDCE->Prev = NextTDCE->Prev;
    TDCE->Prev->Next = TDCE;
    TDCE->Next = NextTDCE;
    TDCE->Next->Prev = TDCE;
   
}

//* CreateTDCE
//
//
TearDownCacheEntry *
CreateTDCE(
    VirtualAddress Address,
    uint PathId,    
    VirtualAddress ReportedBy)
{
    TearDownCacheEntry *TDCE;

    TDCE = ExAllocatePool(NonPagedPool, sizeof *TDCE);
    if (TDCE == NULL)
        return NULL;

    //
    // Initialize the TDCE.
    //
    RtlZeroMemory(TDCE, sizeof *TDCE);
    RtlCopyMemory(TDCE->Address,Address,sizeof(VirtualAddress));
    TDCE->PathId = PathId;
    TDCE->Timeout = KeQueryInterruptTime() + TDOWN_CACHE_LIFETIME;
    RtlCopyMemory(TDCE->ReportedBy,ReportedBy,sizeof(VirtualAddress));

    return TDCE;
}


//* FindTDCE
//
//  Returns TDCE iff in Teardown cache, else NULL.
//
//  Caller must hold the TDC->Lock.
//
TearDownCacheEntry *
FindTDCE(
    TearDownCache *TDC,
    VirtualAddress Address,
    uint PathId,
    VirtualAddress ReportedBy)
{
    TearDownCacheEntry *TDCE;

    VRRASSERT(TDC != NULL);

    for (TDCE = TDC->FirstTDCE; 
         TDCE != SentinelTDCE(TDC);
         TDCE = TDCE->Next) {
         
        if (VirtualAddressEqual(TDCE->Address, Address) &&
            TDCE->PathId == PathId) {
            if (IsUnspecified(ReportedBy) ||
                VirtualAddressEqual(TDCE->ReportedBy, ReportedBy))
                return TDCE;
        }
    }

    return NULL;    
}

//* FindOrCreateTDCE
//
//  Returns TDCE if match found in TearDown cache, else
//  tries to create a matching TDCE.
//
//  A return value of NULL means failure.
//
//  Caller must hold the TDC->Lock.
//
TearDownCacheEntry *
FindOrCreateTDCE(
    TearDownCache *TDC,
    VirtualAddress Address,
    uint PathId,
    VirtualAddress ReportedBy)
{
    TearDownCacheEntry *TDCE;
    
    TDCE = FindTDCE(TDC, Address, PathId, ReportedBy);
    
    if (TDCE == NULL)
    if ((TDCE=CreateTDCE(Address, PathId, ReportedBy)) != NULL)
        InsertTDCE(TDC, TDCE);

    return TDCE;
}

//* TearDownCacheCleanup
//
// Flush the TearDown cache.
//
void
TearDownCacheCleanup(
    TearDownCache *TDC)
{
    TearDownCacheEntry *TDCE;
    KIRQL OldIrql;

    KeAcquireSpinLock(&TDC->Lock, &OldIrql);
    while ((TDCE = TDC->FirstTDCE) != SentinelTDCE(TDC))
        RemoveTDCE(TDC, TDCE);
    KeReleaseSpinLock(&TDC->Lock, OldIrql);
}


//* CreateTearDownOpt
//
//  Creates an SRP Opt encoding a TearDown.
//
//  Note that PidBuf and SizeOfPIdBuff args may cover
//  both a list of SizeofPidBuff PathIds *plus* a
//  trailing vset (e.g. in case that caller wants to
//  fwd a copy of someone else's vset rather than
//  include a copy of this node's vset). In such 
//  cases the caller must supply IncludeVSet=FALSE.
//
//  Caller must not hold the NT->Lock.
//
InternalVrrTearDown *
CreateTearDownOpt(
    MiniportAdapter *VA,
    VirtualAddress Dest,
    uint NumPId,
    uint SizeOfPIdBuff,
    VrrGlobalPathId PidBuf[],
    uint IncludeVSet,
    uint Forwarding)
{
    uint OptSize;
    NodeTableEntry *NTE;
    KIRQL OldIrql;
    uint NTECount = 0;
    uint i;
    InternalVrrTearDown *ITD;
    uint FrameSeqNo = 0;
    VirtualAddress FlatVSet[VRR_MAX_VSET_SIZE];
   
    //
    // Maintain counters.
    //
    if (Forwarding)
        InterlockedIncrement((PLONG)&VA->CountFwdTearDown);
    else
        InterlockedIncrement((PLONG)&VA->CountSendTearDown);

    //
    // Lock the Node Table during our traversals.
    //
    KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);

    //
    // Obtain memory for VrrTearDown option.
    //
    if (IncludeVSet)
        NTECount = VSetToFlatBuffer(VA,FlatVSet);

    OptSize = sizeof *ITD                            // Internal option linkage.
              + sizeof(VrrTearDown)                  // Preamble.
              + SizeOfPIdBuff                        // Supplied by caller.
              + (NTECount * sizeof(VirtualAddress)); // vset, iff generating inline.
                   
    if ((ITD=ExAllocatePool(NonPagedPool, OptSize)) == NULL) {
        goto UnlockReleaseAndReturn;
    }
    
    //
    // Format the TearDown header.
    //
    RtlZeroMemory(ITD, OptSize);
    ITD->Opt.OptionType = VRR_OPTION_TYPE_TEARDOWN;
    ITD->Opt.OptDataLen = OptSize - sizeof(*ITD) - sizeof(VRROption);
    RtlCopyMemory(ITD->Opt.Source, VA->NT.Self->Address, sizeof(VirtualAddress));
    RtlCopyMemory(ITD->Opt.Dest, Dest, sizeof(VirtualAddress));
    RtlCopyMemory(ITD->Opt.Proxy, Dest, sizeof(VirtualAddress));
    ITD->Opt.Flags = 0;
    ITD->Opt.NumGlobalPathId = RtlUlongByteSwap(NumPId);
    RtlCopyMemory(ITD->Opt.PId, PidBuf, SizeOfPIdBuff);
    FrameSeqNo = InterlockedIncrement((unsigned long *)&VrrGlobal.NextFrameSeqNo);
    ITD->Opt.FrameSeqNo = RtlUlongByteSwap(FrameSeqNo);
    
    //
    // Append list of VSet addresses.
    //
    if (IncludeVSet)
        RtlCopyMemory(&ITD->Opt.PId[NumPId],FlatVSet,NTECount*sizeof(VirtualAddress));

    for (i = 0; i < NumPId; i++)
        VrrTrace(VA,3,"TD:TD=New_",VA->Address,Dest,PidBuf[i].Address,"Pid",RtlUlongByteSwap(PidBuf[i].PathId),"FrameSeqNo",FrameSeqNo);

UnlockReleaseAndReturn:
    //
    // Finished with Node Table. Release its lock.
    //
    KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
    
    return ITD;

}

//* IsValidTearDownElement
//
//  Helper for ReceiveTearDown.
//  Given element=(EndpointA,PathId) from a TearDown buffer and an RTE
//  returns TRUE if, and only if, the element should be accepted.
//
//  Caller must hold the RT->Lock.
//
uint
IsValidTearDownElement(
    VirtualAddress Sender,
    VrrGlobalPathId *GPId,
    RouteTableEntry *RTE)
{
    //
    // The RTE must be in state Active.
    //
    if (RTE->State != VRR_RTE_STATE_ACTIVE)
        return FALSE;

    //
    // GPId and RTE must match on EndpointA and PathId.
    //
    if (RTE->PathId != RtlUlongByteSwap(GPId->PathId))
        return FALSE;
    if (! VirtualAddressEqual(RTE->A.Address,GPId->Address))
        return FALSE;
                    
    //
    // Ignore TD sent by node other than RTE->NextA or RTE->NextB.
    //
    if (RTE->A.Next != NULL &&
        VirtualAddressEqual(Sender,RTE->A.Next->VAddress))
        return TRUE;
    if (RTE->B.Next != NULL &&
        VirtualAddressEqual(Sender,RTE->B.Next->VAddress))
        return TRUE;
        
    return FALSE;

}

//* ReceiveTearDown

⌨️ 快捷键说明

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