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

📄 miniport.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 5 页
字号:
void
MiniportReceiveComplete(
    MiniportAdapter *VA,
    SRPacket *srp,
    NDIS_STATUS Status)
{
    UNREFERENCED_PARAMETER(VA);
    UNREFERENCED_PARAMETER(Status);

    //
    // Free the SRPacket. This frees srp->Packet.
    //
    if (srp != NULL)
        SRPacketFree(srp);
}

//* MiniportForwardRequestComplete
//
//  Called after the completion of forwarding of an SRPacket
//  with a Route Request option. The SRPacket still needs
//  to be received locally.
//
static void
MiniportForwardRequestComplete(
    MiniportAdapter *VA,
    SRPacket *srp,
    NDIS_STATUS Status)
{
    UNREFERENCED_PARAMETER(Status);

    //
    // Receive the packet locally too.
    //
    MiniportReceiveLocally(VA, srp, MiniportReceiveComplete);
}

//* ReceiveSRPacket
//
//  Performs receive processing for an inbound packet,
//  after it has been parsed into an SRPacket structure.
//
//  Disposes of srp.
//
void
ReceiveSRPacket(
    MiniportAdapter *VA,
    ProtocolAdapter *PA,
    SRPacket *srp)
{
    InternalAcknowledgement **PrevAck;
    InternalAcknowledgement *Ack;
    uchar NCEState = 0;

    //
    // Consume Hello messages. At most one per packet.
    //
    if (srp->VrrHello != NULL) {
        ReceiveHello(VA, PA, srp);
        ExFreePool(srp->VrrHello);
        srp->VrrHello = NULL;
    }
    else if (SRPContainsMessages(srp) || srp->ack != NULL)
        VrrTrace(VA,3,"MP:**=Rcv_(SRPacket)",srp->Source,srp->Source,srp->Dest,NULL,0,"FrameSeqNo",srp->FrameSeqNo);

    //
    // Deal with probes immediately.  
    //
    if (srp->Probe != NULL) {
        //
        // First verify that we are using the same metric that this probe
        // is using. 
        // 
        // Then, verify that we're the appropriate destination.
        //  
        if (srp->Probe->Opt.MetricType == VA->MetricType &&
            VirtualAddressEqual(srp->Probe->Opt.To, VA->Address) &&
            srp->Probe->Opt.InIf == PA->Index && 
            VA->MetricType == METRIC_TYPE_WCETT) {

            WcettReceiveProbe(VA, srp->Probe, (VRRIf) PA->Index);
        }
    }

    //
    // Process a Probe Reply.
    //
    if (srp->ProbeReply != NULL) {
        //
        // Verify that we're the appropriate destination and that
        // we are using the same metric.
        //
        if (VirtualAddressEqual(srp->ProbeReply->Opt.To, VA->Address) &&
            (srp->ProbeReply->Opt.InIf == PA->Index) &&
            (srp->ProbeReply->Opt.MetricType == VA->MetricType)) {
            //
            // Process the probe reply according to whatever metric
            // we are using. 
            // 
            switch (VA->MetricType) {
            case METRIC_TYPE_WCETT:
                WcettReceivePktPairProbeReply(VA, srp->ProbeReply);
                break;
            }
        } 
    }

    //
    // Unicast messages received over a link in state is FAILED
    // are to be dropped *without* sending an ack, thus helping
    // the sender to detect the link failure through retransmisions. 
    //
    // Find the NCE with the EtherSource address and check its state.
    //
    if (IsIEEEGroupAddress(srp->EtherDest) == FALSE) {
        NeighborCacheEntry *NCE;
        KIRQL OldIrql;

        KeAcquireSpinLock(&VA->NC.Lock, &OldIrql);
        for (NCE = VA->NC.FirstNCE; NCE != SentinelNCE(&VA->NC); NCE = NCE->Next)
            if (RtlEqualMemory(NCE->PAddress, srp->EtherSource, sizeof(PhysicalAddress)))
                break;
        if (NCE != NULL)
            NCEState=NCE->State;
        KeReleaseSpinLock(&VA->NC.Lock, OldIrql);
    }

    if (NCEState == VRR_NCE_STATE_FAILED) {
#if DBG
        if (srp->VrrSetup != NULL)
            VrrTrace(VA,3,"MP:SU=Drop(NCE_FAILED)",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
        if (srp->VrrSetupReq != NULL)
            VrrTrace(VA,3,"MP:SR=Drop(NCE_FAILED)",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
        if (srp->VrrTearDown != NULL)
            VrrTrace(VA,3,"MP:TD=Drop(NCE_FAILED)",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
        if (srp->ackreq != NULL)
            VrrTrace(VA,3,"MP:AR=Drop(NCE_FAILED)",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
        if (srp->ack != NULL)
            VrrTrace(VA,3,"MP:AK=Drop(NCE_FAILED).",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
#endif
        goto FreeSrpAndReturn;
    }

    //
    // Consume VrrSetup messages.
    // Discussions and whiteboarding cause us to diverge from
    // the original simulator code in which we only received 
    // Setup from nodes that were LINKED. Now we are rejecting
    // nodes that are FAILED and advancing LINKED to PENDING
    // within ReceiveSetup.
    //
    // Optimistic Lightweight Transaction Stage 1.
    // ref "ignore setup messages ... from nodes that are not linked"
    //
    if (srp->VrrSetup != NULL) {
        InternalVrrSetup *Setup;
        InternalVrrSetup *NextSetup;
        
        for (Setup = srp->VrrSetup; Setup != NULL; Setup = NextSetup) {
            ReceiveSetup(VA, PA, Setup, srp);
            NextSetup = Setup->Next;
            ExFreePool(Setup);
        }
        srp->VrrSetup = NULL;
    }

    //
    // Consume VrrSetupReq messages.  
    //
    if (srp->VrrSetupReq != NULL) {
        InternalVrrSetupReq *SetupReq;
        InternalVrrSetupReq *NextSetupReq;
        
        for (SetupReq = srp->VrrSetupReq; SetupReq != NULL; SetupReq = NextSetupReq) {
            ReceiveSetupReq(VA, PA, SetupReq, srp);
            NextSetupReq = SetupReq->Next;
            ExFreePool(SetupReq);
        }
        srp->VrrSetupReq = NULL;
    }

    //
    // Consume TearDown messages.  
    //
    if (srp->VrrTearDown != NULL) {
        InternalVrrTearDown *TearDown;
        InternalVrrTearDown *NextTearDown;
        
        for (TearDown = srp->VrrTearDown; TearDown != NULL; TearDown = NextTearDown) {
            ReceiveTearDown(VA, PA, TearDown);
            NextTearDown = TearDown->Next;
            ExFreePool(TearDown);
        }
        srp->VrrTearDown = NULL;
    }

    //
    // Send an Ack immediately, if requested.
    //
    if (srp->ackreq != NULL) {
        uint Index;

        //
        // We may be receiving the packet because sender thinks
        // we're closer to the dest than he is. In other words
        // we may have received on an address that is not our
        // own. In any case we have received the packet and
        // processed or forwarded its messages. Therefore ack
        // the packet.
        //
        // The sender's LocIF is our RemIF, and vice versa, 
        // on the following call to MaintBufSendAck.
        //
        VrrTrace(VA,3,"MP:AR=Rcv_",srp->ackreq->opt.Source,srp->ackreq->opt.Source,srp->ackreq->opt.Dest,
               "SeqNo",srp->ackreq->opt.identification,NULL,0);
        MaintBufSendAck(VA, 
                        srp->ackreq->opt.Dest,        // Source for Ack.
                        srp->ackreq->opt.Source,      // Dest for Ack. 
                        srp->ackreq->opt.identification,
                        srp->ackreq->opt.RackSourceIF,
                        srp->ackreq->opt.RackDestIF,
                        VRR_NCE_STATE_LINKED);

        if (IsIEEEGroupAddress(srp->EtherDest)) {
            VrrKdPrint("ReceiveSRPacket: sending ack to bcast pkt - investigate who sent it and why",NULL,NULL);
        }

        ExFreePool(srp->ackreq);
        srp->ackreq = NULL;
    }

    //
    // Process any received Acks immediately,
    // if they are for us.
    //
    PrevAck = &srp->ack;
    while ((Ack = *PrevAck) != NULL) {
        //
        // Is this Ack for us?
        // NB: We do not check Ack->opt.outif == PA->Index!
        // It doesn't matter how the Ack got to us -
        // it might not have been via the reverse route.
        //
        VrrTrace(VA,3,"MP:AK=Rcv_",Ack->opt.from,Ack->opt.from,Ack->opt.to,"SeqNo",Ack->opt.identification,NULL,0);
        if (VirtualAddressEqual(Ack->opt.to, VA->Address)) {
            //
            // Process the Ack.
            //
            MaintBufRecvAck(VA, Ack->opt.from, Ack->opt.RackSourceIF, Ack->opt.RackDestIF,
                            Ack->opt.identification);
            //
            // Remove the Ack from the packet.
            //
            *PrevAck = Ack->next;
            ExFreePool(Ack);
            continue;
        }
        PrevAck = &Ack->next;
    }

    if (srp->PacketLength == srp->PayloadOffset) {
        //
        // There was nothing in the packet beyond the VRR messages.
        // The packet can now be freed.
        //
        InterlockedIncrement((PLONG)&VA->CountRecvEmpty);
        goto FreeSrpAndReturn;
    }
#if BROADCAST_SUPPORTED
    else if (IsIEEEGroupAddress(srp->EtherDest)) {
        //
        // The packet was broadcast. Placing it on our
        // Broadcast list will filter duplicates and
        // set up for relay service if we provide one.
        //
        BroadcastListEntry *BLE;
        uint PacketLength;
        uint PayloadLength = srp->PacketLength - srp->PayloadOffset;
        char *Buffer;

        Buffer = AllocFlatBuffer(srp->Packet,srp->PacketLength);

        UpdateBroadcastList(VA, srp->Origin,  // rx path
                          srp->FrameSeqNo,srp->HopCount,
                          srp->Source,srp->EtherDest, IsBroadcastRelay(VA),
                          Buffer + srp->PayloadOffset,PayloadLength);

        //
        // Receive L2 broadcast packets iff broadcast relay enabled.
        //
        RtlCopyMemory(srp->Dest,srp->EtherDest,sizeof(VirtualAddress));
        if (IsBroadcastRelay(VA) == TRUE)
            MiniportReceiveLocally(VA, srp, MiniportReceiveComplete);
        else
            SRPacketFree(srp);

        ExFreePool(Buffer);

    }
#endif
    else {
        //
        // Perform lookup via FindNextHop() to decide fate of packet. 
        //
        TxToken Token;
        FindNextHopResult Result;
        
        Result = FindNextHop(VA,
                             srp->Dest,
                             VRR_IFID_UNSPECIFIED,
                             VRR_IFID_UNSPECIFIED,
                             &Token,
                             NULL,
                             NULL_SR_FLAGS);
                             
        if (Result == SuccessFwd) {
            //
            // Forwarding path similar to MaintBufSendPacket() direct tx.
            //
            NDIS_PACKET *Packet = NULL;
            NDIS_STATUS Status;

            //
            // In VRR we do not fwd control messages on data packets.
            //
            srp->TransmitComplete = MiniportReceiveComplete;
            
            Status = SRPacketToPkt(VA, srp, &Packet);
            if (Status != NDIS_STATUS_SUCCESS) {
                goto FreeSrpAndReturn;
            }

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

            if (PC(Packet)->PA == NULL) {
                //
                // This means the packet is trying to use a physical adapter that
                // no longer exists.
                //
                VrrKdPrint("ReceiveSRPacket PC(Packet)->PA == NULL",NULL,NULL);
                MaintBufStaticSendComplete(VA, Packet, NDIS_STATUS_FAILURE);
            }
            else {
                ProtocolTransmit(PC(Packet)->PA, Packet);
            }

            //goto FreeSrpAndReturn;
        }
        else if (Result == SuccessRcvSelf) {
            //
            // We are the exact destination: receive the packet locally.
            //
            MiniportReceiveLocally(VA, srp, MiniportReceiveComplete);
        }
        else if (Result == SuccessRcvNearest) {
            //
            // It may be that one of our virtual neighbours is a closer
            // match to the destination but that FNH could not find a
            // valid route to that neighbour. This can happen while we
            // are probing the neighbour e.g. while attempting recovery
            // of the route to that neighbour following a link failure.
            // In such cases we should avoid receiving packets destined
            // to that neighbour as doing so is likely to destabilize
            // the state of DHT apps running on the VRR API.
            //
            // Do not receive data packet if exists closer NTE or PLE to dest than self.
            //
            if (ExistsCloserNTEorPLEthanSelf(VA, srp->Dest, TRUE, TRUE)) {
                VrrKdPrint("RcvSRP: drop payload, FNH(d)=Nearest but closer [NTE|PLE]", NULL, srp->Dest);
                InterlockedIncrement((PLONG)&VA->CountNTECloserThanSelf);
                goto FreeSrpAndReturn;
            }
            else
                MiniportReceiveLocally(VA, srp, MiniportReceiveComplete);
        }
        else {
            //
            // Result==Error, presumably.
            //
            VrrKdPrint("ReceiveSRPacket: drop payload FNH(d)=Err", NULL, srp->Dest);
            goto FreeSrpAndReturn;
        }
    }

    return;

  FreeSrpAndReturn:
    SRPacketFree(srp);
}

//* MiniportReceivePacket
//
//  Receive an NDIS packet from a virtual link.
//
void
MiniportReceivePacket(
    MiniportAdapter *VA,
    ProtocolAdapter *PA,
    NDIS_PACKET *Packet,
    void (*FreePacket)(ProtocolAdapter *PA, NDIS_PACKET *Packet))
{
    SRPacket *srp;
    NDIS_STATUS Status;

    InterlockedIncrement((PLONG)&VA->CountRecv);

    Status = SRPacketFromPkt(VA, Packet, &srp);
    if (Status != NDIS_STATUS_SUCCESS) {
   

⌨️ 快捷键说明

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