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

📄 sr.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 3 页
字号:
                                     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 per-hop Source and final Dest addresses.
    //
    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->Probe, VRR_OPTION_TYPE_PROBE);
    InsertOptions(&Walk, SRP->ProbeReply, VRR_OPTION_TYPE_PROBEREPLY);

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

    *pPacket = Packet;
    return NDIS_STATUS_SUCCESS;
}


//* FillSRPacket
//
//  Parse VRRHeader options into SRPacket representation.
//
static SRPacket *
FillSRPacket(SRPacket *SRP, VRRHeader *VRR)
{
    VRROption *Walk = (VRROption *)(VRR + 1);
    uint Left = VRR->HeaderLength;
    void **Field;
    SIZE_T Extra;
    void *Entry;
    uint KeepOpt; // gregos: tmp skip inbound SR opts pending final code tidy.

    while (Left != 0) {
        KeepOpt = FALSE;
        //
        // The PAD1 option is the only one that doesn't conform
        // to the generic VRROption format.
        //
        if (Walk->optionType == VRR_OPTION_TYPE_PAD1) {
            Left -= 1;
            (uchar *)Walk += 1;
            continue;
        }

        //
        // Verify that we have enough data to match what the option
        // itself claims is present.
        //
        if ((Left < sizeof *Walk) ||
            (Left < sizeof *Walk + Walk->optDataLen)) {
            KdPrint(("VRR!FillSRPacket: malformed option (type %u)\n",
                     Walk->optionType));
            goto Fail;
        }

        switch (Walk->optionType) {

        case VRR_OPTION_TYPE_PADN:
            goto SkipForward;


        case VRR_OPTION_TYPE_ACKREQ:
            //
            // There should only be one AcknowledgementRequest option.
            //
            if (SRP->ackreq != NULL) {
                KdPrint(("VRR!FillSRPacket: multiple Ack Requests\n"));
                goto Fail;
            }

            Field = &SRP->ackreq;
            Extra = ACK_REQUEST_LEN;
            KeepOpt = TRUE;
            break;

        case VRR_OPTION_TYPE_ACK:
            Field = &SRP->ack;
            Extra = ACKNOWLEDGEMENT_LEN;
            KeepOpt = TRUE;
            break;

        case VRR_OPTION_TYPE_PROBE:
            //
            // There should only be one Probe option.
            //
            if (SRP->Probe != NULL) {
                KdPrint(("VRR!FillSRPacket: multiple Probes\n"));
                goto Fail;
            }
            Field = &SRP->Probe;

            //
            // The value of Extra depends on metric type. 
            // But first, make sure that we have enough
            // data left to read ProbeType correctly. 
            //
            if (Walk->optDataLen < PROBE_LEN) {
                KdPrint(("VRR!FillSRPacket: not enough data in probe packet.\n"));
            }

            // 
            // Just using Wcett PktPair these days (ETX now built into Hello).
            // 
            if (((Probe *)Walk)->ProbeType == METRIC_TYPE_PKTPAIR) {
                Extra = PROBE_LEN;
            }
            else {
                KdPrint(("MCL!FillSRPacket: unknown metric in Probe\n"));
                goto Fail;
            }
            KeepOpt = TRUE;
            break;

        case VRR_OPTION_TYPE_PROBEREPLY:
            //
            // There should only be one ProbeReply option.
            //
            if (SRP->ProbeReply != NULL) {
                KdPrint(("VRR!FillSRPacket: multiple ProbeReplys\n"));
                goto Fail;
            }

            Field = &SRP->ProbeReply;

            //
            // The value of Extra depends on metric type. 
            // But first, make sure that we have enough
            // data left to read ProbeType correctly. 
            //
            if (Walk->optDataLen < PROBE_REPLY_LEN) {
                KdPrint(("VRR!FillSRPacket: not enough data in probe packet.\n"));
            }

            if ((((Probe *)Walk)->ProbeType == METRIC_TYPE_PKTPAIR) &&
                     (Walk->optDataLen == PROBE_REPLY_LEN + sizeof (PRPktPair))) {
                Extra = PROBE_REPLY_LEN + sizeof (PRPktPair);
            }
            else {
                KdPrint(("VRR!FillSRPacket: unknown metric in ProbeReply\n"));
                goto Fail;
            }
            KeepOpt = TRUE;
            break;

        case VRR_OPTION_TYPE_HELLO:
            //
            // NCEList may be null.
            //
            if (Walk->optDataLen < VRR_HELLO_LEN) {
                VrrKdPrint("FillSRPkt: Hello buff too small",NULL,NULL);
                goto Fail;
            }
            Field = &SRP->VrrHello;
            Extra = VRRHELLO_LEN(VRRHELLO_NUM_NCE(Walk->optDataLen));
            KeepOpt = TRUE;
            break;

        case VRR_OPTION_TYPE_SETUP:
            //
            // vset may be null.
            //
            if (Walk->optDataLen < VRR_SETUP_LEN) {
                VrrKdPrint("FillSRPkt: Setup buff too small",NULL,NULL);
                goto Fail;
            }

            Field = &SRP->VrrSetup;
            Extra = VRRSETUP_LEN(VRRSETUP_NUM_VSET(Walk->optDataLen));
            KeepOpt = TRUE;
            break;

        case VRR_OPTION_TYPE_TEARDOWN:
            //
            // GlobalPathId[] and vset[] may be null.
            //
            if (Walk->optDataLen < VRR_TEARDOWN_LEN) {
                VrrKdPrint("FillSRPkt: TD buff too small",NULL,NULL);
                goto Fail;
            }
            else {
                uint NumPid = RtlUlongByteSwap(((VrrTearDown *)Walk)->NumGlobalPathId);
                Field = &SRP->VrrTearDown;
                Extra = VRRTEARDOWN_LEN(NumPid,VRRTEARDOWN_NUM_VSET(NumPid,Walk->optDataLen));
            }
            KeepOpt = TRUE;
            break;

        case VRR_OPTION_TYPE_SETUPREQ:
            //
            // vset may be null.
            //
            if (Walk->optDataLen < VRR_SR_LEN) {
                VrrKdPrint("FillSRPkt: SR buff too small",NULL,NULL);
                goto Fail;
            }
            Field = &SRP->VrrSetupReq;
            Extra = VRRSETUPREQ_LEN(VRRSETUPREQ_NUM_ADDR(Walk->optDataLen));
            KeepOpt = TRUE;
            break;

        default:
            //
            // REVIEW - Handle unknown options in some better way?
            //
            KdPrint(("VRR!FillSRPacket: unknown option %u\n",
                     Walk->optionType));
            goto Fail;
        }

        //
        // Verify that we don't have too much option data to fit
        // into our SRPacket representation.
        //
        if (Walk->optDataLen > Extra) {
            KdPrint(("VRR!FillSRPacket: option too big (type %u, len %u)\n",
                     Walk->optionType, Walk->optDataLen));
            goto Fail;
        }

        if (KeepOpt) {  // gregos: tmp disable inbound LQSR SR opts
            //
            // Allocate a new list entry for this field.
            //
            Entry = (InternalOption *)
                 ExAllocatePool(NonPagedPool, sizeof(InternalOption) + Extra);
            if (Entry == NULL) {
                goto Fail;
            }

            //
            // Initialize the new list entry with the option data.
            //
            ((InternalOption *)Entry)->Next = *Field;
            *Field = Entry;
            RtlCopyMemory(&((InternalOption *)Entry)->Opt, Walk,
                          sizeof(VRROption) + Walk->optDataLen);
        } // KeepOpt
        
      SkipForward:
        //
        // Move on to the next option (if any).
        //
        Left -= sizeof(VRROption) + Walk->optDataLen;
        (uchar *)Walk += sizeof(VRROption) + Walk->optDataLen;
    }

    return SRP;

 Fail:
    SRPacketFree(SRP);
    return NULL;
}

//* SROptionListLength
//
//  Helper function for SROptionLength.
//  Calculates the length (in on-wire packet terms) of a list of VRR options.
//
uint
SROptionListLength(InternalOption *List)
{
    InternalOption *Opt;
    uint Length = 0;

    for (Opt = List; Opt != NULL; Opt = Opt->Next)
        Length += sizeof(VRROption) + Opt->Opt.optDataLen;

    return Length;
}

//* SROptionLength
//
//  Calculate the length (in on-wire packet terms) of VRR options as
//  represented in a SRPacket.
//
static uint
SROptionLength(const SRPacket *SRP)
{
    uint Length = 0;

    Length += SROptionListLength((InternalOption *)SRP->ackreq);
    Length += SROptionListLength((InternalOption *)SRP->ack);
    Length += SROptionListLength((InternalOption *)SRP->Probe);
    Length += SROptionListLength((InternalOption *)SRP->ProbeReply);
    Length += SROptionListLength((InternalOption *)SRP->VrrHello);
    Length += SROptionListLength((InternalOption *)SRP->VrrSetup);
    Length += SROptionListLength((InternalOption *)SRP->VrrTearDown);
    Length += SROptionListLength((InternalOption *)SRP->VrrSetupReq);

    return Length;
}

//* SRPContainsMessages
//
//  Returns TRUE if SRP contains messages other than acks.
//
boolint
SRPContainsMessages(const SRPacket *srp)
{

    if (srp->VrrSetup ||
        srp->VrrTearDown || 
        srp->VrrSetupReq ||
        srp->ackreq)
        return TRUE;

    return FALSE;
}

//* IsFixedDestSRP
//
//  This routine returns false if a given SRP contains one or more
//  VRR message types that must not get rerouted on the tx path.
//  Note that SetupReq are not covered here because SetupReq that
//  are generated by the ProbeList need to take advantage of the
//  mainline forwarding code for IF selection, TxToken generation
//  and EthDest initialization.
//
boolint
IsFixedDestSRP(const SRPacket *srp)
{
    if (srp->ack)
        return TRUE;

    return SRPContainsMessages(srp);
}


⌨️ 快捷键说明

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