VirtualBox

Changeset 26574 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Feb 16, 2010 12:44:10 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
57756
Message:

Networking: Preparing to make the driver return a send buffer to the device emulation.

Location:
trunk/src/VBox/Devices/Network
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DevE1000.cpp

    r26408 r26574  
    46954695        //SSMR3GetBool(pSSM, pState->fIntMaskUsed);
    46964696        SSMR3GetU16(pSSM, &pState->u16TxPktLen);
    4697         SSMR3GetMem(pSSM, &pState->aTxPacket, pState->u16TxPktLen);
     4697        SSMR3GetMem(pSSM, &pState->aTxPacket[0], pState->u16TxPktLen);
    46984698        SSMR3GetBool(pSSM, &pState->fIPcsum);
    46994699        SSMR3GetBool(pSSM, &pState->fTCPcsum);
  • trunk/src/VBox/Devices/Network/DrvIntNet.cpp

    r26305 r26574  
    2828#include <VBox/cfgm.h>
    2929#include <VBox/intnet.h>
     30#include <VBox/intnetinline.h>
    3031#include <VBox/vmm.h>
    3132#include <VBox/err.h>
     
    3536#include <iprt/assert.h>
    3637#include <iprt/ctype.h>
     38#include <iprt/memcache.h>
    3739#include <iprt/net.h>
    3840#include <iprt/semaphore.h>
     
    8991    RTTHREAD                        Thread;
    9092    /** Event semaphore the Thread waits on while the VM is suspended. */
    91     RTSEMEVENT                      EventSuspended;
     93    RTSEMEVENT                      hEvtSuspended;
     94    /** Scatter/gather descriptor cache. */
     95    RTMEMCACHE                      hSgCache;
    9296    /** Set if the link is down.
    9397     * When the link is down all incoming packets will be dropped. */
     
    127131/* -=-=-=-=- PDMINETWORKUP -=-=-=-=- */
    128132
    129 /** Converts a pointer to DRVINTNET::INetworkUpR3 to a PDRVINTNET. */
    130 #define PDMINETWORKUP_2_DRVINTNET(pInterface) \
    131     RT_FROM_MEMBER(pInterface, DRVINTNET, INetworkUpR3)
    132133
    133134/**
     
    187188
    188189/**
    189  * Writes a frame packet to the buffer.
    190  *
    191  * @returns VBox status code.
    192  * @param   pBuf        The buffer.
    193  * @param   pRingBuf    The ring buffer to read from.
    194  * @param   pvFrame     The frame to write.
    195  * @param   cbFrame     The size of the frame.
    196  * @remark  This is the same as INTNETRingWriteFrame
    197  */
    198 static int drvR3IntNetRingWriteFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf, const void *pvFrame, uint32_t cbFrame)
    199 {
    200     /*
    201      * Validate input.
    202      */
    203     Assert(pBuf);
    204     Assert(pRingBuf);
    205     Assert(pvFrame);
    206     Assert(cbFrame >= sizeof(RTMAC) * 2);
    207     uint32_t offWrite = pRingBuf->offWrite;
    208     Assert(offWrite == RT_ALIGN_32(offWrite, sizeof(INTNETHDR)));
    209     uint32_t offRead = pRingBuf->offRead;
    210     Assert(offRead == RT_ALIGN_32(offRead, sizeof(INTNETHDR)));
    211 
    212     const uint32_t cb = RT_ALIGN_32(cbFrame, sizeof(INTNETHDR));
    213     if (offRead <= offWrite)
    214     {
    215         /*
    216          * Try fit it all before the end of the buffer.
    217          */
    218         if (pRingBuf->offEnd - offWrite >= cb + sizeof(INTNETHDR))
     190 * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
     191 */
     192static DECLCALLBACK(int) drvR3IntNetUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbMin, PPPDMSCATTERGATHER ppSgBuf)
     193{
     194    PDRVINTNET  pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, INetworkUpR3);
     195    int         rc    = VINF_SUCCESS;
     196    Assert(cbMin < UINT32_MAX / 2);
     197
     198    /*
     199     * Allocate a S/G buffer.
     200     */
     201    PPDMSCATTERGATHER pSgBuf = (PPDMSCATTERGATHER)RTMemCacheAlloc(pThis->hSgCache);
     202    if (pSgBuf)
     203    {
     204        PINTNETHDR pHdr;
     205        rc = INTNETRingAllocateFrame(&pThis->pBufR3->Send, (uint32_t)cbMin,
     206                                     &pHdr, &pSgBuf->aSegs[0].pvSeg);
     207#if 1 /** @todo implement VERR_TRY_AGAIN once this moves to EMT. */
     208        if (    RT_FAILURE(rc)
     209            &&  pThis->pBufR3->cbSend >= cbMin * 2 + sizeof(INTNETHDR))
    219210        {
    220             PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    221             pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    222             pHdr->cbFrame  = cbFrame;
    223             pHdr->offFrame = sizeof(INTNETHDR);
    224 
    225             memcpy(pHdr + 1, pvFrame, cbFrame);
    226 
    227             offWrite += cb + sizeof(INTNETHDR);
    228             Assert(offWrite <= pRingBuf->offEnd && offWrite >= pRingBuf->offStart);
    229             if (offWrite >= pRingBuf->offEnd)
    230                 offWrite = pRingBuf->offStart;
    231             Log2(("WriteFrame: offWrite: %#x -> %#x (1)\n", pRingBuf->offWrite, offWrite));
    232             ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
     211            INTNETIFSENDREQ SendReq;
     212            SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     213            SendReq.Hdr.cbReq = sizeof(SendReq);
     214            SendReq.pSession = NIL_RTR0PTR;
     215            SendReq.hIf = pThis->hIf;
     216            PDMDrvHlpSUPCallVMMR0Ex(pThis->pDrvInsR3, VMMR0_DO_INTNET_IF_SEND, &SendReq, sizeof(SendReq));
     217
     218            rc = INTNETRingAllocateFrame(&pThis->pBufR3->Send, (uint32_t)cbMin,
     219                                         &pHdr, &pSgBuf->aSegs[0].pvSeg);
     220        }
     221#endif
     222        if (RT_SUCCESS(rc))
     223        {
     224            pSgBuf->fFlags          = PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1;
     225            pSgBuf->cbUsed          = 0;
     226            pSgBuf->cbAvailable     = cbMin;
     227            pSgBuf->pvUser          = pHdr;
     228            pSgBuf->cSegs           = 1;
     229            pSgBuf->aSegs[0].cbSeg  = cbMin;
     230
     231            *ppSgBuf = pSgBuf;
    233232            return VINF_SUCCESS;
    234233        }
    235234
    236235        /*
    237          * Try fit the frame at the start of the buffer.
    238          * (The header fits before the end of the buffer because of alignment.)
     236         * Arm the try again stuff.
    239237         */
    240         AssertMsg(pRingBuf->offEnd - offWrite >= sizeof(INTNETHDR), ("offEnd=%x offWrite=%x\n", pRingBuf->offEnd, offWrite));
    241         if (offRead - pRingBuf->offStart > cb) /* not >= ! */
    242         {
    243             PINTNETHDR  pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    244             void       *pvFrameOut = (PINTNETHDR)((uint8_t *)pBuf + pRingBuf->offStart);
    245             pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    246             pHdr->cbFrame  = cbFrame;
    247             pHdr->offFrame = (intptr_t)pvFrameOut - (intptr_t)pHdr;
    248 
    249             memcpy(pvFrameOut, pvFrame, cbFrame);
    250 
    251             offWrite = pRingBuf->offStart + cb;
    252             ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
    253             Log2(("WriteFrame: offWrite: %#x -> %#x (2)\n", pRingBuf->offWrite, offWrite));
    254             return VINF_SUCCESS;
    255         }
    256     }
    257     /*
    258      * The reader is ahead of the writer, try fit it into that space.
    259      */
    260     else if (offRead - offWrite > cb + sizeof(INTNETHDR)) /* not >= ! */
    261     {
    262         PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    263         pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    264         pHdr->cbFrame  = cbFrame;
    265         pHdr->offFrame = sizeof(INTNETHDR);
    266 
    267         memcpy(pHdr + 1, pvFrame, cbFrame);
    268 
    269         offWrite += cb + sizeof(INTNETHDR);
    270         ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
    271         Log2(("WriteFrame: offWrite: %#x -> %#x (3)\n", pRingBuf->offWrite, offWrite));
    272         return VINF_SUCCESS;
    273     }
    274 
    275     /* (it didn't fit) */
    276     /** @todo stats */
    277     return VERR_BUFFER_OVERFLOW;
    278 }
    279 
     238/** @todo        if (pThis->pBufR3->cbSend >= cbMin * 2 + sizeof(INTNETHDR))
     239            rc = VERR_TRY_AGAIN;
     240        else */
     241            rc = VERR_NO_MEMORY;
     242
     243        RTMemCacheFree(pThis->hSgCache, pSgBuf);
     244    }
     245    else
     246        rc = VERR_NO_MEMORY;
     247    /** @todo implement VERR_TRY_AGAIN  */
     248    return rc;
     249}
     250
     251/**
     252 * @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
     253 */
     254static DECLCALLBACK(int) drvR3IntNetUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
     255{
     256    return VERR_NOT_IMPLEMENTED;
     257}
    280258
    281259/**
    282260 * @interface_method_impl{PDMINETWORKUP,pfnSendDeprecated}
    283261 */
    284 static DECLCALLBACK(int) drvR3IntNetSendDeprecated(PPDMINETWORKUP pInterface, const void *pvBuf, size_t cb)
    285 {
    286     PDRVINTNET pThis = PDMINETWORKUP_2_DRVINTNET(pInterface);
     262static DECLCALLBACK(int) drvR3IntNetUp_SendDeprecated(PPDMINETWORKUP pInterface, const void *pvBuf, size_t cb)
     263{
     264    PDRVINTNET pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, INetworkUpR3);
    287265    STAM_PROFILE_START(&pThis->StatTransmit, a);
    288266
     
    300278     * Add the frame to the send buffer and push it onto the network.
    301279     */
    302     int rc = drvR3IntNetRingWriteFrame(pThis->pBufR3, &pThis->pBufR3->Send, pvBuf, (uint32_t)cb);
     280    int rc = INTNETRingWriteFrame(&pThis->pBufR3->Send, pvBuf, (uint32_t)cb);
    303281    if (    rc == VERR_BUFFER_OVERFLOW
    304282        &&  pThis->pBufR3->cbSend < cb)
     
    311289        PDMDrvHlpSUPCallVMMR0Ex(pThis->pDrvInsR3, VMMR0_DO_INTNET_IF_SEND, &SendReq, sizeof(SendReq));
    312290
    313         rc = drvR3IntNetRingWriteFrame(pThis->pBufR3, &pThis->pBufR3->Send, pvBuf, (uint32_t)cb);
     291        rc = INTNETRingWriteFrame(&pThis->pBufR3->Send, pvBuf, (uint32_t)cb);
    314292    }
    315293
     
    333311 * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
    334312 */
    335 static DECLCALLBACK(void) drvR3IntNetSetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
    336 {
    337     PDRVINTNET pThis = PDMINETWORKUP_2_DRVINTNET(pInterface);
     313static DECLCALLBACK(void) drvR3IntNetUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
     314{
     315    PDRVINTNET pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, INetworkUpR3);
    338316    INTNETIFSETPROMISCUOUSMODEREQ Req;
    339317    Req.Hdr.u32Magic    = SUPVMMR0REQHDR_MAGIC;
     
    343321    Req.fPromiscuous    = fPromiscuous;
    344322    int rc = PDMDrvHlpSUPCallVMMR0Ex(pThis->pDrvInsR3, VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE, &Req, sizeof(Req));
    345     LogFlow(("drvR3IntNetSetPromiscuousMode: fPromiscuous=%RTbool\n", fPromiscuous));
     323    LogFlow(("drvR3IntNetUp_SetPromiscuousMode: fPromiscuous=%RTbool\n", fPromiscuous));
    346324    AssertRC(rc);
    347325}
     
    351329 * @interface_method_impl{PDMINETWORKUP,pfnNotifyLinkChanged}
    352330 */
    353 static DECLCALLBACK(void) drvR3IntNetNotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
    354 {
    355     PDRVINTNET pThis = PDMINETWORKUP_2_DRVINTNET(pInterface);
     331static DECLCALLBACK(void) drvR3IntNetUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
     332{
     333    PDRVINTNET pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, INetworkUpR3);
    356334    bool fLinkDown;
    357335    switch (enmLinkState)
     
    367345            break;
    368346    }
    369     LogFlow(("drvR3IntNetNotifyLinkChanged: enmLinkState=%d %d->%d\n", enmLinkState, pThis->fLinkDown, fLinkDown));
     347    LogFlow(("drvR3IntNetUp_NotifyLinkChanged: enmLinkState=%d %d->%d\n", enmLinkState, pThis->fLinkDown, fLinkDown));
    370348    ASMAtomicXchgSize(&pThis->fLinkDown, fLinkDown);
    371349}
     
    414392         * Process the receive buffer.
    415393         */
    416         while (INTNETRingGetReadable(pRingBuf) > 0)
     394        PINTNETHDR pHdr;
     395        while ((pHdr = INTNETRingGetNextFrameToRead(pRingBuf)) != NULL)
    417396        {
    418397            /*
     
    426405            }
    427406
    428             PINTNETHDR pHdr = (PINTNETHDR)((uintptr_t)pBuf + pRingBuf->offRead);
    429             Log2(("pHdr=%p offRead=%#x: %.8Rhxs\n", pHdr, pRingBuf->offRead, pHdr));
     407            Log2(("pHdr=%p offRead=%#x: %.8Rhxs\n", pHdr, pRingBuf->offReadX, pHdr));
    430408            if (    pHdr->u16Type == INTNETHDR_TYPE_FRAME
    431409                &&  !pThis->fLinkDown)
     
    451429
    452430                    /* skip to the next frame. */
    453                     INTNETRingSkipFrame(pBuf, pRingBuf);
     431                    INTNETRingSkipFrame(pRingBuf);
    454432                }
    455433                else
     
    467445                             */
    468446                            AssertMsg(pHdr->u16Type == INTNETHDR_TYPE_FRAME, ("Unknown frame type %RX16! offRead=%#x\n",
    469                                                                               pHdr->u16Type, pRingBuf->offRead));
    470                             INTNETRingSkipFrame(pBuf, pRingBuf);
     447                                                                              pHdr->u16Type, pRingBuf->offReadX));
     448                            INTNETRingSkipFrame(pRingBuf);
    471449                        }
    472450                        else
     
    485463                 */
    486464                AssertMsg(pHdr->u16Type == INTNETHDR_TYPE_FRAME, ("Unknown frame type %RX16! offRead=%#x\n",
    487                                                                   pHdr->u16Type, pRingBuf->offRead));
    488                 INTNETRingSkipFrame(pBuf, pRingBuf);
     465                                                                  pHdr->u16Type, pRingBuf->offReadX));
     466                INTNETRingSkipFrame(pRingBuf);
     467                STAM_REL_COUNTER_INC(&pBuf->cStatBadFrames);
    489468            }
    490469        } /* while more received data */
     
    542521            case ASYNCSTATE_SUSPENDED:
    543522            {
    544                 int rc = RTSemEventWait(pThis->EventSuspended, 30000);
     523                int rc = RTSemEventWait(pThis->hEvtSuspended, 30000);
    545524                if (    RT_FAILURE(rc)
    546525                    &&  rc != VERR_TIMEOUT)
     
    647626    {
    648627        ASMAtomicXchgSize(&pThis->enmState, ASYNCSTATE_RUNNING);
    649         RTSemEventSignal(pThis->EventSuspended);
     628        RTSemEventSignal(pThis->hEvtSuspended);
    650629        drvR3IntNetUpdateMacAddress(pThis); /* (could be a state restore) */
    651630        drvR3IntNetSetActive(pThis, true /* fActive */);
     
    673652        int rc = pThis->pIAboveConfigR3->pfnGetMac(pThis->pIAboveConfigR3, &Frame.Hdr.SrcMac);
    674653        if (RT_SUCCESS(rc))
    675             rc = drvR3IntNetSendDeprecated(&pThis->INetworkUpR3, &Frame, sizeof(Frame));
     654            rc = drvR3IntNetUp_SendDeprecated(&pThis->INetworkUpR3, &Frame, sizeof(Frame));
    676655        if (RT_FAILURE(rc))
    677656            LogRel(("IntNet#%u: Sending dummy frame failed: %Rrc\n", pDrvIns->iInstance, rc));
     
    709688    {
    710689        ASMAtomicXchgSize(&pThis->enmState, ASYNCSTATE_RUNNING);
    711         RTSemEventSignal(pThis->EventSuspended);
     690        RTSemEventSignal(pThis->hEvtSuspended);
    712691        drvR3IntNetUpdateMacAddress(pThis);
    713692        drvR3IntNetSetActive(pThis, true /* fActive */);
     
    735714    ASMAtomicXchgSize(&pThis->enmState, ASYNCSTATE_TERMINATE);
    736715    ASMAtomicXchgSize(&pThis->fLinkDown, true);
    737     RTSEMEVENT EventSuspended = pThis->EventSuspended;
    738     pThis->EventSuspended = NIL_RTSEMEVENT;
     716    RTSEMEVENT hEvtSuspended = pThis->hEvtSuspended;
     717    pThis->hEvtSuspended = NIL_RTSEMEVENT;
    739718
    740719    /*
     
    758737    if (pThis->Thread != NIL_RTTHREAD)
    759738    {
    760         if (EventSuspended != NIL_RTSEMEVENT)
    761             RTSemEventSignal(EventSuspended);
     739        if (hEvtSuspended != NIL_RTSEMEVENT)
     740            RTSemEventSignal(hEvtSuspended);
    762741        int rc = RTThreadWait(pThis->Thread, 5000, NULL);
    763742        AssertRC(rc);
     
    766745
    767746    /*
    768      * Destroy the semaphores.
    769      */
    770     if (EventSuspended != NIL_RTSEMEVENT)
    771         RTSemEventDestroy(EventSuspended);
     747     * Destroy the semaphore and S/G cache.
     748     */
     749    if (hEvtSuspended != NIL_RTSEMEVENT)
     750        RTSemEventDestroy(hEvtSuspended);
     751
     752    RTMemCacheDestroy(pThis->hSgCache);
     753    pThis->hSgCache = NIL_RTMEMCACHE;
    772754
    773755    /*
    774756     * Deregister statistics in case we're being detached.
    775757     */
    776     PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cbStatRecv);
    777     PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cbStatSend);
    778     PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cStatRecvs);
    779     PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cStatSends);
     758    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Recv.cStatFrames);
     759    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Recv.cbStatWritten);
     760    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Recv.cOverflows);
     761    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Send.cStatFrames);
     762    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Send.cbStatWritten);
     763    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->Send.cOverflows);
     764    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cStatYieldsOk);
     765    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cStatYieldsNok);
    780766    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cStatLost);
    781     PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cStatYieldsNok);
     767    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->pBufR3->cStatBadFrames);
    782768#ifdef VBOX_WITH_STATISTICS
    783769    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatReceive);
     
    804790    pThis->hIf                                      = INTNET_HANDLE_INVALID;
    805791    pThis->Thread                                   = NIL_RTTHREAD;
    806     pThis->EventSuspended                           = NIL_RTSEMEVENT;
     792    pThis->hEvtSuspended                            = NIL_RTSEMEVENT;
     793    pThis->hSgCache                                 = NIL_RTMEMCACHE;
    807794    pThis->enmState                                 = ASYNCSTATE_SUSPENDED;
    808795    pThis->fActivateEarlyDeactivateLate             = false;
     
    812799    pThis->IBaseRC.pfnQueryInterface                = drvR3IntNetIBaseRC_QueryInterface;
    813800    /* INetworkUp */
    814     pThis->INetworkUpR3.pfnSendDeprecated           = drvR3IntNetSendDeprecated;
    815     pThis->INetworkUpR3.pfnSetPromiscuousMode       = drvR3IntNetSetPromiscuousMode;
    816     pThis->INetworkUpR3.pfnNotifyLinkChanged        = drvR3IntNetNotifyLinkChanged;
     801    pThis->INetworkUpR3.pfnAllocBuf                 = drvR3IntNetUp_AllocBuf;
     802    pThis->INetworkUpR3.pfnSendBuf                  = drvR3IntNetUp_SendBuf;
     803    pThis->INetworkUpR3.pfnSendDeprecated           = drvR3IntNetUp_SendDeprecated;
     804    pThis->INetworkUpR3.pfnSetPromiscuousMode       = drvR3IntNetUp_SetPromiscuousMode;
     805    pThis->INetworkUpR3.pfnNotifyLinkChanged        = drvR3IntNetUp_NotifyLinkChanged;
    817806
    818807    /*
     
    10791068
    10801069    /*
    1081      * Create the event semaphores
    1082      */
    1083     rc = RTSemEventCreate(&pThis->EventSuspended);
     1070     * Create the event semaphore and S/G cache.
     1071     */
     1072    rc = RTSemEventCreate(&pThis->hEvtSuspended);
     1073    if (RT_FAILURE(rc))
     1074        return rc;
     1075    rc = RTMemCacheCreate(&pThis->hSgCache, sizeof(PDMSCATTERGATHER), 0, UINT32_MAX, NULL, NULL, pThis, 0);
    10841076    if (RT_FAILURE(rc))
    10851077        return rc;
     
    11231115        return rc;
    11241116    }
    1125 
    1126     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cbStatRecv,     STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Number of received bytes.",    "/Net/IntNet%d/Bytes/Received", pDrvIns->iInstance);
    1127     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cbStatSend,     STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Number of sent bytes.",        "/Net/IntNet%d/Bytes/Sent", pDrvIns->iInstance);
    1128     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cStatRecvs,     STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of received packets.",  "/Net/IntNet%d/Packets/Received", pDrvIns->iInstance);
    1129     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cStatSends,     STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of sent packets.",      "/Net/IntNet%d/Packets/Sent", pDrvIns->iInstance);
    1130     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cStatLost,      STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of lost packets.",      "/Net/IntNet%d/Packets/Lost", pDrvIns->iInstance);
    1131     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cStatYieldsNok, STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of times yielding didn't help fix an overflow.",  "/Net/IntNet%d/YieldNok", pDrvIns->iInstance);
     1117    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->Recv.cbStatWritten, STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Number of received bytes.",    "/Net/IntNet%d/Bytes/Received", pDrvIns->iInstance);
     1118    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->Send.cbStatWritten, STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_BYTES, "Number of sent bytes.",        "/Net/IntNet%d/Bytes/Sent", pDrvIns->iInstance);
     1119    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->Recv.cOverflows,    STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number overflows.",            "/Net/IntNet%d/Overflows/Recv", pDrvIns->iInstance);
     1120    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->Send.cOverflows,    STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number overflows.",            "/Net/IntNet%d/Overflows/Sent", pDrvIns->iInstance);
     1121    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->Recv.cStatFrames,   STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of received packets.",  "/Net/IntNet%d/Packets/Received", pDrvIns->iInstance);
     1122    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->Send.cStatFrames,   STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of sent packets.",      "/Net/IntNet%d/Packets/Sent", pDrvIns->iInstance);
     1123    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cStatLost,          STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of lost packets.",      "/Net/IntNet%d/Packets/Lost", pDrvIns->iInstance);
     1124    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cStatYieldsNok,     STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of times yielding helped fix an overflow.",      "/Net/IntNet%d/YieldOk", pDrvIns->iInstance);
     1125    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cStatYieldsOk,      STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of times yielding didn't help fix an overflow.", "/Net/IntNet%d/YieldNok", pDrvIns->iInstance);
     1126    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->pBufR3->cStatBadFrames,     STAMTYPE_COUNTER,   STAMVISIBILITY_ALWAYS,  STAMUNIT_COUNT, "Number of bad frames seed by the consumers.",           "/Net/IntNet%d/BadFrames", pDrvIns->iInstance);
    11321127#ifdef VBOX_WITH_STATISTICS
    1133     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive,            STAMTYPE_PROFILE,   STAMVISIBILITY_ALWAYS,  STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.",  "/Net/IntNet%d/Receive", pDrvIns->iInstance);
    1134     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit,           STAMTYPE_PROFILE,   STAMVISIBILITY_ALWAYS,  STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Net/IntNet%d/Transmit", pDrvIns->iInstance);
     1128    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive,                STAMTYPE_PROFILE,   STAMVISIBILITY_ALWAYS,  STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.",  "/Net/IntNet%d/Receive", pDrvIns->iInstance);
     1129    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit,               STAMTYPE_PROFILE,   STAMVISIBILITY_ALWAYS,  STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Net/IntNet%d/Transmit", pDrvIns->iInstance);
    11351130#endif
    11361131
     
    11411136    {
    11421137        ASMAtomicXchgSize(&pThis->enmState, ASYNCSTATE_RUNNING);
    1143         RTSemEventSignal(pThis->EventSuspended);
     1138        RTSemEventSignal(pThis->hEvtSuspended);
    11441139        drvR3IntNetUpdateMacAddress(pThis);
    11451140        drvR3IntNetSetActive(pThis, true /* fActive */);
  • trunk/src/VBox/Devices/Network/DrvNAT.cpp

    r26495 r26574  
    217217
    218218
    219 /** Converts a pointer to NAT::INetworkUp to a PRDVNAT. */
    220 #define PDMINETWORKUP_2_DRVNAT(pInterface)   ( (PDRVNAT)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAT, INetworkUp)) )
    221219
    222220static DECLCALLBACK(void) drvNATSlowTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser)
     
    280278    return VINF_SUCCESS;
    281279}
     280
    282281static DECLCALLBACK(int) drvNATUrgRecvWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    283282{
     
    289288}
    290289
    291 static DECLCALLBACK(void) drvNATUrgRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, void *pvArg)
     290static DECLCALLBACK(void) drvNATUrgRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, struct mbuf *m)
    292291{
    293292    int rc = RTCritSectEnter(&pThis->csDevAccess);
     
    309308    AssertRC(rc);
    310309
    311     slirp_ext_m_free(pThis->pNATState, pvArg);
     310    slirp_ext_m_free(pThis->pNATState, m);
    312311#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    313312    RTMemFree(pu8Buf);
     
    321320
    322321
    323 static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, void *pvArg)
     322static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, struct mbuf *m)
    324323{
    325324    int rc;
     
    357356
    358357done_unlocked:
    359     slirp_ext_m_free(pThis->pNATState, pvArg);
     358    slirp_ext_m_free(pThis->pNATState, m);
    360359#ifdef VBOX_WITH_SLIRP_BSD_MBUF
    361360    RTMemFree(pu8Buf);
     
    370369
    371370/**
     371 * Frees a S/G buffer allocated by drvNATNetworkUp_AllocBuf.
     372 *
     373 * @param   pThis               Pointer to the NAT instance.
     374 * @param   pSgBuf              The S/G buffer to free.
     375 */
     376static void drvNATFreeSgBuf(PDRVNAT pThis, PPDMSCATTERGATHER pSgBuf)
     377{
     378    Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) == PDMSCATTERGATHER_FLAGS_MAGIC);
     379    pSgBuf->fFlags = 0;
     380    if (pSgBuf->pvAllocator)
     381    {
     382        slirp_ext_m_free(pThis->pNATState, (struct mbuf *)pSgBuf->pvAllocator);
     383        pSgBuf->pvAllocator = NULL;
     384    }
     385    RTMemFree(pSgBuf);
     386}
     387
     388/**
    372389 * Worker function for drvNATSend().
    373  * @thread "NAT" thread.
    374  */
    375 static void drvNATSendWorker(PDRVNAT pThis, void *pvBuf, size_t cb)
     390 *
     391 * @param   pThis               Pointer to the NAT instance.
     392 * @param   pSgBuf              The scatter/gather buffer.
     393 * @thread  NAT
     394 */
     395static void drvNATSendWorker(PDRVNAT pThis, PPDMSCATTERGATHER pSgBuf)
    376396{
    377397    Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP);
    378398    if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP)
    379         slirp_input(pThis->pNATState, (uint8_t *)pvBuf);
    380 }
    381 
     399    {
     400        struct mbuf *m = (struct mbuf *)pSgBuf->pvAllocator;
     401        pSgBuf->pvAllocator = NULL;
     402        slirp_input(pThis->pNATState, m, pSgBuf->cbUsed);
     403    }
     404    drvNATFreeSgBuf(pThis, pSgBuf);
     405
     406    /** @todo Implement the VERR_TRY_AGAIN drvNATNetworkUp_AllocBuf sematics. */
     407}
     408
     409/**
     410 * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
     411 */
     412static DECLCALLBACK(int) drvNATNetworkUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbMin, PPPDMSCATTERGATHER ppSgBuf)
     413{
     414    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
     415
     416    /*
     417     * Drop the incoming frame if the NAT thread isn't running.
     418     */
     419    if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING)
     420    {
     421        Log(("drvNATNetowrkUp_AllocBuf: returns VERR_NET_NO_NETWORK\n"));
     422        return VERR_NET_NO_NETWORK;
     423    }
     424
     425    /*
     426     * Allocate a scatter/gather buffer and an mbuf.
     427     */
     428    PPDMSCATTERGATHER pSgBuf = (PPDMSCATTERGATHER)RTMemAlloc(sizeof(*pSgBuf));
     429    if (!pSgBuf)
     430        return VERR_NO_MEMORY;
     431    pSgBuf->pvAllocator = slirp_ext_m_get(pThis->pNATState, cbMin,
     432                                          &pSgBuf->aSegs[0].pvSeg, &pSgBuf->aSegs[0].cbSeg);
     433    if (!pSgBuf->pvAllocator)
     434    {
     435        RTMemFree(pSgBuf);
     436        /** @todo Implement the VERR_TRY_AGAIN sematics. */
     437        return VERR_NO_MEMORY;
     438    }
     439
     440    /*
     441     * Initialize the S/G buffer and return.
     442     */
     443    pSgBuf->fFlags      = PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1;
     444    pSgBuf->cbUsed      = 0;
     445    pSgBuf->cbAvailable = pSgBuf->aSegs[0].cbSeg;
     446    pSgBuf->pvUser      = NULL;
     447    pSgBuf->cSegs       = 1;
     448
     449    *ppSgBuf = pSgBuf;
     450    return VINF_SUCCESS;
     451}
     452
     453/**
     454 * @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
     455 */
     456static DECLCALLBACK(int) drvNATNetworkUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
     457{
     458    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
     459    Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_OWNER_MASK) == PDMSCATTERGATHER_FLAGS_OWNER_1);
     460
     461    int rc;
     462    if (pThis->pSlirpThread->enmState == PDMTHREADSTATE_RUNNING)
     463    {
     464#ifdef VBOX_WITH_SLIRP_MT
     465        PRTREQQUEUE pQueue = (PRTREQQUEUE)slirp_get_queue(pThis->pNATState);
     466#else
     467        PRTREQQUEUE pQueue = pThis->pSlirpReqQueue;
     468#endif
     469        rc = RTReqCallEx(pQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     470                         (PFNRT)drvNATSendWorker, 2, pThis, pSgBuf);
     471        if (RT_SUCCESS(rc))
     472        {
     473            drvNATNotifyNATThread(pThis);
     474            return VINF_SUCCESS;
     475        }
     476
     477        rc = VERR_NET_NO_BUFFER_SPACE;
     478    }
     479    else
     480        rc = VERR_NET_DOWN;
     481    drvNATFreeSgBuf(pThis, pSgBuf);
     482    return rc;
     483}
    382484
    383485/**
    384486 * @interface_method_impl{PDMINETWORKUP,pfnSendDeprecated}
    385487 */
    386 static DECLCALLBACK(int) drvNATSendDeprecated(PPDMINETWORKUP pInterface, const void *pvBuf, size_t cb)
    387 {
    388     PDRVNAT pThis = PDMINETWORKUP_2_DRVNAT(pInterface);
    389 
    390     LogFlow(("drvNATSend: pvBuf=%p cb=%#x\n", pvBuf, cb));
    391     Log2(("drvNATSend: pvBuf=%p cb=%#x\n%.*Rhxd\n", pvBuf, cb, cb, pvBuf));
    392 
    393     PRTREQ pReq = NULL;
    394     int rc;
    395     void *buf;
    396 
    397     /* don't queue new requests when the NAT thread is about to stop */
    398     if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING)
    399         return VINF_SUCCESS;
    400 
    401 #ifndef VBOX_WITH_SLIRP_MT
    402     rc = RTReqAlloc(pThis->pSlirpReqQueue, &pReq, RTREQTYPE_INTERNAL);
    403 #else
    404     rc = RTReqAlloc((PRTREQQUEUE)slirp_get_queue(pThis->pNATState), &pReq, RTREQTYPE_INTERNAL);
    405 #endif
    406     AssertRC(rc);
    407 
    408     /* @todo: Here we should get mbuf instead temporal buffer */
    409 #ifndef VBOX_WITH_SLIRP_BSD_MBUF
    410     void *pvmBuf = slirp_ext_m_get(pThis->pNATState);
    411     Assert(pvmBuf);
    412     slirp_ext_m_append(pThis->pNATState, pvmBuf, (uint8_t *)pvBuf, cb);
    413 #else
    414     void *pvmBuf = slirp_ext_m_get(pThis->pNATState, (uint8_t *)pvBuf, cb);
    415     Assert(pvmBuf);
    416 #endif
    417 
    418     pReq->u.Internal.pfn      = (PFNRT)drvNATSendWorker;
    419     pReq->u.Internal.cArgs    = 2;
    420     pReq->u.Internal.aArgs[0] = (uintptr_t)pThis;
    421     pReq->u.Internal.aArgs[1] = (uintptr_t)pvmBuf;
    422     pReq->fFlags              = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT;
    423 
    424     rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */
    425     AssertRC(rc);
    426     drvNATNotifyNATThread(pThis);
    427     LogFlow(("drvNATSend: end\n"));
     488static DECLCALLBACK(int) drvNATNetworkUp_SendDeprecated(PPDMINETWORKUP pInterface, const void *pvBuf, size_t cb)
     489{
     490    PPDMSCATTERGATHER pSgBuf;
     491    int rc = drvNATNetworkUp_AllocBuf(pInterface, cb, &pSgBuf);
     492    if (RT_SUCCESS(rc))
     493    {
     494        memcpy(pSgBuf->aSegs[0].pvSeg, pvBuf, cb);
     495        pSgBuf->cbUsed = cb;
     496        rc = drvNATNetworkUp_SendBuf(pInterface, pSgBuf, false);
     497    }
     498    LogFlow(("drvNATNetworkUp_SendDeprecated: (rc=%Rrc)\n", rc));
    428499    return VINF_SUCCESS;
    429500}
    430 
    431501
    432502/**
     
    446516}
    447517
    448 
    449518/**
    450519 * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
    451520 */
    452 static DECLCALLBACK(void) drvNATSetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
    453 {
    454     LogFlow(("drvNATSetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
     521static DECLCALLBACK(void) drvNATNetworkUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
     522{
     523    LogFlow(("drvNATNetworkUp_SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
    455524    /* nothing to do */
    456525}
    457526
    458527/**
    459  * Worker function for drvNATNotifyLinkChanged().
     528 * Worker function for drvNATNetworkUp_NotifyLinkChanged().
    460529 * @thread "NAT" thread.
    461530 */
     
    478547
    479548        default:
    480             AssertMsgFailed(("drvNATNotifyLinkChanged: unexpected link state %d\n", enmLinkState));
    481     }
    482 }
    483 
     549            AssertMsgFailed(("drvNATNetworkUp_NotifyLinkChanged: unexpected link state %d\n", enmLinkState));
     550    }
     551}
    484552
    485553/**
     
    490558 * @thread  EMT
    491559 */
    492 static DECLCALLBACK(void) drvNATNotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
    493 {
    494     PDRVNAT pThis = PDMINETWORKUP_2_DRVNAT(pInterface);
    495 
    496     LogFlow(("drvNATNotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
    497 
    498     PRTREQ pReq = NULL;
     560static DECLCALLBACK(void) drvNATNetworkUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
     561{
     562    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
     563
     564    LogFlow(("drvNATNetworkUp_NotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
    499565
    500566    /* don't queue new requests when the NAT thread is about to stop */
     
    502568        return;
    503569
    504     int rc = RTReqAlloc(pThis->pSlirpReqQueue, &pReq, RTREQTYPE_INTERNAL);
    505     AssertRC(rc);
    506     pReq->u.Internal.pfn      = (PFNRT)drvNATNotifyLinkChangedWorker;
    507     pReq->u.Internal.cArgs    = 2;
    508     pReq->u.Internal.aArgs[0] = (uintptr_t)pThis;
    509     pReq->u.Internal.aArgs[1] = (uintptr_t)enmLinkState;
    510     pReq->fFlags              = RTREQFLAGS_VOID;
    511     rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */
     570    PRTREQ pReq;
     571    int rc = RTReqCallEx(pThis->pSlirpReqQueue, &pReq, 0 /*cMillies*/, RTREQFLAGS_VOID,
     572                         (PFNRT)drvNATNotifyLinkChangedWorker, 2, pThis, enmLinkState);
    512573    if (RT_LIKELY(rc == VERR_TIMEOUT))
    513574    {
     
    522583
    523584/**
    524  * NAT thread handling the slirp stuff. The slirp implementation is single-threaded
    525  * so we execute this enginre in a dedicated thread. We take care that this thread
    526  * does not become the bottleneck: If the guest wants to send, a request is enqueued
    527  * into the pSlirpReqQueue and handled asynchronously by this thread. If this thread
    528  * wants to deliver packets to the guest, it enqueues a request into pRecvReqQueue
    529  * which is later handled by the Recv thread.
     585 * NAT thread handling the slirp stuff.
     586 *
     587 * The slirp implementation is single-threaded so we execute this enginre in a
     588 * dedicated thread. We take care that this thread does not become the
     589 * bottleneck: If the guest wants to send, a request is enqueued into the
     590 * pSlirpReqQueue and handled asynchronously by this thread.  If this thread
     591 * wants to deliver packets to the guest, it enqueues a request into
     592 * pRecvReqQueue which is later handled by the Recv thread.
    530593 */
    531594static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     
    736799}
    737800
    738 void slirp_urg_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb)
     801void slirp_urg_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
    739802{
    740803    PDRVNAT pThis = (PDRVNAT)pvUser;
     
    747810        return;
    748811
    749     int rc = RTReqAlloc(pThis->pUrgRecvReqQueue, &pReq, RTREQTYPE_INTERNAL);
    750     AssertRC(rc);
    751812    ASMAtomicIncU32(&pThis->cUrgPkt);
    752     pReq->u.Internal.pfn      = (PFNRT)drvNATUrgRecvWorker;
    753     pReq->u.Internal.cArgs    = 4;
    754     pReq->u.Internal.aArgs[0] = (uintptr_t)pThis;
    755     pReq->u.Internal.aArgs[1] = (uintptr_t)pu8Buf;
    756     pReq->u.Internal.aArgs[2] = (uintptr_t)cb;
    757     pReq->u.Internal.aArgs[3] = (uintptr_t)pvArg;
    758     pReq->fFlags              = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT;
    759     rc = RTReqQueue(pReq, 0);
     813    int rc = RTReqCallEx(pThis->pUrgRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     814                         (PFNRT)drvNATUrgRecvWorker, 4, pThis, pu8Buf, cb, m);
    760815    AssertRC(rc);
    761816    drvNATUrgRecvWakeup(pThis->pDrvIns, pThis->pUrgRecvThread);
     
    763818
    764819/**
    765  * Function called by slirp to feed incoming data to the network port.
    766  */
    767 void slirp_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb)
     820 * Function called by slirp to feed incoming data to the NIC.
     821 */
     822void slirp_output(void *pvUser, struct mbuf *m, const uint8_t *pu8Buf, int cb)
    768823{
    769824    PDRVNAT pThis = (PDRVNAT)pvUser;
     
    779834        return;
    780835
    781     int rc = RTReqAlloc(pThis->pRecvReqQueue, &pReq, RTREQTYPE_INTERNAL);
    782     AssertRC(rc);
    783836    ASMAtomicIncU32(&pThis->cPkt);
    784     pReq->u.Internal.pfn      = (PFNRT)drvNATRecvWorker;
    785     pReq->u.Internal.cArgs    = 4;
    786     pReq->u.Internal.aArgs[0] = (uintptr_t)pThis;
    787     pReq->u.Internal.aArgs[1] = (uintptr_t)pu8Buf;
    788     pReq->u.Internal.aArgs[2] = (uintptr_t)cb;
    789     pReq->u.Internal.aArgs[3] = (uintptr_t)pvArg;
    790     pReq->fFlags              = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT;
    791     rc = RTReqQueue(pReq, 0);
     837    int rc = RTReqCallEx(pThis->pRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     838                         (PFNRT)drvNATRecvWorker, 4, pThis, pu8Buf, cb, m);
    792839    AssertRC(rc);
    793840    drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread);
     
    9861033    pDrvIns->IBase.pfnQueryInterface    = drvNATQueryInterface;
    9871034    /* INetwork */
    988 /** @todo implement the new INetworkUp interfaces. */
    989     pThis->INetworkUp.pfnSendDeprecated     = drvNATSendDeprecated;
    990     pThis->INetworkUp.pfnSetPromiscuousMode = drvNATSetPromiscuousMode;
    991     pThis->INetworkUp.pfnNotifyLinkChanged  = drvNATNotifyLinkChanged;
     1035    pThis->INetworkUp.pfnAllocBuf           = drvNATNetworkUp_AllocBuf;
     1036    pThis->INetworkUp.pfnSendBuf            = drvNATNetworkUp_SendBuf;
     1037    pThis->INetworkUp.pfnSendDeprecated     = drvNATNetworkUp_SendDeprecated;
     1038    pThis->INetworkUp.pfnSetPromiscuousMode = drvNATNetworkUp_SetPromiscuousMode;
     1039    pThis->INetworkUp.pfnNotifyLinkChanged  = drvNATNetworkUp_NotifyLinkChanged;
    9921040
    9931041    /*
  • trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp

    r25339 r26574  
    2626#define LOG_GROUP LOG_GROUP_SRV_INTNET
    2727#include <VBox/intnet.h>
     28#include <VBox/intnetinline.h>
    2829#include <VBox/sup.h>
    2930#include <VBox/pdm.h>
     
    15361537
    15371538
    1538 #ifdef IN_INTNET_TESTCASE
    1539 /**
    1540  * Reads the next frame in the buffer.
    1541  * The caller is responsible for ensuring that there is a valid frame in the buffer.
    1542  *
    1543  * @returns Size of the frame in bytes.
    1544  * @param   pBuf        The buffer.
    1545  * @param   pRingBuff   The ring buffer to read from.
    1546  * @param   pvFrame     Where to put the frame. The caller is responsible for
    1547  *                      ensuring that there is sufficient space for the frame.
    1548  */
    1549 static unsigned intnetR0RingReadFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf, void *pvFrame)
    1550 {
    1551     Assert(pRingBuf->offRead < pBuf->cbBuf);
    1552     Assert(pRingBuf->offRead >= pRingBuf->offStart);
    1553     Assert(pRingBuf->offRead < pRingBuf->offEnd);
    1554     uint32_t    offRead   = pRingBuf->offRead;
    1555     PINTNETHDR  pHdr      = (PINTNETHDR)((uint8_t *)pBuf + offRead);
    1556     const void *pvFrameIn = INTNETHdrGetFramePtr(pHdr, pBuf);
    1557     unsigned    cb        = pHdr->cbFrame;
    1558     memcpy(pvFrame, pvFrameIn, cb);
    1559 
    1560     /* skip the frame */
    1561     offRead += pHdr->offFrame + cb;
    1562     offRead = RT_ALIGN_32(offRead, sizeof(INTNETHDR));
    1563     Assert(offRead <= pRingBuf->offEnd && offRead >= pRingBuf->offStart);
    1564     if (offRead >= pRingBuf->offEnd)
    1565         offRead = pRingBuf->offStart;
    1566     ASMAtomicXchgU32(&pRingBuf->offRead, offRead);
    1567     return cb;
    1568 }
    1569 #endif /* IN_INTNET_TESTCASE */
    1570 
    1571 
    1572 /**
    1573  * Writes a frame packet to the buffer.
     1539/**
     1540 * Writes a frame packet to the ring buffer.
    15741541 *
    15751542 * @returns VBox status code.
     
    15791546 * @param   pNewDstMac      Set the destination MAC address to the address if specified.
    15801547 */
    1581 static int intnetR0RingWriteFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf, PCINTNETSG pSG, PCRTMAC pNewDstMac)
    1582 {
    1583     /*
    1584      * Validate input.
    1585      */
    1586     AssertPtr(pBuf);
    1587     AssertPtr(pRingBuf);
    1588     AssertPtr(pSG);
    1589     Assert(pSG->cbTotal >= sizeof(RTMAC) * 2);
    1590     uint32_t offWrite = pRingBuf->offWrite;
    1591     Assert(offWrite == RT_ALIGN_32(offWrite, sizeof(INTNETHDR)));
    1592     uint32_t offRead = pRingBuf->offRead;
    1593     Assert(offRead == RT_ALIGN_32(offRead, sizeof(INTNETHDR)));
    1594 
    1595     const uint32_t cb = RT_ALIGN_32(pSG->cbTotal, sizeof(INTNETHDR));
    1596     if (offRead <= offWrite)
    1597     {
    1598         /*
    1599          * Try fit it all before the end of the buffer.
    1600          */
    1601         if (pRingBuf->offEnd - offWrite >= cb + sizeof(INTNETHDR))
    1602         {
    1603             PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    1604             pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    1605             pHdr->cbFrame  = pSG->cbTotal;
    1606             pHdr->offFrame = sizeof(INTNETHDR);
    1607 
    1608             intnetR0SgRead(pSG, pHdr + 1);
    1609             if (pNewDstMac)
    1610                 ((PRTNETETHERHDR)(pHdr + 1))->DstMac = *pNewDstMac;
    1611 
    1612             offWrite += cb + sizeof(INTNETHDR);
    1613             Assert(offWrite <= pRingBuf->offEnd && offWrite >= pRingBuf->offStart);
    1614             if (offWrite >= pRingBuf->offEnd)
    1615                 offWrite = pRingBuf->offStart;
    1616             Log2(("WriteFrame: offWrite: %#x -> %#x (1)\n", pRingBuf->offWrite, offWrite));
    1617             ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
    1618             return VINF_SUCCESS;
    1619         }
    1620 
    1621         /*
    1622          * Try fit the frame at the start of the buffer.
    1623          * (The header fits before the end of the buffer because of alignment.)
    1624          */
    1625         AssertMsg(pRingBuf->offEnd - offWrite >= sizeof(INTNETHDR), ("offEnd=%x offWrite=%x\n", pRingBuf->offEnd, offWrite));
    1626         if (offRead - pRingBuf->offStart > cb) /* not >= ! */
    1627         {
    1628             PINTNETHDR  pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    1629             void       *pvFrameOut = (PINTNETHDR)((uint8_t *)pBuf + pRingBuf->offStart);
    1630             pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    1631             pHdr->cbFrame  = pSG->cbTotal;
    1632             pHdr->offFrame = (intptr_t)pvFrameOut - (intptr_t)pHdr;
    1633 
    1634             intnetR0SgRead(pSG, pvFrameOut);
    1635             if (pNewDstMac)
    1636                 ((PRTNETETHERHDR)pvFrameOut)->DstMac = *pNewDstMac;
    1637 
    1638             offWrite = pRingBuf->offStart + cb;
    1639             ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
    1640             Log2(("WriteFrame: offWrite: %#x -> %#x (2)\n", pRingBuf->offWrite, offWrite));
    1641             return VINF_SUCCESS;
    1642         }
    1643     }
    1644     /*
    1645      * The reader is ahead of the writer, try fit it into that space.
    1646      */
    1647     else if (offRead - offWrite > cb + sizeof(INTNETHDR)) /* not >= ! */
    1648     {
    1649         PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    1650         pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    1651         pHdr->cbFrame  = pSG->cbTotal;
    1652         pHdr->offFrame = sizeof(INTNETHDR);
    1653 
    1654         intnetR0SgRead(pSG, pHdr + 1);
     1548static int intnetR0RingWriteFrame(PINTNETRINGBUF pRingBuf, PCINTNETSG pSG, PCRTMAC pNewDstMac)
     1549{
     1550    PINTNETHDR  pHdr;
     1551    void       *pvDst;
     1552    int rc = INTNETRingAllocateFrame(pRingBuf, pSG->cbTotal, &pHdr, &pvDst);
     1553    if (RT_SUCCESS(rc))
     1554    {
     1555        intnetR0SgRead(pSG, pvDst);
    16551556        if (pNewDstMac)
    1656             ((PRTNETETHERHDR)(pHdr + 1))->DstMac = *pNewDstMac;
    1657 
    1658         offWrite += cb + sizeof(INTNETHDR);
    1659         ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
    1660         Log2(("WriteFrame: offWrite: %#x -> %#x (3)\n", pRingBuf->offWrite, offWrite));
     1557            ((PRTNETETHERHDR)pvDst)->DstMac = *pNewDstMac;
     1558
     1559        INTNETRingCommitFrame(pRingBuf, pHdr);
    16611560        return VINF_SUCCESS;
    16621561    }
    1663 
    1664     /* (it didn't fit) */
    1665     /** @todo stats */
    1666     return VERR_BUFFER_OVERFLOW;
     1562    return rc;
    16671563}
    16681564
     
    16791575{
    16801576//    LogFlow(("intnetR0IfSend: pIf=%p:{.hIf=%RX32}\n", pIf, pIf->hIf));
    1681     int rc = intnetR0RingWriteFrame(pIf->pIntBuf, &pIf->pIntBuf->Recv, pSG, pNewDstMac);
     1577    int rc = intnetR0RingWriteFrame(&pIf->pIntBuf->Recv, pSG, pNewDstMac);
    16821578    if (RT_SUCCESS(rc))
    16831579    {
    16841580        pIf->cYields = 0;
    1685         STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatRecvs);
    1686         STAM_REL_COUNTER_ADD(&pIf->pIntBuf->cbStatRecv, pSG->cbTotal);
    16871581        RTSemEventSignal(pIf->Event);
    16881582        return;
     
    17171611            RTSemEventSignal(pIf->Event);
    17181612            RTThreadYield();
    1719             rc = intnetR0RingWriteFrame(pIf->pIntBuf, &pIf->pIntBuf->Recv, pSG, pNewDstMac);
     1613            rc = intnetR0RingWriteFrame(&pIf->pIntBuf->Recv, pSG, pNewDstMac);
    17201614            if (RT_SUCCESS(rc))
    17211615            {
    17221616                STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatYieldsOk);
    1723                 STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatRecvs);
    1724                 STAM_REL_COUNTER_ADD(&pIf->pIntBuf->cbStatRecv, pSG->cbTotal);
    17251617                RTSemEventSignal(pIf->Event);
    17261618                return;
     
    23732265
    23742266    /*
    2375      * Send statistics.
    2376      */
    2377     if (pIfSender)
    2378     {
    2379         STAM_REL_COUNTER_INC(&pIfSender->pIntBuf->cStatSends);
    2380         STAM_REL_COUNTER_ADD(&pIfSender->pIntBuf->cbStatSend, pSG->cbTotal);
    2381     }
    2382 
    2383     /*
    23842267     * Get the ethernet header (might theoretically involve multiple segments).
    23852268     */
     
    25182401     * Process the send buffer.
    25192402     */
    2520     while (pIf->pIntBuf->Send.offRead != pIf->pIntBuf->Send.offWrite)
     2403    PINTNETHDR pHdr;
     2404    while ((pHdr = INTNETRingGetNextFrameToRead(&pIf->pIntBuf->Send)) != NULL)
    25212405    {
    25222406        /* Send the frame if the type is sane. */
    2523         PINTNETHDR pHdr = (PINTNETHDR)((uintptr_t)pIf->pIntBuf + pIf->pIntBuf->Send.offRead);
    25242407        if (pHdr->u16Type == INTNETHDR_TYPE_FRAME)
    25252408        {
     
    25332416            }
    25342417        }
    2535         /* else: ignore the frame */
     2418        else
     2419            STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatBadFrames); /* ignore */
    25362420
    25372421        /* Skip to the next frame. */
    2538         INTNETRingSkipFrame(pIf->pIntBuf, &pIf->pIntBuf->Send);
     2422        INTNETRingSkipFrame(&pIf->pIntBuf->Send);
    25392423    }
    25402424
     
    33373221         */
    33383222        /** @todo adjust with minimums and apply defaults here. */
    3339         cbRecv = RT_ALIGN(RT_MAX(cbRecv, sizeof(INTNETHDR) * 4), sizeof(INTNETHDR));
    3340         cbSend = RT_ALIGN(RT_MAX(cbSend, sizeof(INTNETHDR) * 4), sizeof(INTNETHDR));
    3341         const unsigned cbBuf = RT_ALIGN(sizeof(*pIf->pIntBuf), sizeof(INTNETHDR)) + cbRecv + cbSend;
     3223        cbRecv = RT_ALIGN(RT_MAX(cbRecv, sizeof(INTNETHDR) * 4), INTNETRINGBUF_ALIGNMENT);
     3224        cbSend = RT_ALIGN(RT_MAX(cbSend, sizeof(INTNETHDR) * 4), INTNETRINGBUF_ALIGNMENT);
     3225        const unsigned cbBuf = RT_ALIGN(sizeof(*pIf->pIntBuf), INTNETRINGBUF_ALIGNMENT) + cbRecv + cbSend;
    33423226        rc = SUPR0MemAlloc(pIf->pSession, cbBuf, (PRTR0PTR)&pIf->pIntBufDefault, (PRTR3PTR)&pIf->pIntBufDefaultR3);
    33433227        if (RT_SUCCESS(rc))
     
    33473231            pIf->pIntBuf = pIf->pIntBufDefault;
    33483232            pIf->pIntBufR3 = pIf->pIntBufDefaultR3;
    3349             pIf->pIntBuf->cbBuf = cbBuf;
    3350             pIf->pIntBuf->cbRecv = cbRecv;
    3351             pIf->pIntBuf->cbSend = cbSend;
    3352             /* receive ring buffer. */
    3353             pIf->pIntBuf->Recv.offStart = RT_ALIGN_32(sizeof(*pIf->pIntBuf), sizeof(INTNETHDR));
    3354             pIf->pIntBuf->Recv.offRead  = pIf->pIntBuf->Recv.offStart;
    3355             pIf->pIntBuf->Recv.offWrite = pIf->pIntBuf->Recv.offStart;
    3356             pIf->pIntBuf->Recv.offEnd   = pIf->pIntBuf->Recv.offStart + cbRecv;
    3357             /* send ring buffer. */
    3358             pIf->pIntBuf->Send.offStart = pIf->pIntBuf->Recv.offEnd;
    3359             pIf->pIntBuf->Send.offRead  = pIf->pIntBuf->Send.offStart;
    3360             pIf->pIntBuf->Send.offWrite = pIf->pIntBuf->Send.offStart;
    3361             pIf->pIntBuf->Send.offEnd   = pIf->pIntBuf->Send.offStart + cbSend;
     3233            INTNETBufInit(pIf->pIntBuf, cbBuf, cbRecv, cbSend);
    33623234
    33633235            /*
     
    41073979        case kIntNetTrunkType_None:
    41083980        case kIntNetTrunkType_WhateverNone:
    4109             AssertReturn(!*pszTrunk, VERR_INVALID_PARAMETER);
     3981            if (*pszTrunk)
     3982                return VERR_INVALID_PARAMETER;
    41103983            break;
    41113984
    41123985        case kIntNetTrunkType_NetFlt:
    41133986        case kIntNetTrunkType_NetAdp:
    4114             AssertReturn(pszTrunk, VERR_INVALID_PARAMETER);
     3987            if (!*pszTrunk)
     3988                return VERR_INVALID_PARAMETER;
    41153989            break;
    41163990
     
    41304004
    41314005    /*
    4132      * Try open / create the network and create an interface on it for the caller to use.
     4006     * Try open / create the network and create an interface on it for the
     4007     * caller to use.
    41334008     *
    4134      * Note that because of the destructors grabbing INTNET::FastMutex and us being required
    4135      * to own this semaphore for the entire network opening / creation and interface creation
    4136      * sequence, intnetR0CreateNetwork will have to defer the network cleanup to us on failure.
     4009     * Note! Because of the destructors grabbing INTNET::FastMutex and us being
     4010     * required to own this semaphore for the entire network opening / creation
     4011     * and interface creation sequence, intnetR0CreateNetwork will have to
     4012     * defer the network cleanup to us on failure.
    41374013     */
    41384014    PINTNETNETWORK pNetwork = NULL;
     
    42314107    if (pIntNet)
    42324108    {
    4233         //pIntNet->pNetworks              = NULL;
     4109        //pIntNet->pNetworks = NULL;
    42344110
    42354111        rc = RTSemFastMutexCreate(&pIntNet->FastMutex);
  • trunk/src/VBox/Devices/Network/slirp/ip_icmp.c

    r26405 r26574  
    587587    new_m_size = sizeof(struct ip) + ICMP_MINLEN + msrc->m_len + ICMP_MAXDATALEN;
    588588    if (new_m_size > m->m_size)
     589    {
    589590        m_inc(m, new_m_size);
     591        if (new_m_size > m->m_size)
     592            goto end_error_free_m;
     593    }
    590594#endif
    591595
     
    667671    return;
    668672
     673end_error_free_m:
     674    m_free(pData, m);
    669675end_error:
    670676    LogRel(("NAT: error occurred while sending ICMP error message \n"));
  • trunk/src/VBox/Devices/Network/slirp/libslirp.h

    r26404 r26574  
    2323
    2424typedef struct NATState *PNATState;
     25struct mbuf;
    2526
    2627#ifdef __cplusplus
     
    4849#endif /* !RT_OS_WINDOWS */
    4950
    50 void slirp_input(PNATState pData, void *pvData);
     51void slirp_input(PNATState pData, struct mbuf *m, size_t cbBuf);
    5152void slirp_set_ethaddr_and_activate_port_forwarding(PNATState pData, const uint8_t *ethaddr, uint32_t GuestIP);
    5253
     
    5556void slirp_arm_slow_timer(void *pvUser);
    5657int slirp_can_output(void * pvUser);
    57 void slirp_output(void * pvUser, void *pvArg, const uint8_t *pkt, int pkt_len);
    58 void slirp_urg_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb);
     58void slirp_output(void * pvUser, struct mbuf *m, const uint8_t *pkt, int pkt_len);
     59void slirp_urg_output(void *pvUser, struct mbuf *, const uint8_t *pu8Buf, int cb);
    5960void slirp_post_sent(PNATState pData, void *pvArg);
    6061
     
    114115void *slirp_get_queue(PNATState pData);
    115116#endif
     117
    116118#ifndef VBOX_WITH_SLIRP_BSD_MBUF
    117 void *slirp_ext_m_get(PNATState pData);
    118 void slirp_ext_m_free(PNATState pData, void *);
    119 void slirp_ext_m_append(PNATState pData, void *, uint8_t *, size_t);
     119struct mbuf *slirp_ext_m_get(PNATState pData, size_t cbMin, void **ppvBuf, size_t *pcbBuf);
     120void slirp_ext_m_free(PNATState pData, struct mbuf *);
     121void slirp_ext_m_append(PNATState pData, struct mbuf *, uint8_t *, size_t);
    120122void slirp_push_recv_thread(void *pvUser);
    121123#else
  • trunk/src/VBox/Devices/Network/slirp/mbuf.c

    r26495 r26574  
    267267    if (m->m_flags & M_EXT)
    268268    {
     269        void *pvNew;
    269270        datasize = m->m_data - m->m_ext;
    270         m->m_ext = (char *)RTMemRealloc(m->m_ext, size);
    271 #if 0
    272         if (m->m_ext == NULL)
    273             return (struct mbuf *)NULL;
    274 #endif
     271        pvNew = (char *)RTMemRealloc(m->m_ext, size);
     272        if (pvNew)
     273            return; /** @todo better error reporting. */
     274        m->m_ext = (char *)pvNew;
    275275        m->m_data = m->m_ext + datasize;
    276276    }
     
    280280        datasize = m->m_data - m->m_dat;
    281281        dat = (char *)RTMemAlloc(size);
    282 #if 0
    283         if (dat == NULL)
    284             return (struct mbuf *)NULL;
    285 #endif
     282        if (!dat)
     283            return; /** @todo better error reporting. */
    286284        memcpy(dat, m->m_dat, m->m_size);
    287285
     
    365363    return (struct mbuf *)0;
    366364}
     365
    367366#ifndef VBOX_WITH_SLIRP_BSD_MBUF
    368 void *slirp_ext_m_get(PNATState pData)
    369 {
    370     return (void *)m_get(pData);
    371 }
    372 
    373 void slirp_ext_m_free(PNATState pData, void *arg)
    374 {
    375     struct mbuf *m = (struct mbuf *)arg;
     367
     368/**
     369 * Interface that DrvNAT.cpp uses for allocating a buffer.
     370 *
     371 * @returns Opaque m_buf pointer.
     372 *
     373 * @param   pData       The NAT state.
     374 * @param   cbMin       The minimum buffer size.
     375 * @param   ppvBuf      Where to return the pointer to the start of the data
     376 *                      buffer.
     377 * @param   pcbBuf      Where to return the actual buffer size.
     378 */
     379struct mbuf *slirp_ext_m_get(PNATState pData, size_t cbMin, void **ppvBuf, size_t *pcbBuf)
     380{
     381    struct mbuf *m = m_get(pData);
     382    if (!m)
     383        return NULL;
     384    if (cbMin > M_FREEROOM(m))
     385    {
     386        m_inc(m, cbMin);
     387        if (RT_UNLIKELY(cbMin > M_FREEROOM(m)))
     388        {
     389            m_free(pData, m);
     390            return NULL;
     391        }
     392    }
     393
     394    *ppvBuf = mtod(m, void *);
     395    *pcbBuf = M_FREEROOM(m);
     396    return m;
     397}
     398
     399void slirp_ext_m_free(PNATState pData, struct mbuf *m)
     400{
    376401    m_free(pData, m);
    377402}
    378 void slirp_ext_m_append(PNATState pData, void *arg, uint8_t *pu8Buf, size_t cbBuf)
     403
     404void slirp_ext_m_append(PNATState pData, struct mbuf *m, uint8_t *pu8Buf, size_t cbBuf)
    379405{
    380406    char *c;
    381     struct mbuf *m = (struct mbuf *)arg;
    382407    if (cbBuf > M_FREEROOM(m))
    383408    {
    384409        m_inc(m, cbBuf);
     410        if (RT_UNLIKELY(cbBuf > M_FREEROOM(m)))
     411            cbBuf = M_FREEROOM(m);
    385412    }
    386413    c = mtod(m, char *);
     
    388415    m->m_len = cbBuf;
    389416}
    390 #endif
     417
     418#endif /* VBOX_WITH_SLIRP_BSD_MBUF */
  • trunk/src/VBox/Devices/Network/slirp/slirp.c

    r26495 r26574  
    15611561}
    15621562
    1563 void slirp_input(PNATState pData, void *pvArg)
    1564 {
    1565     struct mbuf *m;
     1563/**
     1564 * Feed a packet into the slirp engine.
     1565 *
     1566 * @param   m               Data buffer, m_len is not valid.
     1567 * @param   cbBuf           The length of the data in m.
     1568 */
     1569void slirp_input(PNATState pData, struct mbuf *m, size_t cbBuf)
     1570{
    15661571    int proto;
    15671572    static bool fWarnedIpv6;
     
    15691574    uint8_t au8Ether[ETH_ALEN];
    15701575
    1571     m = (struct mbuf *)pvArg;
    1572     if (m->m_len < ETH_HLEN)
    1573     {
    1574         LogRel(("NAT: packet having size %d has been ingnored\n", m->m_len));
     1576    m->m_len = cbBuf;
     1577    if (cbBuf < ETH_HLEN)
     1578    {
     1579        LogRel(("NAT: packet having size %d has been ignored\n", m->m_len));
    15751580        m_free(pData, m);
    15761581        return;
  • trunk/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp

    r26517 r26574  
    2424*******************************************************************************/
    2525#include <VBox/intnet.h>
     26#include <VBox/intnetinline.h>
    2627#include <VBox/sup.h>
    2728#include <VBox/vmm.h>
     
    167168
    168169/**
    169  * Writes a frame packet to the buffer.
    170  *
    171  * @returns VBox status code.
    172  * @param   pBuf        The buffer.
    173  * @param   pRingBuf    The ring buffer to read from.
    174  * @param   pvFrame     The frame to write.
    175  * @param   cbFrame     The size of the frame.
    176  * @remark  This is the same as INTNETRingWriteFrame and drvIntNetRingWriteFrame.
    177  */
    178 static int tstIntNetWriteFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf, const void *pvFrame, uint32_t cbFrame)
    179 {
    180     /*
    181      * Validate input.
    182      */
    183     Assert(pBuf);
    184     Assert(pRingBuf);
    185     Assert(pvFrame);
    186     Assert(cbFrame >= sizeof(RTMAC) * 2);
    187     uint32_t offWrite = pRingBuf->offWrite;
    188     Assert(offWrite == RT_ALIGN_32(offWrite, sizeof(INTNETHDR)));
    189     uint32_t offRead = pRingBuf->offRead;
    190     Assert(offRead == RT_ALIGN_32(offRead, sizeof(INTNETHDR)));
    191 
    192     const uint32_t cb = RT_ALIGN_32(cbFrame, sizeof(INTNETHDR));
    193     if (offRead <= offWrite)
    194     {
    195         /*
    196          * Try fit it all before the end of the buffer.
    197          */
    198         if (pRingBuf->offEnd - offWrite >= cb + sizeof(INTNETHDR))
    199         {
    200             PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    201             pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    202             pHdr->cbFrame  = cbFrame;
    203             pHdr->offFrame = sizeof(INTNETHDR);
    204 
    205             memcpy(pHdr + 1, pvFrame, cbFrame);
    206 
    207             offWrite += cb + sizeof(INTNETHDR);
    208             Assert(offWrite <= pRingBuf->offEnd && offWrite >= pRingBuf->offStart);
    209             if (offWrite >= pRingBuf->offEnd)
    210                 offWrite = pRingBuf->offStart;
    211             Log2(("WriteFrame: offWrite: %#x -> %#x (1)\n", pRingBuf->offWrite, offWrite));
    212             ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
    213             return VINF_SUCCESS;
    214         }
    215 
    216         /*
    217          * Try fit the frame at the start of the buffer.
    218          * (The header fits before the end of the buffer because of alignment.)
    219          */
    220         AssertMsg(pRingBuf->offEnd - offWrite >= sizeof(INTNETHDR), ("offEnd=%x offWrite=%x\n", pRingBuf->offEnd, offWrite));
    221         if (offRead - pRingBuf->offStart > cb) /* not >= ! */
    222         {
    223             PINTNETHDR  pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    224             void       *pvFrameOut = (PINTNETHDR)((uint8_t *)pBuf + pRingBuf->offStart);
    225             pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    226             pHdr->cbFrame  = cbFrame;
    227             pHdr->offFrame = (intptr_t)pvFrameOut - (intptr_t)pHdr;
    228 
    229             memcpy(pvFrameOut, pvFrame, cbFrame);
    230 
    231             offWrite = pRingBuf->offStart + cb;
    232             ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
    233             Log2(("WriteFrame: offWrite: %#x -> %#x (2)\n", pRingBuf->offWrite, offWrite));
    234             return VINF_SUCCESS;
    235         }
    236     }
    237     /*
    238      * The reader is ahead of the writer, try fit it into that space.
    239      */
    240     else if (offRead - offWrite > cb + sizeof(INTNETHDR)) /* not >= ! */
    241     {
    242         PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
    243         pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
    244         pHdr->cbFrame  = cbFrame;
    245         pHdr->offFrame = sizeof(INTNETHDR);
    246 
    247         memcpy(pHdr + 1, pvFrame, cbFrame);
    248 
    249         offWrite += cb + sizeof(INTNETHDR);
    250         ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
    251         Log2(("WriteFrame: offWrite: %#x -> %#x (3)\n", pRingBuf->offWrite, offWrite));
    252         return VINF_SUCCESS;
    253     }
    254 
    255     /* (it didn't fit) */
    256     /** @todo stats */
    257     return VERR_BUFFER_OVERFLOW;
    258 }
    259 
    260 
    261 /**
    262170 * Transmits one frame after appending the CRC.
    263171 *
     
    295203     * it's not supposed to happen here in this testcase.
    296204     */
    297     int rc = tstIntNetWriteFrame(pBuf, &pBuf->Send, pvFrame, (uint32_t)cbFrame);
     205    int rc = INTNETRingWriteFrame(&pBuf->Send, pvFrame, cbFrame);
    298206    if (RT_SUCCESS(rc))
    299207    {
     
    303211    else
    304212    {
    305         RTPrintf("tstIntNet-1: tstIntNetWriteFrame failed, %Rrc; cbFrame=%d pBuf->cbSend=%d\n", rc, cbFrame, pBuf->cbSend);
     213        RTPrintf("tstIntNet-1: INTNETRingWriteFrame failed, %Rrc; cbFrame=%d pBuf->cbSend=%d\n", rc, cbFrame, pBuf->cbSend);
    306214        g_cErrors++;
    307215    }
     
    555463         * Process the receive buffer.
    556464         */
    557         while (INTNETRingGetReadable(pRingBuf) > 0)
     465        PINTNETHDR pHdr;
     466        while ((pHdr = INTNETRingGetNextFrameToRead(pRingBuf)))
    558467        {
    559             PINTNETHDR pHdr = (PINTNETHDR)((uintptr_t)pBuf + pRingBuf->offRead);
    560468            if (pHdr->u16Type == INTNETHDR_TYPE_FRAME)
    561469            {
    562470                size_t      cbFrame = pHdr->cbFrame;
    563471                const void *pvFrame = INTNETHdrGetFramePtr(pHdr, pBuf);
    564                 uint64_t    NanoTS = RTTimeNanoTS() - g_StartTS;
     472                uint64_t    NanoTS  = RTTimeNanoTS() - g_StartTS;
    565473
    566474                if (pFileRaw)
     
    638546            {
    639547                RTPrintf("tstIntNet-1: Unknown frame type %d\n", pHdr->u16Type);
     548                STAM_REL_COUNTER_INC(&pBuf->cStatBadFrames);
    640549                g_cErrors++;
    641550            }
    642551
    643552            /* Advance to the next frame. */
    644             INTNETRingSkipFrame(pBuf, pRingBuf);
     553            INTNETRingSkipFrame(pRingBuf);
    645554        }
    646555    }
     
    650559                 "%3RU64.%09u: stopped. cRecvs=%RU64 cbRecv=%RU64 cLost=%RU64 cOYs=%RU64 cNYs=%RU64\n",
    651560                 NanoTS / 1000000000, (uint32_t)(NanoTS % 1000000000),
    652                  pBuf->cStatRecvs.c,
    653                  pBuf->cbStatRecv.c,
     561                 pBuf->Recv.cStatFrames.c,
     562                 pBuf->Recv.cbStatWritten.c,
    654563                 pBuf->cStatLost.c,
    655564                 pBuf->cStatYieldsOk.c,
  • trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp

    r26517 r26574  
    2727*   Header Files                                                               *
    2828*******************************************************************************/
     29#define RTMEM_WRAP_TO_EF_APIS       // debugging debugging remove
     30#define INTNET_POISON_READ_FRAMES   // debugging debugging remove
    2931#define IN_INTNET_TESTCASE
    3032#define IN_INTNET_R3
     
    212214#include "../SrvIntNetR0.cpp"
    213215
    214 typedef struct ARGS
     216typedef struct MYARGS
    215217{
    216218    PINTNET pIntNet;
     
    220222    uint64_t u64Start;
    221223    uint64_t u64End;
    222 } ARGS, *PARGS;
     224} MYARGS, *PMYARGS;
    223225
    224226
     
    231233DECLCALLBACK(int) SendThread(RTTHREAD Thread, void *pvArg)
    232234{
    233     PARGS   pArgs = (PARGS)pvArg;
     235    PMYARGS pArgs = (PMYARGS)pvArg;
    234236
    235237    /*
     
    237239     */
    238240    uint8_t abBuf[4096] = {0};
    239     PRTMAC pMacSrc = (PRTMAC)&abBuf[0];
    240     PRTMAC pMacDst = pMacSrc + 1;
     241    PRTMAC  pMacSrc = (PRTMAC)&abBuf[0];
     242    PRTMAC  pMacDst = pMacSrc + 1;
    241243    *pMacSrc = pArgs->Mac;
    242244    *pMacDst = pArgs->Mac;
     
    244246    unsigned *puFrame = (unsigned *)(pMacDst + 1);
    245247    unsigned iFrame = 0;
    246     unsigned cbSent = 0;
     248    uint32_t cbSent = 0;
     249    uint32_t cSend  = 0;
    247250    pArgs->u64Start = RTTimeNanoTS();
    248251    for (; cbSent < TEST_TRANSFER_SIZE; iFrame++)
     
    255258        INTNETSG Sg;
    256259        intnetR0SgInitTemp(&Sg, abBuf, cb);
    257         int rc = intnetR0RingWriteFrame(pArgs->pBuf, &pArgs->pBuf->Send, &Sg, NULL);
     260        int rc = intnetR0RingWriteFrame(&pArgs->pBuf->Send, &Sg, NULL);
    258261        if (RT_SUCCESS(rc))
    259262            rc = INTNETR0IfSend(pArgs->pIntNet, pArgs->hIf, g_pSession, NULL, 0);
     
    285288    }
    286289
    287     RTPrintf("tstIntNetR0: sender thread %.6Rhxs terminating. iFrame=%d cbSent=%d\n", &pArgs->Mac, iFrame, cbSent);
     290    RTPrintf("tstIntNetR0: sender   thread %.6Rhxs terminating.\n"
     291             "tstIntNetR0:   iFrame=%u  cb=%'u\n",
     292             &pArgs->Mac, iFrame, cbSent);
    288293    return 0;
    289294}
     
    299304DECLCALLBACK(int) ReceiveThread(RTTHREAD Thread, void *pvArg)
    300305{
    301     unsigned    cbReceived = 0;
    302     unsigned    cLostFrames = 0;
    303     unsigned    iFrame = ~0;
    304     PARGS       pArgs = (PARGS)pvArg;
     306    uint32_t    cbReceived = 0;
     307    uint32_t    cLostFrames = 0;
     308    uint32_t    iFrame      = UINT32_MAX;
     309    PMYARGS     pArgs       = (PMYARGS)pvArg;
    305310    for (;;)
    306311    {
     
    315320                break;
    316321            case VERR_SEM_DESTROYED:
    317                 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs terminating. cbReceived=%u cLostFrames=%u iFrame=%u\n",
    318                          &pArgs->Mac, cbReceived, cLostFrames, iFrame);
     322                RTPrintf("tstIntNetR0: receiver thread %.6Rhxs terminating. iFrame=%u cb=%'u c=%'u cLost=%'u\n",
     323                         &pArgs->Mac, iFrame, cbReceived, iFrame - cLostFrames, cLostFrames);
    319324                return VINF_SUCCESS;
    320325
    321326            default:
    322                 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs got odd return value %Rrc! cbReceived=%u cLostFrames=%u iFrame=%u\n",
    323                          &pArgs->Mac, rc, cbReceived, cLostFrames, iFrame);
     327                RTPrintf("tstIntNetR0: receiver thread %.6Rhxs got odd return value %Rrc! iFrame=%u cb=%'u c=%'u cLost=%'u\n",
     328                         &pArgs->Mac, rc, iFrame, cbReceived, iFrame - cLostFrames, cLostFrames);
    324329                g_cErrors++;
    325330                return rc;
     
    329334         * Read data.
    330335         */
    331         while (INTNETRingGetReadable(&pArgs->pBuf->Recv))
     336        while (INTNETRingHasMoreToRead(&pArgs->pBuf->Recv))
    332337        {
    333338            uint8_t abBuf[16384];
    334             unsigned cb = intnetR0RingReadFrame(pArgs->pBuf, &pArgs->pBuf->Recv, abBuf);
     339            uint32_t cb = INTNETRingReadAndSkipFrame(&pArgs->pBuf->Recv, abBuf);
    335340            unsigned *puFrame = (unsigned *)&abBuf[sizeof(RTMAC) * 2];
    336341
     
    342347                &&  puFrame[3] == 0xffffdead)
    343348            {
    344                 RTPrintf("tstIntNetR0: receiver thread %.6Rhxs terminating. cbReceived=%u cLostFrames=%u iFrame=%u\n",
    345                          &pArgs->Mac, cbReceived, cLostFrames, iFrame);
    346349                pArgs->u64End = RTTimeNanoTS();
     350                RTPrintf("tstIntNetR0: receiver thread %.6Rhxs terminating.\n"
     351                         "tstIntNetR0:   iFrame=%u  cb=%'u  c=%'u  %'uKB/s  %'ufps  cLost=%'u \n",
     352                         &pArgs->Mac, iFrame, cbReceived, iFrame - cLostFrames,
     353                         (unsigned)(cbReceived * 1000000000.0 / 1024 / (pArgs->u64End - pArgs->u64Start)),
     354                         (unsigned)((iFrame - cLostFrames) * 1000000000.0 / (pArgs->u64End - pArgs->u64Start)),
     355                         cLostFrames);
    347356                return VINF_SUCCESS;
    348357            }
     
    523532                                g_cErrors++;
    524533                            }
    525                             unsigned cb = intnetR0RingReadFrame(pBuf1, &pBuf1->Recv, abBuf);
     534                            uint32_t cb = INTNETRingReadAndSkipFrame(&pBuf1->Recv, abBuf);
    526535                            if (cb != sizeof(g_TestFrame0))
    527536                            {
     
    555564                            if (!g_cErrors)
    556565                            {
    557                                 ARGS Args0;
     566                                MYARGS Args0;
    558567                                RT_ZERO(Args0);
    559568                                Args0.hIf = hIf0;
     
    564573                                Args0.Mac.au16[2] = 0;
    565574
    566                                 ARGS Args1;
     575                                MYARGS Args1;
    567576                                RT_ZERO(Args1);
    568577                                Args1.hIf = hIf1;
     
    588597                                    int rc2 = VINF_SUCCESS;
    589598                                    rc = RTThreadWait(ThreadSend0, 5*60*1000, &rc2);
    590 #if 1 /** @todo it looks like I'm subject to some false wakeup calls here (2.6.23-gentoo-r3 amd64). See #3023.*/
    591                                     for (int cTries = 100; rc == VERR_TIMEOUT && cTries > 0; cTries--)
    592                                     {
    593                                         RTThreadSleep(1);
    594                                         rc = RTThreadWait(ThreadSend0, 1, &rc2);
    595                                     }
    596 #endif
    597599                                    AssertRC(rc);
    598600                                    if (RT_SUCCESS(rc))
     
    600602                                        ThreadSend0 = NIL_RTTHREAD;
    601603                                        rc = RTThreadWait(ThreadSend1, 5*60*1000, RT_SUCCESS(rc2) ? &rc2 : NULL);
    602 #if 1 /** @todo it looks like I'm subject to some false wakeup calls here (2.6.23-gentoo-r3 amd64). See #3023.*/
    603                                         for (int cTries = 100; rc == VERR_TIMEOUT && cTries > 0; cTries--)
    604                                         {
    605                                             RTThreadSleep(1);
    606                                             rc = RTThreadWait(ThreadSend1, 1, &rc2);
    607                                         }
    608 #endif
    609604                                        AssertRC(rc);
    610605                                        if (RT_SUCCESS(rc))
     
    618613                                         */
    619614                                        unsigned cYields = 100000;
    620                                         while (     (   INTNETRingGetReadable(&pBuf0->Recv)
    621                                                     ||  INTNETRingGetReadable(&pBuf1->Recv))
     615                                        while (     (  INTNETRingHasMoreToRead(&pBuf0->Recv)
     616                                                    || INTNETRingHasMoreToRead(&pBuf1->Recv))
    622617                                               &&   cYields-- > 0)
    623618                                            RTThreadYield();
     
    625620                                        uint64_t u64Elapsed = RT_MAX(Args0.u64End, Args1.u64End) - RT_MIN(Args0.u64Start, Args1.u64Start);
    626621                                        uint64_t u64Speed = (uint64_t)((2 * TEST_TRANSFER_SIZE / 1024) / (u64Elapsed / 1000000000.0));
    627                                         RTPrintf("tstIntNetR0: transfered %d bytes in %RU64 ns (%RU64 KB/s)\n",
     622                                        RTPrintf("tstIntNetR0: transfered %d bytes in %'RU64 ns (%'RU64 KB/s)\n",
    628623                                                 2 * TEST_TRANSFER_SIZE, u64Elapsed, u64Speed);
    629624
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette