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

📄 setupreq.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 3 页
字号:
        // Preserve the JOIN flag from the SetupReq.
        // If this was a join attempt then the proxy node must
        // bypass the normal forwarding logic in favour of its
        // physical neighbor that sent the SetupReq.
        //
        if (SetupReq->Flags & VRR_MSG_FLAG_JOIN_ATTEMPT)
            Setup->Opt.Flags |= VRR_MSG_FLAG_JOIN_ATTEMPT;
            
        //
        // If we are the proxy then we must adjust the message
        // for direct transmission (no proxy involved). Note
        // that we cannot use the mainline forwarding routines
        // because the sender, and hence our NCE for the sender,
        // is not yet in state ACTIVE.
        // 
        if (IsProxy) {
            //
            // Special (rare) case. We are the proxy in a join attempt.
            //
            NeighborCacheEntry *NCE;
                
            RtlCopyMemory(Setup->Opt.Dest, *source, sizeof(VirtualAddress));
            RtlCopyMemory(Setup->Opt.Proxy, VA->Address, sizeof(VirtualAddress));
            Setup->Opt.Flags |= VRR_MSG_FLAG_PASTPROXY;
        }

        //
        // Signal LocIF and RemIF in Setup message.
        //
        Setup->Opt.LocIF = Tok.LocIF;
        Setup->Opt.RemIF = Tok.RemIF;

        //
        // Add sender to our VSet. This will create a new
        // NTE if necessary.
        //
        VSetAddNode(VA,SetupReq->Source,CountVSet,MsgVSet);

        //
        // Schedule the Setup message for reliable transmission.
        //
        VrrTrace(VA,3,"SR:SR=Rcv_(SendSetup)",VA->Address,Tok.NextVAddress,*source,NULL,0,"SeqNo",FrameSeqNo);
        MsgQueueMessage(VA, Tok.NextVAddress, (InternalOption *) Setup, Setup->Opt.LocIF,Setup->Opt.RemIF,SETUP_DELAY,NULL);
        SentSetup = TRUE;

    } else {
        //
        // Reject the sender as a neighbor. Send msg SetupReq(NACK).
        // Use the sender's FrameSeqNo to match original SR->FrameSeqNo.
        //
        SendSRNack(VA, *source, SetupReq->Proxy, FrameSeqNo, SetupReq->Target, SetupReq->Flags);
    }
    
    //
    // Process the vset from the SetupReq message.
    //
    ReceiveVSet(VA,CountVSet,MsgVSet);
    
ReleaseAndReturn:

    if (SRcAntiRoute != NULL)
        AddressListFree(SRcAntiRoute);

    if (Setup != NULL && SentSetup == FALSE)
        ExFreePool(Setup);

    return;
}

