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

📄 maintbuf.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 3 页
字号:
//
void
MaintBufRecvAck(
    MiniportAdapter *VA,
    const VirtualAddress Address,
    VRRIf InIf,
    VRRIf OutIf,
    VRRAckId AckNum)
{
    MaintBuf *MB = VA->MaintBuf;
    MaintBufNode *MBN;
    MaintBufPacket **PrevMBP;
    MaintBufPacket *MBP = NULL;
    MaintBufPacket *NextMBP;
    uint NumPackets;
    KIRQL OldIrql;

    //
    // Find the appropriate MaintBufNode.
    //
    KeAcquireSpinLock(&MB->Lock, &OldIrql);
    MBN = MaintBufFindNode(MB, Address, InIf, OutIf);
    if (MBN != NULL) {
        //
        // Is this a valid ack?
        // That is, between LastAckNum and NextAckNum.
        //
        if (MaintBufValidAck(MBN, AckNum)) {
        
            //
            // We have received a valid ack, confirming the link.
            //
            MBN->NumValidAcks++;
            MBN->LastAckNum = AckNum;
            MBN->LastAckRcv = KeQueryInterruptTime();

            //
            // Remove any acknowledged packets.
            // This maintains the invariant that waiting packets
            // have a sequence number between LastAckNum and NextAckNum.
            //
            NumPackets = 0;
            for (PrevMBP = &MBN->MBP;
                 (MBP = *PrevMBP) != NULL;
                 PrevMBP = &MBP->Next) {

                //
                // If we receive MBP->AckNum, will it be valid?
                //
                if (! MaintBufValidAck(MBN, MBP->AckNum)) {
                    //
                    // Remove this packet (and any older ones).
                    //
                    *PrevMBP = NULL;
                    MB->NumPackets -= MBN->NumPackets - NumPackets;
                    MBN->NumPackets = NumPackets;
                    break;
                }
                NumPackets++;
            }
        }
        else {
            //
            // This is an invalid ack, because the ack sequence number
            // is not in the proper range.
            //
            MBN->NumInvalidAcks++;
            
        }
    }

    //
    // Track count of successful MB packet transmissions.
    //
    for (NextMBP = MBP; NextMBP != NULL; NextMBP = NextMBP->Next)
        MBN->MBNTxSuccess++;

    KeReleaseSpinLock(&MB->Lock, OldIrql);

    //
    // Did we find any packets to complete?
    //
    while (MBP != NULL) {
        NextMBP = MBP->Next;
        MaintBufPacketRelease(VA, MBP);
        MBP = NextMBP;
    }
}

//* MaintBufStaticSendComplete
//
//  Completion handler for statically source-routed packets.
//
void
MaintBufStaticSendComplete(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet,
    NDIS_STATUS Status)
{
    SRPacket *SRP = PC(Packet)->srp;

    PrintfNdisStatus(__FUNCTION__,Status,FALSE);

    NdisFreePacketClone(Packet);

   (*SRP->TransmitComplete)(VA, SRP, Status);
}

//* MaintBufSendPacket
//
//  Sends a Source-Routed packet that must be explicitly
//  acked by the destination.
//
//  TxQueueIsFull has already been called, but if we retransmit
//  then we should call it again.
//
//  NB: We must create a new NDIS_PACKET for every (re)transmission.
//  We can not allow a single NDIS_PACKET to be sent twice simultaneously.
//
//  Returns TRUE if the packet was transmitted successfully, else FALSE.
//
uint
MaintBufSendPacket(
    MiniportAdapter *VA,
    SRPacket *srp,
    void (*Complete)(MiniportAdapter *VA, SRPacket *srp, NDIS_STATUS Status))
{
    MaintBuf *MB = VA->MaintBuf;
    InternalAcknowledgementRequest *AR = NULL;
    MaintBufNode *MBN;
    MaintBufPacket *MBP = NULL;
    NDIS_PACKET *Packet = NULL;
    Time Now;
    Time Timeout = 0;
    uint Index;
    KIRQL OldIrql;
    NDIS_STATUS Status;

    VRRASSERT(srp->ackreq == NULL);

    //
    // We have to initialize this before unlocking MaintBuf.
    //
    srp->TransmitComplete = Complete;

    //
    // If the packet contains nothing more than ack(s) then
    // we do not send it via the maintbuf in order to avoid
    // generating Acks for Acks.
    //
    if (SRPContainsMessages(srp)) {
        //
        // Use the Maintenance Buffer to send the packet,
        // requesting an acknowledgement.
        //
        InterlockedIncrement((PLONG)&VA->CountXmitMaintBuf);

        //
        // In testing we sometimes supress all tx.
        //
        if (VA->TxDropAllButHello) {
            (*Complete)(VA, srp, NDIS_STATUS_RESOURCES);
            return TRUE;
        }

        //
        // VRR control messages have fixed NextHop.
        // They must not be rerouted by FNH.
        // At this point the NextHop should already be known.
        //
        VRRASSERT(! IsNullTxToken(&srp->Token) );

        AR = ExAllocatePool(NonPagedPool, sizeof *AR);
        if (AR == NULL) {
            (*Complete)(VA, srp, NDIS_STATUS_RESOURCES);
            return FALSE;
        }

        srp->ackreq = AR;
        RtlZeroMemory(AR, sizeof *AR);
        AR->opt.optionType = VRR_OPTION_TYPE_ACKREQ;
        AR->opt.optDataLen = ACK_REQUEST_LEN;
        RtlCopyMemory(&AR->opt.Source, &srp->Token.Source, sizeof(VirtualAddress));
        RtlCopyMemory(&AR->opt.Dest, &srp->Token.NextVAddress, sizeof(VirtualAddress));
        AR->opt.RackSourceIF = srp->Token.LocIF;
        AR->opt.RackDestIF = srp->Token.RemIF;

        // AR->opt.identification initialized in MaintBufAddPacket.

        //
        // Find the MaintBufNode for the packet.
        //
        KeAcquireSpinLock(&MB->Lock, &OldIrql);
        Now = KeQueryInterruptTime();
        
        MBN = MaintBufFindNode(MB,
                               srp->Token.NextVAddress,
                               srp->Token.LocIF,   // InIf.
                               srp->Token.RemIF);  // OutIf.

        if (MBN != NULL) {

            InterlockedIncrement((PLONG)&MBN->MBNCountPackets);

            //
            // Create and initialize a new MaintBufPacket structure.
            //
            MBP = ExAllocatePool(NonPagedPool, sizeof *MBP);
            if (MBP != NULL) {
                //
                // Initialize the MaintBufPacket. It starts with 1 ref
                // for its existence on MBN.
                //
                MBP->RefCnt = 1;
                MBP->srp = srp;

                //
                // Are we requesting the first ack?
                //
                if (! MaintBufAckExpected(MBN))
                    MBN->FirstAckReq = Now;

                //
                // If MaintBufAddPacket returns an NDIS_PACKET,
                // it also adds a reference to MBP.
                //
                if ((Packet=MaintBufAddPacket(VA, MBN, MBP))==NULL) {
                    MBN->MBP = MBP->Next;
                    ExFreePool(MBP);
                    MBP = NULL;
                }
                else {
                    //
                    // We are sending an Ack Request to this node.
                    //
                    MBN->NumAckReqs++;
                    MBN->LastAckReq = Now;
                    Timeout = MBN->LastAckReq + MAINTBUF_REXMIT_TIMEOUT;
                }
            }
        }
        KeReleaseSpinLock(&MB->Lock, OldIrql);

        //
        // Error handling.
        //
        if (MBP == NULL) {
            (*Complete)(VA, srp, NDIS_STATUS_RESOURCES);
            return FALSE;
        }

        //
        // Reschedule the next MaintBufTimer call.
        //
        if (Timeout != 0)
            MiniportRescheduleTimeout(VA, Now, Timeout);

        //
        // Ensure PC(PC(Packet)->PA is valid.
        //
        PC(Packet)->PA = FindPhysicalAdapterFromIndex(VA, srp->Token.LocIF);

        MaintBufTransmit(VA, MBP, Packet);
    }
    else {
        //
        // Just send the packet directly.
        //

        Status = SRPacketToPkt(VA, srp, &Packet);
        if (Status != NDIS_STATUS_SUCCESS) {
            (*Complete)(VA, srp, Status);
            return FALSE;
        }

        PC(Packet)->srp = srp;
        PC(Packet)->TransmitComplete = MaintBufStaticSendComplete;

        //
        // In testing we sometimes supress all tx.
        //
        if (VA->TxDropAllButHello) {
            MaintBufStaticSendComplete(VA, Packet, NDIS_STATUS_FAILURE);
            return TRUE;
        }

        if (PC(Packet)->PA == NULL) {
            //
            // This means the packet is trying to use a physical adapter that
            // no longer exists.
            //
            VrrKdPrint("MBSendPacket MaintBufStaticSendComplete",NULL,NULL);
            MaintBufStaticSendComplete(VA, Packet, NDIS_STATUS_FAILURE);
            return FALSE;
        }
        else {
            VrrTrace(VA,3,"MB:MP=ReTx(MaintBufStaticSendComplete)",srp->Source,srp->Token.NextVAddress,srp->Dest,NULL,0,"FrameSeqNo",srp->FrameSeqNo);
            ProtocolTransmit(PC(Packet)->PA, Packet);
        }
    }

    return TRUE;
}

//* MaintBufSendAck
//
//  Requests delayed transmission of an Ack.
//
void
MaintBufSendAck(
    MiniportAdapter *VA,
    VirtualAddress Source,
    VirtualAddress Dest,
    VRRAckId AckId,
    VRRIf RackSourceIF,
    VRRIf RackDestIF,
    uchar NCEState)
{
    InternalAcknowledgement *Ack;

    //
    // Allocate the Acknowledgement option.
    //
    Ack = ExAllocatePool(NonPagedPool, sizeof *Ack);
    if (Ack == NULL)
        return;

    //
    // Initialize the Acknowledgement option.
    //
    RtlZeroMemory(Ack, sizeof *Ack);
    Ack->opt.optionType = VRR_OPTION_TYPE_ACK;
    Ack->opt.optDataLen = ACKNOWLEDGEMENT_LEN;
    Ack->opt.identification = AckId;
    Ack->opt.RackSourceIF = RackSourceIF;
    Ack->opt.RackDestIF = RackDestIF;
    RtlCopyMemory(Ack->opt.from, Source, SR_ADDR_LEN);
    RtlCopyMemory(Ack->opt.to, Dest, SR_ADDR_LEN);

    //
    // Send the Acknowledgement option.
    //
    MsgQueueMessage(VA, Ack->opt.to,(InternalOption *)Ack,RackDestIF,RackSourceIF,MAX_ACK_DELAY,NULL);
}

//* MaintBufResetStatistics
//
//  Resets all counters and statistics gathering for the maintenance buffer.
//
void
MaintBufResetStatistics(MiniportAdapter *VA)
{
    MaintBuf *MB = VA->MaintBuf;
    MaintBufNode *MBN;
    KIRQL OldIrql;

    KeAcquireSpinLock(&MB->Lock, &OldIrql);
    MB->HighWater = MB->NumPackets;
    for (MBN = MB->MBN; MBN != NULL; MBN = MBN->Next) {
        MBN->HighWater = MBN->NumPackets;
        MBN->NumAckReqs = 0;
        MBN->NumFastReqs = 0;
        MBN->NumValidAcks = 0;
        MBN->NumInvalidAcks = 0;
        MBN->MBNCountPackets = 0;
        MBN->MBNTxSuccess = 0;
        MBN->MBNRexmits = 0;
        MBN->MBNTxFailed = 0;
    }
    KeReleaseSpinLock(&MB->Lock, OldIrql);
}

⌨️ 快捷键说明

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