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

📄 setupreq.c

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

//* ForwardSR
//
//  Check if a SetupReq is for us. If not, try to
//  copy and forward it.
//
//  Originally a generic routine but in practice was
//  only used on the SR forwarding path.
//
//  Returns TRUE iff the option was forwarded.
//
boolint
ForwardSR(
    MiniportAdapter *VA,
    InternalOption *InternalOpt,
    AddressList *SRcAntiRoute)
{
    uint Forwarded = FALSE;
    VrrMsgPrefix *MsgOld = (VrrMsgPrefix *)&InternalOpt->Opt;
    FindNextHopResult Result;
    VrrSetupReq *SROld = (VrrSetupReq *)&InternalOpt->Opt;
    TxToken Token;
    uint AmProxy = FALSE;
    uint FrameSeqNo = RtlUlongByteSwap(SROld->FrameSeqNo);
    
    VRRASSERT(VRR_OPTION_TYPE_SETUPREQ == InternalOpt->Opt.optionType);
    VRRASSERT((SROld->Type & VRR_SR_TYPE_NACK) || AddressListCount(SRcAntiRoute) != 0);
    VRRASSERT((SROld->Type & VRR_SR_TYPE_NACK) || AddressListContains(SRcAntiRoute,SROld->Source));

    //
    // Ensure that forwarding will not exceed max hop count on this message.
    //
    if (MsgOld->HopCount >= VRR_MAX_HOPCOUNT) {
        VrrTrace(VA,2,"SR:SR=Drop(HopsXs)",SROld->Source,SROld->Source,SROld->Dest,NULL,0,"SeqNo",FrameSeqNo);
        InterlockedIncrement((PLONG)&VA->CountSRDropHopCount);
        return TRUE;
    }

    //
    // Check if we should perform proxy functions.
    //
    if (! (SROld->Flags & VRR_MSG_FLAG_PASTPROXY))
    if (VirtualAddressEqual(SROld->Dest,VA->Address)) {
        //
        // We are the proxy: swap the Dest and Proxy addresses.
        //
        VirtualAddress Swap;
        
        //
        // Adjust the message as though routed beyond proxy.
        //
        RtlCopyMemory(Swap, SROld->Dest, sizeof(VirtualAddress));
        RtlCopyMemory(SROld->Dest, SROld->Proxy, sizeof(VirtualAddress));
        RtlCopyMemory(SROld->Proxy, Swap, sizeof(VirtualAddress));
        SROld->Flags |= VRR_MSG_FLAG_PASTPROXY;
        AmProxy = TRUE;
    }

    //
    // Deal with the case of the last hop of an SR(NACK) to a node joining the ring.
    // The SR(NACK) is trying to reach the joiner's proxy, and the final hop uses
    // physical neighbour state because the mainline forwarding state may be incomplete.
    //
    if (AmProxy && (SROld->Type & VRR_SR_TYPE_NACK)) {
        InternalOption *NewOpt;
        VrrSetupReq *SRNew;

        //
        // Bail if the originator is no longer a linked neighbour of ours.
        //
        if (! GetPhysNeighborTxToken(VA,SROld->Dest,VRR_IFID_UNSPECIFIED,
                                     VRR_IFID_UNSPECIFIED,&Token,VRR_NCE_STATE_LINKED)) {
            VrrTrace(VA,2,"SR:SR=Drop(ProxyNoNCE)",VA->Address,NULL,SROld->Dest,NULL,0,"FrameSeqNo",FrameSeqNo);
            return TRUE;
        }

        if ((NewOpt=CopyInternalOption(VA,InternalOpt)) == NULL) {
            VrrKdPrint("FwdSR: error, NULL==CopyInternalOption()",NULL,NULL);
            return TRUE;        
        }
        SRNew = (VrrSetupReq *)&NewOpt->Opt;
        VrrTrace(VA, 2,"SR:SR=Fwd_(NACKJoinProxy)",SRNew->Source,Token.NextVAddress,SRNew->Dest,NULL,0,"FrameSeqNo",FrameSeqNo);
        MsgQueueMessage(VA, SRNew->Dest, NewOpt, VRR_IFID_UNSPECIFIED,VRR_IFID_UNSPECIFIED,FWD_DELAY,&Token);
        return TRUE;
    }

    //
    // Current routing state dictates how to handle the message. 
    //
    Result = FindNextHop(VA,
                         SROld->Dest,
                         VRR_IFID_UNSPECIFIED,
                         VRR_IFID_UNSPECIFIED,
                         &Token,
                         SRcAntiRoute,
                         SR_DIRECTION_BITS(SROld->Type));

    if (Result == Error) {
        VrrTrace(VA,2,"SR:SR=Drop(ErrFNH)",SROld->Source,NULL,SROld->Dest,NULL,0,"FrameSeqNo",FrameSeqNo);
        return TRUE;
    }

    if (Result == SuccessFwd) {
        //
        // We are not the destination or the closest node to it.
        // Copy and forward the message.
        //
        InternalOption *NewOpt = NULL;
        VrrSetupReq *SRNew;

        if ((NewOpt=CopyInternalOption(VA,InternalOpt)) == NULL) {
            VrrKdPrint("FwdSR: error, NULL==CopyInternalOption()",NULL,NULL);
            return TRUE;        
        }

        SRNew = (VrrSetupReq *)&NewOpt->Opt;
        if (SRNew->Flags & VRR_MSG_FLAG_JOIN_ATTEMPT)
            SRNew->Flags |= VRR_MSG_FLAG_JOIN_ATTEMPT;
        MsgQueueMessage(VA, SRNew->Dest, NewOpt, VRR_IFID_UNSPECIFIED,VRR_IFID_UNSPECIFIED,FWD_DELAY,&Token);
        return TRUE;
    }

    //
    // We are expected to receive this message.
    //
    return FALSE;

}