//* CreateSetupReqOpt
//
//  Creates an SRP Opt encoding a SetupReq.
//
//  Returns NULL if memory allocation failed or if rate
//  limit exceeded on SR generation.
//
//  Caller must not hold NT->Lock.
//
InternalVrrSetupReq *
CreateSetupReqOpt(
    MiniportAdapter *VA,
    VirtualAddress Dest,
    uchar Type,
    VirtualAddress Proxy,
    uint FrameSeqNo,
    VirtualAddress Target,   // used in SR(NACK) to report original SR(Dest).
    AddressList *SRcAntiRoute)
{
    NDIS_STATUS Status;
    uint OptSize;
    NodeTable *NT = &VA->NT;
    NodeTableEntry *NTE;
    KIRQL OldIrql;
    uint NTECount = 0;
    uint i;
    uchar CountSRcAntiRoute = AddressListCount(SRcAntiRoute);
    InternalVrrSetupReq *VSR;
    Time Now = KeQueryInterruptTime();
    VirtualAddress FlatVSet[VRR_MAX_VSET_SIZE];

    VRRASSERT(VRR_SR_VALID_TYPE(Type));
    if (Type & VRR_SR_TYPE_REQUEST)
        InterlockedIncrement((PLONG)&VA->CountSendSetupReq);
    if (Type & VRR_SR_TYPE_NACK)
        InterlockedIncrement((PLONG)&VA->CountSendSetupReqNack);

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

    //
    // Obtain memory for VrrSetupReq option. Include as many neighbours
    // as a single packet can accommodate.
    //
    if (CountSRcAntiRoute != 0)
        VrrTrace(VA,4,"SR:SR=New_(CountSRcAntiRoute!=0)",VA->Address,Proxy,Dest,"CountSRcAntiRoute",CountSRcAntiRoute,NULL,0);

    NTECount = VSetToFlatBuffer(VA,FlatVSet);
    OptSize = sizeof *VSR                                   // Internal option linkage.
              + sizeof(VrrSetupReq)                         // Preamble.
              + (CountSRcAntiRoute * sizeof(VirtualAddress))   // SRcAntiRoute
              + (NTECount * sizeof(VirtualAddress));        // vset.
                   
    VSR = ExAllocatePool(NonPagedPool, OptSize);
    if (VSR == NULL) {
        Status = NDIS_STATUS_RESOURCES;
        goto ReleaseAndReturn;
    }

    VrrTrace(VA,3,"gregos:CreateSetupReqOpt (Target)",NULL,Target,NULL,NULL,0,"*ptr=",(uint)VSR);
    
    //
    // Format the VrrSetupReq option.
    //
    RtlZeroMemory(VSR, OptSize);
    VSR->Opt.OptionType = VRR_OPTION_TYPE_SETUPREQ;
    VSR->Opt.OptDataLen = VRRSETUPREQ_LEN(NTECount + CountSRcAntiRoute);
    VSR->Opt.Type = Type;
    RtlCopyMemory(VSR->Opt.Source, VA->NT.Self->Address, sizeof(VirtualAddress));
    VSR->Opt.FrameSeqNo = RtlUlongByteSwap(FrameSeqNo);
    RtlCopyMemory(VSR->Opt.Target, Target, sizeof(VirtualAddress));
    VSR->Opt.CountSRcAntiRoute = CountSRcAntiRoute;
    AddressListToArray(SRcAntiRoute, VSR->Opt.addr, CountSRcAntiRoute);

    //
    // The packet will go to the dest via the proxy.
    //
    RtlCopyMemory(VSR->Opt.Dest, Proxy, sizeof(VirtualAddress));
    RtlCopyMemory(VSR->Opt.Proxy, Dest, sizeof(VirtualAddress));
    
    //
    // Append list of VSet addresses.
    //
    RtlCopyMemory(&VSR->Opt.addr[CountSRcAntiRoute], FlatVSet,
                  NTECount*sizeof(VirtualAddress));

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

    return VSR;

ReleaseAndReturn:
    KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
    return NULL;
}

//* JoinSendSetupReqComplete
//
//  Packet completion routine for JoinSendSetupReq.
//
void
JoinSendSetupReqComplete(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet,
    NDIS_STATUS Status)
{
    SRPacket *srp = PC(Packet)->srp;

    UNREFERENCED_PARAMETER(VA);
    UNREFERENCED_PARAMETER(Status);

    NdisFreePacketClone(Packet);
    SRPacketFree(srp);
}

//* JoinSendSetupReq
//
//  Constructs and sends SetupReq in the special case of a
//  node that is attempting to join the ring and which
//  therefore lacks the routing state required by the main
//  forwarding routines. In this case we use this routine and
//  rely upon NTE state and timers to cause retransmission.
//
//  Returns TRUE iff the packet was successfully transmitted.
//
boolint
JoinSendSetupReq(
    MiniportAdapter *VA,
    VirtualAddress Dest,
    VirtualAddress Proxy,
    uint FrameSeqNo,
    AddressList *SRcAntiRoute)
{
    SRPacket *SRP;
    NDIS_PACKET *Packet;
    TxToken Tok;
    Time Now = KeQueryInterruptTime();
    uint RateLimitExceeded = FALSE;
    EtherHeader UNALIGNED *Ether;
    KIRQL OldIrql;
    
    //
    // Bail if join attempts have been disabled.
    //
    if (IsJoiningOnHold(VA)) {
        InterlockedDecrement((PLONG)&VA->CountSendSetupReq);
        VrrTrace(VA,2,"SR:SR=Drop(JoiningOnHold=T)",VA->Address,Proxy,Dest,NULL,0,"FrameSeqNo",FrameSeqNo);
        return FALSE;
    }

    //
    // Construct and send a SetupReq message.
    //
    InterlockedIncrement((PLONG)&VA->CountSendSetupReq);
    VrrTrace(VA,3,"SR:SR=New_(Join)",VA->Address,Proxy,Dest,NULL,0,"FrameSeqNo",FrameSeqNo);

    //
    // Initialize an SRPacket to encode the SetupReq.
    //
    SRP = ExAllocatePool(NonPagedPool, sizeof *SRP);
    if (SRP == NULL) {
        KdPrint(("JoinSendSR: malloc(SRP) failed\n"));
        return FALSE;
    }
    RtlZeroMemory(SRP, sizeof *SRP);

    //
    // Initialize the source & destination of the SRPacket.
    //
    RtlCopyMemory(SRP->Dest, Proxy, sizeof(VirtualAddress));
    RtlCopyMemory(SRP->Source, VA->Address, sizeof(VirtualAddress));
    RtlCopyMemory(SRP->Origin, VA->Address, sizeof(VirtualAddress));
    SRP->FrameSeqNo = InterlockedIncrement(&VrrGlobal.NextFrameSeqNo);
    SRP->HopCount = 0;

    //
    // Check that Proxy is a physical neighbor in state ACTIVE.
    //
    if (FALSE == GetPhysNeighborTxToken(VA, Proxy, VRR_IFID_UNSPECIFIED,
                                        VRR_IFID_UNSPECIFIED,&SRP->Token, VRR_NCE_STATE_ACTIVE)) {
                                        
        VrrKdPrint("JoinSendSR: GetPhysNeighborTxToken(proxy=d)==F",NULL,Proxy);
        goto FreeSRPAndExit;
    }

    //
    // Allocate a formatted SetupReq message.
    //
    SRP->VrrSetupReq = CreateSetupReqOpt(VA, 
                                         Dest, 
                                         VRR_SR_TYPE_REQUEST, 
                                         Proxy, 
                                         FrameSeqNo,
                                         Dest,
                                         SRcAntiRoute);
    if (NULL == SRP->VrrSetupReq) {
        KdPrint(("JoinSendSR: CreateSROpt failed\n"));
        goto FreeSRPAndExit;
    }
    
    //
    // Set the Flag bit VRR_MSG_FLAG_JOIN_ATTEMPT.
    // The proxy node via which we attempt to join
    // the ring needs this in order to bypass the
    // normal forwarding logic which expects to
    // find an RTE for the destination.
    //
    SRP->VrrSetupReq->Opt.Flags |= VRR_MSG_FLAG_JOIN_ATTEMPT;

    //
    // Construct an NDISPacket from the SRPacket.
    //
    if (SRPacketToPkt(VA, SRP, &Packet) != NDIS_STATUS_SUCCESS) {
        KdPrint(("JoinSendSR: SRPacketToPkt failed\n"));
        goto FreeSRPAndExit;
    }

    //
    // The SRPacketToPkt() call generated a TxToken from
    // RT state and if the destination is multi-homed may
    // have chosen a different RemIF to the one in Tok and
    // thus set SRP->Token and the packet EthDest incorrectly. 
    // Therefore we reinstate SRP->Token and overwrite the
    // packet EthDest using our original TxToken.
    //
    //RtlCopyMemory(&SRP->Token,&Tok,sizeof(TxToken));
    PC(Packet)->PA = SRP->Token.PA;
    Ether = (EtherHeader UNALIGNED *) NdisFirstBuffer(Packet)->MappedSystemVa;
    //RtlCopyMemory(Ether->Dest, Tok.NextPAddress, IEEE_802_ADDR_LENGTH);
    PC(Packet)->srp = SRP;
    UpdatePacketIndex(VA, 
                      SRP->VrrSetupReq->Opt.Source, 
                      RtlUlongByteSwap(SRP->VrrSetupReq->Opt.FrameSeqNo),
                      SRP->VrrSetupReq->Opt.HopCount++,
                      SRP->Source, 
                      SRP->Dest, 
                      SRP->Token.LocIF, 
                     (SRP->VrrSetupReq->Opt.Type & VRR_SR_TYPE_REQUEST) ? VRR_OPTION_TYPE_SETUPREQ : VRR_OPTION_TYPE_SR_NACK);

    //
    // Send the join SetupReq.
    //
    VrrTrace(VA,3,"SR:SR=Tx__(Join)",VA->Address,Proxy,Dest,NULL,0,"FrameSeqNo",FrameSeqNo);
    if (VA->MsFirstJoinSetupReq == 0)
        VA->MsFirstJoinSetupReq = TIME_TO_MS(Now);
    PC(Packet)->TransmitComplete = JoinSendSetupReqComplete;
    ProtocolTransmit(PC(Packet)->PA, Packet);

    return TRUE;

FreeSRPAndExit:
    SRPacketFree(SRP);
    
    return FALSE;
}




⌨️ 快捷键说明

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