📄 protocol.c
字号:
None
--*/
{
PVELAN pVElan;
PNDIS_PACKET pOriginalPacket;
PMUX_TD_RSVD pTDReserved;
UNREFERENCED_PARAMETER(ProtocolBindingContext);
pTDReserved = MUX_RSVD_FROM_TD_PACKET(Packet);
pOriginalPacket = pTDReserved->pOriginalPacket;
pVElan = pTDReserved->pVElan;
//
// Complete the original TransferData request.
//
NdisMTransferDataComplete(pVElan->MiniportAdapterHandle,
pOriginalPacket,
Status,
BytesTransferred);
//
// Free our packet.
//
NdisFreePacket(Packet);
}
BOOLEAN
PtMulticastMatch(
IN PVELAN pVElan,
IN PUCHAR pDstMac
)
/*++
Routine Description:
Check if the given multicast destination MAC address matches
any of the multicast address entries set on the VELAN.
NOTE: the caller is assumed to hold a READ/WRITE lock
to the parent ADAPT structure. This is so that the multicast
list on the VELAN is invariant for the duration of this call.
Arguments:
pVElan - VELAN to look in
pDstMac - Destination MAC address to compare
Return Value:
TRUE iff the address matches an entry in the VELAN
--*/
{
ULONG i;
UINT AddrCompareResult;
for (i = 0; i < pVElan->McastAddrCount; i++)
{
ETH_COMPARE_NETWORK_ADDRESSES_EQ(pVElan->McastAddrs[i],
pDstMac,
&AddrCompareResult);
if (AddrCompareResult == 0)
{
break;
}
}
return (i != pVElan->McastAddrCount);
}
BOOLEAN
PtMatchPacketToVElan(
IN PVELAN pVElan,
IN PUCHAR pDstMac,
IN BOOLEAN bIsMulticast,
IN BOOLEAN bIsBroadcast
)
/*++
Routine Description:
Check if the destination address of a received packet
matches the receive criteria on the specified VELAN.
NOTE: the caller is assumed to hold a READ/WRITE lock
to the parent ADAPT structure.
Arguments:
pVElan - VELAN to check on
pDstMac - Destination MAC address in received packet
bIsMulticast - is this a multicast address
bIsBroadcast - is this a broadcast address
Return Value:
TRUE iff this packet should be received on the VELAN
--*/
{
UINT AddrCompareResult;
ULONG PacketFilter;
BOOLEAN bPacketMatch;
PacketFilter = pVElan->PacketFilter;
//
// Handle the directed packet case first.
//
if (!bIsMulticast)
{
//
// If the VELAN is not in promisc. mode, check if
// the destination MAC address matches the local
// address.
//
if ((PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) == 0)
{
ETH_COMPARE_NETWORK_ADDRESSES_EQ(pVElan->CurrentAddress,
pDstMac,
&AddrCompareResult);
bPacketMatch = ((AddrCompareResult == 0) &&
((PacketFilter & NDIS_PACKET_TYPE_DIRECTED) != 0));
}
else
{
bPacketMatch = TRUE;
}
}
else
{
//
// Multicast or broadcast packet.
//
//
// Indicate if the filter is set to promisc mode ...
//
if ((PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
||
//
// or if this is a broadcast packet and the filter
// is set to receive all broadcast packets...
//
(bIsBroadcast &&
(PacketFilter & NDIS_PACKET_TYPE_BROADCAST))
||
//
// or if this is a multicast packet, and the filter is
// either set to receive all multicast packets, or
// set to receive specific multicast packets. In the
// latter case, indicate receive only if the destn
// MAC address is present in the list of multicast
// addresses set on the VELAN.
//
(!bIsBroadcast &&
((PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) ||
((PacketFilter & NDIS_PACKET_TYPE_MULTICAST) &&
PtMulticastMatch(pVElan, pDstMac))))
)
{
bPacketMatch = TRUE;
}
else
{
//
// No protocols above are interested in this
// multicast/broadcast packet.
//
bPacketMatch = FALSE;
}
}
return (bPacketMatch);
}
NDIS_STATUS
PtReceive(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookAheadBufferSize,
IN UINT PacketSize
)
/*++
Routine Description:
Handle receive data indicated up by the miniport below.
We forward this up to all VELANs that are eligible to
receive this packet:
- If this is directed to a broadcast/multicast address,
indicate up on all VELANs that have multicast or broadcast
or promisc. bits set in their packet filters.
- If this is a directed packet, indicate it up on all VELANs
that have the a matching MAC address or have the promisc.
bit set in their packet filters.
We acquire a read lock on the ADAPT structure to ensure
that the VELAN list on the adapter is undisturbed.
If the miniport below indicates packets, NDIS would more
likely call us at our ReceivePacket handler. However we
might be called here in certain situations even though
the miniport below has indicated a receive packet, e.g.
if the miniport had set packet status to NDIS_STATUS_RESOURCES.
Arguments:
<see DDK ref page for ProtocolReceive>
Return Value:
NDIS_STATUS_SUCCESS if we processed the receive successfully,
NDIS_STATUS_XXX error code if we discarded it.
--*/
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PLIST_ENTRY p;
PVELAN pVElan;
PNDIS_PACKET MyPacket, Packet;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PUCHAR pData;
PUCHAR pDstMac;
BOOLEAN bIsMulticast, bIsBroadcast;
PMUX_RECV_RSVD pRecvReserved;
LOCK_STATE LockState;
BOOLEAN bContinue = TRUE;
#if IEEE_VLAN_SUPPORT
VLAN_TAG_HEADER UNALIGNED * pTagHeader;
USHORT UNALIGNED * pTpid;
MUX_RCV_CONTEXT MuxRcvContext;
#endif
do
{
if (HeaderBufferSize != ETH_HEADER_SIZE)
{
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
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.
//
Status = NDIS_STATUS_NOT_ACCEPTED;
break;
}
//
// Collect some information from the packet.
//
pData = (PUCHAR)HeaderBuffer;
pDstMac = pData;
bIsMulticast = ETH_IS_MULTICAST(pDstMac);
bIsBroadcast = ETH_IS_BROADCAST(pDstMac);
//
// Get at the packet, if any, indicated up by the miniport below.
//
Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
//
// 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;
}
if (Packet != NULL)
{
//
// The miniport below did indicate up a packet. Use information
// from that packet to construct a new packet to indicate up.
//
//
// Get a packet off our receive pool and indicate that up.
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pVElan->RecvPacketPoolHandle);
if (Status == NDIS_STATUS_SUCCESS)
{
//
// Make our packet point to data from the original
// packet. NOTE: this works only because we are
// indicating a receive directly from the context of
// our receive indication. If we need to queue this
// packet and indicate it from another thread context,
// we will also have to allocate a new buffer and copy
// over the packet contents, OOB data and per-packet
// information. This is because the packet data
// is available only for the duration of this
// receive indication call.
//
NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(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
//
// 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
// at protocols above.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket,
NDIS_GET_ORIGINAL_PACKET(Packet));
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
//
// Copy packet flags.
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
//
// Force protocols above to make a copy if they want to hang
// on to data in this packet. This is because we are in our
// Receive handler (not ReceivePacket), and the original
// packet can't be accessed after we return from here.
//
NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
//
// Set our context information in the packet. Since
// the original packet from the miniport below is not being
// queued up, set this to NULL:
//
pRecvReserved = MUX_RSVD_FROM_RECV_PACKET(MyPacket);
pRecvReserved->pOriginalPacket = NULL;
MUX_INCR_STATISTICS64(&pVElan->GoodReceives);
//
// By setting NDIS_STATUS_RESOURCES, we also know that
// we can reclaim this packet as soon as the call to
// NdisMIndicateReceivePacket returns.
//
//
// NOTE: we queue the packet and indicate this packet immediately with
// the already queued packets together. We have to the queue the packet
// first because some versions of NDIS might call protocols'
// ReceiveHandler(not ReceivePacketHandler) if the packet indicate status
// is NDIS_STATUS_RESOURCES. If the miniport below indicates an array of
// packets, some of them with status NDIS_STATUS_SUCCESS, some of them
// with status NDIS_STATUS_RESOURCES, PtReceive might be called, by
// doing this way, we preserve the receive order of packets.
//
PtQueueReceivedPacket(pVElan, MyPacket, TRUE);
//
// Reclaim the indicated packet. Since we had set its status
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -