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

📄 wcett.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 3 页
字号:
        //
        // We have received no valid packet-pair samples.
        // Reduce the bandwidth estimate.
        //
        Bandwidth = WcettDecodeBandwidth(Link->wcett.Bandwidth);
        Bandwidth = WcettDefaultBandwidth(Bandwidth);
    }
    else {
        uint Delay;

        //
        // Calculate the bandwidth using the minimum delay sample
        // from the last sample period.
        //
        Delay = Link->MetricInfo.Wcett.PktPair.CurrMin;
        Bandwidth = WcettConvertPktPairDelayToBandwidth(Delay);
    }

    Link->wcett.Bandwidth = WcettEncodeBandwidth(Bandwidth);
}

//* WcettSendPktPairProbes
//
//  Sends probes to adjacent nodes as needed.
//
Time
WcettSendPktPairProbes(
    MiniportAdapter *VA,
    Time Now)
{
    NeighborCache *NC = &VA->NC;
    NeighborCacheEntry *NCE;
    NDIS_PACKET *ProbePackets = NULL;
    NDIS_PACKET *FirstPkt, *SecondPkt, *Packet;
    Link *Adj;
    Time Timeout;
    KIRQL OldIrql;
    NDIS_STATUS Status;
    uint Diff;

    Timeout = MAXTIME;

    KeAcquireSpinLock(&NC->Lock, &OldIrql);

    //
    // Loop through outgoing links, creating a probe pair for each,
    // when warranted by timeout value. Store the probe packets temporarily 
    // on a list since we can't send them while holding the lock on the 
    // Neighbor Cache.
    //
    for (NCE = NC->FirstNCE; NCE != SentinelNCE(NC); NCE = NCE->Next) {

        //
        // For link quality metric, if layer 2 driver supports it, 
        // we prefer OID_MSRC_QUERY_SIB_TABLE to packet pair.
        //
        if (NCE->Flags & VRR_NCE_FLAG_SIB_OID)
            continue;

        Adj = &NCE->AdjOut;

        if (Adj->MetricInfo.Wcett.PktPair.ProbeTimeout <= Now) {

            //
            // Is it time to calculate a new link bandwidth?
            //
            if ((Adj->MetricInfo.Wcett.PktPair.PairsSent % VA->MetricParams.Wcett.PktPairMinOverProbes) == 0) {
                //
                // Update the bandwidth using CurrMin.
                //
                WcettUpdateBandwidth(Adj);

                //
                // Reset CurrMin to a large number.
                //
                Adj->MetricInfo.Wcett.PktPair.CurrMin = (uint)-1;
            }

            //
            // Create two packets, one with Seq and another with Seq + 1. 
            //
            Status = PktPairCreateProbePacket(VA, Adj, 0, &FirstPkt,
                                              Adj->MetricInfo.Wcett.PktPair.ProbeSeq, FALSE, METRIC_TYPE_PKTPAIR);
            if (Status == NDIS_STATUS_SUCCESS) {
                Status = PktPairCreateProbePacket(VA, Adj, 0, &SecondPkt, 
                                                  Adj->MetricInfo.Wcett.PktPair.ProbeSeq + 1, TRUE, METRIC_TYPE_PKTPAIR);
                if (Status == NDIS_STATUS_SUCCESS) {
                    //
                    // We created both packets successfuly. Bump the 
                    // sequence number by two. 
                    //
                    Adj->MetricInfo.Wcett.PktPair.ProbeSeq += 2;
                    Adj->MetricInfo.Wcett.PktPair.PairsSent++;
                    Adj->MetricInfo.Wcett.PktPair.Outstanding = Adj->MetricInfo.Wcett.PktPair.ProbeSeq - 1;

                    //
                    // Queue the packets using the OrigPacket link.
                    // The queue is "backward", so insert second packet
                    // first.
                    //
                    PC(SecondPkt)->OrigPacket = ProbePackets;
                    PC(FirstPkt)->OrigPacket = SecondPkt;
                    ProbePackets = FirstPkt;
                }
                else {
                    //
                    // We failed to create the second probe. 
                    //
                    KdPrint(("VRR!WcettSendPktPairProbes SECOND PktPairCreateProbePacket returned %x\n", Status));
                    PktPairSendProbeComplete(VA, FirstPkt, Status);
                }
            }
            else {
                //
                // We failed to create the first probe. 
                //
                KdPrint(("VRR!WcettSendPktPairProbes FIRST PktPairCreateProbePacket returned %x\n", Status));
            }

            //
            // Calculate next probe timeout. Randomize by adding 25% delay. 
            //
            Diff = VA->MetricParams.Wcett.PktPairProbePeriod + GetRandomNumber(VA->MetricParams.Wcett.PktPairProbePeriod >> 2);
            Adj->MetricInfo.Wcett.PktPair.ProbeTimeout = Now + Diff; 
        }

        //
        // We need to keep track of only the earliest timeout.
        //
        if (Adj->MetricInfo.Wcett.PktPair.ProbeTimeout < Timeout)
            Timeout = Adj->MetricInfo.Wcett.PktPair.ProbeTimeout;
    }
    
    KeReleaseSpinLock(&NC->Lock, OldIrql);
    
    //
    // Loop through queued packets, sending out each probe.
    //
    while ((Packet = ProbePackets) != NULL) {
        ProbePackets = PC(Packet)->OrigPacket;
        PC(Packet)->OrigPacket = NULL;

        if (PC(Packet)->PA == NULL) {
            //
            // This means the packet is trying to use a physical adapter
            // that no longer exists. 
            //
            VRRASSERT(PC(Packet)->TransmitComplete == PktPairSendProbeComplete);
            PktPairSendProbeComplete(VA, Packet, NDIS_STATUS_FAILURE);

        } else {
            //
            // Transmit the packet.
            //
            ProtocolTransmit(PC(Packet)->PA, Packet);
        }
    }

    return Timeout;
}

