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

📄 send.c

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


//* VrrBroadcastComplete
//
//  Completes an individual packet transmission for VrrBroadcastComplete.
//
void
VrrBroadcastComplete(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet,
    NDIS_STATUS Status)
{
    SRPacket *srp = PC(Packet)->srp;

    //
    // Free the packet structure.
    //
    NdisFreePacketClone(Packet);

    //
    // Update the current cumulative status.
    // If the current status is NDIS_STATUS_SUCCESS,
    // we replace it with our new status.
    //
    InterlockedCompareExchange((PLONG)&srp->ForwardStatus,
                               Status,
                               NDIS_STATUS_SUCCESS);

    if (InterlockedDecrement((PLONG)&srp->ForwardCount) == 0) {
        //
        // Complete the operation.
        //
        (*srp->TransmitComplete)(VA, srp, srp->ForwardStatus);
    }
}

//* VrrBroadcastHello
//
//  Sends a packet via every physical adapter simultaneously.
//  The operation completes when the last underlying transmit completes.
//  The operation completes successfully only if every
//  underlying transmit is successful.
//
//  Our caller supplies srp->TransmitComplete, which is always called
//  to consume the SRPacket.
//
void
VrrBroadcastHello(
    MiniportAdapter *VA,
    SRPacket *srp)
{
    ProtocolAdapter *PA;
    NDIS_PACKET *PacketList = NULL;
    NDIS_PACKET *Packet;
    NDIS_STATUS Status;
    KIRQL OldIrql;
    uint HeaderLength = SROptionListLength((InternalOption *)srp->VrrHello);

    //
    // We start with one reference (our own) for the SRPacket.
    //
    srp->ForwardCount = 1;
    srp->ForwardStatus = NDIS_STATUS_SUCCESS;

    //
    // First we build a temporary list of packet structures
    // and corresponding physical adapters. While doing this,
    // we also initialize the transmission count.
    // It starts with one, for our own reference for OrigPacket.
    //
    KeAcquireSpinLock(&VA->Lock, &OldIrql);
    for (PA = VA->PhysicalAdapters;
         PA != NULL;
         PA = PA->Next) {

        void *Data;
        EtherHeader *Ether;
        VRRHeader *VRR;
        char* Hello;
        InternalOption *IntOpt;

        //
        // Insert Index for this physical adapter into the VrrHello message.
        //
        if (NULL != srp->VrrHello)
            srp->VrrHello->Opt.SentFromIF = (VRRIf)PA->Index;

        //
        // Unpack SRPacket into NDIS packet for transmission.
        // Do this manually: we hold VA->Lock which prevents
        // us using the normal tx path through FindNextHop.
        //
        Status = MiniportMakeEmptyPacket(VA,
                        sizeof(EtherHeader) + sizeof(VRRHeader) + HeaderLength,
                        &Packet, &Data);

        if (Status != NDIS_STATUS_SUCCESS) {
            KdPrint(("VrrBroadcast: MiniportMakeEmptyPacket() -> %8x\n",Status));
            continue;
        }

        //
        // Initialize ether header.
        //
        Ether = (EtherHeader *) Data;
        RtlFillMemory(Ether->Dest, IEEE_802_ADDR_LENGTH, (uchar)0xff);
        Ether->Type = ETYPE_MSFT;

        //
        // Initialize VRR header.
        //
        VRR = (VRRHeader *) (Ether + 1);
        VRR->Code = VRR_CODE;
        RtlCopyMemory(VRR->IV, srp->IV, VRR_IV_LENGTH);
        VRR->HeaderLength = (ushort) HeaderLength;
        RtlCopyMemory(VRR->Source, VA->Address, sizeof(VirtualAddress));
        RtlCopyMemory(VRR->Dest, srp->Token.Dest, sizeof(VirtualAddress));
        RtlFillMemory(VRR->Dest, sizeof(VirtualAddress), (uchar)0xff);
        RtlCopyMemory(VRR->Origin, VA->Address, sizeof(VirtualAddress));
        VRR->FrameSeqNo = RtlUlongByteSwap(srp->FrameSeqNo);
        VRR->HopCount = 1;
        RtlCopyMemory(VRR->MAC, VA->CryptoKeyMAC, VRR_MAC_LENGTH);

        //
        // Initialize hello message. 
        //
        Hello = (char*)(VRR + 1);
        IntOpt = (InternalOption *)srp->VrrHello;
        RtlCopyMemory(Hello, &srp->VrrHello->Opt, sizeof(VRROption) + IntOpt->Opt.optDataLen);

        //
        // Remember the packet and corresponding physical adapter.
        // We temporarily use the OrigPacket field to build our list.
        //
        PC(Packet)->PA = PA;
        PC(Packet)->OrigPacket = PacketList;
        PacketList = Packet;
        srp->ForwardCount++;
    }
    KeReleaseSpinLock(&VA->Lock, OldIrql);

    //
    // Now we can transmit the packet via each physical adapter,
    // using the new packet structures.
    //
    while ((Packet = PacketList) != NULL) {
        PacketList = PC(Packet)->OrigPacket;
        PA = PC(Packet)->PA;

        //
        // Send the packet via a physical adapter.
        //
        PC(Packet)->srp = srp;
        PC(Packet)->TransmitComplete = VrrBroadcastComplete;
        ProtocolTransmit(PA, Packet);
    }

    //
    // Release our reference for the original packet.
    //
    if (InterlockedDecrement((PLONG)&srp->ForwardCount) == 0) {
        //
        // Complete the operation.
        //
        (*srp->TransmitComplete)(VA, srp, srp->ForwardStatus);
    }
}

