📄 setupreq.c
字号:
// Preserve the JOIN flag from the SetupReq.
// If this was a join attempt then the proxy node must
// bypass the normal forwarding logic in favour of its
// physical neighbor that sent the SetupReq.
//
if (SetupReq->Flags & VRR_MSG_FLAG_JOIN_ATTEMPT)
Setup->Opt.Flags |= VRR_MSG_FLAG_JOIN_ATTEMPT;
//
// If we are the proxy then we must adjust the message
// for direct transmission (no proxy involved). Note
// that we cannot use the mainline forwarding routines
// because the sender, and hence our NCE for the sender,
// is not yet in state ACTIVE.
//
if (IsProxy) {
//
// Special (rare) case. We are the proxy in a join attempt.
//
NeighborCacheEntry *NCE;
RtlCopyMemory(Setup->Opt.Dest, *source, sizeof(VirtualAddress));
RtlCopyMemory(Setup->Opt.Proxy, VA->Address, sizeof(VirtualAddress));
Setup->Opt.Flags |= VRR_MSG_FLAG_PASTPROXY;
}
//
// Signal LocIF and RemIF in Setup message.
//
Setup->Opt.LocIF = Tok.LocIF;
Setup->Opt.RemIF = Tok.RemIF;
//
// Add sender to our VSet. This will create a new
// NTE if necessary.
//
VSetAddNode(VA,SetupReq->Source,CountVSet,MsgVSet);
//
// Schedule the Setup message for reliable transmission.
//
VrrTrace(VA,3,"SR:SR=Rcv_(SendSetup)",VA->Address,Tok.NextVAddress,*source,NULL,0,"SeqNo",FrameSeqNo);
MsgQueueMessage(VA, Tok.NextVAddress, (InternalOption *) Setup, Setup->Opt.LocIF,Setup->Opt.RemIF,SETUP_DELAY,NULL);
SentSetup = TRUE;
} else {
//
// Reject the sender as a neighbor. Send msg SetupReq(NACK).
// Use the sender's FrameSeqNo to match original SR->FrameSeqNo.
//
SendSRNack(VA, *source, SetupReq->Proxy, FrameSeqNo, SetupReq->Target, SetupReq->Flags);
}
//
// Process the vset from the SetupReq message.
//
ReceiveVSet(VA,CountVSet,MsgVSet);
ReleaseAndReturn:
if (SRcAntiRoute != NULL)
AddressListFree(SRcAntiRoute);
if (Setup != NULL && SentSetup == FALSE)
ExFreePool(Setup);
return;
}
//* CreateSetupReqOpt
//
// Creates an SRP Opt encoding a SetupReq.
//
// Returns NULL if memory allocation failed or if rate
// limit exceeded on SR generation.
//
// Caller must not hold NT->Lock.
//
InternalVrrSetupReq *
CreateSetupReqOpt(
MiniportAdapter *VA,
VirtualAddress Dest,
uchar Type,
VirtualAddress Proxy,
uint FrameSeqNo,
VirtualAddress Target, // used in SR(NACK) to report original SR(Dest).
AddressList *SRcAntiRoute)
{
NDIS_STATUS Status;
uint OptSize;
NodeTable *NT = &VA->NT;
NodeTableEntry *NTE;
KIRQL OldIrql;
uint NTECount = 0;
uint i;
uchar CountSRcAntiRoute = AddressListCount(SRcAntiRoute);
InternalVrrSetupReq *VSR;
Time Now = KeQueryInterruptTime();
VirtualAddress FlatVSet[VRR_MAX_VSET_SIZE];
VRRASSERT(VRR_SR_VALID_TYPE(Type));
if (Type & VRR_SR_TYPE_REQUEST)
InterlockedIncrement((PLONG)&VA->CountSendSetupReq);
if (Type & VRR_SR_TYPE_NACK)
InterlockedIncrement((PLONG)&VA->CountSendSetupReqNack);
//
// Lock the Node Table during our traversals.
//
KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
//
// Obtain memory for VrrSetupReq option. Include as many neighbours
// as a single packet can accommodate.
//
if (CountSRcAntiRoute != 0)
VrrTrace(VA,4,"SR:SR=New_(CountSRcAntiRoute!=0)",VA->Address,Proxy,Dest,"CountSRcAntiRoute",CountSRcAntiRoute,NULL,0);
NTECount = VSetToFlatBuffer(VA,FlatVSet);
OptSize = sizeof *VSR // Internal option linkage.
+ sizeof(VrrSetupReq) // Preamble.
+ (CountSRcAntiRoute * sizeof(VirtualAddress)) // SRcAntiRoute
+ (NTECount * sizeof(VirtualAddress)); // vset.
VSR = ExAllocatePool(NonPagedPool, OptSize);
if (VSR == NULL) {
Status = NDIS_STATUS_RESOURCES;
goto ReleaseAndReturn;
}
VrrTrace(VA,3,"gregos:CreateSetupReqOpt (Target)",NULL,Target,NULL,NULL,0,"*ptr=",(uint)VSR);
//
// Format the VrrSetupReq option.
//
RtlZeroMemory(VSR, OptSize);
VSR->Opt.OptionType = VRR_OPTION_TYPE_SETUPREQ;
VSR->Opt.OptDataLen = VRRSETUPREQ_LEN(NTECount + CountSRcAntiRoute);
VSR->Opt.Type = Type;
RtlCopyMemory(VSR->Opt.Source, VA->NT.Self->Address, sizeof(VirtualAddress));
VSR->Opt.FrameSeqNo = RtlUlongByteSwap(FrameSeqNo);
RtlCopyMemory(VSR->Opt.Target, Target, sizeof(VirtualAddress));
VSR->Opt.CountSRcAntiRoute = CountSRcAntiRoute;
AddressListToArray(SRcAntiRoute, VSR->Opt.addr, CountSRcAntiRoute);
//
// The packet will go to the dest via the proxy.
//
RtlCopyMemory(VSR->Opt.Dest, Proxy, sizeof(VirtualAddress));
RtlCopyMemory(VSR->Opt.Proxy, Dest, sizeof(VirtualAddress));
//
// Append list of VSet addresses.
//
RtlCopyMemory(&VSR->Opt.addr[CountSRcAntiRoute], FlatVSet,
NTECount*sizeof(VirtualAddress));
//
// Finished with Node Table. Release its lock.
//
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
return VSR;
ReleaseAndReturn:
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
return NULL;
}
//* JoinSendSetupReqComplete
//
// Packet completion routine for JoinSendSetupReq.
//
void
JoinSendSetupReqComplete(
MiniportAdapter *VA,
NDIS_PACKET *Packet,
NDIS_STATUS Status)
{
SRPacket *srp = PC(Packet)->srp;
UNREFERENCED_PARAMETER(VA);
UNREFERENCED_PARAMETER(Status);
NdisFreePacketClone(Packet);
SRPacketFree(srp);
}
//* JoinSendSetupReq
//
// Constructs and sends SetupReq in the special case of a
// node that is attempting to join the ring and which
// therefore lacks the routing state required by the main
// forwarding routines. In this case we use this routine and
// rely upon NTE state and timers to cause retransmission.
//
// Returns TRUE iff the packet was successfully transmitted.
//
boolint
JoinSendSetupReq(
MiniportAdapter *VA,
VirtualAddress Dest,
VirtualAddress Proxy,
uint FrameSeqNo,
AddressList *SRcAntiRoute)
{
SRPacket *SRP;
NDIS_PACKET *Packet;
TxToken Tok;
Time Now = KeQueryInterruptTime();
uint RateLimitExceeded = FALSE;
EtherHeader UNALIGNED *Ether;
KIRQL OldIrql;
//
// Bail if join attempts have been disabled.
//
if (IsJoiningOnHold(VA)) {
InterlockedDecrement((PLONG)&VA->CountSendSetupReq);
VrrTrace(VA,2,"SR:SR=Drop(JoiningOnHold=T)",VA->Address,Proxy,Dest,NULL,0,"FrameSeqNo",FrameSeqNo);
return FALSE;
}
//
// Construct and send a SetupReq message.
//
InterlockedIncrement((PLONG)&VA->CountSendSetupReq);
VrrTrace(VA,3,"SR:SR=New_(Join)",VA->Address,Proxy,Dest,NULL,0,"FrameSeqNo",FrameSeqNo);
//
// Initialize an SRPacket to encode the SetupReq.
//
SRP = ExAllocatePool(NonPagedPool, sizeof *SRP);
if (SRP == NULL) {
KdPrint(("JoinSendSR: malloc(SRP) failed\n"));
return FALSE;
}
RtlZeroMemory(SRP, sizeof *SRP);
//
// Initialize the source & destination of the SRPacket.
//
RtlCopyMemory(SRP->Dest, Proxy, sizeof(VirtualAddress));
RtlCopyMemory(SRP->Source, VA->Address, sizeof(VirtualAddress));
RtlCopyMemory(SRP->Origin, VA->Address, sizeof(VirtualAddress));
SRP->FrameSeqNo = InterlockedIncrement(&VrrGlobal.NextFrameSeqNo);
SRP->HopCount = 0;
//
// Check that Proxy is a physical neighbor in state ACTIVE.
//
if (FALSE == GetPhysNeighborTxToken(VA, Proxy, VRR_IFID_UNSPECIFIED,
VRR_IFID_UNSPECIFIED,&SRP->Token, VRR_NCE_STATE_ACTIVE)) {
VrrKdPrint("JoinSendSR: GetPhysNeighborTxToken(proxy=d)==F",NULL,Proxy);
goto FreeSRPAndExit;
}
//
// Allocate a formatted SetupReq message.
//
SRP->VrrSetupReq = CreateSetupReqOpt(VA,
Dest,
VRR_SR_TYPE_REQUEST,
Proxy,
FrameSeqNo,
Dest,
SRcAntiRoute);
if (NULL == SRP->VrrSetupReq) {
KdPrint(("JoinSendSR: CreateSROpt failed\n"));
goto FreeSRPAndExit;
}
//
// Set the Flag bit VRR_MSG_FLAG_JOIN_ATTEMPT.
// The proxy node via which we attempt to join
// the ring needs this in order to bypass the
// normal forwarding logic which expects to
// find an RTE for the destination.
//
SRP->VrrSetupReq->Opt.Flags |= VRR_MSG_FLAG_JOIN_ATTEMPT;
//
// Construct an NDISPacket from the SRPacket.
//
if (SRPacketToPkt(VA, SRP, &Packet) != NDIS_STATUS_SUCCESS) {
KdPrint(("JoinSendSR: SRPacketToPkt failed\n"));
goto FreeSRPAndExit;
}
//
// The SRPacketToPkt() call generated a TxToken from
// RT state and if the destination is multi-homed may
// have chosen a different RemIF to the one in Tok and
// thus set SRP->Token and the packet EthDest incorrectly.
// Therefore we reinstate SRP->Token and overwrite the
// packet EthDest using our original TxToken.
//
//RtlCopyMemory(&SRP->Token,&Tok,sizeof(TxToken));
PC(Packet)->PA = SRP->Token.PA;
Ether = (EtherHeader UNALIGNED *) NdisFirstBuffer(Packet)->MappedSystemVa;
//RtlCopyMemory(Ether->Dest, Tok.NextPAddress, IEEE_802_ADDR_LENGTH);
PC(Packet)->srp = SRP;
UpdatePacketIndex(VA,
SRP->VrrSetupReq->Opt.Source,
RtlUlongByteSwap(SRP->VrrSetupReq->Opt.FrameSeqNo),
SRP->VrrSetupReq->Opt.HopCount++,
SRP->Source,
SRP->Dest,
SRP->Token.LocIF,
(SRP->VrrSetupReq->Opt.Type & VRR_SR_TYPE_REQUEST) ? VRR_OPTION_TYPE_SETUPREQ : VRR_OPTION_TYPE_SR_NACK);
//
// Send the join SetupReq.
//
VrrTrace(VA,3,"SR:SR=Tx__(Join)",VA->Address,Proxy,Dest,NULL,0,"FrameSeqNo",FrameSeqNo);
if (VA->MsFirstJoinSetupReq == 0)
VA->MsFirstJoinSetupReq = TIME_TO_MS(Now);
PC(Packet)->TransmitComplete = JoinSendSetupReqComplete;
ProtocolTransmit(PC(Packet)->PA, Packet);
return TRUE;
FreeSRPAndExit:
SRPacketFree(SRP);
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -