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

📄 sr.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 3 页
字号:
            break;

        case VRR_OPTION_TYPE_SETUP:
            //
            // VrrSetup options must be large enough to hold Setup preamble.
            //
            if (Walk->optDataLen < VRRSETUP_LEN(0)) {
                KdPrint(("VRR!CheckPacket: Setup length < sizeof(VrrSetup preamble)\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            //
            // VrrSetup vset length must be a multiple of VirtualAddress.
            //
            if (Walk->optDataLen > VRRSETUP_LEN(0)) {
                uint VABuff = Walk->optDataLen - (sizeof(VrrSetup) - sizeof(VRROption));
                if (0 != VABuff % sizeof(VirtualAddress)) {
                    KdPrint(("VRR!CheckPacket: VrrSetup trailer not multiple of VirtualAddress\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
            }
            
            break;

        case VRR_OPTION_TYPE_TEARDOWN:
            //
            // VrrTearDown options must be large enough to hold TearDown preamble.
            //
            if (Walk->optDataLen < VRRTEARDOWN_LEN(0,0)) {
                KdPrint(("VRR!CheckPacket: VrrTearDown length < sizeof(TearDown preamble)\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            //
            // VrrTearDown options must be large enough to hold the specified Global PathId list.
            //
            if (Walk->optDataLen < VRRTEARDOWN_LEN(((VrrTearDown *)Walk)->NumGlobalPathId, 0)) {
                KdPrint(("VRR!CheckPacket: VrrTearDown length < sizeof(GlobalPIF[NumPId])\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            
            //
            // TearDown vset length must be a multiple of VirtualAddress.
            //
            if (Walk->optDataLen > (((VrrTearDown *)Walk)->NumGlobalPathId, 0)) {
                uint VABuff = Walk->optDataLen 
                              - (sizeof(VrrTearDown) 
                              - sizeof(VRROption) 
                              - VRRTEARDOWN_LEN(((VrrTearDown *)Walk)->NumGlobalPathId, 0));
                if (0 != VABuff % sizeof(VirtualAddress)) {
                    KdPrint(("VRR!CheckPacket: VrrSetup trailer not multiple of VirtualAddress\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
            }

            break;

        case VRR_OPTION_TYPE_SETUPREQ:
            //
            // SetupReq options must be large enough to hold SetupReq preamble.
            //
            if (Walk->optDataLen < VRRSETUPREQ_LEN(0)) {
                KdPrint(("VRR!CheckPacket: SetupReq length < sizeof(SetupReq preamble)\n"));
                return NDIS_STATUS_INVALID_PACKET;
            }
            //
            // VrrSetupReq vset length must be a multiple of VirtualAddress.
            //
            if (Walk->optDataLen > VRRSETUPREQ_LEN(0)) {
                uint VABuff = Walk->optDataLen - (sizeof(VrrSetupReq) - sizeof(VRROption));
                if (0 != VABuff % sizeof(VirtualAddress)) {
                    KdPrint(("VRR!CheckPacket: VrrSetupReq trailer not multiple of VirtualAddress\n"));
                    return NDIS_STATUS_INVALID_PACKET;
                }
            }
            
            break;

        default:
            KdPrint(("VRR!CheckPacket: bad option type\n"));
            return NDIS_STATUS_INVALID_PACKET;
        }

        //
        // Move on to the next option (if any).
        //
        Left -= sizeof(VRROption) + Walk->optDataLen;
        (uchar *)Walk += sizeof(VRROption) + Walk->optDataLen;
    }

    return NDIS_STATUS_SUCCESS;
}

//* InsertOptions
//
//  Helper function for SRPacketToPkt.
//
static void
InsertOptions(VRROption **Walk, void *Field, uchar Type)
{
    InternalOption *IntOpt;
    SIZE_T Amount;

    UNREFERENCED_PARAMETER(Type);  // Only used in checked builds.

    for (IntOpt = Field; IntOpt != NULL; IntOpt = IntOpt->Next) {

        VRRASSERT(IntOpt->Opt.optionType == Type);

        Amount = sizeof(VRROption) + IntOpt->Opt.optDataLen;
        RtlCopyMemory(*Walk, &IntOpt->Opt, Amount);
        *Walk = (VRROption *)(((char *)*Walk) + Amount);
    }
}

//* SRPacketToPkt
//
//  Converts the SRPacket to an NDIS packet that can be transmitted.
//  The NDIS packet should be deallocated with NdisFreePacketClone.
//
//  If the packet will be transmitted via a single physical adapter,
//  then PC(Packet)->PA is initialized.
//
NDIS_STATUS
SRPacketToPkt(
    MiniportAdapter *VA,
    const SRPacket *SRP,
    NDIS_PACKET **pPacket)
{
    uint HeaderLength = SROptionLength(SRP);
    NDIS_PACKET *Packet;
#if DBG
    uint PacketLength;
#endif
    void *CloneHeader;
    EtherHeader *CloneEther;
    VRRHeader *CloneVRR;
    VRROption *Walk;
    NDIS_STATUS Status;
    const uchar *Dest;
    VRRIf OutIf;
    VRRIf InIf;
    VRRIf LocIF;
    VRRIf RemIF;
    ProtocolAdapter *PA;
    uint FoundNextHop;
    FindNextHopResult Result;

    if (IsFixedDestSRP(SRP)) {

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

    }
    else {
        //
        // Use routing state to initialize for tx.
        // First, confirm we are forwarding the packet.
        // Find the next hop to Dest from the Route Table and
        // update the SRPacket TxToken.
        //
        Result = FindNextHop(VA,
                             (uchar *)SRP->Dest,
                             VRR_IFID_UNSPECIFIED,
                             VRR_IFID_UNSPECIFIED,
                             (TxToken *)&SRP->Token,
                             NULL,
                             NULL_SR_FLAGS);

        if (Result == Error) {
            VrrKdPrint("SRPacketToPkt: FNH(d)=Error - cannot forward SRPacket", NULL, (char *)SRP->Dest);
            return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;
        }
        else if (Result == SuccessRcvNearest) {
            //
            // Do not form NDIS packet for SRP if exists closer node to dest than self.
            //
            if (ExistsCloserNTEorPLEthanSelf(VA, SRP->Dest, FALSE, FALSE)) {
                VrrKdPrint("SRPacketToPkt: drop: FNH(d)=Nearest but closer [NTE|PLE] exists", NULL, (char *)SRP->Dest);
                InterlockedIncrement((PLONG)&VA->CountNTECloserThanSelf);
                return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;
            }
        }
    }

    //
    // Obtain an NDIS packet (clone).
    //
    if (SRP->Packet == NULL) {
        VRRASSERT(SRP->PayloadOffset == 0);

        Status = MiniportMakeEmptyPacket(VA,
                        sizeof(EtherHeader) + sizeof(VRRHeader) + HeaderLength,
                        &Packet, &CloneHeader);
    }
    else {
        void *OrigHeader;

        Status = MiniportClonePacket(VA, SRP->Packet,
                                     SRP->PayloadOffset,
                                     (sizeof(EtherHeader) +
                                      sizeof(VRRHeader) +
                                      HeaderLength),
                                     0, // No lookahead needed.
                                     &OrigHeader, &Packet, &CloneHeader);
    }
    if (Status != NDIS_STATUS_SUCCESS)
        return Status;

    PC(Packet)->PA = SRP->Token.PA;

#if DBG
    //
    // Check that we are not exceeding the physical link MTU.
    // The basic VRR header fits in PROTOCOL_MIN_FRAME_SIZE (1500) -
    // MINIPORT_MAX_FRAME_SIZE (1280) bytes, and
    // the piggy-backing code will avoid adding too many options.
    //
    NdisQueryPacketLength(Packet, &PacketLength);
    VRRASSERT(PacketLength <= sizeof(EtherHeader) + PROTOCOL_MIN_FRAME_SIZE);
#endif

    CloneEther = (EtherHeader *) CloneHeader;
    CloneVRR = (VRRHeader *) (CloneEther + 1);
    Walk = (VRROption *) (CloneVRR + 1);

    CloneEther->Type = ETYPE_MSFT;
    CloneVRR->Code = VRR_CODE;

    // CloneVRR->MAC computed below.
    RtlCopyMemory(CloneVRR->IV, SRP->IV, VRR_IV_LENGTH);
    CloneVRR->HeaderLength = (ushort) HeaderLength;

    //
    // Fill in VRR header.
    //
    RtlCopyMemory(CloneVRR->Source, VA->Address, sizeof(VirtualAddress));
    RtlCopyMemory(CloneVRR->Dest, SRP->Token.Dest, sizeof(VirtualAddress));
    RtlCopyMemory(CloneVRR->Origin, SRP->Origin, sizeof(VirtualAddress));
    CloneVRR->FrameSeqNo = RtlUlongByteSwap(SRP->FrameSeqNo);
    CloneVRR->HopCount = SRP->HopCount + 1;
 
    if (SRP->VrrHello == NULL) {
        //
        // Common case. Transmit packet to physical address of
        // node with nearest virtual address to the desination
        // virtual address.
        //
        RtlCopyMemory(CloneEther->Dest, SRP->Token.NextPAddress, sizeof(PhysicalAddress));
        RtlCopyMemory((SRPacket *)SRP->EtherDest, SRP->Token.NextPAddress, sizeof(PhysicalAddress));
    }
    else {
        //
        // In a few special cases we use link local broadcast.
        //
        RtlFillMemory(CloneEther->Dest, IEEE_802_ADDR_LENGTH, (uchar)0xff);
        RtlFillMemory(CloneVRR->Dest, sizeof(VirtualAddress), (uchar)0xff);
        
    }

    //
    // Reassembly order doesn't matter.
    //
    InsertOptions(&Walk, SRP->ackreq, VRR_OPTION_TYPE_ACKREQ);
    InsertOptions(&Walk, SRP->ack, VRR_OPTION_TYPE_ACK);
    InsertOptions(&Walk, SRP->Probe, VRR_OPTION_TYPE_PROBE);
    InsertOptions(&Walk, SRP->ProbeReply, VRR_OPTION_TYPE_PROBEREPLY);
    InsertOptions(&Walk, SRP->VrrHello, VRR_OPTION_TYPE_HELLO);
    InsertOptions(&Walk, SRP->VrrSetup, VRR_OPTION_TYPE_SETUP);
    InsertOptions(&Walk, SRP->VrrTearDown, VRR_OPTION_TYPE_TEARDOWN);
    InsertOptions(&Walk, SRP->VrrSetupReq, VRR_OPTION_TYPE_SETUPREQ);

    //
    // Compute the MAC.
    //
    SRPacketMAC(VA, CloneVRR->MAC, Packet);


    *pPacket = Packet;
    return NDIS_STATUS_SUCCESS;
}

//* SRPacketToProbe
//
//  Similar to SRPacketToPkt adapted to support probe packets which
//  are often sent to nodes whose NCE state is rejected by the
//  mainline forwarding code in FindNextHop(). Since the target of
//  a probe is often not an active member of the ring, or even in a
//  position to join the ring, we will only send it messages of type
//  PROBE or PROBEREPLY.
//
//  gregos: better to get SRPacketToProbe effect with extra arg to SRPacketToPkt?
//
//  Converts the SRPacket to an NDIS packet that can be transmitted.
//  The NDIS packet should be deallocated with NdisFreePacketClone.
//
//  If the packet will be transmitted via a single physical adapter,
//  then PC(Packet)->PA is initialized.
//
//  The caller must hold NC->Lock.
//
NDIS_STATUS
SRPacketToProbe(
    MiniportAdapter *VA,
    SRPacket *SRP,
    NDIS_PACKET **pPacket)
{
    uint HeaderLength = SROptionLength(SRP);
    NDIS_PACKET *Packet;
#if DBG
    uint PacketLength;
#endif
    void *CloneHeader;
    EtherHeader *CloneEther;
    VRRHeader *CloneVRR;
    VRROption *Walk;
    NDIS_STATUS Status;
    const uchar *Dest;
    VRRIf OutIf;
    VRRIf InIf;
    VRRIf LocIF;
    VRRIf RemIF;
    ProtocolAdapter *PA;
    uint FoundNextHop;
    NeighborCache *NC = &VA->NC;
    NeighborCacheEntry *NCE;

    //
    // Probes are constructed using NCE state rather than route state.
    // Why is because we often want to probe nodes whose NCE is not LINKED.
    //
    VRRASSERT(SRP->Probe != NULL || SRP->ProbeReply != NULL);
    VRRASSERT(SRP->Probe == NULL || SRP->ProbeReply == NULL);
    if (SRP->Probe != NULL) {
        LocIF = SRP->Probe->Opt.OutIf;
        RemIF = SRP->Probe->Opt.InIf;
    }else {
        LocIF = SRP->ProbeReply->Opt.OutIf;
        RemIF = SRP->ProbeReply->Opt.InIf;
    }
    NCE = FindNCE(NC,
                  SRP->Dest,
                  LocIF,
                  RemIF,
                  VRR_NCE_STATE_VALID);

    if (NCE == NULL) {
        VrrKdPrint("SRPacketToProbe: FindNCE(d)==NULL, okay if rare",NULL,SRP->Dest);
        return NDIS_STATUS_NO_ROUTE_TO_DESTINATION;
    }

    VRRASSERT(VirtualAddressEqual(SRP->Dest,NCE->VAddress));
    
    //
    // Init the SRP->TxToken from state in NCE. 
    //
    RtlZeroMemory(&SRP->Token, sizeof(TxToken));
    SRP->Token.PA=FindPhysicalAdapterFromIndex(VA, NCE->LocIF);
    RtlCopyMemory(SRP->Token.Source, VA->Address, sizeof(VirtualAddress));
    RtlCopyMemory(SRP->Token.Dest, NCE->VAddress, sizeof(VirtualAddress));
    RtlCopyMemory(SRP->Token.NextVAddress, NCE->VAddress, sizeof(VirtualAddress));
    RtlCopyMemory(SRP->Token.NextPAddress, NCE->PAddress, sizeof(PhysicalAddress));
    SRP->Token.LocIF = NCE->LocIF;
    SRP->Token.RemIF = NCE->RemIF;
    
    //
    // Obtain an NDIS packet (clone).
    //
    if (SRP->Packet == NULL) {
        VRRASSERT(SRP->PayloadOffset == 0);

        Status = MiniportMakeEmptyPacket(VA,
                        sizeof(EtherHeader) + sizeof(VRRHeader) + HeaderLength,
                        &Packet, &CloneHeader);
    }
    else {
        void *OrigHeader;

        Status = MiniportClonePacket(VA, SRP->Packet,
                                     SRP->PayloadOffset,
                                     (sizeof(EtherHeader) +
                                      sizeof(VRRHeader) +
                                      HeaderLength),

⌨️ 快捷键说明

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