📄 miniport.c
字号:
void
MiniportReceiveComplete(
MiniportAdapter *VA,
SRPacket *srp,
NDIS_STATUS Status)
{
UNREFERENCED_PARAMETER(VA);
UNREFERENCED_PARAMETER(Status);
//
// Free the SRPacket. This frees srp->Packet.
//
if (srp != NULL)
SRPacketFree(srp);
}
//* MiniportForwardRequestComplete
//
// Called after the completion of forwarding of an SRPacket
// with a Route Request option. The SRPacket still needs
// to be received locally.
//
static void
MiniportForwardRequestComplete(
MiniportAdapter *VA,
SRPacket *srp,
NDIS_STATUS Status)
{
UNREFERENCED_PARAMETER(Status);
//
// Receive the packet locally too.
//
MiniportReceiveLocally(VA, srp, MiniportReceiveComplete);
}
//* ReceiveSRPacket
//
// Performs receive processing for an inbound packet,
// after it has been parsed into an SRPacket structure.
//
// Disposes of srp.
//
void
ReceiveSRPacket(
MiniportAdapter *VA,
ProtocolAdapter *PA,
SRPacket *srp)
{
InternalAcknowledgement **PrevAck;
InternalAcknowledgement *Ack;
uchar NCEState = 0;
//
// Consume Hello messages. At most one per packet.
//
if (srp->VrrHello != NULL) {
ReceiveHello(VA, PA, srp);
ExFreePool(srp->VrrHello);
srp->VrrHello = NULL;
}
else if (SRPContainsMessages(srp) || srp->ack != NULL)
VrrTrace(VA,3,"MP:**=Rcv_(SRPacket)",srp->Source,srp->Source,srp->Dest,NULL,0,"FrameSeqNo",srp->FrameSeqNo);
//
// Deal with probes immediately.
//
if (srp->Probe != NULL) {
//
// First verify that we are using the same metric that this probe
// is using.
//
// Then, verify that we're the appropriate destination.
//
if (srp->Probe->Opt.MetricType == VA->MetricType &&
VirtualAddressEqual(srp->Probe->Opt.To, VA->Address) &&
srp->Probe->Opt.InIf == PA->Index &&
VA->MetricType == METRIC_TYPE_WCETT) {
WcettReceiveProbe(VA, srp->Probe, (VRRIf) PA->Index);
}
}
//
// Process a Probe Reply.
//
if (srp->ProbeReply != NULL) {
//
// Verify that we're the appropriate destination and that
// we are using the same metric.
//
if (VirtualAddressEqual(srp->ProbeReply->Opt.To, VA->Address) &&
(srp->ProbeReply->Opt.InIf == PA->Index) &&
(srp->ProbeReply->Opt.MetricType == VA->MetricType)) {
//
// Process the probe reply according to whatever metric
// we are using.
//
switch (VA->MetricType) {
case METRIC_TYPE_WCETT:
WcettReceivePktPairProbeReply(VA, srp->ProbeReply);
break;
}
}
}
//
// Unicast messages received over a link in state is FAILED
// are to be dropped *without* sending an ack, thus helping
// the sender to detect the link failure through retransmisions.
//
// Find the NCE with the EtherSource address and check its state.
//
if (IsIEEEGroupAddress(srp->EtherDest) == FALSE) {
NeighborCacheEntry *NCE;
KIRQL OldIrql;
KeAcquireSpinLock(&VA->NC.Lock, &OldIrql);
for (NCE = VA->NC.FirstNCE; NCE != SentinelNCE(&VA->NC); NCE = NCE->Next)
if (RtlEqualMemory(NCE->PAddress, srp->EtherSource, sizeof(PhysicalAddress)))
break;
if (NCE != NULL)
NCEState=NCE->State;
KeReleaseSpinLock(&VA->NC.Lock, OldIrql);
}
if (NCEState == VRR_NCE_STATE_FAILED) {
#if DBG
if (srp->VrrSetup != NULL)
VrrTrace(VA,3,"MP:SU=Drop(NCE_FAILED)",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
if (srp->VrrSetupReq != NULL)
VrrTrace(VA,3,"MP:SR=Drop(NCE_FAILED)",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
if (srp->VrrTearDown != NULL)
VrrTrace(VA,3,"MP:TD=Drop(NCE_FAILED)",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
if (srp->ackreq != NULL)
VrrTrace(VA,3,"MP:AR=Drop(NCE_FAILED)",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
if (srp->ack != NULL)
VrrTrace(VA,3,"MP:AK=Drop(NCE_FAILED).",srp->Source,srp->Source,NULL,NULL,0,NULL,0);
#endif
goto FreeSrpAndReturn;
}
//
// Consume VrrSetup messages.
// Discussions and whiteboarding cause us to diverge from
// the original simulator code in which we only received
// Setup from nodes that were LINKED. Now we are rejecting
// nodes that are FAILED and advancing LINKED to PENDING
// within ReceiveSetup.
//
// Optimistic Lightweight Transaction Stage 1.
// ref "ignore setup messages ... from nodes that are not linked"
//
if (srp->VrrSetup != NULL) {
InternalVrrSetup *Setup;
InternalVrrSetup *NextSetup;
for (Setup = srp->VrrSetup; Setup != NULL; Setup = NextSetup) {
ReceiveSetup(VA, PA, Setup, srp);
NextSetup = Setup->Next;
ExFreePool(Setup);
}
srp->VrrSetup = NULL;
}
//
// Consume VrrSetupReq messages.
//
if (srp->VrrSetupReq != NULL) {
InternalVrrSetupReq *SetupReq;
InternalVrrSetupReq *NextSetupReq;
for (SetupReq = srp->VrrSetupReq; SetupReq != NULL; SetupReq = NextSetupReq) {
ReceiveSetupReq(VA, PA, SetupReq, srp);
NextSetupReq = SetupReq->Next;
ExFreePool(SetupReq);
}
srp->VrrSetupReq = NULL;
}
//
// Consume TearDown messages.
//
if (srp->VrrTearDown != NULL) {
InternalVrrTearDown *TearDown;
InternalVrrTearDown *NextTearDown;
for (TearDown = srp->VrrTearDown; TearDown != NULL; TearDown = NextTearDown) {
ReceiveTearDown(VA, PA, TearDown);
NextTearDown = TearDown->Next;
ExFreePool(TearDown);
}
srp->VrrTearDown = NULL;
}
//
// Send an Ack immediately, if requested.
//
if (srp->ackreq != NULL) {
uint Index;
//
// We may be receiving the packet because sender thinks
// we're closer to the dest than he is. In other words
// we may have received on an address that is not our
// own. In any case we have received the packet and
// processed or forwarded its messages. Therefore ack
// the packet.
//
// The sender's LocIF is our RemIF, and vice versa,
// on the following call to MaintBufSendAck.
//
VrrTrace(VA,3,"MP:AR=Rcv_",srp->ackreq->opt.Source,srp->ackreq->opt.Source,srp->ackreq->opt.Dest,
"SeqNo",srp->ackreq->opt.identification,NULL,0);
MaintBufSendAck(VA,
srp->ackreq->opt.Dest, // Source for Ack.
srp->ackreq->opt.Source, // Dest for Ack.
srp->ackreq->opt.identification,
srp->ackreq->opt.RackSourceIF,
srp->ackreq->opt.RackDestIF,
VRR_NCE_STATE_LINKED);
if (IsIEEEGroupAddress(srp->EtherDest)) {
VrrKdPrint("ReceiveSRPacket: sending ack to bcast pkt - investigate who sent it and why",NULL,NULL);
}
ExFreePool(srp->ackreq);
srp->ackreq = NULL;
}
//
// Process any received Acks immediately,
// if they are for us.
//
PrevAck = &srp->ack;
while ((Ack = *PrevAck) != NULL) {
//
// Is this Ack for us?
// NB: We do not check Ack->opt.outif == PA->Index!
// It doesn't matter how the Ack got to us -
// it might not have been via the reverse route.
//
VrrTrace(VA,3,"MP:AK=Rcv_",Ack->opt.from,Ack->opt.from,Ack->opt.to,"SeqNo",Ack->opt.identification,NULL,0);
if (VirtualAddressEqual(Ack->opt.to, VA->Address)) {
//
// Process the Ack.
//
MaintBufRecvAck(VA, Ack->opt.from, Ack->opt.RackSourceIF, Ack->opt.RackDestIF,
Ack->opt.identification);
//
// Remove the Ack from the packet.
//
*PrevAck = Ack->next;
ExFreePool(Ack);
continue;
}
PrevAck = &Ack->next;
}
if (srp->PacketLength == srp->PayloadOffset) {
//
// There was nothing in the packet beyond the VRR messages.
// The packet can now be freed.
//
InterlockedIncrement((PLONG)&VA->CountRecvEmpty);
goto FreeSrpAndReturn;
}
#if BROADCAST_SUPPORTED
else if (IsIEEEGroupAddress(srp->EtherDest)) {
//
// The packet was broadcast. Placing it on our
// Broadcast list will filter duplicates and
// set up for relay service if we provide one.
//
BroadcastListEntry *BLE;
uint PacketLength;
uint PayloadLength = srp->PacketLength - srp->PayloadOffset;
char *Buffer;
Buffer = AllocFlatBuffer(srp->Packet,srp->PacketLength);
UpdateBroadcastList(VA, srp->Origin, // rx path
srp->FrameSeqNo,srp->HopCount,
srp->Source,srp->EtherDest, IsBroadcastRelay(VA),
Buffer + srp->PayloadOffset,PayloadLength);
//
// Receive L2 broadcast packets iff broadcast relay enabled.
//
RtlCopyMemory(srp->Dest,srp->EtherDest,sizeof(VirtualAddress));
if (IsBroadcastRelay(VA) == TRUE)
MiniportReceiveLocally(VA, srp, MiniportReceiveComplete);
else
SRPacketFree(srp);
ExFreePool(Buffer);
}
#endif
else {
//
// Perform lookup via FindNextHop() to decide fate of packet.
//
TxToken Token;
FindNextHopResult Result;
Result = FindNextHop(VA,
srp->Dest,
VRR_IFID_UNSPECIFIED,
VRR_IFID_UNSPECIFIED,
&Token,
NULL,
NULL_SR_FLAGS);
if (Result == SuccessFwd) {
//
// Forwarding path similar to MaintBufSendPacket() direct tx.
//
NDIS_PACKET *Packet = NULL;
NDIS_STATUS Status;
//
// In VRR we do not fwd control messages on data packets.
//
srp->TransmitComplete = MiniportReceiveComplete;
Status = SRPacketToPkt(VA, srp, &Packet);
if (Status != NDIS_STATUS_SUCCESS) {
goto FreeSrpAndReturn;
}
PC(Packet)->srp = srp;
PC(Packet)->TransmitComplete = MaintBufStaticSendComplete;
if (PC(Packet)->PA == NULL) {
//
// This means the packet is trying to use a physical adapter that
// no longer exists.
//
VrrKdPrint("ReceiveSRPacket PC(Packet)->PA == NULL",NULL,NULL);
MaintBufStaticSendComplete(VA, Packet, NDIS_STATUS_FAILURE);
}
else {
ProtocolTransmit(PC(Packet)->PA, Packet);
}
//goto FreeSrpAndReturn;
}
else if (Result == SuccessRcvSelf) {
//
// We are the exact destination: receive the packet locally.
//
MiniportReceiveLocally(VA, srp, MiniportReceiveComplete);
}
else if (Result == SuccessRcvNearest) {
//
// It may be that one of our virtual neighbours is a closer
// match to the destination but that FNH could not find a
// valid route to that neighbour. This can happen while we
// are probing the neighbour e.g. while attempting recovery
// of the route to that neighbour following a link failure.
// In such cases we should avoid receiving packets destined
// to that neighbour as doing so is likely to destabilize
// the state of DHT apps running on the VRR API.
//
// Do not receive data packet if exists closer NTE or PLE to dest than self.
//
if (ExistsCloserNTEorPLEthanSelf(VA, srp->Dest, TRUE, TRUE)) {
VrrKdPrint("RcvSRP: drop payload, FNH(d)=Nearest but closer [NTE|PLE]", NULL, srp->Dest);
InterlockedIncrement((PLONG)&VA->CountNTECloserThanSelf);
goto FreeSrpAndReturn;
}
else
MiniportReceiveLocally(VA, srp, MiniportReceiveComplete);
}
else {
//
// Result==Error, presumably.
//
VrrKdPrint("ReceiveSRPacket: drop payload FNH(d)=Err", NULL, srp->Dest);
goto FreeSrpAndReturn;
}
}
return;
FreeSrpAndReturn:
SRPacketFree(srp);
}
//* MiniportReceivePacket
//
// Receive an NDIS packet from a virtual link.
//
void
MiniportReceivePacket(
MiniportAdapter *VA,
ProtocolAdapter *PA,
NDIS_PACKET *Packet,
void (*FreePacket)(ProtocolAdapter *PA, NDIS_PACKET *Packet))
{
SRPacket *srp;
NDIS_STATUS Status;
InterlockedIncrement((PLONG)&VA->CountRecv);
Status = SRPacketFromPkt(VA, Packet, &srp);
if (Status != NDIS_STATUS_SUCCESS) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -