📄 sr.c
字号:
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 + -