//* SendSRNack
//
// Reject the sender as a neighbor. Send msg SetupReq(NACK).
// Use the sender's FrameSeqNo to match original SR->FrameSeqNo.
//
void
SendSRNack(
    MiniportAdapter *VA,
    VirtualAddress SRSource,
    VirtualAddress SRProxy,
    uint FrameSeqNo,
    VirtualAddress SRTarget,
    uchar SRFlags)
{
    InternalVrrSetupReq *SRNack;

    SRNack = CreateSetupReqOpt(VA, 
                               SRSource,
                               VRR_SR_TYPE_NACK, 
                               SRProxy,
                               FrameSeqNo,
                               SRTarget,
                               NULL);
    
    if (SRNack == NULL)
        return;

    if (SRFlags & VRR_MSG_FLAG_JOIN_ATTEMPT)
        SRNack->Opt.Flags |= VRR_MSG_FLAG_JOIN_ATTEMPT;

    if (ForwardSR(VA,(InternalOption *)SRNack,NULL) != TRUE) {
        //
        // Failed to forward the Nack: drop it and protest.
        //
        VrrTrace(VA,2,"SR:SR=Drop(Fwd(SendNack)==F)",SRTarget,SRProxy,SRSource,NULL,0,"FrameSeqNo",FrameSeqNo);
    }

    VrrTrace(VA,3,"SR:SR=Rcv_(SendNack)",SRTarget,SRProxy,SRSource,NULL,0,"FrameSeqNo",FrameSeqNo);

    //
    // ForwardSR will have clone the SRNack iff put to MsgQ.
    //
    ExFreePool(SRNack);

}

//* ReceiveSetupReq
//
//  Receive a VRR SetupReq message. Called from ReceiveSRPacket.
//
//  Note: basic packet parsing performed in ReceiveSRPacket, which
//  provides us the VrrSetupReq structure in an SRPacket option.
//
void
ReceiveSetupReq(
    MiniportAdapter *VA,
    ProtocolAdapter *PA,
    InternalVrrSetupReq *InternalSetupReq,
    SRPacket *srp)
{
    KIRQL OldIrql;
    VirtualAddress *source;
    VirtualAddress *PVSET = NULL;
    VirtualAddress *MsgVSet = NULL;
    uint i;
    uint VSetLen;
    uint CountVSet;
    uint IsProxy = FALSE;
    VrrSetupReq *SetupReq;
    TxToken Token;
    FindNextHopResult Result;
    uint NewPXE;
    uint CountSRcAntiRoute;
    uint FrameSeqNo;
    AddressList *SRcAntiRoute = NULL;
    Time Now = KeQueryInterruptTime();
    InternalVrrSetup *Setup = NULL;
    uint SentSetup = FALSE;

    //
    // Find start of vset in VrrSetupReq message, and cardinality of vset.
    //
    VRRASSERT(InternalSetupReq != NULL);
    source = &InternalSetupReq->Opt.Source;
    SetupReq = &InternalSetupReq->Opt;
    FrameSeqNo = RtlUlongByteSwap(SetupReq->FrameSeqNo);
    CountSRcAntiRoute = SetupReq->CountSRcAntiRoute;
    MsgVSet = &SetupReq->addr[CountSRcAntiRoute];
    VSetLen = (uint)SetupReq->OptDataLen
             - sizeof(SetupReq->Type)
             - sizeof(SetupReq->Source)
             - sizeof(SetupReq->Dest)
             - sizeof(SetupReq->Proxy)
             - sizeof(SetupReq->Flags)
             - sizeof(SetupReq->FrameSeqNo)
             - sizeof(SetupReq->HopCount)
             - sizeof(SetupReq->Target)
             - sizeof(SetupReq->CountSRcAntiRoute)
             - (CountSRcAntiRoute * sizeof(VirtualAddress));
    CountVSet = VSetLen / sizeof(VirtualAddress);
    
    //
    // Validate the VrrSetupReq message.
    //
    VrrTrace(VA, 3, (SetupReq->Type & VRR_SR_TYPE_REQUEST) ? "SR:SR=Rcv_(Req)" : "SR:SR=Rcv_(Nack)",
        SetupReq->Source, SetupReq->Source, SetupReq->Dest, "CountSRcAntiRoute", CountSRcAntiRoute, "FrameSeqNo" , FrameSeqNo);
    if (CountSRcAntiRoute != 0) {
        VrrTrace(VA,3,"SR:SR=Rcv_(NonZBL)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,
               "CountSRcAntiRoute", CountSRcAntiRoute,"FrameSeqNo" , FrameSeqNo);
    }
    if (CountSRcAntiRoute > (uint)InterlockedCompareExchange((PLONG)&VA->MaxPLESRcAntiRouteRcv,0,0))
        VA->MaxPLESRcAntiRouteRcv = CountSRcAntiRoute;

    if (VSetLen != CountVSet * sizeof(VirtualAddress)) {
        VrrTrace(VA,2,"SR:SR=Drop(BadVsetLen)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,
                   "CountSRcAntiRoute",CountSRcAntiRoute, "SeqNo",FrameSeqNo);
        return;
    }

    if (CountVSet == 0) {
        VrrTrace(VA,2,"SR:SR=Drop(CountVSet==0)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,
                   "CountSRcAntiRoute",CountSRcAntiRoute, "SeqNo",FrameSeqNo);
        return;
    }
    
    if ((SetupReq->Type & VRR_SR_TYPE_NACK)==0 &&
        (SetupReq->Type & VRR_SR_TYPE_REQUEST)==0 ) {
            VrrTrace(VA,2,"SR:SR=Drop(BadType)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,
                   "Type",SetupReq->Type, "SeqNo",FrameSeqNo);
        return;
    }
    
    //
    // Add to packet index and check for looping messages.
    // The only time we should see a dup (FrameSeqNo,Type) is on SR(NACK).
    //
    NewPXE = UpdatePacketIndex(VA, SetupReq->Source, FrameSeqNo, SetupReq->HopCount,
                               SetupReq->Source, SetupReq->Dest, (VRRIf)PA->Index,
                               (SetupReq->Type & VRR_SR_TYPE_REQUEST) ? VRR_OPTION_TYPE_SETUPREQ : VRR_OPTION_TYPE_SR_NACK);
    if (NewPXE == FALSE &&
        (SetupReq->Type & VRR_SR_TYPE_NACK)==0) {
            VrrTrace(VA,2,"SR:SR=Drop(Dup)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
        InterlockedIncrement((PLONG)&VA->CountSRDropLoop);
        return;
    }

    //
    // Ignore any SetupReq that we sent ourselves while attempting join.
    // gregos: will need to strengthen this for DAD handling.
    //
    if (VirtualAddressEqual(VA->Address, SetupReq->Dest))
    if (VirtualAddressEqual(VA->Address, SetupReq->Source)) {
        VrrTrace(VA,2,"SR:SR=Drop(BadSelf)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
        return;
    }

    //
    // Construct SRcAntiRoute of addresses the orginator has asked us
    // to avoid for purposes of forwarding this SR. Reason is that
    // SetupRequests (SR) may get captured in a region of the mesh
    // that has local knowledge of addresses numerically close to
    // the destination address with no through routes allowing SR
    // to escape the region. The numerically close nodes will Nack
    // the SR and subsequent SR's use SRcAntiRoute to avoid ending up
    // at a node that has already Nacked the SR. This is most likely
    // to occur during initialization or after large-scale failure.
    //
    SRcAntiRoute = AddressListFromArray(&SetupReq->addr[0],CountSRcAntiRoute);

    //
    // In addition to the senders SRcAntiRoute, which may be NULL, we
    // always exclude the SR->Source from our forwarding decisions.
    //
    SRcAntiRoute = AddressListAdd(SRcAntiRoute,SetupReq->Source);

    //
    // Likewise ignore SetupReq that we sent ourselves and we are now 
    // nearest to Dest; this can happen when we attempt vset repair
    // and our SetupReq gets returned to us.
    // gregos: will need to strengthen this for DAD handling.
    //
    if (VirtualAddressEqual(VA->Address, SetupReq->Source)) {

        Result = FindNextHop(VA,
                             SetupReq->Dest,
                             VRR_IFID_UNSPECIFIED,
                             VRR_IFID_UNSPECIFIED,
                             NULL,
                             SRcAntiRoute,
                             NULL_SR_FLAGS);
                             
        if (Result == SuccessRcvNearest) {
            VrrTrace(VA,2,"SR:SR=Drop(BadSelf2)",SetupReq->Source,SetupReq->Source,SetupReq->Dest,NULL,0,"SeqNo",FrameSeqNo);
            InterlockedIncrement((PLONG)&VA->CountMisroutedSetupReq);

⌨️ 快捷键说明

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