//* VrrBroadcastSRPComplete
//
//  Completion handler after sending an srp packet.
//  Cleans up the SRP packet from which NDIS packets were cloned.
//  Used by routines that set up an srp packet as input to VrrBroadcast.
//
void
VrrBroadcastSRPComplete(
    MiniportAdapter *VA,
    SRPacket *srp,
    NDIS_STATUS Status)
{
    UNREFERENCED_PARAMETER(VA);
    UNREFERENCED_PARAMETER(Status);

    SRPacketFree(srp);
}

//* GetPhysNeighborTxToken
//
//  Attempts to construct a TxToken to a physical neighbor.
//
//  Used during join operations to forward a packet before
//  the route state for the destination has been created.
//
//  Caller must not hold NC->Lock.
//
//  Returns TRUE iff a TxToken was constructed.
//
boolint
GetPhysNeighborTxToken(
    MiniportAdapter *VA,
    VirtualAddress Dest,
    VRRIf LocIF,
    VRRIf RemIF,
    TxToken *Tok,
    uchar State)
{
    KIRQL OldIrql;
    NeighborCacheEntry *NCE = NULL;
    ProtocolAdapter *PA;

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

    //
    // Exists an NCE for the Destination?
    //
    NCE = FindNCE(&VA->NC, Dest, LocIF, RemIF, State);

    if (NULL != NCE) {
        PA = FindPhysicalAdapterFromIndex(VA, NCE->LocIF);

        if (NULL == PA) {
            //
            // Cannot transmit without a PA. Abort the transmission.
            //
            NCE = NULL;
            
        } else {
            //
            // Initialize the caller's token.
            //
            RtlZeroMemory(Tok, sizeof(TxToken));
            RtlCopyMemory(Tok->Source, VA->Address, sizeof(VirtualAddress));
            RtlCopyMemory(Tok->Dest, Dest, sizeof(VirtualAddress));
            RtlCopyMemory(Tok->NextVAddress, NCE->VAddress, sizeof(VirtualAddress));
            RtlCopyMemory(Tok->NextPAddress, NCE->PAddress, sizeof(PhysicalAddress));
            Tok->LocIF = NCE->LocIF;
            Tok->RemIF = NCE->RemIF;
            Tok->PA = PA;
        }
    }
    KeReleaseSpinLock(&VA->NC.Lock, OldIrql);

    return (NULL != NCE) ? TRUE : FALSE;
}

//* SendTransmitComplete
//
//  Simple completion routine for packets made with MiniportMakeEmptyPacket.
//  Only use when there are no packet clones or SRPackets to be freed.
//
void
SendTransmitComplete(
    MiniportAdapter *VA,
    NDIS_PACKET *Packet,
    NDIS_STATUS Status)
{
    UNREFERENCED_PARAMETER(VA);
    UNREFERENCED_PARAMETER(Status);

    NdisFreePacketClone(Packet);
}

⌨️ 快捷键说明

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