//* WcettReceivePktPairProbe
//
//  Receive a Probe, and Reply if necessary.
//
void
WcettReceivePktPairProbe(
    MiniportAdapter *VA, 
    InternalProbe *Probe)
{
    NeighborCache *NC = &VA->NC;
    NeighborCacheEntry *NCE;
    Link *Adj;
    Time Now, OutDelta;
    LARGE_INTEGER Timestamp;
    LARGE_INTEGER Frequency;
    KIRQL OldIrql;
    boolint SendProbeReply = FALSE; 

    //
    // Do not send a response to ourselves.
    //
    if (VirtualAddressEqual(Probe->Opt.From, VA->Address))
        return;
   
    Timestamp = KeQueryPerformanceCounter(&Frequency);
    Now = Timestamp.QuadPart;
    OutDelta = 0;

    //
    // When we receive a probe:
    //   - Find the NCE for the sender.
    //   - If the seq number is even, store current time
    //     and seq number.
    //   - If the seq number is odd, and if it is the next expected
    //     probe, send a reply. 
    //

    KeAcquireSpinLock(&NC->Lock, &OldIrql);

    //
    // Find NCE of the sender. Bail if Hello protocol has yet to see sender.
    //
    NCE = FindNCE(NC,
                  Probe->Opt.From,
                  Probe->Opt.InIf,   // InIf = recv's rx = LocIF.
                  Probe->Opt.OutIf,  // OutIf = sender's tx = RemIF.
                  VRR_NCE_STATE_VALID);

    if (NCE == NULL) {
        VrrKdPrint("WcettReceivePktPairProbe: no NCE(s)",Probe->Opt.From,NULL);
    
    } else {
        Adj = &NCE->AdjIn;
        
        if ((Probe->Opt.Seq % 2) == 0) {
            Adj->MetricInfo.Wcett.PktPair.TimeLastProbeRcvd = Now;
            Adj->MetricInfo.Wcett.PktPair.LastProbeSeq = Probe->Opt.Seq;
        }
        else if ((Adj->MetricInfo.Wcett.PktPair.TimeLastProbeRcvd != 0) &&
                 ((Adj->MetricInfo.Wcett.PktPair.LastProbeSeq + 1) == Probe->Opt.Seq)) {
            //
            // Calculate OutDelta - the packet-pair delay.
            // We must scale OutDelta to 100ns units.
            //
            OutDelta = Now - Adj->MetricInfo.Wcett.PktPair.TimeLastProbeRcvd;
            Adj->MetricInfo.Wcett.PktPair.TimeLastProbeRcvd = 0;

            if ((10000000L * OutDelta) < OutDelta) {
                //
                // We got an overly large OutDelta, so we
                // can't report a reasonable number. Therefore, don't.
                //
                KdPrint(("VRR!WcettReceivePktPairProbe: Not sending reply due to OutDelta overflow.\n"));
            }
            OutDelta = (10000000L * OutDelta)/Frequency.QuadPart;

            //
            // Remember to send probe reply, and update counters. 
            //
            SendProbeReply = TRUE;
            Adj->MetricInfo.Wcett.PktPair.RepliesSent++;
        }
    }

    KeReleaseSpinLock(&NC->Lock, OldIrql);

    if (SendProbeReply) {
        InterlockedIncrement((PLONG)&VA->CountXmitProbeReply);
        PktPairSendProbeReply(VA, Probe, Now, OutDelta);
    }
}    


