Index: trunk/include/VBox/intnet.h
===================================================================
--- trunk/include/VBox/intnet.h	(revision 5282)
+++ trunk/include/VBox/intnet.h	(revision 5283)
@@ -20,4 +20,5 @@
 #include <VBox/types.h>
 #include <VBox/stam.h>
+#include <VBox/sup.h>
 #include <iprt/assert.h>
 #include <iprt/asm.h>
@@ -25,4 +26,7 @@
 __BEGIN_DECLS
 
+
+/** Pointer to an internal network ring-0 instance. */
+typedef struct INTNET *PINTNET;
 
 /**
@@ -164,5 +168,5 @@
     Assert(pHdr->u16Type == INTNETHDR_TYPE_FRAME);
     Assert(off < pBuf->cbBuf);
-    Assert(off + pHdr->cbFrame < pBuf->cbBuf);
+    Assert(off + pHdr->cbFrame <= pBuf->cbBuf);
 #endif
     NOREF(pBuf);
@@ -198,11 +202,12 @@
 
 
-
-/**
- * The packed down arguments of INTNETR0Open().
- * @see INTNETR0Open()
- */
-typedef struct INTNETOPENARGS
-{
+/**
+ * Request buffer for INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN.
+ * @see INTNETR0Open.
+ */
+typedef struct INTNETOPENREQ
+{
+    /** The request header. */
+    SUPVMMR0REQHDR  Hdr;
     /** The network name. (input) */
     char            szNetwork[INTNET_MAX_NETWORK_NAME];
@@ -215,81 +220,100 @@
     /** The handle to the network interface. (output) */
     INTNETIFHANDLE  hIf;
-} INTNETOPENARGS;
-/** Pointer to an INTNETR0Open() argument package. */
-typedef INTNETOPENARGS *PINTNETOPENARGS;
-
-
-/**
- * The packed down arguments of INTNETR0IfClose().
- * @see INTNETR0IfClose()
- */
-typedef struct INTNETCLOSEARGS
-{
+} INTNETOPENREQ;
+/** Pointer to an INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN request buffer. */
+typedef INTNETOPENREQ *PINTNETOPENREQ;
+
+INTNETR0DECL(int) INTNETR0OpenReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETOPENREQ pReq);
+
+
+/**
+ * Request buffer for INTNETR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE.
+ * @see INTNETR0IfClose.
+ */
+typedef struct INTNETIFCLOSEREQ
+{
+    /** The request header. */
+    SUPVMMR0REQHDR  Hdr;
     /** The handle to the network interface. */
     INTNETIFHANDLE  hIf;
-} INTNETIFCLOSEARGS;
-/** Pointer to an INTNETR0Open() argument package. */
-typedef INTNETIFCLOSEARGS *PINTNETIFCLOSEARGS;
-
-
-/**
- * Argument buffer for calling INTNETR0IfGetRing3Buffer().
- * @see INTNETR0IfGetRing3Buffer()
- */
-typedef struct INTNETIFGETRING3BUFFERARGS
-{
+} INTNETIFCLOSEREQ;
+/** Pointer to an INTNETR0IfCloseReq / VMMR0_DO_INTNET_IF_CLOSE request buffer. */
+typedef INTNETIFCLOSEREQ *PINTNETIFCLOSEREQ;
+
+INTNETR0DECL(int) INTNETR0IfCloseReq(PINTNET pIntNet, PINTNETIFCLOSEREQ pReq);
+
+
+/**
+ * Request buffer for INTNETR0IfGetRing3BufferReq / VMMR0_DO_INTNET_IF_GET_RING3_BUFFER.
+ * @see INTNETR0IfGetRing3Buffer.
+ */
+typedef struct INTNETIFGETRING3BUFFERREQ
+{
+    /** The request header. */
+    SUPVMMR0REQHDR          Hdr;
     /** Handle to the interface. */
-    INTNETIFHANDLE  hIf;
+    INTNETIFHANDLE          hIf;
     /** The pointer to the ring3 buffer. (output) */
-    PINTNETBUF      pRing3Buf;
-} INTNETIFGETRING3BUFFERARGS;
-/** Pointer to an INTNETR0IfGetRing3Buffer() argument package. */
-typedef INTNETIFGETRING3BUFFERARGS *PINTNETIFGETRING3BUFFERARGS;
-
-/**
- * Argument buffer for calling INTNETR0IfSetPromiscuousMode().
- * @see INTNETR0IfSetPromiscuousMode()
- */
-typedef struct INTNETIFSETPROMISCUOUSMODEARGS
-{
+    R3PTRTYPE(PINTNETBUF)   pRing3Buf;
+} INTNETIFGETRING3BUFFERREQ;
+/** Pointer to an INTNETR0IfGetRing3BufferReq / VMMR0_DO_INTNET_IF_GET_RING3_BUFFER request buffer. */
+typedef INTNETIFGETRING3BUFFERREQ *PINTNETIFGETRING3BUFFERREQ;
+
+INTNETR0DECL(int) INTNETR0IfGetRing3BufferReq(PINTNET pIntNet, PINTNETIFGETRING3BUFFERREQ pReq);
+
+
+/**
+ * Request buffer for INTNETR0IfSetPromiscuousModeReq / VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE.
+ * @see INTNETR0IfSetPromiscuousMode.
+ */
+typedef struct INTNETIFSETPROMISCUOUSMODEREQ
+{
+    /** The request header. */
+    SUPVMMR0REQHDR  Hdr;
     /** Handle to the interface. */
     INTNETIFHANDLE  hIf;
     /** The new promiscuous mode. */
     bool            fPromiscuous;
-} INTNETIFSETPROMISCUOUSMODEARGS;
-/** Pointer to an INTNETR0IfSetPromiscuousMode() argument package. */
-typedef INTNETIFSETPROMISCUOUSMODEARGS *PINTNETIFSETPROMISCUOUSMODEARGS;
-
-
-/**
- * Argument buffer for calling INTNETR0IfSend().
- * @see INTNETR0IfSend()
- */
-typedef struct INTNETIFSENDARGS
-{
+} INTNETIFSETPROMISCUOUSMODEREQ;
+/** Pointer to an INTNETR0IfSetPromiscuousModeReq / VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE request buffer. */
+typedef INTNETIFSETPROMISCUOUSMODEREQ *PINTNETIFSETPROMISCUOUSMODEREQ;
+
+INTNETR0DECL(int) INTNETR0IfSetPromiscuousModeReq(PINTNET pIntNet, PINTNETIFSETPROMISCUOUSMODEREQ pReq);
+
+
+/**
+ * Request buffer for INTNETR0IfSendReq / VMMR0_DO_INTNET_IF_SEND.
+ * @see INTNETR0IfSend.
+ */
+typedef struct INTNETIFSENDREQ
+{
+    /** The request header. */
+    SUPVMMR0REQHDR  Hdr;
     /** Handle to the interface. */
     INTNETIFHANDLE  hIf;
-    /** Pointer to the frame. (Optional) */
-    const void     *pvFrame;
-    /** The size of the frame. (Optional) */
-    uint32_t        cbFrame;
-} INTNETIFSENDARGS;
+} INTNETIFSENDREQ;
 /** Pointer to an INTNETR0IfSend() argument package. */
-typedef INTNETIFSENDARGS *PINTNETIFSENDARGS;
-
-
-/**
- * Argument buffer for calling INTNETR0IfWait().
- * @see INTNETR0IfWait()
- */
-typedef struct INTNETIFWAITARGS
-{
+typedef INTNETIFSENDREQ *PINTNETIFSENDREQ;
+
+INTNETR0DECL(int) INTNETR0IfSendReq(PINTNET pIntNet, PINTNETIFSENDREQ pReq);
+
+
+/**
+ * Request buffer for INTNETR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT.
+ * @see INTNETR0IfWait.
+ */
+typedef struct INTNETIFWAITREQ
+{
+    /** The request header. */
+    SUPVMMR0REQHDR  Hdr;
     /** Handle to the interface. */
     INTNETIFHANDLE  hIf;
     /** The number of milliseconds to wait. */
-    unsigned        cMillies;
-} INTNETSENDARGS;
-/** Pointer to an INTNETR0IfWait() argument package. */
-typedef INTNETIFWAITARGS *PINTNETIFWAITARGS;
+    uint32_t        cMillies;
+} INTNETIFWAITREQ;
+/** Pointer to an INTNETR0IfWaitReq / VMMR0_DO_INTNET_IF_WAIT request buffer. */
+typedef INTNETIFWAITREQ *PINTNETIFWAITREQ;
+
+INTNETR0DECL(int) INTNETR0IfWaitReq(PINTNET pIntNet, PINTNETIFWAITREQ pReq);
 
 
@@ -298,7 +322,4 @@
  * @{
  */
-
-/** Pointer to an internal network ring-0 instance. */
-typedef struct INTNET *PINTNET;
 
 /**
@@ -358,5 +379,5 @@
  * @param   ppRing3Buf  Where to store the address of the ring-3 mapping.
  */
-INTNETR0DECL(int) INTNETR0IfGetRing3Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, PINTNETBUF *ppRing3Buf);
+INTNETR0DECL(int) INTNETR0IfGetRing3Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, R3PTRTYPE(PINTNETBUF) *ppRing3Buf);
 
 /**
@@ -396,5 +417,5 @@
  *                      used if indefinite wait is desired.
  */
-INTNETR0DECL(int) INTNETR0IfWait(PINTNET pIntNet, INTNETIFHANDLE hIf, unsigned cMillies);
+INTNETR0DECL(int) INTNETR0IfWait(PINTNET pIntNet, INTNETIFHANDLE hIf, uint32_t cMillies);
 
 /** @} */
Index: trunk/src/VBox/Devices/Network/DrvIntNet.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/DrvIntNet.cpp	(revision 5282)
+++ trunk/src/VBox/Devices/Network/DrvIntNet.cpp	(revision 5283)
@@ -113,4 +113,97 @@
 
 /**
+ * Writes a frame packet to the buffer.
+ *
+ * @returns VBox status code.
+ * @param   pBuf        The buffer.
+ * @param   pRingBuf    The ring buffer to read from.
+ * @param   pvFrame     The frame to write.
+ * @param   cbFrame     The size of the frame.
+ * @remark  This is the same as INTNETRingWriteFrame
+ */
+static int drvIntNetRingWriteFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf, const void *pvFrame, uint32_t cbFrame)
+{
+    /*
+     * Validate input.
+     */
+    Assert(pBuf);
+    Assert(pRingBuf);
+    Assert(pvFrame);
+    Assert(cbFrame >= sizeof(PDMMAC) * 2);
+    uint32_t offWrite = pRingBuf->offWrite;
+    Assert(offWrite == RT_ALIGN_32(offWrite, sizeof(INTNETHDR)));
+    uint32_t offRead = pRingBuf->offRead;
+    Assert(offRead == RT_ALIGN_32(offRead, sizeof(INTNETHDR)));
+
+    const uint32_t cb = RT_ALIGN_32(cbFrame, sizeof(INTNETHDR));
+    if (offRead <= offWrite)
+    {
+        /*
+         * Try fit it all before the end of the buffer.
+         */
+        if (pRingBuf->offEnd - offWrite >= cb + sizeof(INTNETHDR))
+        {
+            PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
+            pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
+            pHdr->cbFrame  = cbFrame;
+            pHdr->offFrame = sizeof(INTNETHDR);
+
+            memcpy(pHdr + 1, pvFrame, cbFrame);
+
+            offWrite += cb + sizeof(INTNETHDR);
+            Assert(offWrite <= pRingBuf->offEnd && offWrite >= pRingBuf->offStart);
+            if (offWrite >= pRingBuf->offEnd)
+                offWrite = pRingBuf->offStart;
+            Log2(("WriteFrame: offWrite: %#x -> %#x (1)\n", pRingBuf->offWrite, offWrite));
+            ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
+            return VINF_SUCCESS;
+        }
+
+        /*
+         * Try fit the frame at the start of the buffer.
+         * (The header fits before the end of the buffer because of alignment.)
+         */
+        AssertMsg(pRingBuf->offEnd - offWrite >= sizeof(INTNETHDR), ("offEnd=%x offWrite=%x\n", pRingBuf->offEnd, offWrite));
+        if (offRead - pRingBuf->offStart > cb) /* not >= ! */
+        {
+            PINTNETHDR  pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
+            void       *pvFrameOut = (PINTNETHDR)((uint8_t *)pBuf + pRingBuf->offStart);
+            pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
+            pHdr->cbFrame  = cbFrame;
+            pHdr->offFrame = (intptr_t)pvFrameOut - (intptr_t)pHdr;
+
+            memcpy(pvFrameOut, pvFrame, cbFrame);
+
+            offWrite = pRingBuf->offStart + cb;
+            ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
+            Log2(("WriteFrame: offWrite: %#x -> %#x (2)\n", pRingBuf->offWrite, offWrite));
+            return VINF_SUCCESS;
+        }
+    }
+    /*
+     * The reader is ahead of the writer, try fit it into that space.
+     */
+    else if (offRead - offWrite > cb + sizeof(INTNETHDR)) /* not >= ! */
+    {
+        PINTNETHDR pHdr = (PINTNETHDR)((uint8_t *)pBuf + offWrite);
+        pHdr->u16Type  = INTNETHDR_TYPE_FRAME;
+        pHdr->cbFrame  = cbFrame;
+        pHdr->offFrame = sizeof(INTNETHDR);
+
+        memcpy(pHdr + 1, pvFrame, cbFrame);
+
+        offWrite += cb + sizeof(INTNETHDR);
+        ASMAtomicXchgU32(&pRingBuf->offWrite, offWrite);
+        Log2(("WriteFrame: offWrite: %#x -> %#x (3)\n", pRingBuf->offWrite, offWrite));
+        return VINF_SUCCESS;
+    }
+
+    /* (it didn't fit) */
+    /** @todo stats */
+    return VERR_BUFFER_OVERFLOW;
+}
+
+
+/**
  * Send data to the network.
  *
@@ -136,10 +229,28 @@
 #endif
 
-    /** @todo copy to send buffer, this is not safe. */
-    INTNETIFSENDARGS SendArgs;
-    SendArgs.hIf = pThis->hIf;
-    SendArgs.pvFrame = pvBuf;
-    SendArgs.cbFrame = cb;
-    int rc = pThis->pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pThis->pDrvIns, VMMR0_DO_INTNET_IF_SEND, &SendArgs, sizeof(SendArgs));
+    /*
+     * Add the frame to the send buffer and push it onto the network.
+     */
+    int rc = drvIntNetRingWriteFrame(pThis->pBuf, &pThis->pBuf->Send, pvBuf, cb);
+    if (    rc == VERR_BUFFER_OVERFLOW
+        &&  pThis->pBuf->cbSend < cb)
+    {
+        INTNETIFSENDREQ SendReq;
+        SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+        SendReq.Hdr.cbReq = sizeof(SendReq);
+        SendReq.hIf = pThis->hIf;
+        pThis->pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pThis->pDrvIns, VMMR0_DO_INTNET_IF_SEND, &SendReq, sizeof(SendReq));
+
+        rc = drvIntNetRingWriteFrame(pThis->pBuf, &pThis->pBuf->Send, pvBuf, cb);
+    }
+
+    if (RT_SUCCESS(rc))
+    {
+        INTNETIFSENDREQ SendReq;
+        SendReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+        SendReq.Hdr.cbReq = sizeof(SendReq);
+        SendReq.hIf = pThis->hIf;
+        rc = pThis->pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pThis->pDrvIns, VMMR0_DO_INTNET_IF_SEND, &SendReq, sizeof(SendReq));
+    }
 
     STAM_PROFILE_STOP(&pThis->StatTransmit, a);
@@ -162,9 +273,11 @@
 {
     PDRVINTNET pThis = PDMINETWORKCONNECTOR_2_DRVINTNET(pInterface);
-    INTNETIFSETPROMISCUOUSMODEARGS SetArgs = {0};
-    SetArgs.hIf          = pThis->hIf;
-    SetArgs.fPromiscuous = fPromiscuous;
-    int rc = pThis->pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pThis->pDrvIns, VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE, &SetArgs, sizeof(SetArgs));
-    LogFlow(("drvIntNetSetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
+    INTNETIFSETPROMISCUOUSMODEREQ Req;
+    Req.Hdr.u32Magic    = SUPVMMR0REQHDR_MAGIC;
+    Req.Hdr.cbReq       = sizeof(Req);
+    Req.hIf             = pThis->hIf;
+    Req.fPromiscuous    = fPromiscuous;
+    int rc = pThis->pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pThis->pDrvIns, VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE, &Req, sizeof(Req));
+    LogFlow(("drvIntNetSetPromiscuousMode: fPromiscuous=%RTbool\n", fPromiscuous));
     AssertRC(rc);
 }
@@ -368,9 +481,11 @@
             return VERR_STATE_CHANGED;
         }
-        INTNETIFWAITARGS WaitArgs;
-        WaitArgs.hIf      = pThis->hIf;
-        WaitArgs.cMillies = 30000;      /* don't wait forever, timeout now and then. */
+        INTNETIFWAITREQ WaitReq;
+        WaitReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+        WaitReq.Hdr.cbReq    = sizeof(WaitReq);
+        WaitReq.hIf          = pThis->hIf;
+        WaitReq.cMillies     = 30000; /* 30s - don't wait forever, timeout now and then. */
         STAM_PROFILE_ADV_STOP(&pThis->StatReceive, a);
-        int rc = pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_WAIT, &WaitArgs, sizeof(WaitArgs));
+        int rc = pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_WAIT, &WaitReq, sizeof(WaitReq));
         if (    VBOX_FAILURE(rc)
             &&  rc != VERR_TIMEOUT
@@ -547,8 +662,10 @@
     if (pThis->hIf != INTNET_HANDLE_INVALID)
     {
-        INTNETIFCLOSEARGS CloseArgs = {0};
-        CloseArgs.hIf = pThis->hIf;
+        INTNETIFCLOSEREQ CloseReq;
+        CloseReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+        CloseReq.Hdr.cbReq = sizeof(CloseReq);
+        CloseReq.hIf = pThis->hIf;
         pThis->hIf = INTNET_HANDLE_INVALID;
-        int rc = pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_CLOSE, &CloseArgs, sizeof(CloseArgs));
+        int rc = pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_CLOSE, &CloseReq, sizeof(CloseReq));
         AssertRC(rc);
     }
@@ -638,29 +755,37 @@
      * Read the configuration.
      */
-    INTNETOPENARGS OpenArgs;
-    memset(&OpenArgs, 0, sizeof(OpenArgs));
-    rc = CFGMR3QueryString(pCfgHandle, "Network", OpenArgs.szNetwork, sizeof(OpenArgs.szNetwork));
+    INTNETOPENREQ OpenReq;
+    memset(&OpenReq, 0, sizeof(OpenReq));
+    OpenReq.Hdr.cbReq = sizeof(OpenReq);
+    OpenReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+
+    rc = CFGMR3QueryString(pCfgHandle, "Network", OpenReq.szNetwork, sizeof(OpenReq.szNetwork));
     if (VBOX_FAILURE(rc))
         return PDMDRV_SET_ERROR(pDrvIns, rc,
                                 N_("Configuration error: Failed to get the \"Network\" value"));
-    strcpy(pThis->szNetwork, OpenArgs.szNetwork);
-
-    rc = CFGMR3QueryU32(pCfgHandle, "ReceiveBufferSize", &OpenArgs.cbRecv);
+    strcpy(pThis->szNetwork, OpenReq.szNetwork);
+
+    rc = CFGMR3QueryU32(pCfgHandle, "ReceiveBufferSize", &OpenReq.cbRecv);
     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
-        OpenArgs.cbRecv = _256K;
+        OpenReq.cbRecv = _256K;
     else if (VBOX_FAILURE(rc))
         return PDMDRV_SET_ERROR(pDrvIns, rc,
                                 N_("Configuration error: Failed to get the \"ReceiveBufferSize\" value"));
 
-    rc = CFGMR3QueryU32(pCfgHandle, "SendBufferSize", &OpenArgs.cbSend);
+    rc = CFGMR3QueryU32(pCfgHandle, "SendBufferSize", &OpenReq.cbSend);
     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
-        OpenArgs.cbSend = _4K;
+        OpenReq.cbSend = _4K;
     else if (VBOX_FAILURE(rc))
         return PDMDRV_SET_ERROR(pDrvIns, rc,
                                 N_("Configuration error: Failed to get the \"SendBufferSize\" value"));
-
-    rc = CFGMR3QueryBool(pCfgHandle, "RestrictAccess", &OpenArgs.fRestrictAccess);
+    if (OpenReq.cbSend < 16)
+        return PDMDRV_SET_ERROR(pDrvIns, rc,
+                                N_("Configuration error: The \"SendBufferSize\" value is too small."));
+    if (OpenReq.cbSend < 1536*2 + 4)
+        LogRel(("DrvIntNet: Warning! SendBufferSize=%u, Recommended minimum size %u butes.\n", OpenReq.cbSend, 1536*2 + 4));
+
+    rc = CFGMR3QueryBool(pCfgHandle, "RestrictAccess", &OpenReq.fRestrictAccess);
     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
-        OpenArgs.fRestrictAccess = true;
+        OpenReq.fRestrictAccess = true;
     else if (VBOX_FAILURE(rc))
         return PDMDRV_SET_ERROR(pDrvIns, rc,
@@ -680,11 +805,11 @@
      * Create the interface.
      */
-    OpenArgs.hIf = INTNET_HANDLE_INVALID;
-    rc = pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_OPEN, &OpenArgs, sizeof(OpenArgs));
+    OpenReq.hIf = INTNET_HANDLE_INVALID;
+    rc = pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_OPEN, &OpenReq, sizeof(OpenReq));
     if (VBOX_FAILURE(rc))
         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
                                    N_("Failed to open/create the internal network '%s'"), pThis->szNetwork);
-    AssertRelease(OpenArgs.hIf != INTNET_HANDLE_INVALID);
-    pThis->hIf = OpenArgs.hIf;
+    AssertRelease(OpenReq.hIf != INTNET_HANDLE_INVALID);
+    pThis->hIf = OpenReq.hIf;
     Log(("IntNet%d: hIf=%RX32 '%s'\n", pDrvIns->iInstance, pThis->hIf, pThis->szNetwork));
 
@@ -692,13 +817,15 @@
      * Get default buffer.
      */
-    INTNETIFGETRING3BUFFERARGS GetRing3BufferArgs = {0};
-    GetRing3BufferArgs.hIf = pThis->hIf;
-    GetRing3BufferArgs.pRing3Buf = NULL;
-    rc = pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, &GetRing3BufferArgs, sizeof(GetRing3BufferArgs));
+    INTNETIFGETRING3BUFFERREQ GetRing3BufferReq;
+    GetRing3BufferReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
+    GetRing3BufferReq.Hdr.cbReq = sizeof(GetRing3BufferReq);
+    GetRing3BufferReq.hIf = pThis->hIf;
+    GetRing3BufferReq.pRing3Buf = NULL;
+    rc = pDrvIns->pDrvHlp->pfnSUPCallVMMR0Ex(pDrvIns, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, &GetRing3BufferReq, sizeof(GetRing3BufferReq));
     if (VBOX_FAILURE(rc))
         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
                                    N_("Failed to get ring-3 buffer for the newly created interface to '%s'"), pThis->szNetwork);
-    AssertRelease(VALID_PTR(GetRing3BufferArgs.pRing3Buf));
-    pThis->pBuf = GetRing3BufferArgs.pRing3Buf;
+    AssertRelease(VALID_PTR(GetRing3BufferReq.pRing3Buf));
+    pThis->pBuf = GetRing3BufferReq.pRing3Buf;
 
     /*
@@ -737,5 +864,5 @@
 #endif
 
-    LogRel(("IntNet#%u: cbRecv=%u cbSend=%u fRestrictAccess=%d\n", pDrvIns->iInstance, OpenArgs.cbRecv, OpenArgs.cbSend, OpenArgs.fRestrictAccess));
+    LogRel(("IntNet#%u: cbRecv=%u cbSend=%u fRestrictAccess=%d\n", pDrvIns->iInstance, OpenReq.cbRecv, OpenReq.cbSend, OpenReq.fRestrictAccess));
 
     return rc;
Index: trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp	(revision 5282)
+++ trunk/src/VBox/Devices/Network/SrvIntNetR0.cpp	(revision 5283)
@@ -60,9 +60,9 @@
     PINTNETBUF              pIntBuf;
     /** Pointer to ring-3 mapping of the current exchange buffer. */
-    PINTNETBUF              pIntBufR3;
+    R3PTRTYPE(PINTNETBUF)   pIntBufR3;
     /** Pointer to the default exchange buffer for the interface. */
     PINTNETBUF              pIntBufDefault;
     /** Pointer to ring-3 mapping of the default exchange buffer. */
-    PINTNETBUF              pIntBufDefaultR3;
+    R3PTRTYPE(PINTNETBUF)   pIntBufDefaultR3;
     /** Event semaphore which a receiver thread will sleep on while waiting for data to arrive. */
     RTSEMEVENT              Event;
@@ -625,28 +625,36 @@
      * Process the send buffer.
      */
