BOOLEAN ParaNdis_BindRxBufferToPacket(
    PARANDIS_ADAPTER *pContext,
    pRxNetDescriptor p)
{
    ULONG i;
    PMDL *NextMdlLinkage = &p->Holder;

    for(i = PARANDIS_FIRST_RX_DATA_PAGE; i < p->BufferSGLength; i++)
    {
        *NextMdlLinkage = NdisAllocateMdl(
            pContext->MiniportHandle,
            p->PhysicalPages[i].Virtual,
            p->PhysicalPages[i].size);
        if(*NextMdlLinkage == NULL) goto error_exit;

        NextMdlLinkage = &(NDIS_MDL_LINKAGE(*NextMdlLinkage));
    }
    *NextMdlLinkage = NULL;

    return TRUE;

error_exit:

    ParaNdis_UnbindRxBufferFromPacket(p);
    return FALSE;
}
Esempio n. 2
0
static PMDL
OvsAllocateMDLAndData(NDIS_HANDLE ndisHandle,
                      UINT32 dataSize)
{
    PMDL mdl;
    PVOID data;

    data = OvsAllocateMemoryWithTag(dataSize, OVS_MDL_POOL_TAG);
    if (data == NULL) {
        return NULL;
    }

    mdl = NdisAllocateMdl(ndisHandle, data, dataSize);
    if (mdl == NULL) {
        OvsFreeMemoryWithTag(data, OVS_MDL_POOL_TAG);
    }

    return mdl;
}
Esempio n. 3
0
NDIS_STATUS
BasePortTranslateRxPacketsToRxNBLs(
    __in  PMP_PORT                Port,
    __in  PMP_RX_MSDU             PacketList,
    __out PNET_BUFFER_LIST*       NetBufferLists
    )
{
    PNET_BUFFER_LIST            outputNetBufferList = NULL;
    PNET_BUFFER_LIST            currentNetBufferList, prevNetBufferList = NULL;
    USHORT                      fragmentIndex = 0;
    PMP_RX_MSDU                 currentPacket = PacketList, nextPacket;
    PMP_RX_MPDU                 currentFragment;
    NDIS_STATUS                 ndisStatus = NDIS_STATUS_SUCCESS;
    PDOT11_EXTSTA_RECV_CONTEXT  osRecvContext;  // This is same for ExtAP & ExtSTA
    PMDL                        currentMdl, prevMdl = NULL, mdlChain = NULL;
    ULONG                       totalLength = 0;
    
    *NetBufferLists = NULL;

    // Convert each PACKET and FRAGMENT to OS structures
    while (currentPacket != NULL)
    {
        nextPacket = MP_RX_MSDU_NEXT_MSDU(currentPacket);
        
        // Go through the FRAGMENTs in this PACKET & create an MDL chain
        mdlChain = NULL;
        totalLength = 0;
        
        for (fragmentIndex = 0; 
             fragmentIndex < MP_RX_MSDU_MPDU_COUNT(currentPacket);
             fragmentIndex++)
        {
            currentFragment = MP_RX_MSDU_MPDU_AT(currentPacket, fragmentIndex);
            totalLength += MP_RX_MPDU_LENGTH(currentFragment);
            
            // Populate the MDL with Fragment contents
            currentMdl = NdisAllocateMdl(Port->MiniportAdapterHandle,
                                MP_RX_MPDU_DATA(currentFragment),
                                MP_RX_MPDU_LENGTH(currentFragment)
                                );
            if (currentMdl == NULL)
            {
                MpTrace(COMP_RECV, DBG_SERIOUS, ("Failed to allocate MDL for a MP_RX_MPDU data\n"));
                ndisStatus = NDIS_STATUS_RESOURCES;
                break;
            }

            // Add this to the MDL chain
            if (mdlChain == NULL)
            {
                // Add this to the head
                mdlChain = currentMdl;
            }
            else
            {
                NDIS_MDL_LINKAGE(prevMdl) = currentMdl;
            }
            prevMdl = currentMdl;
        }
        
        if (ndisStatus != NDIS_STATUS_SUCCESS)
        {
            while (mdlChain != NULL)
            {
                currentMdl = mdlChain;
                mdlChain = NDIS_MDL_LINKAGE(currentMdl);
                
                // MDL was allocated
                NdisFreeMdl(currentMdl);
            }            
            break;
        }

        // Allocate the NET_BUFFER_LIST and the NET_BUFFER
        currentNetBufferList = NdisAllocateNetBufferAndNetBufferList(
                                    Port->RxNetBufferListPool,
                                    0,
                                    0,
                                    mdlChain,
                                    0,
                                    totalLength
                                    );
        if (currentNetBufferList == NULL)
        {
            MpTrace(COMP_SEND, DBG_SERIOUS, ("Failed to allocate NET_BUFFER_LIST for MP_RX_MSDU  \n"));        
            ndisStatus = NDIS_STATUS_RESOURCES;
            break;
        }
        
        // Populate the RX_PACKET
        MP_NBL_WRAPPED_RX_MSDU(currentNetBufferList) = currentPacket;
        MP_NBL_SOURCE_PORT(currentNetBufferList) = Port;
        
        if (outputNetBufferList == NULL)
        {
            outputNetBufferList = currentNetBufferList;
        }
        else
        {
            NET_BUFFER_LIST_NEXT_NBL(prevNetBufferList) = currentNetBufferList;
        }
        
        // The Next PACKET's NBL would be added after the current PACKET's NBL
        prevNetBufferList = currentNetBufferList;

        osRecvContext = MP_RX_MSDU_RECV_CONTEXT(currentPacket);

        MP_ASSIGN_NDIS_OBJECT_HEADER(osRecvContext->Header, 
             NDIS_OBJECT_TYPE_DEFAULT,
             DOT11_EXTSTA_RECV_CONTEXT_REVISION_1,
             sizeof(DOT11_EXTSTA_RECV_CONTEXT));
        
        MP_SET_RECEIVE_CONTEXT(currentNetBufferList, osRecvContext);        
        
        currentPacket = nextPacket;
    }


    if (ndisStatus != NDIS_STATUS_SUCCESS)
    {
        if (outputNetBufferList != NULL)
        {
            BasePortFreeTranslatedRxNBLs(Port, outputNetBufferList);
            outputNetBufferList = NULL;
        }
    }

    *NetBufferLists = outputNetBufferList;

    return ndisStatus;
}
Esempio n. 4
0
VOID
IndicateReceivePacket(
    __in PTAP_ADAPTER_CONTEXT  Adapter,
    __in PUCHAR packetData,
    __in const unsigned int packetLength
    )
{
    PUCHAR  injectBuffer;

    //
    // Handle miniport Pause
    // ---------------------
    // NDIS 6 miniports implement a temporary "Pause" state normally followed
    // by the Restart. While in the Pause state it is forbidden for the miniport
    // to indicate receive NBLs.
    //
    // That is: The device interface may be "up", but the NDIS miniport send/receive
    // interface may be temporarily "down".
    //
    // BUGBUG!!! In the initial implementation of the NDIS 6 TapOas inject path
    // the code below will simply ignore inject packets passed to the driver while
    // the miniport is in the Paused state.
    //
    // The correct implementation is to go ahead and build the NBLs corresponding
    // to the inject packet - but queue them. When Restart is entered the
    // queued NBLs would be dequeued and indicated to the host.
    //
    if(tapAdapterSendAndReceiveReady(Adapter) != NDIS_STATUS_SUCCESS)
    {
        DEBUGP (("[%s] Lying send in IndicateReceivePacket while adapter paused\n",
            MINIPORT_INSTANCE_ID (Adapter)));

        return;
    }

    // Allocate flat buffer for packet data.
    injectBuffer = (PUCHAR )NdisAllocateMemoryWithTagPriority(
                        Adapter->MiniportAdapterHandle,
                        packetLength,
                        TAP_RX_INJECT_BUFFER_TAG,
                        NormalPoolPriority
                        );

    if( injectBuffer)
    {
        PMDL    mdl;

        // Copy packet data to flat buffer.
        NdisMoveMemory (injectBuffer, packetData, packetLength);

        // Allocate MDL for flat buffer.
        mdl = NdisAllocateMdl(
                Adapter->MiniportAdapterHandle,
                injectBuffer,
                packetLength
                );

        if( mdl )
        {
            PNET_BUFFER_LIST    netBufferList;

            mdl->Next = NULL;   // No next MDL

            // Allocate the NBL and NB. Link MDL chain to NB.
            netBufferList = NdisAllocateNetBufferAndNetBufferList(
                                Adapter->ReceiveNblPool,
                                0,                  // ContextSize
                                0,                  // ContextBackFill
                                mdl,                // MDL chain
                                0,
                                packetLength
                                );

            if(netBufferList != NULL)
            {
                ULONG       receiveFlags = 0;
                LONG        nblCount;

                NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                if(KeGetCurrentIrql() == DISPATCH_LEVEL)
                {
                    receiveFlags |= NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
                }

                // Set flag indicating that this is an injected packet
                TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);
                TAP_RX_NBL_FLAG_SET(netBufferList,TAP_RX_NBL_FLAGS_IS_INJECTED);

                netBufferList->MiniportReserved[0] = NULL;
                netBufferList->MiniportReserved[1] = NULL;

                // Increment in-flight receive NBL count.
                nblCount = NdisInterlockedIncrement(&Adapter->ReceiveNblInFlightCount);
                ASSERT(nblCount > 0 );

                netBufferList->SourceHandle = Adapter->MiniportAdapterHandle;

                //
                // Indicate the packet
                // -------------------
                // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
                // contains the complete packet including Ethernet header and payload.
                //
                NdisMIndicateReceiveNetBufferLists(
                    Adapter->MiniportAdapterHandle,
                    netBufferList,
                    NDIS_DEFAULT_PORT_NUMBER,
                    1,      // NumberOfNetBufferLists
                    receiveFlags
                    );

                return;
            }
            else
            {
                DEBUGP (("[%s] NdisAllocateNetBufferAndNetBufferList failed in IndicateReceivePacket\n",
                    MINIPORT_INSTANCE_ID (Adapter)));
                NOTE_ERROR ();

                NdisFreeMdl(mdl);
                NdisFreeMemory(injectBuffer,0,0);
            }
        }
        else
        {
            DEBUGP (("[%s] NdisAllocateMdl failed in IndicateReceivePacket\n",
                MINIPORT_INSTANCE_ID (Adapter)));
            NOTE_ERROR ();

            NdisFreeMemory(injectBuffer,0,0);
        }
    }
    else
    {
        DEBUGP (("[%s] NdisAllocateMemoryWithTagPriority failed in IndicateReceivePacket\n",
            MINIPORT_INSTANCE_ID (Adapter)));
        NOTE_ERROR ();
    }
}
Esempio n. 5
0
// IRP_MJ_WRITE callback.
NTSTATUS
TapDeviceWrite(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )
{
    NTSTATUS                ntStatus = STATUS_SUCCESS;// Assume success
    PIO_STACK_LOCATION      irpSp;// Pointer to current stack location
    PTAP_ADAPTER_CONTEXT    adapter = NULL;
    ULONG                   dataLength;

    PAGED_CODE();

    irpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    // Fetch adapter context for this device.
    // --------------------------------------
    // Adapter pointer was stashed in FsContext when handle was opened.
    //
    adapter = (PTAP_ADAPTER_CONTEXT )(irpSp->FileObject)->FsContext;

    ASSERT(adapter);

    //
    // Sanity checks on state variables
    //
    if (!tapAdapterReadAndWriteReady(adapter))
    {
        //DEBUGP (("[%s] Interface is down in IRP_MJ_WRITE\n",
        //    MINIPORT_INSTANCE_ID (adapter)));
        //NOTE_ERROR();

        Irp->IoStatus.Status = ntStatus = STATUS_CANCELLED;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    // Save IRP-accessible copy of buffer length
    Irp->IoStatus.Information = irpSp->Parameters.Write.Length;

    if (Irp->MdlAddress == NULL)
    {
        DEBUGP (("[%s] MdlAddress is NULL for IRP_MJ_WRITE\n",
            MINIPORT_INSTANCE_ID (adapter)));

        NOTE_ERROR();
        Irp->IoStatus.Status = ntStatus = STATUS_INVALID_PARAMETER;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    //
    // Try to get a virtual address for the MDL.
    //
    NdisQueryMdl(
        Irp->MdlAddress,
        &Irp->AssociatedIrp.SystemBuffer,
        &dataLength,
        NormalPagePriority
        );

    if (Irp->AssociatedIrp.SystemBuffer == NULL)
    {
        DEBUGP (("[%s] Could not map address in IRP_MJ_WRITE\n",
            MINIPORT_INSTANCE_ID (adapter)));

        NOTE_ERROR();
        Irp->IoStatus.Status = ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);

        return ntStatus;
    }

    ASSERT(dataLength == irpSp->Parameters.Write.Length);

    Irp->IoStatus.Information = irpSp->Parameters.Write.Length;

    //
    // Handle miniport Pause
    // ---------------------
    // NDIS 6 miniports implement a temporary "Pause" state normally followed
    // by the Restart. While in the Pause state it is forbidden for the miniport
    // to indicate receive NBLs.
    //
    // That is: The device interface may be "up", but the NDIS miniport send/receive
    // interface may be temporarily "down".
    //
    // BUGBUG!!! In the initial implementation of the NDIS 6 TapOas receive path
    // the code below will perform a "lying send" for write IRPs passed to the
    // driver while the miniport is in the Paused state.
    //
    // The correct implementation is to go ahead and build the NBLs corresponding
    // to the user-mode write - but queue them. When Restart is entered the
    // queued NBLs would be dequeued and indicated to the host.
    //
    if(tapAdapterSendAndReceiveReady(adapter) == NDIS_STATUS_SUCCESS)
    {
        if (!adapter->m_tun && ((irpSp->Parameters.Write.Length) >= ETHERNET_HEADER_SIZE))
        {
            PNET_BUFFER_LIST    netBufferList;

            DUMP_PACKET ("IRP_MJ_WRITE ETH",
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length);

            //=====================================================
            // If IPv4 packet, check whether or not packet
            // was truncated.
            //=====================================================
#if PACKET_TRUNCATION_CHECK
            IPv4PacketSizeVerify (
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length,
                FALSE,
                "RX",
                &adapter->m_RxTrunc
                );
#endif
            (Irp->MdlAddress)->Next = NULL; // No next MDL

            // Allocate the NBL and NB. Link MDL chain to NB.
            netBufferList = NdisAllocateNetBufferAndNetBufferList(
                adapter->ReceiveNblPool,
                0,                  // ContextSize
                0,                  // ContextBackFill
                Irp->MdlAddress,    // MDL chain
                0,
                dataLength
                );

            if(netBufferList != NULL)
            {
                LONG    nblCount;

                NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                // Stash IRP pointer in NBL MiniportReserved[0] field.
                netBufferList->MiniportReserved[0] = Irp;
                netBufferList->MiniportReserved[1] = NULL;

                // BUGBUG!!! Setup for IRP cancel!!!

                TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);

                // Increment in-flight receive NBL count.
                nblCount = NdisInterlockedIncrement(&adapter->ReceiveNblInFlightCount);
                ASSERT(nblCount > 0 );

                //
                // Indicate the packet
                // -------------------
                // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
                // contains the complete packet including Ethernet header and payload.
                //
                NdisMIndicateReceiveNetBufferLists(
                    adapter->MiniportAdapterHandle,
                    netBufferList,
                    NDIS_DEFAULT_PORT_NUMBER,
                    1,      // NumberOfNetBufferLists
                    0       // ReceiveFlags
                    );

                ntStatus = STATUS_PENDING;
            }
            else
            {
                DEBUGP (("[%s] NdisMIndicateReceiveNetBufferLists failed in IRP_MJ_WRITE\n",
                    MINIPORT_INSTANCE_ID (adapter)));
                NOTE_ERROR ();

                // Fail the IRP
                Irp->IoStatus.Information = 0;
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
        else if (adapter->m_tun && ((irpSp->Parameters.Write.Length) >= IP_HEADER_SIZE))
        {
            PETH_HEADER         p_UserToTap = &adapter->m_UserToTap;
            PMDL                mdl;    // Head of MDL chain.

            // For IPv6, need to use Ethernet header with IPv6 proto
            if ( IPH_GET_VER( ((IPHDR*) Irp->AssociatedIrp.SystemBuffer)->version_len) == 6 )
            {
                p_UserToTap = &adapter->m_UserToTap_IPv6;
            }

            DUMP_PACKET2 ("IRP_MJ_WRITE P2P",
                p_UserToTap,
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length);

            //=====================================================
            // If IPv4 packet, check whether or not packet
            // was truncated.
            //=====================================================
#if PACKET_TRUNCATION_CHECK
            IPv4PacketSizeVerify (
                (unsigned char *) Irp->AssociatedIrp.SystemBuffer,
                irpSp->Parameters.Write.Length,
                TRUE,
                "RX",
                &adapter->m_RxTrunc
                );
#endif

            //
            // Allocate MDL for Ethernet header
            // --------------------------------
            // Irp->AssociatedIrp.SystemBuffer with length irpSp->Parameters.Write.Length
            // contains the only the Ethernet payload. Prepend the user-mode provided
            // payload with the Ethernet header pointed to by p_UserToTap.
            //
            mdl = NdisAllocateMdl(
                adapter->MiniportAdapterHandle,
                p_UserToTap,
                sizeof(ETH_HEADER)
                );

            if(mdl != NULL)
            {
                PNET_BUFFER_LIST    netBufferList;

                // Chain user's Ethernet payload behind Ethernet header.
                mdl->Next = Irp->MdlAddress;
                (Irp->MdlAddress)->Next = NULL; // No next MDL

                // Allocate the NBL and NB. Link MDL chain to NB.
                netBufferList = NdisAllocateNetBufferAndNetBufferList(
                    adapter->ReceiveNblPool,
                    0,          // ContextSize
                    0,          // ContextBackFill
                    mdl,        // MDL chain
                    0,
                    sizeof(ETH_HEADER) + dataLength
                    );

                if(netBufferList != NULL)
                {
                    LONG        nblCount;

                    NET_BUFFER_LIST_NEXT_NBL(netBufferList) = NULL; // Only one NBL

                    // This IRP is pended.
                    IoMarkIrpPending(Irp);

                    // This IRP cannot be cancelled while in-flight.
                    IoSetCancelRoutine(Irp,NULL);

                    // Stash IRP pointer in NBL MiniportReserved[0] field.
                    netBufferList->MiniportReserved[0] = Irp;
                    netBufferList->MiniportReserved[1] = NULL;

                    // Set flag indicating that this is P2P packet
                    TAP_RX_NBL_FLAGS_CLEAR_ALL(netBufferList);
                    TAP_RX_NBL_FLAG_SET(netBufferList,TAP_RX_NBL_FLAGS_IS_P2P);

                    // Increment in-flight receive NBL count.
                    nblCount = NdisInterlockedIncrement(&adapter->ReceiveNblInFlightCount);
                    ASSERT(nblCount > 0 );

                    //
                    // Indicate the packet
                    //
                    NdisMIndicateReceiveNetBufferLists(
                        adapter->MiniportAdapterHandle,
                        netBufferList,
                        NDIS_DEFAULT_PORT_NUMBER,
                        1,      // NumberOfNetBufferLists
                        0       // ReceiveFlags
                        );

                    ntStatus = STATUS_PENDING;
                }
                else
                {
                    mdl->Next = NULL;
                    NdisFreeMdl(mdl);

                    DEBUGP (("[%s] NdisMIndicateReceiveNetBufferLists failed in IRP_MJ_WRITE\n",
                        MINIPORT_INSTANCE_ID (adapter)));
                    NOTE_ERROR ();

                    // Fail the IRP
                    Irp->IoStatus.Information = 0;
                    ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                }
            }
            else
            {
                DEBUGP (("[%s] NdisAllocateMdl failed in IRP_MJ_WRITE\n",
                    MINIPORT_INSTANCE_ID (adapter)));
                NOTE_ERROR ();

                // Fail the IRP
                Irp->IoStatus.Information = 0;
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            }
        }
        else
        {
            DEBUGP (("[%s] Bad buffer size in IRP_MJ_WRITE, len=%d\n",
                MINIPORT_INSTANCE_ID (adapter),
                irpSp->Parameters.Write.Length));
            NOTE_ERROR ();

            Irp->IoStatus.Information = 0;	// ETHERNET_HEADER_SIZE;
            Irp->IoStatus.Status = ntStatus = STATUS_BUFFER_TOO_SMALL;
        }
    }
    else
    {
        DEBUGP (("[%s] Lying send in IRP_MJ_WRITE while adapter paused\n",
            MINIPORT_INSTANCE_ID (adapter)));

        ntStatus = STATUS_SUCCESS;
    }

    if (ntStatus != STATUS_PENDING)
    {
        Irp->IoStatus.Status = ntStatus;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }

    return ntStatus;
}
Esempio n. 6
0
NDIS_STATUS
shared_flush(
	IN shared_info_t *shared,
	IN uchar *va,
	IN ULONG pa,
	IN ULONG len,
	IN BOOLEAN writetodevice
)
{
#ifndef NDIS60
	PNDIS_BUFFER b;
	NDIS_STATUS status;
	NDIS_PHYSICAL_ADDRESS npa;

	/* if receive, buffer must begin and end on a cacheline boundary */
	if (!writetodevice) {
		ASSERT(ISALIGNED((uintptr)va, shared->cacheline));
		len = ROUNDUP(len, shared->cacheline);
	}

	/* alloc a temp buffer descriptor */
	NdisAllocateBuffer(&status, &b, shared->rxbufferpool, va, len);
	if (status != NDIS_STATUS_SUCCESS) {
		ND_ERROR(("%s%d: shared_flush: NdisAllocateBuffer error 0x%x\n",
			shared->id, shared->unit, status));
		return status;
	}

	/* flush processor cache */
	NdisAdjustBufferLength(b, len);
	NdisFlushBuffer(b, writetodevice);

	npa.HighPart = 0;
	npa.LowPart = pa;

#ifndef USEWDK


	if (!writetodevice)
		NdisMUpdateSharedMemory(shared->adapterhandle, len, va, npa);

#endif /* USEWDK */

	/* free the temp buffer descriptor */
	NdisFreeBuffer(b);
#else /* NDIS60 */
	PMDL b;

	/* if receive, buffer must begin and end on a cacheline boundary */
	if (!writetodevice) {
		ASSERT(ISALIGNED((uintptr)va, shared->cacheline));
		len = ROUNDUP(len, shared->cacheline);
	}

	/* alloc a temp MDL */
	b = NdisAllocateMdl(shared->adapterhandle, va, len);
	if (b == NULL) {
		ND_ERROR(("%s%d: shared_flush: NdisAllocateMdl error\n", shared->id, shared->unit));
		return NDIS_STATUS_FAILURE;
	}

	/* flush processor cache */
	NdisAdjustMdlLength(b, len);
	NdisFlushBuffer(b, writetodevice);

	/* free the temp MDL */
	NdisFreeMdl(b);
#endif /* NDIS60 */
	return NDIS_STATUS_SUCCESS;
}