Index: /trunk/include/VBox/VBoxHDD.h
===================================================================
--- /trunk/include/VBox/VBoxHDD.h	(revision 30308)
+++ /trunk/include/VBox/VBoxHDD.h	(revision 30309)
@@ -1060,5 +1060,5 @@
 
     /**
-     * Send data from a socket.
+     * Send data to a socket.
      *
      * @return  iprt status code.
@@ -1066,15 +1066,32 @@
      * @param   pvBuffer    Buffer to write data to socket.
      * @param   cbBuffer    How much to write.
-     * @param   pcbRead     Number of bytes read.
      */
     DECLR3CALLBACKMEMBER(int, pfnWrite, (RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer));
 
     /**
-     * Flush socket write buffers.
+     * Send data from scatter/gather buffer to a socket.
      *
      * @return  iprt status code.
      * @param   Sock        Socket descriptor.
+     * @param   pSgBuf      Scatter/gather buffer to write data to socket.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnSgWrite, (RTSOCKET Sock, PCRTSGBUF pSgBuf));
+
+    /**
+     * Flush socket write buffers.
+     *
+     * @return  iprt status code.
+     * @param   Sock        Socket descriptor.
      */
     DECLR3CALLBACKMEMBER(int, pfnFlush, (RTSOCKET Sock));
+
+    /**
+     * Enables or disables delaying sends to coalesce packets.
+     *
+     * @return  iprt status code.
+     * @param   Sock        Socket descriptor.
+     * @param   fEnable     When set to true enables coalescing.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnSetSendCoalescing, (RTSOCKET Sock, bool fEnable));
 
     /**
Index: /trunk/src/VBox/Devices/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Devices/Makefile.kmk	(revision 30308)
+++ /trunk/src/VBox/Devices/Makefile.kmk	(revision 30309)
@@ -150,9 +150,6 @@
  VBoxDD_DEFS           += VBOX_WITH_AHCI
 endif
-ifdef VBOX_WITH_ISCSI
- VBoxDD_DEFS           += VBOX_WITH_ISCSI
- ifdef VBOX_WITH_INIP
-  VBoxDD_DEFS          += VBOX_WITH_INIP
- endif
+ifdef VBOX_WITH_INIP
+ VBoxDD_DEFS           += VBOX_WITH_INIP
 endif
 ifdef VBOX_WITH_E1000
@@ -819,4 +816,7 @@
 Drivers_DEFS           += VBOX_WITH_NETFLT
 endif
+ifdef VBOX_WITH_INIP
+Drivers_DEFS           += VBOX_WITH_INIP
+endif
 ifdef VBOX_WITH_DRV_DISK_INTEGRITY
 Drivers_DEFS           += VBOX_WITH_DRV_DISK_INTEGRITY
Index: /trunk/src/VBox/Devices/Storage/DrvVD.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 30308)
+++ /trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 30309)
@@ -586,4 +586,12 @@
 *******************************************************************************/
 
+typedef union INIPSOCKADDRUNION
+{
+    struct sockaddr     Addr;
+    struct sockaddr_in  Ipv4;
+} INIPSOCKADDRUNION;
+
+static DECLCALLBACK(int) drvvdINIPFlush(RTSOCKET Sock);
+
 /** @copydoc VDINTERFACETCPNET::pfnClientConnect */
 static DECLCALLBACK(int) drvvdINIPClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
@@ -605,5 +613,5 @@
     }
     /* Create socket and connect. */
-    RTSOCKET Sock = lwip_socket(PF_INET, SOCK_STREAM, 0);
+    int Sock = lwip_socket(PF_INET, SOCK_STREAM, 0);
     if (Sock != -1)
     {
@@ -614,5 +622,5 @@
         if (!lwip_connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
         {
-            *pSock = Sock;
+            *pSock = (RTSOCKET)Sock;
             return VINF_SUCCESS;
         }
@@ -628,5 +636,5 @@
 static DECLCALLBACK(int) drvvdINIPClientClose(RTSOCKET Sock)
 {
-    lwip_close(Sock);
+    lwip_close((uintptr_t)Sock);
     return VINF_SUCCESS; /** @todo real solution needed */
 }
@@ -637,10 +645,10 @@
     fd_set fdsetR;
     FD_ZERO(&fdsetR);
-    FD_SET(Sock, &fdsetR);
+    FD_SET((uintptr_t)Sock, &fdsetR);
     fd_set fdsetE = fdsetR;
 
     int rc;
     if (cMillies == RT_INDEFINITE_WAIT)
-        rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
+        rc = lwip_select((uintptr_t)Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
     else
     {
@@ -648,5 +656,5 @@
         timeout.tv_sec = cMillies / 1000;
         timeout.tv_usec = (cMillies % 1000) * 1000;
-        rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
+        rc = lwip_select((uintptr_t)Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
     }
     if (rc > 0)
@@ -678,5 +686,5 @@
          * needed it, so I added it here, too). Didn't investigate if this
          * really has issues. Better be safe than sorry. */
-        ssize_t cbBytesRead = lwip_recv(Sock, (char *)pvBuffer + cbRead,
+        ssize_t cbBytesRead = lwip_recv((uintptr_t)Sock, (char *)pvBuffer + cbRead,
                                         RT_MIN(cbToRead, 32768), 0);
         if (cbBytesRead < 0)
@@ -712,5 +720,5 @@
          * don't get any wraparounds. This should be moved to DevINIP
          * stack interface once that's implemented. */
-        ssize_t cbWritten = lwip_send(Sock, (void *)pvBuffer,
+        ssize_t cbWritten = lwip_send((uintptr_t)Sock, (void *)pvBuffer,
                                       RT_MIN(cbBuffer, 32768), 0);
         if (cbWritten < 0)
@@ -725,27 +733,52 @@
 }
 
+/** @copydoc VDINTERFACETCPNET::pfnSgWrite */
+static DECLCALLBACK(int) drvvdINIPSgWrite(RTSOCKET Sock, PCRTSGBUF pSgBuf)
+{
+    int rc = VINF_SUCCESS;
+
+    /* This is an extremely crude emulation, however it's good enough
+     * for our iSCSI code. INIP has no sendmsg(). */
+    for (unsigned i = 0; i < pSgBuf->cSeg; i++)
+    {
+        rc = drvvdINIPWrite(Sock, pSgBuf->pcaSeg[i].pvSeg,
+                            pSgBuf->pcaSeg[i].cbSeg);
+        if (RT_FAILURE(rc))
+            break;
+    }
+    if (RT_SUCCESS(rc))
+        drvvdINIPFlush(Sock);
+
+    return rc;
+}
+
 /** @copydoc VDINTERFACETCPNET::pfnFlush */
 static DECLCALLBACK(int) drvvdINIPFlush(RTSOCKET Sock)
 {
     int fFlag = 1;
-    lwip_setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY,
+    lwip_setsockopt((uintptr_t)Sock, IPPROTO_TCP, TCP_NODELAY,
                     (const char *)&fFlag, sizeof(fFlag));
     fFlag = 0;
-    lwip_setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY,
+    lwip_setsockopt((uintptr_t)Sock, IPPROTO_TCP, TCP_NODELAY,
                     (const char *)&fFlag, sizeof(fFlag));
     return VINF_SUCCESS;
 }
 
+/** @copydoc VDINTERFACETCPNET::pfnSetSendCoalescing */
+static DECLCALLBACK(int) drvvdINIPSetSendCoalescing(RTSOCKET Sock, bool fEnable)
+{
+    int fFlag = fEnable ? 0 : 1;
+    lwip_setsockopt((uintptr_t)Sock, IPPROTO_TCP, TCP_NODELAY,
+                    (const char *)&fFlag, sizeof(fFlag));
+    return VINF_SUCCESS;
+}
+
 /** @copydoc VDINTERFACETCPNET::pfnGetLocalAddress */
 static DECLCALLBACK(int) drvvdINIPGetLocalAddress(RTSOCKET Sock, PRTNETADDR pAddr)
 {
-   union
-    {
-        struct sockaddr     Addr;
-        struct sockaddr_in  Ipv4;
-    }               u;
-    socklen_t       cbAddr = sizeof(u);
+    INIPSOCKADDRUNION u;
+    socklen_t cbAddr = sizeof(u);
     RT_ZERO(u);
-    if (!lwip_getsockname(Sock, &u.Addr, &cbAddr))
+    if (!lwip_getsockname((uintptr_t)Sock, &u.Addr, &cbAddr))
     {
         /*
@@ -770,12 +803,8 @@
 static DECLCALLBACK(int) drvvdINIPGetPeerAddress(RTSOCKET Sock, PRTNETADDR pAddr)
 {
-   union
-    {
-        struct sockaddr     Addr;
-        struct sockaddr_in  Ipv4;
-    }               u;
-    socklen_t       cbAddr = sizeof(u);
+    INIPSOCKADDRUNION u;
+    socklen_t cbAddr = sizeof(u);
     RT_ZERO(u);
-    if (!lwip_getpeername(Sock, &u.Addr, &cbAddr))
+    if (!lwip_getpeername((uintptr_t)Sock, &u.Addr, &cbAddr))
     {
         /*
@@ -1386,5 +1415,7 @@
             pThis->VDITcpNetCallbacks.pfnRead = RTTcpRead;
             pThis->VDITcpNetCallbacks.pfnWrite = RTTcpWrite;
+            pThis->VDITcpNetCallbacks.pfnSgWrite = RTTcpSgWrite;
             pThis->VDITcpNetCallbacks.pfnFlush = RTTcpFlush;
+            pThis->VDITcpNetCallbacks.pfnSetSendCoalescing = RTTcpSetSendCoalescing;
             pThis->VDITcpNetCallbacks.pfnGetLocalAddress = RTTcpGetLocalAddress;
             pThis->VDITcpNetCallbacks.pfnGetPeerAddress = RTTcpGetPeerAddress;
@@ -1403,5 +1434,7 @@
             pThis->VDITcpNetCallbacks.pfnRead = drvvdINIPRead;
             pThis->VDITcpNetCallbacks.pfnWrite = drvvdINIPWrite;
+            pThis->VDITcpNetCallbacks.pfnSgWrite = drvvdINIPSgWrite;
             pThis->VDITcpNetCallbacks.pfnFlush = drvvdINIPFlush;
+            pThis->VDITcpNetCallbacks.pfnSetSendCoalescing = drvvdINIPSetSendCoalescing;
             pThis->VDITcpNetCallbacks.pfnGetLocalAddress = drvvdINIPGetLocalAddress;
             pThis->VDITcpNetCallbacks.pfnGetPeerAddress = drvvdINIPGetPeerAddress;
Index: /trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp	(revision 30308)
+++ /trunk/src/VBox/Devices/Storage/ISCSIHDDCore.cpp	(revision 30309)
@@ -218,4 +218,7 @@
 /** ISCSI BHS word 0: response includes status. */
 #define ISCSI_STATUS_BIT 0x00010000
+
+/** Maximum number of scatter/gather segments needed to send a PDU. */
+#define ISCSI_SG_SEGMENTS_MAX 4
 
 
@@ -548,4 +551,7 @@
         return rc;
     }
+
+    /* Disable Nagle algorithm, we want things to be sent immediately. */
+    pImage->pInterfaceNetCallbacks->pfnSetSendCoalescing(pImage->Socket, false);
 
     /* Make initiator name and ISID unique on this host. */
@@ -714,25 +720,37 @@
     if (RT_SUCCESS(rc))
     {
+        /* Construct scatter/gather buffer for entire request, worst case
+         * needs twice as many entries to allow for padding. */
+        unsigned cBuf = 0;
         for (i = 0; i < cnRequest; i++)
         {
-            /* Write one chunk of data. */
-            rc = pImage->pInterfaceNetCallbacks->pfnWrite(pImage->Socket,
-                                                          paRequest[i].pcvSeg,
-                                                          paRequest[i].cbSeg);
-            if (RT_FAILURE(rc))
-                break;
-            /* Insert proper padding before the next chunk us written. */
+            cBuf++;
+            if (paRequest[i].cbSeg & 3)
+                cBuf++;
+        }
+        Assert(cBuf < ISCSI_SG_SEGMENTS_MAX);
+        RTSGBUF buf;
+        RTSGSEG aSeg[ISCSI_SG_SEGMENTS_MAX];
+        static char aPad[4] = { 0, 0, 0, 0 };
+        RTSgBufInit(&buf, &aSeg[0], cBuf);
+        unsigned iBuf = 0;
+        for (i = 0; i < cnRequest; i++)
+        {
+            /* Actual data chunk. */
+            aSeg[iBuf].pvSeg = (void *)paRequest[i].pcvSeg;
+            aSeg[iBuf].cbSeg = paRequest[i].cbSeg;
+            iBuf++;
+            /* Insert proper padding before the next chunk. */
             if (paRequest[i].cbSeg & 3)
             {
-                rc = pImage->pInterfaceNetCallbacks->pfnWrite(pImage->Socket,
-                                                              &pad,
-                                                              4 - (paRequest[i].cbSeg & 3));
-                if (RT_FAILURE(rc))
-                    break;
+                aSeg[iBuf].pvSeg = &aPad[0];
+                aSeg[iBuf].cbSeg = 4 - (paRequest[i].cbSeg & 3);
+                iBuf++;
             }
         }
-        /* Send out the request as soon as possible, otherwise the target will
-         * answer after an unnecessary delay. */
-        pImage->pInterfaceNetCallbacks->pfnFlush(pImage->Socket);
+        /* Send out the request, the socket is set to send data immediately,
+         * avoiding unnecessary delays. */
+        rc = pImage->pInterfaceNetCallbacks->pfnSgWrite(pImage->Socket, &buf);
+
     }
 
Index: /trunk/src/VBox/Main/MediumImpl.cpp
===================================================================
--- /trunk/src/VBox/Main/MediumImpl.cpp	(revision 30308)
+++ /trunk/src/VBox/Main/MediumImpl.cpp	(revision 30309)
@@ -673,5 +673,7 @@
     m->vdIfCallsTcpNet.pfnRead = RTTcpRead;
     m->vdIfCallsTcpNet.pfnWrite = RTTcpWrite;
+    m->vdIfCallsTcpNet.pfnSgWrite = RTTcpSgWrite;
     m->vdIfCallsTcpNet.pfnFlush = RTTcpFlush;
+    m->vdIfCallsTcpNet.pfnSetSendCoalescing = RTTcpSetSendCoalescing;
     m->vdIfCallsTcpNet.pfnGetLocalAddress = RTTcpGetLocalAddress;
     m->vdIfCallsTcpNet.pfnGetPeerAddress = RTTcpGetPeerAddress;
