Example #1
0
VOID NicCompletePacket(IN PMP_ADAPTER Adapter, IN PNDIS_PACKET_OR_NBL pNBSPacket)
{
    NET_BUFFER_LIST_STATUS(pNBSPacket) = NDIS_STATUS_SUCCESS;
    NdisMSendNetBufferListsComplete(Adapter->AdapterHandle,
                    pNBSPacket,
                    0);
    InterlockedIncrement64(&Adapter->ullGoodTransmits);
}
Example #2
0
/*
SdrLLSendPacketComplete cleans resouces occupied by SdrLLSendPacket.

History:
    3/Nov/2009: Created by senxiang

Note:
    Different SdrLLSendPacket implementation needs different complete handler.
*/
VOID
SdrLLSendPacketComplete(
    PSDR_CONTEXT SDRContext,
    PDLCB pDLCB)
{
    PSEND_QUEUE_MANAGER pSendQueueManager = GET_SEND_QUEUE_MANAGER((PMAC)SDRContext->Mac);

    if (DLCB_CONTAIN_VALID_PACKET(pDLCB))
    {
        CleanWLanPacket(
            pDLCB->pDot11HeaderVa,
            pDLCB->Dot11HeaderSize,
            pDLCB->PacketBase.pMdl); //cleanup resources in EthToWlan.
    }
    pDLCB->pDot11HeaderVa = NULL;
    pDLCB->PacketBase.pMdl = NULL;

    if(pDLCB->pNdisPktOrNBL)
    {
        //One NB fail the whole NBL fail
        if(pDLCB->bSendOK == FALSE)
        {
            NET_BUFFER_LIST_STATUS((PNET_BUFFER_LIST)(pDLCB->pNdisPktOrNBL)) = NDIS_STATUS_FAILURE;
        }

        //If it's the last NB
        if(pDLCB->bLastNB)
        {
            if(NET_BUFFER_LIST_STATUS((PNET_BUFFER_LIST)(pDLCB->pNdisPktOrNBL)) == NDIS_STATUS_SUCCESS)
            {
                NicCompletePacket((PMP_ADAPTER)SDRContext->Nic, (PNET_BUFFER_LIST)(pDLCB->pNdisPktOrNBL));
            }
            else
            {
                NicDropPacket((PMP_ADAPTER)SDRContext->Nic, (PNET_BUFFER_LIST)(pDLCB->pNdisPktOrNBL));
            }
        }

        //clear
        pDLCB->pNdisPktOrNBL = NULL;
    }

    SoraPacketCleanup (&pDLCB->PacketBase);
    SafeEnqueue(pSendQueueManager, SendFreeList, pDLCB);
    InterlockedIncrement(&pSendQueueManager->nFreeTCB);
}
Example #3
0
VOID NicDropPacket(IN PMP_ADAPTER Adapter, IN PNDIS_PACKET_OR_NBL pNBSPacket)
{
    NET_BUFFER_LIST_STATUS(pNBSPacket) = NDIS_STATUS_FAILURE;
    NdisMSendNetBufferListsComplete(Adapter->AdapterHandle,
                    pNBSPacket,
                    0);
    InterlockedIncrement64(&Adapter->ullTransmitFail);
}
Example #4
0
VOID
MPSendNetBufferLists(
    NDIS_HANDLE             MiniportAdapterContext,
    PNET_BUFFER_LIST        NetBufferLists,
    NDIS_PORT_NUMBER        PortNumber,
    ULONG                   SendFlags
    )
{
    PADAPTER                    adapter = (PADAPTER)MiniportAdapterContext;
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PMP_PORT                    destinationPort = NULL;
    PNET_BUFFER_LIST            currentNetBufferList;

    //
    // We increment the port list refcount. This would avoid a pause from finishing
    // while we are processing this NBL and that ensures that the port list does not
    // change
    //    
    MP_INCREMENT_PORTLIST_REFCOUNT(adapter);


    do
    {
        //
        // If the adapter is paused, surprise removed, etc, fail the send
        //
        if (MP_TEST_ADAPTER_STATUS(adapter, MP_ADAPTER_CANNOT_SEND_MASK))
        {
            ndisStatus = MpGetAdapterStatus(adapter);
            MpTrace(COMP_SEND, DBG_NORMAL, ("Sends failed as adapter is not in a valid send state\n"));
            break;
        }

        //
        // First we would need to translate from the NDIS_PORT_NUMBER
        // to our port structure. This is done by walking the PortList
        //
        destinationPort = Port11TranslatePortNumberToPort(
                            adapter, 
                            PortNumber
                            );
        if (destinationPort == NULL)
        {
            MpTrace(COMP_SEND, DBG_SERIOUS, ("Unable to find Port corresponding to PortNumber %d\n", 
                PortNumber));

            ndisStatus = NDIS_STATUS_INVALID_PORT;
        }
        else
        {
            //
            // Pass it to the appropriate port for processing
            //
            Port11HandleSendNetBufferLists(
                destinationPort,
                NetBufferLists,
                SendFlags
                );
        }

    } while (FALSE);

    //
    // We were protecting the port list only until we hand it to the port. After this point, the port
    // is responsible for ensuring that it does not let the port get deleted while
    // it has packets pending on it
    //
    MP_DECREMENT_PORTLIST_REFCOUNT(adapter);

    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        #if DBG
        ULONG ulNumFailedNBLs = 0;
        #endif
        
        //
        // Send failed. Complete the NBLs back to NDIS
        //
        for(currentNetBufferList = NetBufferLists;
            currentNetBufferList != NULL;
            currentNetBufferList = NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList))
        {
            #if DBG
            ulNumFailedNBLs++;
            #endif
            NET_BUFFER_LIST_STATUS(currentNetBufferList) = ndisStatus;
        }
        
        #if DBG
            MpTrace(COMP_SEND, DBG_NORMAL, ("NdisMSendNetBufferListsComplete called with %d NBLs\n", ulNumFailedNBLs));
        #endif

        if (NetBufferLists != NULL)
        {
            NdisMSendNetBufferListsComplete(
                adapter->MiniportAdapterHandle, 
                NetBufferLists, 
                (NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags) ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0)
                );
        }
    }

}
Example #5
0
VOID
NdisprotSendComplete(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN PNET_BUFFER_LIST             pNetBufferList,
    IN ULONG                        SendCompleteFlags
    )
