⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 网络驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
                    // 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 + -