Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h	(revision 24122)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h	(revision 24123)
@@ -207,4 +207,12 @@
             /** Original interface flags */
             unsigned int flags;
+            /** Input queue */
+            struct ifqueue inq;
+            /** Output queue */
+            struct ifqueue outq;
+            /** Input task */
+            struct task tskin;
+            /** Output task */
+            struct task tskout;
             /** The MAC address of the interface. */
             RTMAC Mac;
@@ -241,4 +249,6 @@
 # endif
 #elif defined(RT_OS_LINUX)
+        uint8_t abPadding[320];
+#elif defined(RT_OS_FREEBSD)
         uint8_t abPadding[320];
 #else
Index: /trunk/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
===================================================================
--- /trunk/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c	(revision 24122)
+++ /trunk/src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c	(revision 24123)
@@ -44,4 +44,6 @@
 #include <sys/sockio.h>
 #include <sys/syscallsubr.h>
+#include <sys/queue.h>
+#include <sys/taskqueue.h>
 
 #include <net/if.h>
@@ -79,6 +81,4 @@
 static ng_disconnect_t    ng_vboxnetflt_disconnect;
 static int        ng_vboxnetflt_mod_event(module_t mod, int event, void *data);
-static int        ng_vboxnetflt_rcv_in(hook_p node, item_p item);
-static int        ng_vboxnetflt_rcv_out(hook_p node, item_p item);
 
 /** Netgraph node type */
@@ -113,6 +113,6 @@
     .version =    NG_ABI_VERSION,
     .name =        NG_VBOXNETFLT_NODE_TYPE,
-    .mod_event =    vboxnetflt_modevent,    
-    .constructor =    ng_vboxnetflt_constructor,    
+    .mod_event =    vboxnetflt_modevent,
+    .constructor =    ng_vboxnetflt_constructor,
     .rcvmsg =     ng_vboxnetflt_rcvmsg,
     .shutdown =    ng_vboxnetflt_shutdown,
@@ -268,5 +268,4 @@
     {
 #if __FreeBSD_version >= 800000
-        NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_in);
         NG_HOOK_SET_TO_INBOUND(hook);
 #endif
@@ -275,7 +274,4 @@
     else if (strcmp(name, NG_VBOXNETFLT_HOOK_OUT) == 0)
     {
-#if __FreeBSD_version >= 800000
-        NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_out);
-#endif
         pThis->u.s.output = hook;
     }
@@ -311,45 +307,23 @@
 /**
  * Handle data on netgraph hooks.
+ * Frames processing is deferred to a taskqueue because this might
+ * be called with non-sleepable locks held and code paths inside
+ * the virtual switch might sleep.
  */
 static int ng_vboxnetflt_rcvdata(hook_p hook, item_p item)
 {
-    const node_p node = NG_HOOK_NODE(hook);
-    PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
-    struct mbuf *m;
-
-    if (pThis->u.s.input == hook)
-        return ng_vboxnetflt_rcv_in(hook, item);
-    else if (pThis->u.s.output == hook)
-        return ng_vboxnetflt_rcv_out(hook, item);
-    else
-    {
-        NGI_GET_M(item, m);
-        NG_FREE_ITEM(item);
-    }
-    return (0);
-}
-
-/**
- * Handle incoming hook. This is connected to the
- * input path of the interface, thus handling incoming frames.
- */
-static int ng_vboxnetflt_rcv_in(hook_p hook, item_p item)
-{
-    struct mbuf *m, *m0;
-    struct m_tag *mtag;
     const node_p node = NG_HOOK_NODE(hook);
     PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
     struct ifnet *ifp = pThis->u.s.ifp;
-    bool fActive, fDropIt = false;
-    unsigned int cSegs = 0;
-    PINTNETSG pSG;
+    struct mbuf *m;
+    struct m_tag *mtag;
+    bool fActive;
+
+    fActive = ASMAtomicUoReadBool(&pThis->fActive);
 
     NGI_GET_M(item, m);
     NG_FREE_ITEM(item);
 
-    fActive = ASMAtomicUoReadBool(&pThis->fActive);
-    if (!fActive)
-        goto out;
-
+    /* Locate tag to see if processing should be skipped for this frame */
     mtag = m_tag_locate(m, MTAG_VBOX, PACKET_TAG_VBOX, NULL);
     if (mtag != NULL)
@@ -357,93 +331,39 @@
         m_tag_unlink(m, mtag);
         m_tag_free(mtag);
-        goto out;
-    }
-    vboxNetFltRetain(pThis, true /* fBusy */);
-
-    for (m0 = m; m0 != NULL; m0 = m0->m_next)
-    {
-        if (m0->m_len > 0)
-            cSegs++;
-    }
-
-#ifdef PADD_RUNT_FRAMES_FROM_HOST
-    if (m_length(m, NULL) < 60)
-        cSegs++;
-#endif
-
-    /* Create a copy of the mbuf and hand it to the virtual switch */
-    pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
-    vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
-    fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_WIRE);
-    RTMemTmpFree(pSG);
-    vboxNetFltRelease(pThis, true /* fBusy */);
-
-out:
-    /* Only deliver it to the host stack if the destination weren't a guest */
-    if (fDropIt)
+    }
+
+    /*
+     * Handle incoming hook. This is connected to the
+     * input path of the interface, thus handling incoming frames.
+     */
+    if (pThis->u.s.input == hook)
+    {
+        if (mtag != NULL || !fActive)
+        {
+            ether_demux(ifp, m);
+            return (0);
+        }
+        mtx_lock_spin(&pThis->u.s.inq.ifq_mtx);
+        _IF_ENQUEUE(&pThis->u.s.inq, m);
+        mtx_unlock_spin(&pThis->u.s.inq.ifq_mtx);
+        taskqueue_enqueue_fast(taskqueue_fast, &pThis->u.s.tskin);
+    }
+    /**
+     * Handle mbufs on the outgoing hook, frames going to the interface
+     */
+    else if (pThis->u.s.output == hook)
+    {
+        if (mtag != NULL || !fActive)
+            return ether_output_frame(ifp, m);
+        mtx_lock_spin(&pThis->u.s.outq.ifq_mtx);
+        _IF_ENQUEUE(&pThis->u.s.outq, m);
+        mtx_unlock_spin(&pThis->u.s.outq.ifq_mtx);
+        taskqueue_enqueue_fast(taskqueue_fast, &pThis->u.s.tskout);
+    }
+    else
     {
         m_freem(m);
-        return (0);
-    }
-    ether_demux(ifp, m);
+    }
     return (0);
-}
-
-/**
- * Handle mbufs on the outgoing hook, frames going to the interface
- */
-static int ng_vboxnetflt_rcv_out(hook_p hook, item_p item)
-{
-    struct mbuf *m, *m0;
-    struct m_tag *mtag;
-    const node_p node = NG_HOOK_NODE(hook);
-    PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
-    struct ifnet *ifp = pThis->u.s.ifp;
-    unsigned int cSegs = 0;
-    bool fDropIt = false, fActive;
-    PINTNETSG pSG;
-
-    NGI_GET_M(item, m);
-    NG_FREE_ITEM(item);
-
-    fActive = ASMAtomicUoReadBool(&pThis->fActive);
-    if (!fActive)
-        return ether_output_frame(ifp, m);
-
-    vboxNetFltRetain(pThis, true /* fBusy */);
-    /* Pass directly to interface if the packet originated from us */
-    mtag = m_tag_locate(m, MTAG_VBOX, PACKET_TAG_VBOX, NULL);
-    if (mtag != NULL)
-    {
-        m_tag_unlink(m, mtag);
-        m_tag_free(mtag);
-        goto out;
-    }
-
-    for (m0 = m; m0 != NULL; m0 = m0->m_next)
-    {
-        if (m0->m_len > 0)
-            cSegs++;
-    }
-
-#ifdef PADD_RUNT_FRAMES_FROM_HOST
-    if (m_length(m, NULL) < 60)
-        cSegs++;
-#endif
-    /* Create a copy and deliver to the virtual switch */
-    pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
-    vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
-    fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST);
-    RTMemTmpFree(pSG);
-
-out:
-    vboxNetFltRelease(pThis, true /* fBusy */);
-    if (fDropIt)
-    {
-        m_freem(m);
-        return (0);
-    }
-
-    return ether_output_frame(ifp, m);
 }
 
@@ -464,4 +384,90 @@
 {
     return (0);
+}
+
+/**
+ * Input processing task, handles incoming frames
+ */
+static void vboxNetFltFreeBSDinput(void *arg, int pending)
+{
+    PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+    struct mbuf *m, *m0;
+    struct ifnet *ifp = pThis->u.s.ifp;
+    unsigned int cSegs = 0;
+    bool fDropIt = false, fActive;
+    PINTNETSG pSG;
+
+    vboxNetFltRetain(pThis, true /* fBusy */);
+    for (;;)
+    {
+        mtx_lock_spin(&pThis->u.s.inq.ifq_mtx);
+        _IF_DEQUEUE(&pThis->u.s.inq, m);
+        mtx_unlock_spin(&pThis->u.s.inq.ifq_mtx);
+        if (m == NULL)
+            break;
+
+        for (m0 = m; m0 != NULL; m0 = m0->m_next)
+            if (m0->m_len > 0)
+                cSegs++;
+
+#ifdef PADD_RUNT_FRAMES_FROM_HOST
+        if (m_length(m, NULL) < 60)
+            cSegs++;
+#endif
+
+        /* Create a copy and deliver to the virtual switch */
+        pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
+        vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
+        fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST);
+        RTMemTmpFree(pSG);
+        if (fDropIt)
+            m_freem(m);
+        else
+            ether_demux(ifp, m);
+    }
+    vboxNetFltRelease(pThis, true /* fBusy */);
+}
+
+/**
+ * Output processing task, handles outgoing frames
+ */
+static void vboxNetFltFreeBSDoutput(void *arg, int pending)
+{
+    PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+    struct mbuf *m, *m0;
+    struct ifnet *ifp = pThis->u.s.ifp;
+    unsigned int cSegs = 0;
+    bool fDropIt = false, fActive;
+    PINTNETSG pSG;
+
+    vboxNetFltRetain(pThis, true /* fBusy */);
+    for (;;)
+    {
+        mtx_lock_spin(&pThis->u.s.outq.ifq_mtx);
+        _IF_DEQUEUE(&pThis->u.s.outq, m);
+        mtx_unlock_spin(&pThis->u.s.outq.ifq_mtx);
+        if (m == NULL)
+            break;
+
+        for (m0 = m; m0 != NULL; m0 = m0->m_next)
+            if (m0->m_len > 0)
+                cSegs++;
+
+#ifdef PADD_RUNT_FRAMES_FROM_HOST
+        if (m_length(m, NULL) < 60)
+            cSegs++;
+#endif
+        /* Create a copy and deliver to the virtual switch */
+        pSG = RTMemTmpAlloc(RT_OFFSETOF(INTNETSG, aSegs[cSegs]));
+        vboxNetFltFreeBSDMBufToSG(pThis, m, pSG, cSegs, 0);
+        fDropIt = pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST);
+        RTMemTmpFree(pSG);
+
+        if (fDropIt)
+            m_freem(m);
+        else
+            ether_output_frame(ifp, m);
+    }
+    vboxNetFltRelease(pThis, true /* fBusy */);
 }
 
@@ -537,5 +543,5 @@
     /* Create a new netgraph node for this instance */
     if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0)
-        return VERR_INTERNAL_ERROR;        
+        return VERR_INTERNAL_ERROR;
 
     RTSpinlockAcquire(pThis->hSpinlock, &Tmp);
@@ -544,4 +550,14 @@
     bcopy(IF_LLADDR(ifp), &pThis->u.s.Mac, ETHER_ADDR_LEN);
     ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false);
+    /* Initialize deferred input queue */
+    bzero(&pThis->u.s.inq, sizeof(struct ifqueue));
+    mtx_init(&pThis->u.s.inq.ifq_mtx, "vboxnetflt inq", NULL, MTX_SPIN);
+    TASK_INIT(&pThis->u.s.tskin, 0, vboxNetFltFreeBSDinput, pThis);
+
+    /* Initialize deferred output queue */
+    bzero(&pThis->u.s.outq, sizeof(struct ifqueue));
+    mtx_init(&pThis->u.s.outq.ifq_mtx, "vboxnetflt outq", NULL, MTX_SPIN);
+    TASK_INIT(&pThis->u.s.tskout, 0, vboxNetFltFreeBSDoutput, pThis);
+
     RTSpinlockRelease(pThis->hSpinlock, &Tmp);
 
@@ -572,5 +588,8 @@
 
     if (ifp0 != NULL)
+    {
+        vboxNetFltOsDeleteInstance(pThis);
         vboxNetFltOsInitInstance(pThis, NULL);
+    }
 
     return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
@@ -579,4 +598,10 @@
 void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis)
 {
+
+    taskqueue_drain(taskqueue_fast, &pThis->u.s.tskin);
+    taskqueue_drain(taskqueue_fast, &pThis->u.s.tskout);
+
+    mtx_destroy(&pThis->u.s.inq.ifq_mtx);
+    mtx_destroy(&pThis->u.s.outq.ifq_mtx);
 
     if (pThis->u.s.node != NULL)
