📄 protocol.c
字号:
// to NDIS_STATUS_RESOURCES, we are guaranteed that protocols
// above are done with it. Our ReturnPacket handler will
// not be called for this packet, so call it ourselves.
//
MPReturnPacket((NDIS_HANDLE)pVElan, MyPacket);
//
// Done with this VELAN.
//
if (bContinue == FALSE)
{
break;
}
continue;
}
//
// else...
//
// Failed to allocate a packet to indicate up - fall through.
// We will still indicate up using the non-packet API, but
// other per-packet/OOB information won't be available
// to protocols above.
//
}
else
{
//
// The miniport below us uses the old-style (not packet)
// receive indication. Fall through.
//
}
//
// Fall through to here if the miniport below us has
// either not indicated an NDIS_PACKET or we could not
// allocate one.
//
if (Packet != NULL)
{
//
// We are here because we failed to allocate packet
//
PtFlushReceiveQueue(pVElan);
}
//
// Mark the VELAN so that we will forward up a receive
// complete indication.
//
#if IEEE_VLAN_SUPPORT
//
// Get at the EtherType field.
//
pTpid = (PUSHORT)((PUCHAR)HeaderBuffer + 2 * ETH_LENGTH_OF_ADDRESS);
//
// Check if the EtherType indicates presence of a tag header.
//
if (*pTpid == TPID)
{
pTagHeader = (VLAN_TAG_HEADER UNALIGNED *)LookAheadBuffer;
//
// Drop this frame if it contains Routing information;
// we don't support this.
//
if (GET_CANONICAL_FORMAT_ID_FROM_TAG(pTagHeader) != 0)
{
Status = NDIS_STATUS_INVALID_PACKET;
MUX_DECR_PENDING_RECEIVES(pVElan);
MUX_INCR_STATISTICS(&pVElan->RcvFormatErrors);
continue;
}
//
// If there is a VLAN ID in this frame, and we have
// a configured VLAN ID for this VELAN, check if they
// are the same - drop if not.
//
if ((GET_VLAN_ID_FROM_TAG(pTagHeader) != (unsigned)0) &&
(pVElan->VlanId != (unsigned)0) &&
(ULONG)(GET_VLAN_ID_FROM_TAG(pTagHeader) != pVElan->VlanId))
{
Status = NDIS_STATUS_NOT_ACCEPTED;
MUX_DECR_PENDING_RECEIVES(pVElan);
MUX_INCR_STATISTICS(&pVElan->RcvVlanIdErrors);
continue;
}
//
// Copy information from the tag header to per-packet
// info fields.
//
MuxRcvContext.NdisPacket8021QInfo.Value = NULL;
COPY_TAG_INFO_FROM_HEADER_TO_PACKET_INFO(
MuxRcvContext.NdisPacket8021QInfo,
pTagHeader);
//
// Prepare for indicating up this frame (the tag
// header must be removed). First, copy in the real
// EtherType value from the tag header.
//
*pTpid = *((PUSHORT)((PUCHAR)LookAheadBuffer + sizeof(pTagHeader->TagInfo)));
//
// Account for removing the tag header.
//
LookAheadBuffer = (PVOID)((PUCHAR)LookAheadBuffer + VLAN_TAG_HEADER_SIZE);
LookAheadBufferSize -= VLAN_TAG_HEADER_SIZE;
PacketSize -= VLAN_TAG_HEADER_SIZE;
//
// Use MuxRcvContext to store context for the receive,
// to be used in MpTransferData, if called.
//
MuxRcvContext.TagHeaderLen = VLAN_TAG_HEADER_SIZE;
bContinue = FALSE;
}
else
{
MuxRcvContext.TagHeaderLen = 0;
}
MuxRcvContext.MacRcvContext = MacReceiveContext;
//
// In order not to change the code a lot
//
MacReceiveContext = &MuxRcvContext;
#endif
//
// Here the driver checks if the miniport adapter is in lower power state, do not indicate the
// packets, but the check does not close the window, it only minimizes the window. To close
// the window completely, we need to add synchronization in the receive code path; because
// NDIS can handle the case that miniport drivers indicate packets in lower power state,
// we don't add the synchronization in the hot code path.
//
if ((pVElan->MiniportAdapterHandle == NULL)
|| (pVElan->MPDevicePowerState > NdisDeviceStateD0))
{
MUX_DECR_PENDING_RECEIVES(pVElan);
if (bContinue == FALSE)
{
break;
}
continue;
}
pVElan->IndicateRcvComplete = TRUE;
MUX_INCR_STATISTICS64(&pVElan->GoodReceives);
//
// Indicate receive using the non-packet API.
//
NdisMEthIndicateReceive(pVElan->MiniportAdapterHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
MUX_DECR_PENDING_RECEIVES(pVElan);
if (bContinue == FALSE)
{
break;
}
} // for (each VELAN)
MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
}
while(FALSE);
return Status;
}
VOID
PtReceiveComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
/*++
Routine Description:
Called by the adapter below us when it is done indicating a batch of
received packets. We forward this up on all VELANs that need
this indication.
Arguments:
ProtocolBindingContext Pointer to our adapter structure.
Return Value:
None
--*/
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
PLIST_ENTRY p;
PVELAN pVElan;
LOCK_STATE LockState;
PNDIS_PACKET PacketArray[MAX_RECEIVE_PACKET_ARRAY_SIZE];
ULONG NumberOfPackets = 0;
MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
for (p = pAdapt->VElanList.Flink;
p != &pAdapt->VElanList;
p = p->Flink)
{
pVElan = CONTAINING_RECORD(p, VELAN, Link);
PtFlushReceiveQueue(pVElan);
if (pVElan->IndicateRcvComplete)
{
pVElan->IndicateRcvComplete = FALSE;
NdisMEthIndicateReceiveComplete(pVElan->MiniportAdapterHandle);
}
}
MUX_RELEASE_ADAPT_READ_LOCK(pAdapt, &LockState);
}
INT
PtReceivePacket(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
)
/*++
Routine Description:
ReceivePacket handler. Called by NDIS if the miniport below supports
NDIS 4.0 style receives. Re-package the buffer chain in a new packet
and indicate the new packet to interested protocols above us.
Arguments:
ProtocolBindingContext - Pointer to our adapter structure.
Packet - Pointer to the packet
Return Value:
== 0 -> We are done with the packet
!= 0 -> We will keep the packet and call NdisReturnPackets() this
many times when done.
--*/
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
PVELAN pVElan;
PLIST_ENTRY p;
NDIS_STATUS Status;
NDIS_STATUS PacketStatus;
PNDIS_PACKET MyPacket;
PUCHAR pData;
PNDIS_BUFFER pNdisBuffer;
UINT FirstBufferLength;
UINT TotalLength;
PUCHAR pDstMac;
BOOLEAN bIsMulticast, bIsBroadcast;
PMUX_RECV_RSVD pRecvReserved;
ULONG ReturnCount;
LOCK_STATE LockState;
BOOLEAN bContinue = TRUE;
ReturnCount = 0;
do
{
if (pAdapt->PacketFilter == 0)
{
//
// We could get receives in the interval between
// initiating a request to set the packet filter on
// the binding to 0 and completion of that request.
// Drop such packets.
//
break;
}
#ifdef NDIS51
//
// Collect some information from the packet.
//
NdisGetFirstBufferFromPacketSafe(Packet,
&pNdisBuffer,
&pData,
&FirstBufferLength,
&TotalLength,
NormalPagePriority);
if (pNdisBuffer == NULL)
{
//
// Out of system resources. Drop this packet.
//
break;
}
#else
NdisGetFirstBufferFromPacket(Packet,
&pNdisBuffer,
&pData,
&FirstBufferLength,
&TotalLength);
#endif
pDstMac = pData;
bIsMulticast = ETH_IS_MULTICAST(pDstMac);
bIsBroadcast = ETH_IS_BROADCAST(pDstMac);
//
// Lock down the VELAN list on the adapter so that
// no insertions/deletions to this list happen while
// we loop through it. The packet filter will also not
// change during the time we hold the read lock.
//
MUX_ACQUIRE_ADAPT_READ_LOCK(pAdapt, &LockState);
for (p = pAdapt->VElanList.Flink;
p != &pAdapt->VElanList;
p = p->Flink)
{
BOOLEAN bIndicateReceive;
bContinue = TRUE;
pVElan = CONTAINING_RECORD(p, VELAN, Link);
//
// Should the packet be indicated up on this VELAN?
//
bIndicateReceive = PtMatchPacketToVElan(pVElan,
pDstMac,
bIsMulticast,
bIsBroadcast);
if (!bIndicateReceive)
{
continue;
}
//
// Make sure we don't Halt the VELAN miniport while
// we are accessing it here. See MPHalt.
//
// Also don't indicate receives if the virtual miniport
// has been set to a low power state. A specific case
// is when the system is resuming from "Stand-by", if
// the lower adapter is restored to D0 before the upper
// miniports are.
//
MUX_INCR_PENDING_RECEIVES(pVElan);
if ((pVElan->MiniportHalting) ||
(MUX_IS_LOW_POWER_STATE(pVElan->MPDevicePowerState)))
{
MUX_DECR_PENDING_RECEIVES(pVElan);
continue;
}
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pVElan->RecvPacketPoolHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
PacketStatus = NDIS_GET_PACKET_STATUS(Packet);
pRecvReserved = MUX_RSVD_FROM_RECV_PACKET(MyPacket);
if (PacketStatus != NDIS_STATUS_RESOURCES)
{
pRecvReserved->pOriginalPacket = Packet;
}
else
{
//
// This will ensure we don't call NdisReturnPacket for the packet if the packet
// status is NDIS_STATUS_RESOURCES
//
pRecvReserved->pOriginalPacket = NULL;
}
NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);
//
// Get the original packet (it could be the same
// packet as the one received or a different one
// based on the number of layered miniports below)
// and set it on the indicated packet so the OOB
// data is visible correctly to protocols above us.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
//
// Copy Packet Flags
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
NDIS_SET_PACKET_STATUS(MyPacket, PacketStatus);
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));
#if IEEE_VLAN_SUPPORT
Status = PtHandleRcvTagging(pVElan, Packet, MyPacket, &bContinue);
if (Status != NDIS_STATUS_SUCCESS)
{
NdisFreePacket(MyPacket);
MUX_DECR_PENDING_RECEIVES(pVElan);
if (bContinue)
{
continue;
}
else
{
break;
}
}
#endif
MUX_INCR_STATISTICS64(&pVElan->GoodReceives);
//
// Indicate it up.
//
if (Pa
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -