Index: /trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/DevVirtioNet.cpp	(revision 41808)
+++ /trunk/src/VBox/Devices/Network/DevVirtioNet.cpp	(revision 41809)
@@ -1074,5 +1074,9 @@
 
     VQUEUEELEM elem;
-    while (vqueueGet(&pState->VPCI, pQueue, &elem))
+    /*
+     * Do not remove descriptors from available ring yet, try to allocate the
+     * buffer first.
+     */
+    while (vqueuePeek(&pState->VPCI, pQueue, &elem))
     {
         unsigned int uOffset = 0;
@@ -1165,5 +1169,11 @@
                 }
                 else
-                    LogRel(("virtio-net: failed to allocate SG buffer: size=%u rc=%Rrc\n", uSize, rc));
+                {
+                    Log4(("virtio-net: failed to allocate SG buffer: size=%u rc=%Rrc\n", uSize, rc));
+                    STAM_PROFILE_STOP(&pState->StatTransmitSend, a);
+                    STAM_PROFILE_ADV_STOP(&pState->StatTransmit, a);
+                    /* Stop trying to fetch TX descriptors until we get more bandwidth. */
+                    break;
+                }
 
                 STAM_PROFILE_STOP(&pState->StatTransmitSend, a);
@@ -1171,4 +1181,6 @@
             }
         }
+        /* Remove this descriptor chain from the available ring */
+        vqueueSkip(&pState->VPCI, pQueue);
         vqueuePut(&pState->VPCI, pQueue, &elem, sizeof(VNETHDR) + uOffset);
         vqueueSync(&pState->VPCI, pQueue);
Index: /trunk/src/VBox/Devices/VirtIO/Virtio.cpp
===================================================================
--- /trunk/src/VBox/Devices/VirtIO/Virtio.cpp	(revision 41808)
+++ /trunk/src/VBox/Devices/VirtIO/Virtio.cpp	(revision 41809)
@@ -111,9 +111,20 @@
 }
 
-bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem)
+bool vqueueSkip(PVPCISTATE pState, PVQUEUE pQueue)
 {
     if (vqueueIsEmpty(pState, pQueue))
         return false;
 
+    Log2(("%s vqueueSkip: %s avail_idx=%u\n", INSTANCE(pState),
+          QUEUENAME(pState, pQueue), pQueue->uNextAvailIndex));
+    pQueue->uNextAvailIndex++;
+    return true;
+}
+
+bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove)
+{
+    if (vqueueIsEmpty(pState, pQueue))
+        return false;
+
     pElem->nIn = pElem->nOut = 0;
 
@@ -122,5 +133,7 @@
 
     VRINGDESC desc;
-    uint16_t  idx = vringReadAvail(pState, &pQueue->VRing, pQueue->uNextAvailIndex++);
+    uint16_t  idx = vringReadAvail(pState, &pQueue->VRing, pQueue->uNextAvailIndex);
+    if (fRemove)
+        pQueue->uNextAvailIndex++;
     pElem->uIndex = idx;
     do
Index: /trunk/src/VBox/Devices/VirtIO/Virtio.h
===================================================================
--- /trunk/src/VBox/Devices/VirtIO/Virtio.h	(revision 41808)
+++ /trunk/src/VBox/Devices/VirtIO/Virtio.h	(revision 41809)
@@ -304,9 +304,14 @@
 }
 
-bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem);
+bool vqueueSkip(PVPCISTATE pState, PVQUEUE pQueue);
+bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true);
 void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen, uint32_t uReserved = 0);
 void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue);
 void vqueueSync(PVPCISTATE pState, PVQUEUE pQueue);
 
+DECLINLINE(bool) vqueuePeek(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem)
+{
+    return vqueueGet(pState, pQueue, pElem, /* fRemove */ false);
+}
 
 DECLINLINE(bool) vqueueIsReady(PVPCISTATE pState, PVQUEUE pQueue)