-    if (pIf->pIntBuf->Send.offRead != pIf->pIntBuf->Send.offWrite)
-    {
-        for (;;)
+    while (pIf->pIntBuf->Send.offRead != pIf->pIntBuf->Send.offWrite)
+    {
+        /* Send the frame if the type is sane. */
+        PINTNETHDR pHdr = (PINTNETHDR)((uintptr_t)pIf->pIntBuf + pIf->pIntBuf->Send.offRead);
+        if (pHdr->u16Type == INTNETHDR_TYPE_FRAME)
         {
-            /*
-             * Anything we know what is, if so send it.
-             */
-            PINTNETHDR pHdr = (PINTNETHDR)((uintptr_t)pIf->pIntBuf + pIf->pIntBuf->Send.offRead);
-            if (pHdr->u16Type == INTNETHDR_TYPE_FRAME)
-            {
-                void *pvCurFrame = INTNETHdrGetFramePtr(pHdr, pIf->pIntBuf);
-                if (pvCurFrame)
-                    intnetNetworkSend(pIf->pNetwork, pIf, pvCurFrame, pHdr->cbFrame);
-            }
-            /* else: ignore the frame */
-
-            /*
-             * Skip to the next frame.
-             */
-            INTNETRingSkipFrame(pIf->pIntBuf, &pIf->pIntBuf->Send);
+            void *pvCurFrame = INTNETHdrGetFramePtr(pHdr, pIf->pIntBuf);
+            if (pvCurFrame)
+                intnetNetworkSend(pIf->pNetwork, pIf, pvCurFrame, pHdr->cbFrame);
         }
+        /* else: ignore the frame */
+
+        /* Skip to the next frame. */
+        INTNETRingSkipFrame(pIf->pIntBuf, &pIf->pIntBuf->Send);
     }
 
     return RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
+}
+
+
+/**
+ * VMMR0 request wrapper for INTNETR0IfSend.
+ *
+ * @returns see INTNETR0IfSend.
+ * @param   pIntNet         The internal networking instance.
+ * @param   pReq            The request packet.
+ */
+INTNETR0DECL(int) INTNETR0IfSendReq(PINTNET pIntNet, PINTNETIFSENDREQ pReq)
+{
+    if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
+        return VERR_INVALID_PARAMETER;
+    return INTNETR0IfSend(pIntNet, pReq->hIf, NULL, 0);
 }
 
@@ -660,5 +668,5 @@
  * @param   ppRing3Buf  Where to store the address of the ring-3 mapping.
  */
-INTNETR0DECL(int) INTNETR0IfGetRing3Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, PINTNETBUF *ppRing3Buf)
+INTNETR0DECL(int) INTNETR0IfGetRing3Buffer(PINTNET pIntNet, INTNETIFHANDLE hIf, R3PTRTYPE(PINTNETBUF) *ppRing3Buf)
 {
     LogFlow(("INTNETR0IfGetRing3Buffer: pIntNet=%p hIf=%RX32 ppRing3Buf=%p\n", pIntNet, hIf, ppRing3Buf));
@@ -687,4 +695,19 @@
     LogFlow(("INTNETR0IfGetRing3Buffer: returns %Vrc *ppRing3Buf=%p\n", rc, *ppRing3Buf));
     return rc;
+}
+
+
+/**
+ * VMMR0 request wrapper for INTNETR0IfGetRing3Buffer.
+ *
+ * @returns see INTNETR0IfGetRing3Buffer.
+ * @param   pIntNet         The internal networking instance.
+ * @param   pReq            The request packet.
+ */
+INTNETR0DECL(int) INTNETR0IfGetRing3BufferReq(PINTNET pIntNet, PINTNETIFGETRING3BUFFERREQ pReq)
+{
+    if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
+        return VERR_INVALID_PARAMETER;
+    return INTNETR0IfGetRing3Buffer(pIntNet, pReq->hIf, &pReq->pRing3Buf);
 }
 
@@ -799,4 +822,19 @@
 
 /**
+ * VMMR0 request wrapper for INTNETR0IfSetPromiscuousMode.
+ *
+ * @returns see INTNETR0IfSetPromiscuousMode.
+ * @param   pIntNet         The internal networking instance.
+ * @param   pReq            The request packet.
+ */
+INTNETR0DECL(int) INTNETR0IfSetPromiscuousModeReq(PINTNET pIntNet, PINTNETIFSETPROMISCUOUSMODEREQ pReq)
+{
+    if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
+        return VERR_INVALID_PARAMETER;
+    return INTNETR0IfSetPromiscuousMode(pIntNet, pReq->hIf, pReq->fPromiscuous);
+}
+
+
+/**
  * Wait for the interface to get signaled.
  * The interface will be signaled when is put into the receive buffer.
@@ -808,5 +846,5 @@
  *                      used if indefinite wait is desired.
  */
-INTNETR0DECL(int) INTNETR0IfWait(PINTNET pIntNet, INTNETIFHANDLE hIf, unsigned cMillies)
+INTNETR0DECL(int) INTNETR0IfWait(PINTNET pIntNet, INTNETIFHANDLE hIf, uint32_t cMillies)
 {
     LogFlow(("INTNETR0IfWait: pIntNet=%p hIf=%RX32 cMillies=%u\n", pIntNet, hIf, cMillies));
@@ -844,5 +882,5 @@
      */
     ASMAtomicIncU32(&pIf->cSleepers);
-    int rc = RTSemEventWait(Event, cMillies);
+    int rc = RTSemEventWaitNoResume(Event, cMillies);
     if (pIf->Event == Event)
     {
@@ -859,4 +897,19 @@
 
 /**
+ * VMMR0 request wrapper for INTNETR0IfWait.
+ *
+ * @returns see INTNETR0IfWait.
+ * @param   pIntNet         The internal networking instance.
+ * @param   pReq            The request packet.
+ */
+INTNETR0DECL(int) INTNETR0IfWaitReq(PINTNET pIntNet, PINTNETIFWAITREQ pReq)
+{
+    if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
+        return VERR_INVALID_PARAMETER;
+    return INTNETR0IfWait(pIntNet, pReq->hIf, pReq->cMillies);
+}
+
+
+/**
  * Close an interface.
  *
@@ -880,4 +933,19 @@
     LogFlow(("INTNETR0IfClose: returns %Vrc\n", rc));
     return rc;
+}
+
+
+/**
+ * VMMR0 request wrapper for INTNETR0IfCloseReq.
+ *
+ * @returns see INTNETR0IfClose.
+ * @param   pIntNet         The internal networking instance.
+ * @param   pReq            The request packet.
+ */
+INTNETR0DECL(int) INTNETR0IfCloseReq(PINTNET pIntNet, PINTNETIFCLOSEREQ pReq)
+{
+    if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
+        return VERR_INVALID_PARAMETER;
+    return INTNETR0IfClose(pIntNet, pReq->hIf);
 }
 
@@ -978,7 +1046,7 @@
         SUPR0MemFree(pIf->pSession, (RTHCUINTPTR)pIf->pIntBufDefault);
         pIf->pIntBufDefault = NULL;
-        pIf->pIntBufDefaultR3 = NULL;
-        pIf->pIntBufR3 = NULL;
+        pIf->pIntBufDefaultR3 = 0;
         pIf->pIntBuf = NULL;
+        pIf->pIntBufR3 = 0;
     }
 
@@ -1419,4 +1487,20 @@
 
 /**
+ * VMMR0 request wrapper for GMMR0MapUnmapChunk.
+ *
+ * @returns see GMMR0MapUnmapChunk.
+ * @param   pIntNet         The internal networking instance.
+ * @param   pSession        The session handle.
+ * @param   pReq            The request packet.
+ */
+INTNETR0DECL(int) INTNETR0OpenReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETOPENREQ pReq)
+{
+    if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
+        return VERR_INVALID_PARAMETER;
+    return INTNETR0Open(pIntNet, pSession, &pReq->szNetwork[0], pReq->cbSend, pReq->cbRecv, pReq->fRestrictAccess, &pReq->hIf);
+}
+
+
+/**
  * Destroys an instance of the Ring-0 internal networking service.
  *
Index: trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp	(revision 5282)
+++ trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp	(revision 5283)
@@ -202,5 +202,5 @@
 
 
-#define TEST_TRANSFER_SIZE (_1M*128)
+#define TEST_TRANSFER_SIZE (_1M*384)
 
 /**
@@ -229,9 +229,15 @@
         const unsigned cb = iFrame % 1519 + 12 + sizeof(unsigned);
         *puFrame = iFrame;
+#if 0
         int rc = INTNETR0IfSend(pArgs->pIntNet, pArgs->hIf, abBuf, cb);
+#else
+        int rc = INTNETRingWriteFrame(pArgs->pBuf, &pArgs->pBuf->Send, abBuf, cb);
+        if (RT_SUCCESS(rc))
+            rc = INTNETR0IfSend(pArgs->pIntNet, pArgs->hIf, NULL, 0);
+#endif
         if (VBOX_FAILURE(rc))
         {
             g_cErrors++;
-            RTPrintf("tstIntNetR0: Failed sending %d bytes, rc=%Vrc\n", cb, rc);
+            RTPrintf("tstIntNetR0: Failed sending %d bytes, rc=%Vrc (%d)\n", cb, rc, INTNETRingGetWritable(&pArgs->pBuf->Send));
         }
         cbSent += cb;
@@ -384,5 +390,5 @@
      */
     INTNETIFHANDLE hIf0 = INTNET_HANDLE_INVALID;
-    rc = INTNETR0Open(pIntNet, g_pSession, "test", 1536, 0x8000, true, &hIf0);
+    rc = INTNETR0Open(pIntNet, g_pSession, "test", 1536*2 + 4, 0x8000, true, &hIf0);
     if (VBOX_SUCCESS(rc))
     {
@@ -390,5 +396,5 @@
         {
             INTNETIFHANDLE hIf1 = INTNET_HANDLE_INVALID;
-            rc = INTNETR0Open(pIntNet, g_pSession, "test", 1536, 0x8000, true, &hIf1);
+            rc = INTNETR0Open(pIntNet, g_pSession, "test", 1536*2 + 4, 0x8000, true, &hIf1);
             if (VBOX_SUCCESS(rc))
             {
Index: trunk/src/VBox/VMM/PDMDriver.cpp
===================================================================
--- trunk/src/VBox/VMM/PDMDriver.cpp	(revision 5282)
+++ trunk/src/VBox/VMM/PDMDriver.cpp	(revision 5283)
@@ -991,12 +991,5 @@
     if (    uOperation >= VMMR0_DO_SRV_START
         &&  uOperation <  VMMR0_DO_SRV_END)
-#if 0 /** @todo fix internal networking */
-        rc = SUPCallVMMR0Ex(pDrvIns->Internal.s.pVM->pVMR0, uOperation, pvArg, cbArg);
-#else
-{
-LogRel(("Sorry, internal networking is currently broken in the devlopment tree. Will be fixed in a bit, no time right now.\n"));
-rc = VERR_NOT_IMPLEMENTED;
-}
-#endif
+        rc = SUPCallVMMR0Ex(pDrvIns->Internal.s.pVM->pVMR0, uOperation, 0, (PSUPVMMR0REQHDR)pvArg);
     else
     {
Index: trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 5282)
+++ trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 5283)
@@ -832,74 +832,49 @@
 
 
-#if 0//def VBOX_WITH_INTERNAL_NETWORKING - currently busted
-        /*
-         * Services.
+#ifdef VBOX_WITH_INTERNAL_NETWORKING
+        /*
+         * Requests to the internal networking service.
          */
         case VMMR0_DO_INTNET_OPEN:
+            if (!pVM || u64Arg)
+                return VERR_INVALID_PARAMETER;
+            if (!g_pIntNet)
+                return VERR_NOT_SUPPORTED;
+            return INTNETR0OpenReq(g_pIntNet, pVM->pSession, (PINTNETOPENREQ)pReqHdr);
+
         case VMMR0_DO_INTNET_IF_CLOSE:
+            if (!pVM || u64Arg)
+                return VERR_INVALID_PARAMETER;
+            if (!g_pIntNet)
+                return VERR_NOT_SUPPORTED;
+            return INTNETR0IfCloseReq(g_pIntNet, (PINTNETIFCLOSEREQ)pReqHdr);
+
         case VMMR0_DO_INTNET_IF_GET_RING3_BUFFER:
+            if (!pVM || u64Arg)
+                return VERR_INVALID_PARAMETER;
+            if (!g_pIntNet)
+                return VERR_NOT_SUPPORTED;
+            return INTNETR0IfGetRing3BufferReq(g_pIntNet, (PINTNETIFGETRING3BUFFERREQ)pReqHdr);
+
         case VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE:
+            if (!pVM || u64Arg)
+                return VERR_INVALID_PARAMETER;
+            if (!g_pIntNet)
+                return VERR_NOT_SUPPORTED;
+            return INTNETR0IfSetPromiscuousModeReq(g_pIntNet, (PINTNETIFSETPROMISCUOUSMODEREQ)pReqHdr);
+
         case VMMR0_DO_INTNET_IF_SEND:
+            if (!pVM || u64Arg)
+                return VERR_INVALID_PARAMETER;
+            if (!g_pIntNet)
+                return VERR_NOT_SUPPORTED;
+            return INTNETR0IfSendReq(g_pIntNet, (PINTNETIFSENDREQ)pReqHdr);
+
         case VMMR0_DO_INTNET_IF_WAIT:
-        {
-            /*
-             * Validate arguments a bit first.
-             */
-            if (!VALID_PTR(pvArg))
-                return VERR_INVALID_POINTER;
-            if (!VALID_PTR(pVM))
-                return VERR_INVALID_POINTER;
-            if (pVM->pVMR0 != pVM)
-                return VERR_INVALID_POINTER;
-            if (!VALID_PTR(pVM->pSession))
-                return VERR_INVALID_POINTER;
+            if (!pVM || u64Arg)
+                return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
-                return VERR_FILE_NOT_FOUND; ///@todo fix this status code!
-
-            /*
-             * Unpack the arguments and call the service.
-             */
-            switch (enmOperation)
-            {
-                case VMMR0_DO_INTNET_OPEN:
-                {
-                    PINTNETOPENARGS pArgs = (PINTNETOPENARGS)pvArg;
-                    return INTNETR0Open(g_pIntNet, pVM->pSession, &pArgs->szNetwork[0], pArgs->cbSend, pArgs->cbRecv, pArgs->fRestrictAccess, &pArgs->hIf);
-                }
-
-                case VMMR0_DO_INTNET_IF_CLOSE:
-                {
-                    PINTNETIFCLOSEARGS pArgs = (PINTNETIFCLOSEARGS)pvArg;
-                    return INTNETR0IfClose(g_pIntNet, pArgs->hIf);
-                }
-
-                case VMMR0_DO_INTNET_IF_GET_RING3_BUFFER:
-                {
-                    PINTNETIFGETRING3BUFFERARGS pArgs = (PINTNETIFGETRING3BUFFERARGS)pvArg;
-                    return INTNETR0IfGetRing3Buffer(g_pIntNet, pArgs->hIf, &pArgs->pRing3Buf);
-                }
-
-                case VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE:
-                {
-                    PINTNETIFSETPROMISCUOUSMODEARGS pArgs = (PINTNETIFSETPROMISCUOUSMODEARGS)pvArg;
-                    return INTNETR0IfSetPromiscuousMode(g_pIntNet, pArgs->hIf, pArgs->fPromiscuous);
-                }
-
-                case VMMR0_DO_INTNET_IF_SEND:
-                {
-                    PINTNETIFSENDARGS pArgs = (PINTNETIFSENDARGS)pvArg;
-                    return INTNETR0IfSend(g_pIntNet, pArgs->hIf, pArgs->pvFrame, pArgs->cbFrame);
-                }
-
-                case VMMR0_DO_INTNET_IF_WAIT:
-                {
-                    PINTNETIFWAITARGS pArgs = (PINTNETIFWAITARGS)pvArg;
-                    return INTNETR0IfWait(g_pIntNet, pArgs->hIf, pArgs->cMillies);
-                }
-
-                default:
-                    return VERR_NOT_SUPPORTED;
-            }
-        }
+                return VERR_NOT_SUPPORTED;
+            return INTNETR0IfWaitReq(g_pIntNet, (PINTNETIFWAITREQ)pReqHdr);
 #endif /* VBOX_WITH_INTERNAL_NETWORKING */
 