/*++

Routine Description:

    NDIS entry point called to signify completion of a packet send.
    We pick up and complete the Write IRP corresponding to this packet.

Arguments:

    ProtocolBindingContext - pointer to open context
    pNetBufferList - NetBufferList that completed send
    SendCompleteFlags - Specifies if the caller is at DISPATCH level

Return Value:

    None

--*/
{
    PNDISPROT_OPEN_CONTEXT      pOpenContext;
    PNET_BUFFER_LIST            CurrNetBufferList = NULL;
    PNET_BUFFER_LIST            NextNetBufferList;
    NDIS_STATUS                 CompletionStatus;
    BOOLEAN                     DispatchLevel;
    WDFREQUEST                  request;
    PREQUEST_CONTEXT            reqContext;


    pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
    NPROT_STRUCT_ASSERT(pOpenContext, oc);
    DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendCompleteFlags);


    for (CurrNetBufferList = pNetBufferList;
            CurrNetBufferList != NULL;
            CurrNetBufferList = NextNetBufferList)
    {
        NextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrNetBufferList);

        request = NPROT_REQUEST_FROM_SEND_NBL(CurrNetBufferList);
        reqContext = GetRequestContext(request);
        CompletionStatus = NET_BUFFER_LIST_STATUS(CurrNetBufferList);

        DEBUGP(DL_INFO, ("SendComplete: NetBufferList %p/IRP %p/Length %d "
                        "completed with status %x\n",
                        CurrNetBufferList, request, reqContext->Length,
                        CompletionStatus));

		//
        //  We are done with the NDIS_PACKET:
        //
        NPROT_DEREF_SEND_NBL(CurrNetBufferList, DispatchLevel);
        CurrNetBufferList = NULL;

        if (CompletionStatus == NDIS_STATUS_SUCCESS)
        {
            WdfRequestCompleteWithInformation(request, STATUS_SUCCESS, reqContext->Length);
         }
        else
        {
            WdfRequestCompleteWithInformation(request, STATUS_UNSUCCESSFUL, 0);
        }

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, DispatchLevel);
        pOpenContext->PendedSendCount--;

        if ((NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_CLOSING))
                && (pOpenContext->PendedSendCount == 0))
        {
            NPROT_ASSERT(pOpenContext->ClosingEvent != NULL);
            NPROT_SIGNAL_EVENT(pOpenContext->ClosingEvent);
            pOpenContext->ClosingEvent = NULL;
        }
        NPROT_RELEASE_LOCK(&pOpenContext->Lock, DispatchLevel);

        NPROT_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP
    }

}
Example #6
0
VOID
BasePortCompleteFailedPackets(
    __in  PMP_PORT                Port,
    __in  PMP_TX_MSDU             PacketList,
    __in  ULONG                   SendCompleteFlags
    )
{
    PMP_TX_MSDU                 currentPacket = PacketList;
    PNET_BUFFER_LIST            currentNetBufferList, prevNetBufferList = NULL;
    PNET_BUFFER_LIST            netBufferListsToComplete = NULL;
    #if DBG
    ULONG ulNumNBLs = 0, ulInternalSends = 0;
    #endif
        

    while (currentPacket != NULL)
    {        
        //
        // No refcount is added yet, so we dont need to remove anything
        //

        if (MP_TX_MSDU_WRAPPED_NBL(currentPacket) == NULL)
        {
            #if DBG
            ulInternalSends++;
            #endif
            // Internal packet submitted from BasePortSendInternalPacket, free the memory
            // we allocated for the buffer
            MP_FREE_MEMORY(MP_TX_MSDU_MPDU_AT(currentPacket, 0)->InternalSendBuffer);
        }
        else
        {
            #if DBG
            ulNumNBLs++;
            #endif
            //
            // There were from the OS. We need to convert back to NBLs and 
            // complete them to the OS
            //

            //
            // Get the NBLs out
            //
            currentNetBufferList = currentPacket->NetBufferList;
            NET_BUFFER_LIST_NEXT_NBL(currentNetBufferList) = NULL;
            NET_BUFFER_LIST_STATUS(currentNetBufferList) = currentPacket->Status;

            if (netBufferListsToComplete == NULL)
            {
                netBufferListsToComplete = currentNetBufferList;
            }
            else
            {
                NET_BUFFER_LIST_NEXT_NBL(prevNetBufferList) = currentNetBufferList;
            }
            
            prevNetBufferList = currentNetBufferList;
        }

        currentPacket = MP_TX_MSDU_NEXT_MSDU(currentPacket);
    }

    //
    // Free our packet wrapper structures for all the packets
    //
    BasePortFreeTranslatedTxPackets(Port, PacketList);

    #if DBG
        MpTrace(COMP_SEND, DBG_NORMAL, ("Port(%d): NdisMSendNetBufferListsComplete called with %d NBLs\n", Port->PortNumber, ulNumNBLs));
        MpTrace(COMP_SEND, DBG_NORMAL, ("Port(%d): Completed %d internal sends\n", Port->PortNumber, ulInternalSends));
    #endif        

    if (netBufferListsToComplete != NULL)
    {
        // Complete the NBLs back to NDIS
        NdisMSendNetBufferListsComplete(
            Port->MiniportAdapterHandle,
            netBufferListsToComplete,
            SendCompleteFlags
            );
    }
}
Example #7
0
VOID
FilterSendNetBufferLists(
        IN  NDIS_HANDLE         FilterModuleContext,
        IN  PNET_BUFFER_LIST    NetBufferLists,
        IN  NDIS_PORT_NUMBER    PortNumber,
        IN  ULONG               SendFlags
        )
/*++
 
Routine Description:

    Send Net Buffer List handler
    This function is an optional function for filter drivers. If provided, NDIS
    will call this function to transmit a linked list of NetBuffers, described by a 
    NetBuferList, over the network. If this handler is NULL, NDIS will skip calling
    this fitler when sending a NetBufferList and will call the next lower fitler 
    in the stack with a non_NULL FilterSendNetBufferList handleror the miniport driver.
    A filter that doesn't provide a FilerSendNetBufferList handler can not initiate a 
    send o its own.

Arguments:

    FilterModuleContext: Pointer to our filter context area.
    NetBufferLists: Pointer to a List of NetBufferLists.
    PortNumber - Port Number to which this send is targetted
    SendFlags-  Specifies if the call is at DISPATCH_LEVEL                     
  

Return Value:
 
    NDIS_STATUS_SUCCESS: 
    NDIS_STATUS_PENDING:
    NDIS_STATUS_INVALID_PACKET:
    NDIS_STATUS_RESOURCES:
    NDIS_STATUS_FAILURE:


NOTE: The filter will act like a passthru filter.       
 
--*/
{
    PMS_FILTER          pFilter = (PMS_FILTER)FilterModuleContext;
    NDIS_STATUS         Status = NDIS_STATUS_SUCCESS;
    PNET_BUFFER_LIST    CurrNbl;
    BOOLEAN             DispatchLevel;

	// ++
	PNET_BUFFER_LIST	CurrentBufferList	= NULL;
	PNET_BUFFER			CurrentBuffer		= NULL;
	PNET_BUFFER_DATA	CurrentBufferData	= NULL;
	PMDL				PacketMdl			= NULL;
	ULONG				DataOffset			= 0;
	ULONG				PacketSize			= 0;
	PUCHAR				PacketData			= NULL;
	ARP_PACKET*			ArpPacket			= NULL;
	BOOLEAN				bWanAdapter			= FALSE;
    // --

    
    DEBUGP(DL_TRACE, ("===>SendNetBufferList: NBL = %p.\n", NetBufferLists));

    do
    {

       DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);
#if DBG
        //
        // we should never get packets to send if we are not in running state
        //
        
        FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
        //
        // If the filter is not in running state, fail the send
        // 
        if (pFilter->State != FilterRunning)
        {
            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
            
            CurrNbl = NetBufferLists;
            while (CurrNbl)
            {
                NET_BUFFER_LIST_STATUS(CurrNbl) = NDIS_STATUS_PAUSED;
                CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
            }
            NdisFSendNetBufferListsComplete(pFilter->FilterHandle, 
                        NetBufferLists, 
                        DispatchLevel ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
            break;
            
        }
        FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
#endif

		//  ++
		CurrentBufferList = NetBufferLists;

		while(CurrentBufferList)
		{
			// Each NET_BUFFER structure packages a packet of network data
			CurrentBuffer = NET_BUFFER_LIST_FIRST_NB(CurrentBufferList);
			while(CurrentBuffer)
			{
				// 检测其中是否有ARP协议包
				PacketMdl		= NET_BUFFER_FIRST_MDL(CurrentBuffer);
				DataOffset		= NET_BUFFER_DATA_OFFSET(CurrentBuffer);
				PacketSize	= NET_BUFFER_DATA_LENGTH(CurrentBuffer);
				
				if(PacketMdl && PacketSize)
				{
					PacketData = (UCHAR*)MmGetSystemAddressForMdlSafe(PacketMdl,NormalPagePriority);
					if(PacketData)
					{
						if(DataOffset)
						{
							PacketData = PacketData + DataOffset;
						}
						// PacketData 是网络包数据,PacketSize 是网络包数据长度

						KdPrint((" PacketData : %p , PacketSize : %d ",PacketData,PacketSize));

						ArpPacket = (ARP_PACKET*)PacketData;

						// 记录网关回应查询次数
						NdisAcquireSpinLock(&GlobalLock);
						if( ArpPacket->EthType == ETHERNET_ARP)
						{
							if( g_bRecord_ARP_Reply						&&
								ArpPacket->OperateCode == ARP_QUERY		&&
								NdisEqualMemory(ArpPacket->DestIPAddress,g_Want_ARP_Reply_IP,4)	)
							{
								g_Reply_Record->ulQueryCount ++;
								//开始记录网关查询操作
								BeginCheckGateway();
							}
						}
						NdisReleaseSpinLock(&GlobalLock);

					}
				}
				CurrentBuffer = NET_BUFFER_NEXT_NB(CurrentBuffer);
			}
			CurrentBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrentBufferList);
		}
		// --


        if (pFilter->TrackSends)
        {
            FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
            CurrNbl = NetBufferLists;
            while (CurrNbl)
            {
                pFilter->OutstandingSends++;
                FILTER_LOG_SEND_REF(1, pFilter, CurrNbl, pFilter->OutstandingSends);
                
                CurrNbl = NET_BUFFER_LIST_NEXT_NBL(CurrNbl);
            }
            FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
        }
        //
        // If necessary, queue the NetBufferList in a local structure for later processing
        //
        NdisFSendNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, SendFlags);
        
        
    }
    while (FALSE);
    
    DEBUGP(DL_TRACE, ("<===SendNetBufferList: Status = %8x.\n", Status));
}
Example #8
0
VOID
MPSendNetBufferLists(
    _In_  NDIS_HANDLE             MiniportAdapterContext,
    _In_  PNET_BUFFER_LIST        NetBufferLists,
    _In_  NDIS_PORT_NUMBER        PortNumber,
    _In_  ULONG                   SendFlags)
/*++

Routine Description:

    Send Packet Array handler. Called by NDIS whenever a protocol
    bound to our miniport sends one or more packets.

    The input packet descriptor pointers have been ordered according
    to the order in which the packets should be sent over the network
    by the protocol driver that set up the packet array. The NDIS
    library preserves the protocol-determined ordering when it submits
    each packet array to MiniportSendPackets

    As a deserialized driver, we are responsible for holding incoming send
    packets in our internal queue until they can be transmitted over the
    network and for preserving the protocol-determined ordering of packet
    descriptors incoming to its MiniportSendPackets function.
    A deserialized miniport driver must complete each incoming send packet
    with NdisMSendComplete, and it cannot call NdisMSendResourcesAvailable.

    Runs at IRQL <= DISPATCH_LEVEL

Arguments:

    MiniportAdapterContext      Pointer to our adapter
    NetBufferLists              Head of a list of NBLs to send
    PortNumber                  A miniport adapter port.  Default is 0.
    SendFlags                   Additional flags for the send operation

Return Value:

    None.  Write status directly into each NBL with the NET_BUFFER_LIST_STATUS
    macro.

--*/
{
    PMP_ADAPTER       Adapter = MP_ADAPTER_FROM_CONTEXT(MiniportAdapterContext);
    PNET_BUFFER_LIST  Nbl;
    PNET_BUFFER_LIST  NextNbl = NULL;
    BOOLEAN           fAtDispatch = (SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL) ? TRUE:FALSE;
    NDIS_STATUS       Status;
    ULONG             NumNbls=0;

    DEBUGP(MP_TRACE, "[%p] ---> MPSendNetBufferLists\n", Adapter);

    UNREFERENCED_PARAMETER(PortNumber);
    UNREFERENCED_PARAMETER(SendFlags);
    ASSERT(PortNumber == 0); // Only the default port is supported


    //
    // Each NET_BUFFER_LIST has a list of NET_BUFFERs.
    // Loop over all the NET_BUFFER_LISTs, sending each NET_BUFFER.
    //
    for (
        Nbl = NetBufferLists;
        Nbl!= NULL;
        Nbl = NextNbl, ++NumNbls)
    {
        PNET_BUFFER NetBuffer;

        NextNbl = NET_BUFFER_LIST_NEXT_NBL(Nbl);

        //
        // Unlink the NBL and prepare our bookkeeping.
        //
        // We use a reference count to make sure that we don't send complete
        // the NBL until we're done reading each NB on the NBL.
        //
        NET_BUFFER_LIST_NEXT_NBL(Nbl) = NULL;
        SEND_REF_FROM_NBL(Nbl) = 0;

        Status = TXNblReference(Adapter, Nbl);

        if(Status == NDIS_STATUS_SUCCESS)
        {
            NET_BUFFER_LIST_STATUS(Nbl) = NDIS_STATUS_SUCCESS;

            //
            // Queue each NB for transmission.
            //
            for (
                NetBuffer = NET_BUFFER_LIST_FIRST_NB(Nbl);
                NetBuffer != NULL;
                NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer))
            {
                NBL_FROM_SEND_NB(NetBuffer) = Nbl;
                TXQueueNetBufferForSend(Adapter, NetBuffer);
            }

            TXNblRelease(Adapter, Nbl, fAtDispatch);
        }
        else
        {
            //
            // We can't send this NBL now.  Indicate failure.
            //
            if (MP_TEST_FLAG(Adapter, fMP_RESET_IN_PROGRESS))
            {
                NET_BUFFER_LIST_STATUS(Nbl) = NDIS_STATUS_RESET_IN_PROGRESS;
            }
            else if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_PAUSE_IN_PROGRESS|fMP_ADAPTER_PAUSED))
            {
                NET_BUFFER_LIST_STATUS(Nbl) = NDIS_STATUS_PAUSED;
            }
            else if (MP_TEST_FLAG(Adapter, fMP_ADAPTER_LOW_POWER))
            {
                NET_BUFFER_LIST_STATUS(Nbl) = NDIS_STATUS_LOW_POWER_STATE;
            }
            else
            {
                NET_BUFFER_LIST_STATUS(Nbl) = Status;
            }

            NdisMSendNetBufferListsComplete(
                    Adapter->AdapterHandle,
                    Nbl,
                    fAtDispatch ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL:0);

            continue;
        }
    }

    DEBUGP(MP_TRACE, "[%p] %i NBLs processed.\n", Adapter, NumNbls);

    //
    // Now actually go send each of the queued NBs.
    //
    TXTransmitQueuedSends(Adapter, fAtDispatch);

    DEBUGP(MP_TRACE, "[%p] <--- MPSendNetBufferLists\n", Adapter);
}
Example #9
0
VOID
TXFlushSendQueue(
    _In_  PMP_ADAPTER  Adapter,
    _In_  NDIS_STATUS  CompleteStatus)
/*++

Routine Description:

    This routine is called by the Halt or Reset handler to fail all
    the queued up Send NBLs because the device is either gone, being
    stopped for resource rebalance, or reset.

Arguments:

    Adapter                     Pointer to our adapter
    CompleteStatus              The status code with which to complete each NBL

Return Value:

    None.

--*/
{
    PTCB Tcb;

    DEBUGP(MP_TRACE, "[%p] ---> TXFlushSendQueue Status = 0x%08x\n", Adapter, CompleteStatus);


    //
    // First, free anything queued in the driver.
    //

    while (TRUE)
    {
        PLIST_ENTRY pEntry;
        PNET_BUFFER NetBuffer;
        PNET_BUFFER_LIST NetBufferList;

        pEntry = NdisInterlockedRemoveHeadList(
                &Adapter->SendWaitList,
                &Adapter->SendWaitListLock);

        if (!pEntry)
        {
            // End of list -- nothing left to free.
            break;
        }

        NetBuffer = NB_FROM_SEND_WAIT_LIST(pEntry);
        NetBufferList = NBL_FROM_SEND_NB(NetBuffer);

        DEBUGP(MP_TRACE, "[%p] Dropping Send NB: 0x%p.\n", Adapter, NetBuffer);

        NET_BUFFER_LIST_STATUS(NetBufferList) = CompleteStatus;
        TXNblRelease(Adapter, NetBufferList, FALSE);
    }


    //
    // Next, cancel anything queued in the hardware.
    //

    while (NULL != (Tcb = TXGetNextTcbToSend(Adapter)))
    {
        NET_BUFFER_LIST_STATUS(NBL_FROM_SEND_NB(Tcb->NetBuffer)) = CompleteStatus;
        ReturnTCB(Adapter, Tcb);
    }


    DEBUGP(MP_TRACE, "[%p] <--- TXFlushSendQueue\n", Adapter);
}
Example #10
0
VOID
TXSendComplete(
    _In_ PMP_ADAPTER Adapter)
/*++

Routine Description:

    This routine completes pending sends for the given adapter.

    Each busy TCB is popped from the BusyTcbList and its corresponding NB is
    released.  If there was an error sending the frame, the NB's NBL's status
    is updated.

--*/
{
    BOOLEAN fRescheduleThisDpcAgain = TRUE;
    ULONG NumFramesSent = 0;

    DEBUGP(MP_TRACE, "[%p] ---> TXSendComplete.\n", Adapter);

    for (NumFramesSent = 0; NumFramesSent < NIC_MAX_SENDS_PER_DPC; NumFramesSent++)
    {
        ULONG BytesSent;

        PTCB Tcb = TXGetNextTcbToSend(Adapter);
        if (!Tcb)
        {
            //
            // There are no more TCBs remaining to send.  We're all done.
            //
            fRescheduleThisDpcAgain = FALSE;
            break;
        }


        //
        // Finish the transmit operation.  For our hardware, that means the
        // frame is pushed onto the RecvWaitLists of each other adapter.
        //

        BytesSent = HWGetBytesSent(Adapter, Tcb);

        if (BytesSent == 0)
        {
            //
            // Failed to send the frame.
            //

            Adapter->TransmitFailuresOther++;
            NET_BUFFER_LIST_STATUS(NBL_FROM_SEND_NB(Tcb->NetBuffer)) = NDIS_STATUS_RESOURCES;
        }
        else
        {
            //
            // We've finished sending this NB successfully; update the stats.
            //
            switch (Tcb->FrameType)
            {
                case NDIS_PACKET_TYPE_BROADCAST:
                    Adapter->FramesTxBroadcast++;
                    Adapter->BytesTxBroadcast += BytesSent;
                    break;

                case NDIS_PACKET_TYPE_MULTICAST:
                    Adapter->FramesTxMulticast++;
                    Adapter->BytesTxMulticast += BytesSent;
                    break;

                case NDIS_PACKET_TYPE_DIRECTED:
                default:
                    Adapter->FramesTxDirected++;
                    Adapter->BytesTxDirected += BytesSent;
            }
        }


        //
        // Now that we've finished using the TCB and its associated NET_BUFFER,
        // we can release the NET_BUFFER back to the protocol and the TCB back
        // to the free list.
        //
        ReturnTCB(Adapter, Tcb);
    }

    TXTransmitQueuedSends(Adapter, TRUE);

    if (fRescheduleThisDpcAgain)
    {
        TXScheduleTheSendComplete(Adapter);
    }

    DEBUGP(MP_TRACE, "[%p] <--- TXSendComplete.\n", Adapter);
}
Example #11
0
VOID
TXQueueNetBufferForSend(
    _In_  PMP_ADAPTER       Adapter,
    _In_  PNET_BUFFER       NetBuffer)
/*++

Routine Description:

    This routine inserts the NET_BUFFER into the SendWaitList, then calls
    TXTransmitQueuedSends to start sending data from the list.

    We use this indirect queue to send data because the miniport should try to
    send frames in the order in which the protocol gave them.  If we just sent
    the NET_BUFFER immediately, then it would be out-of-order with any data on
    the SendWaitList.


    Runs at IRQL <= DISPATCH_LEVEL

Arguments:

    Adapter                     Adapter that is transmitting this NB
    NetBuffer                   NB to be transfered

Return Value:

    None.

--*/
{
    NDIS_STATUS       Status;
    UCHAR             DestAddress[NIC_MACADDR_SIZE];

    DEBUGP(MP_TRACE, "[%p] ---> TXQueueNetBufferForSend, NB= 0x%p\n", Adapter, NetBuffer);

    do
    {
        //
        // First, do a sanity check on the frame data.
        //
        Status = HWGetDestinationAddress(NetBuffer, DestAddress);
        if (Status != NDIS_STATUS_SUCCESS)
        {
            NET_BUFFER_LIST_STATUS(NBL_FROM_SEND_NB(NetBuffer)) = NDIS_STATUS_INVALID_DATA;
            break;
        }

        //
        // Stash away the frame type.  We'll use that later, when updating
        // our send statistics (since we don't have NIC hardware to compute the
        // send statistics for us).
        //
        FRAME_TYPE_FROM_SEND_NB(NetBuffer) = NICGetFrameTypeFromDestination(DestAddress);

        //
        // Pin the original NBL with a reference, so it isn't completed until
        // we're done with its NB.
        //
        Status = TXNblReference(Adapter, NBL_FROM_SEND_NB(NetBuffer));
        if(Status == NDIS_STATUS_SUCCESS)
        {
            //
            // Insert the NB into the queue.  The caller will flush the queue when
            // it's done adding items to the queue.
            //
            NdisInterlockedInsertTailList(
                    &Adapter->SendWaitList,
                    SEND_WAIT_LIST_FROM_NB(NetBuffer),
                    &Adapter->SendWaitListLock);
        }

    } while (FALSE);


    DEBUGP(MP_TRACE, "[%p] <--- TXQueueNetBufferForSend\n", Adapter);
}
Example #12
0
VOID
RXReceiveIndicate(
    _In_ PMP_ADAPTER Adapter,
    _In_ PMP_ADAPTER_RECEIVE_DPC AdapterDpc,
    BOOLEAN AtDpc)
/*++

Routine Description:

    This function performs the receive indications for the specified RECEIVE_DPC structure.

    Runs at IRQL <= DISPATCH_LEVEL.

Arguments:

    Adapter             Pointer to our adapter
    AdapterDpc          PMP_ADAPTER_RECEIVE_DPC structure for this receive
    AtDpc               TRUE if the function was called from the context of the DPC, FALSE if called from work item (to avoid watchdog)

Return Value:

    None.

--*/

{

    ULONG NumNblsReceived = 0;
    PNET_BUFFER_LIST FirstNbl = NULL, LastNbl = NULL;
    USHORT CurrentQueue;

    DEBUGP(MP_TRACE, "[%p] ---> RXReceiveIndicate. Processor: %i, AtDpc: %i\n", Adapter, AdapterDpc->ProcessorNumber, AtDpc);

    //
    // Exit DPC if we've queued a work item to avoid DPC watchdog timer expiration
    //
    if(AtDpc && WorkItemQueuedForWatchdogAvoidance(AdapterDpc->WorkItem,
                                                   &AdapterDpc->WorkItemQueued,
                                                   RXReceiveIndicateWorkItem,
                                                   AdapterDpc))
    {
        DEBUGP(MP_TRACE, "[%p] <--- RXReceiveIndicate. Processor: %i\n", Adapter, AdapterDpc->ProcessorNumber);
        return;
    }

    for(CurrentQueue = 0; CurrentQueue <NIC_SUPPORTED_NUM_QUEUES; ++CurrentQueue)
    {
        //
        // Consume RCBs for queue if we're the assigned consumer
        //
        if(AdapterDpc->RecvBlock[CurrentQueue])
        {
            PMP_ADAPTER_RECEIVE_BLOCK ReceiveBlock = &Adapter->ReceiveBlock[CurrentQueue];
            FirstNbl = LastNbl = NULL;

            //
            // Collect pending NBLs, indicate up to MaxNblCountPerIndicate per receive block
            //
            for(NumNblsReceived=0; NumNblsReceived < AdapterDpc->MaxNblCountPerIndicate; ++NumNblsReceived)
            {
                PLIST_ENTRY Entry;
                PRCB Rcb = NULL;

                Entry = NdisInterlockedRemoveHeadList(&ReceiveBlock->ReceiveList, &ReceiveBlock->ReceiveListLock);
                if(Entry)
                {
                    Rcb = CONTAINING_RECORD(Entry, RCB, RcbLink);
                }

                if(!Rcb)
                {
                    break;
                }

                ASSERT(Rcb->Data);

                //
                // The recv NBL's data was filled out by the hardware.  Now just update
                // its bookkeeping.
                //
                NET_BUFFER_LIST_STATUS(Rcb->Nbl) = NDIS_STATUS_SUCCESS;
                Rcb->Nbl->SourceHandle = Adapter->AdapterHandle;

                //
                // Add this NBL to the chain of NBLs to indicate up.
                //
                if (!FirstNbl)
                {
                    LastNbl = FirstNbl = Rcb->Nbl;
                }
                else
                {
                    NET_BUFFER_LIST_NEXT_NBL(LastNbl) = Rcb->Nbl;
                    LastNbl = Rcb->Nbl;
                }
            }

            //
            // Indicate NBLs
            //
            if (FirstNbl)
            {
                DEBUGP(MP_TRACE, "[%p] Receive Block %i: %i frames indicated.\n", Adapter, CurrentQueue, NumNblsReceived);

                NET_BUFFER_LIST_NEXT_NBL(LastNbl) = NULL;

                //
                // Indicate up the NBLs.
                //
                // The NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL allows a perf optimization:
                // NDIS doesn't have to check and raise the current IRQL, since we
                // promise that the current IRQL is exactly DISPATCH_LEVEL already.
                //
                NdisMIndicateReceiveNetBufferLists(
                        Adapter->AdapterHandle,
                        FirstNbl,
                        0,  // default port
                        NumNblsReceived,
                        (AtDpc?NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL:0)
                        | NDIS_RECEIVE_FLAGS_PERFECT_FILTERED
#if (NDIS_SUPPORT_NDIS620)
                        | NDIS_RECEIVE_FLAGS_SINGLE_QUEUE
                        | (CurrentQueue?NDIS_RECEIVE_FLAGS_SHARED_MEMORY_INFO_VALID:0) //non-default queues use shared memory
#endif
                        );
            }

            if(!AtDpc)
            {
                //
                // Clear work item flag to allow DPCs to be queued
                //
                InterlockedExchange(&AdapterDpc->WorkItemQueued, FALSE);
            }

            if (!IsListEmpty(&ReceiveBlock->ReceiveList))
            {
                //
                // More left to indicate for this receive block, queue this DPC again
                //
                DEBUGP(MP_TRACE, "[%p] Receive Block %i: Requeued DPC.\n", Adapter, CurrentQueue);
                KeInsertQueueDpc(&AdapterDpc->Dpc, AdapterDpc, NULL);
            }

        }

    }

    DEBUGP(MP_TRACE, "[%p] <--- RXReceiveIndicate. Processor: %i\n", Adapter, AdapterDpc->ProcessorNumber);
}
Example #13
0
/*
SdrLLSendPacket transforms NDIS packet and enqueue it in MAC send queue.

History:
    3/Nov/2009: Created by senxiang
*/
VOID SdrLLSendPacket(PSDR_CONTEXT SDRContext, PNDIS_PACKET_OR_NBL pNBSPacket)
{
    PMDL                pEthBuffer          = NULL;
    PMDL                pWlanBuffer         = NULL;
    PDLCB               pDLCB               = NULL;
    ULONG               Dot11HeaderSize     = 0;
    PUCHAR              pDot11HeaderVa      = NULL;
    PMAC                pMac                = (PMAC)SDRContext->Mac;
    PLL                 lnk                 = (PLL)SDRContext->LinkLayer;
    PSEND_QUEUE_MANAGER pSendQueueManager   = GET_SEND_QUEUE_MANAGER(pMac);
    PNET_BUFFER         pCurrentNB          = NET_BUFFER_LIST_FIRST_NB(pNBSPacket);

    ULONG               NetBufferCount      = GetNetBufferCount(pNBSPacket);
    LIST_ENTRY          DLCBList;

    BOOL                fSufficientDLCBs    = GetNFreeDLCB(&DLCBList, pSendQueueManager, NetBufferCount);
    DbgPrint("[LL_Send] %d net buffer in the NBL\n", NetBufferCount);

    if(pCurrentNB == NULL || !fSufficientDLCBs)
    {
        DbgPrint("[Error] Get NetBuffer failed, PACKET DROPPED\n");
        NicDropPacket((PMP_ADAPTER)SDRContext->Nic, pNBSPacket);
        return;
    }

    NET_BUFFER_LIST_STATUS(pNBSPacket) = NDIS_STATUS_SUCCESS; //init its status to success

    while(pCurrentNB)
    {
        //Get MDL
        ASSERT(!IsListEmpty(&DLCBList));
        pDLCB = CONTAINING_RECORD(RemoveHeadList(&DLCBList), DLCB, List);
        pDLCB->pNdisPktOrNBL = (PVOID)pNBSPacket;
        pDLCB->bLastNB = !(NET_BUFFER_NEXT_NB(pCurrentNB));

        lnk->CurSendSeqNo.SequenceNumber++;

        pEthBuffer = NET_BUFFER_CURRENT_MDL(pCurrentNB);
        if(pEthBuffer == NULL)
        {
            pDLCB->PacketBase.pMdl = NULL;
            DbgPrint("[Error] Get MDL failed, PACKET DROPPED\n");
        }
        else
        {
            EthToWlan(pEthBuffer,
                      &pWlanBuffer,
                      &Dot11HeaderSize,
                      &pDot11HeaderVa,
                      lnk->CurSendSeqNo.usValue,
                      NET_BUFFER_CURRENT_MDL_OFFSET(pCurrentNB));
            pDLCB->PacketType = PACKET_NEED_ACK;
            if(pDot11HeaderVa &&
                    (ETH_IS_BROADCAST(&((PDOT11RFC1042ENCAP)pDot11HeaderVa)->MacHeader.Address1)
                     || ETH_IS_MULTICAST(&((PDOT11RFC1042ENCAP)pDot11HeaderVa)->MacHeader.Address1)))
            {
                pDLCB->PacketType = PACKET_NOT_NEED_ACK;
            }

            //Config DLCB
            pDLCB->Dot11HeaderSize          = Dot11HeaderSize;
            pDLCB->pDot11HeaderVa           = pDot11HeaderVa;
            pDLCB->PacketBase.pMdl          = pWlanBuffer;

            pDLCB->PacketBase.PacketSize    = NET_BUFFER_DATA_LENGTH(pCurrentNB) + sizeof(DOT11RFC1042ENCAP) - sizeof(ETHERNET_HEADER);

            {   // we update the copied mdl length to packet length for baseband
                ULONG len = pDLCB->PacketBase.PacketSize;
                PMDL mdl = pDLCB->PacketBase.pMdl;
                while(mdl) {
                    if (mdl->ByteCount > len) {
                        mdl->ByteCount = len;
                        break;
                    }
                    else if (mdl->ByteCount < len) {
                        len-= mdl->ByteCount;
                        mdl = mdl->Next;
                        continue;
                    }
                    else
                        break;
                }
            }

            pDLCB->PacketBase.Reserved1     = CalcMDLChainCRC32(pWlanBuffer);
            pDLCB->RetryCount               = 0;
            pDLCB->bSendOK                  = FALSE;
        }

        SafeEnqueue(pSendQueueManager, SendSrcWaitList, pDLCB);
        InterlockedIncrement(&pSendQueueManager->nSrcPacket);

        //Notify send thread
        NIC_NOTIFY_SEND_THREAD(pMac);

        //Get next NetBuffer
        pCurrentNB = NET_BUFFER_NEXT_NB(pCurrentNB);
    }

}
Example #14
0
VOID
NdisprotSendComplete(
    IN NDIS_HANDLE                  ProtocolBindingContext,
    IN PNET_BUFFER_LIST             pNetBufferList,
    IN ULONG                        SendCompleteFlags
    )
/*++

Routine Description:

    NDIS entry point called to signify completion of a packet send.
    We pick up and complete the Write IRP corresponding to this packet.

Arguments:

    ProtocolBindingContext - pointer to open context
    pNetBufferList - NetBufferList that completed send
    SendCompleteFlags - Specifies if the caller is at DISPATCH level

Return Value:

    None

--*/
{
    PIRP                        pIrp;
    PIO_STACK_LOCATION          pIrpSp;
    PNDISPROT_OPEN_CONTEXT      pOpenContext;
    PNET_BUFFER_LIST            CurrNetBufferList = NULL;
    PNET_BUFFER_LIST            NextNetBufferList;
    NDIS_STATUS                 CompletionStatus;
    BOOLEAN                     DispatchLevel;

    pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
    NPROT_STRUCT_ASSERT(pOpenContext, oc);
    DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendCompleteFlags);

    for (CurrNetBufferList = pNetBufferList;
            CurrNetBufferList != NULL;
            CurrNetBufferList = NextNetBufferList)
    {
        NextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(CurrNetBufferList);
        
        pIrp = NPROT_IRP_FROM_SEND_NBL(CurrNetBufferList);

        IoAcquireCancelSpinLock(&pIrp->CancelIrql);
        IoSetCancelRoutine(pIrp, NULL);
        pIrp->Tail.Overlay.DriverContext[0] = NULL;
        pIrp->Tail.Overlay.DriverContext[1] = NULL;
        IoReleaseCancelSpinLock(pIrp->CancelIrql);

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, DispatchLevel);

        NPROT_REMOVE_ENTRY_LIST(&pIrp->Tail.Overlay.ListEntry);

        NPROT_RELEASE_LOCK(&pOpenContext->Lock, DispatchLevel);
        
        CompletionStatus = NET_BUFFER_LIST_STATUS(CurrNetBufferList);
        
        
        //
        //  We are done with the NDIS_PACKET:
        //
        NPROT_DEREF_SEND_NBL(CurrNetBufferList, DispatchLevel);

        //
        //  Complete the Write IRP with the right status.
        //
        pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
        if (CompletionStatus == NDIS_STATUS_SUCCESS)
        {
            pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length;
            pIrp->IoStatus.Status = STATUS_SUCCESS;
        }
        else
        {
            pIrp->IoStatus.Information = 0;
            pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        }

        DEBUGP(DL_INFO, ("SendComplete: NetBufferList %p/IRP %p/Length %d "
                        "completed with status %x\n",
                        CurrNetBufferList, pIrp, pIrp->IoStatus.Information, pIrp->IoStatus.Status));

        IoCompleteRequest(pIrp, IO_NO_INCREMENT);

        NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, DispatchLevel);
        pOpenContext->PendedSendCount--;

        if ((NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_CLOSING))
                && (pOpenContext->PendedSendCount == 0))
        {
            ASSERT(pOpenContext->ClosingEvent != NULL);
            NPROT_SIGNAL_EVENT(pOpenContext->ClosingEvent);
            pOpenContext->ClosingEvent = NULL;
        }
        NPROT_RELEASE_LOCK(&pOpenContext->Lock, DispatchLevel);

        NPROT_DEREF_OPEN(pOpenContext); // send complete - dequeued send IRP
    }
    
}