//* WcettReceiveProbe
//
//  Receive a Probe. Called from ReceiveSRPacket.
//  We have already verified that the MetricType is WCETT.
//
void
WcettReceiveProbe(
    MiniportAdapter *VA,
    InternalProbe *Probe,
    VRRIf InIf)
{
    VRRASSERT(Probe->Opt.MetricType == METRIC_TYPE_WCETT);
    if (Probe->Opt.ProbeType == METRIC_TYPE_PKTPAIR)
        WcettReceivePktPairProbe(VA, Probe);
}


//* WcettReceivePktPairProbeReply
//
//  Receive a Probe Reply.  Called from ReceiveSRPacket.
//
void
WcettReceivePktPairProbeReply(
    MiniportAdapter *VA,
    InternalProbeReply *ProbeReply)
{
    NeighborCache *NC = &VA->NC;
    NeighborCacheEntry *NCE;
    Link *Adj;
    KIRQL OldIrql;
    PRPktPair *Special; 

    //
    // Loop through NCE looking for the neighbor to whom the
    // probe to which this probe reply is a response was sent.
    //

    KeAcquireSpinLock(&NC->Lock, &OldIrql);

    NCE = FindNCE(NC,
                  ProbeReply->Opt.From,
                  ProbeReply->Opt.InIf,     // LocIF: local IF to which counterparty sent Reply.
                  ProbeReply->Opt.OutIf,    // RemIF: remote IF from which counterparty sent Reply.
                  VRR_NCE_STATE_VALID);
    if (NCE == NULL) {
        VrrKdPrint("WcettReceivePktPairProbeReply: no NCE(s)",ProbeReply->Opt.From,NULL);
        KdPrint(("WcettReceivePktPairProbeReply: ProbeRep->OutIf=%u, ProbeRep->InIf=%u\n",
                  ProbeReply->Opt.OutIf,ProbeReply->Opt.InIf));
    }
    else {
        Adj = &NCE->AdjOut;


//        if (VirtualAddressEqual(ProbeReply->Opt.From,
//                                LC->nodes[Adj->targetIndex].address) &&
//            (ProbeReply->Opt.OutIf == Adj->inif) &&
//            (ProbeReply->Opt.InIf == Adj->outif)) {
            
        //
        // Found NCE to which probe was sent.
        // If it's a response for the last probe 
        // we sent, calculate the bandwidth on the link.
        //
        if (Adj->MetricInfo.Wcett.PktPair.Outstanding ==
                                            ProbeReply->Opt.Seq) {
            Special = (PRPktPair *)ProbeReply->Opt.Special; 
            Adj->MetricInfo.Wcett.PktPair.RepliesRcvd++;

            //
            // Update CurrMin from this sample.
            //
            WcettUpdateMin(Adj, Special->OutDelta);
                
            if (Adj->MetricInfo.Wcett.PktPair.PairsSent < VA->MetricParams.Wcett.PktPairMinOverProbes) {
                //
                // Update the bandwidth and keep accumulating CurrMin.
                // This lets the bandwidth converge quickly
                // after first discovering the link.
                //
                WcettUpdateBandwidth(Adj);
            }
        }
        else {
            //
            // We got a late probe reply. Throw it away.
            // This should not happen too often. 
            //
            KdPrint(("VRR!WcettPktPairReceiveProbeReply LATE outstanding %u rcvd %u\n", 
                       Adj->MetricInfo.Wcett.PktPair.Outstanding, ProbeReply->Opt.Seq));
        }
        Adj->MetricInfo.Wcett.PktPair.Outstanding = 0;
    }

    KeReleaseSpinLock(&NC->Lock, OldIrql);

}

⌨️ 快捷键说明

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