summaryrefslogtreecommitdiff
path: root/emulators
diff options
context:
space:
mode:
authorBeat Gaetzi <beat@FreeBSD.org>2009-09-29 15:15:02 +0000
committerBeat Gaetzi <beat@FreeBSD.org>2009-09-29 15:15:02 +0000
commit972faa0f831ccb4abea40c815f85055002905d94 (patch)
tree71644769d717f376a81bf9a8491fc937ae6d4d9f /emulators
parent- Updated to 1.9.3PL1 (diff)
- Improve error message if /usr/lib32 is not installed on amd64. [1]
- Fix pkg-plist. Additions directory is only created with WITH_GUESTADDITIONS option. [2] - Add patch to fix panic with vboxnet driver. [3] - Bump PORTREVISION. PR: ports/138935 [1] (based on) Reported by: scf@ [3] Submitted by: Julian H. Stacey <jhs AT berklix.com> [1], Bernhard Froehlich <decke AT bluelife.at> [2], Fredrik Lindberg <fli AT shapeshifter.se> [3] On behalf of: vbox@ (decke, dhn, itetcu, miwi, nox) Feature safe: yes
Notes
Notes: svn path=/head/; revision=242234
Diffstat (limited to 'emulators')
-rw-r--r--emulators/virtualbox-ose-kmod-legacy/Makefile13
-rw-r--r--emulators/virtualbox-ose-kmod-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h28
-rw-r--r--emulators/virtualbox-ose-kmod-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c375
-rw-r--r--emulators/virtualbox-ose-kmod-legacy/pkg-plist2
-rw-r--r--emulators/virtualbox-ose-kmod/Makefile13
-rw-r--r--emulators/virtualbox-ose-kmod/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h28
-rw-r--r--emulators/virtualbox-ose-kmod/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c375
-rw-r--r--emulators/virtualbox-ose-kmod/pkg-plist2
-rw-r--r--emulators/virtualbox-ose-legacy/Makefile13
-rw-r--r--emulators/virtualbox-ose-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h28
-rw-r--r--emulators/virtualbox-ose-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c375
-rw-r--r--emulators/virtualbox-ose-legacy/pkg-plist2
-rw-r--r--emulators/virtualbox-ose/Makefile13
-rw-r--r--emulators/virtualbox-ose/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h28
-rw-r--r--emulators/virtualbox-ose/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c375
-rw-r--r--emulators/virtualbox-ose/pkg-plist2
-rw-r--r--emulators/virtualbox/Makefile13
-rw-r--r--emulators/virtualbox/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h28
-rw-r--r--emulators/virtualbox/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c375
-rw-r--r--emulators/virtualbox/pkg-plist2
20 files changed, 2070 insertions, 20 deletions
diff --git a/emulators/virtualbox-ose-kmod-legacy/Makefile b/emulators/virtualbox-ose-kmod-legacy/Makefile
index 3538d0054d94..a1a5891255f7 100644
--- a/emulators/virtualbox-ose-kmod-legacy/Makefile
+++ b/emulators/virtualbox-ose-kmod-legacy/Makefile
@@ -7,6 +7,7 @@
PORTNAME= virtualbox
DISTVERSION= 3.0.51r22902
+PORTREVISION= 1
CATEGORIES= emulators kld
MASTER_SITES= http://tmp.chruetertee.ch/ \
http://freebsd.unixfreunde.de/sources/ \
@@ -142,15 +143,21 @@ BROKEN= Does not compile on FreeBSD 6.X
KMK_ARCH= freebsd.x86
PLIST_SUB+= I386=""
.else
-.if !exists(/usr/lib32)
-IGNORE= requires 32-bit libraries installed under /usr/lib32
-.endif
KMK_ARCH= freebsd.${ARCH}
PLIST_SUB+= I386="@comment "
.endif
.include <bsd.port.pre.mk>
+pre-everything::
+.if ${ARCH} == "amd64"
+.if !exists(/usr/lib32)
+ @${ECHO} 'Requires 32-bit libraries installed under /usr/lib32.'
+ @${ECHO} 'Do: cd /usr/src; make build32 install32; ldconfig -v -m -R /usr/lib32'
+ @${FALSE}
+.endif
+.endif
+
post-patch:
@${ECHO} 'VBOX_PATH_APP_PRIVATE_ARCH = ${PREFIX}/lib/virtualbox' > ${WRKSRC}/LocalConfig.kmk
@${ECHO} 'VBOX_PATH_SHARED_LIBS = ${PREFIX}/lib/virtualbox' >> ${WRKSRC}/LocalConfig.kmk
diff --git a/emulators/virtualbox-ose-kmod-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h b/emulators/virtualbox-ose-kmod-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
new file mode 100644
index 000000000000..1924d8dd90ef
--- /dev/null
+++ b/emulators/virtualbox-ose-kmod-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
@@ -0,0 +1,28 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (working copy)
+@@ -206,6 +206,14 @@
+ hook_p output;
+ /** 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,6 +249,8 @@
+ # endif
+ #elif defined(RT_OS_LINUX)
+ uint8_t abPadding[320];
++#elif defined(RT_OS_FREEBSD)
++ uint8_t abPadding[256];
+ #else
+ uint8_t abPadding[128];
+ #endif
diff --git a/emulators/virtualbox-ose-kmod-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c b/emulators/virtualbox-ose-kmod-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
new file mode 100644
index 000000000000..bc23fb14a545
--- /dev/null
+++ b/emulators/virtualbox-ose-kmod-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
@@ -0,0 +1,375 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (working copy)
+@@ -43,6 +43,8 @@
+ #include <sys/socket.h>
+ #include <sys/sockio.h>
+ #include <sys/syscallsubr.h>
++#include <sys/queue.h>
++#include <sys/taskqueue.h>
+
+ #include <net/if.h>
+ #include <net/if_var.h>
+@@ -78,8 +80,6 @@
+ static ng_rcvdata_t ng_vboxnetflt_rcvdata;
+ 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 */
+ #define NG_VBOXNETFLT_NODE_TYPE "vboxnetflt"
+@@ -112,8 +112,8 @@
+ {
+ .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,
+ .newhook = ng_vboxnetflt_newhook,
+@@ -267,16 +267,12 @@
+ if (strcmp(name, NG_VBOXNETFLT_HOOK_IN) == 0)
+ {
+ #if __FreeBSD_version >= 800000
+- NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_in);
+ NG_HOOK_SET_TO_INBOUND(hook);
+ #endif
+ pThis->u.s.input = hook;
+ }
+ 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;
+ }
+ else
+@@ -310,161 +306,171 @@
+
+ /**
+ * 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 ifnet *ifp = pThis->u.s.ifp;
+ struct mbuf *m;
++ struct m_tag *mtag;
++ bool fActive;
+
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++
++ NGI_GET_M(item, m);
++ NG_FREE_ITEM(item);
++
++ /* 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)
++ {
++ m_tag_unlink(m, mtag);
++ m_tag_free(mtag);
++ }
++
++ /*
++ * Handle incoming hook. This is connected to the
++ * input path of the interface, thus handling incoming frames.
++ */
+ if (pThis->u.s.input == hook)
+- return ng_vboxnetflt_rcv_in(hook, item);
++ {
++ 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)
+- return ng_vboxnetflt_rcv_out(hook, item);
++ {
++ 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
+ {
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
++ m_freem(m);
+ }
+ return (0);
+ }
+
++static int ng_vboxnetflt_shutdown(node_p node)
++{
++ PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
++ bool fActive;
++
++ /* Prevent node shutdown if we're active */
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++ if (fActive)
++ return (EBUSY);
++ NG_NODE_UNREF(node);
++ return (0);
++}
++
++static int ng_vboxnetflt_disconnect(hook_p hook)
++{
++ return (0);
++}
++
+ /**
+- * Handle incoming hook. This is connected to the
+- * input path of the interface, thus handling incoming frames.
++ * Input processing task, handles incoming frames
+ */
+-static int ng_vboxnetflt_rcv_in(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDinput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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;
++ bool fDropIt = false, fActive;
+ PINTNETSG pSG;
+
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
+-
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (!fActive)
+- goto out;
+-
+- 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;
+- }
+ vboxNetFltRetain(pThis, true /* fBusy */);
+-
+- for (m0 = m; m0 != NULL; m0 = m0->m_next)
++ for (;;)
+ {
+- if (m0->m_len > 0)
+- cSegs++;
+- }
++ 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++;
++ 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);
++ /* 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 */);
+-
+-out:
+- /* Only deliver it to the host stack if the destination weren't a guest */
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+- ether_demux(ifp, m);
+- return (0);
+ }
+
+ /**
+- * Handle mbufs on the outgoing hook, frames going to the interface
++ * Output processing task, handles outgoing frames
+ */
+-static int ng_vboxnetflt_rcv_out(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDoutput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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)
++ for (;;)
+ {
+- m_tag_unlink(m, mtag);
+- m_tag_free(mtag);
+- goto out;
+- }
++ 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++;
+- }
++ 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++;
++ 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);
++ /* 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:
++ if (fDropIt)
++ m_freem(m);
++ else
++ ether_output_frame(ifp, m);
++ }
+ vboxNetFltRelease(pThis, true /* fBusy */);
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+-
+- return ether_output_frame(ifp, m);
+ }
+
+-static int ng_vboxnetflt_shutdown(node_p node)
+-{
+- PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
+- bool fActive;
+-
+- /* Prevent node shutdown if we're active */
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (fActive)
+- return (EBUSY);
+- NG_NODE_UNREF(node);
+- return (0);
+-}
+-
+-static int ng_vboxnetflt_disconnect(hook_p hook)
+-{
+- return (0);
+-}
+-
+ /**
+ * Called to deliver a frame to either the host, the wire or both.
+ */
+@@ -536,13 +542,23 @@
+
+ /* 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);
+ ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.ifp, ifp);
+ pThis->u.s.node = node;
+ 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);
+
+ NG_NODE_SET_PRIVATE(node, pThis);
+@@ -571,7 +587,10 @@
+ }
+
+ if (ifp0 != NULL)
++ {
++ vboxNetFltOsDeleteInstance(pThis);
+ vboxNetFltOsInitInstance(pThis, NULL);
++ }
+
+ return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
+ }
+@@ -579,6 +598,12 @@
+ 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)
+ ng_rmnode_self(pThis->u.s.node);
+ pThis->u.s.node = NULL;
diff --git a/emulators/virtualbox-ose-kmod-legacy/pkg-plist b/emulators/virtualbox-ose-kmod-legacy/pkg-plist
index 701bcf61f230..bdafc64fb6ee 100644
--- a/emulators/virtualbox-ose-kmod-legacy/pkg-plist
+++ b/emulators/virtualbox-ose-kmod-legacy/pkg-plist
@@ -592,7 +592,7 @@ include/virtualbox/xpcom/xpcom-config.h
%%QT4%%@dirrmtry share/icons
%%QT4%%@dirrmtry share/applications
@dirrm lib/virtualbox/components
-@dirrm lib/virtualbox/additions
+%%GUESTADDITIONS%%@dirrm lib/virtualbox/additions
@dirrm lib/virtualbox
@cwd /
%%KMODDIR%%/vboxdrv.ko
diff --git a/emulators/virtualbox-ose-kmod/Makefile b/emulators/virtualbox-ose-kmod/Makefile
index 3538d0054d94..a1a5891255f7 100644
--- a/emulators/virtualbox-ose-kmod/Makefile
+++ b/emulators/virtualbox-ose-kmod/Makefile
@@ -7,6 +7,7 @@
PORTNAME= virtualbox
DISTVERSION= 3.0.51r22902
+PORTREVISION= 1
CATEGORIES= emulators kld
MASTER_SITES= http://tmp.chruetertee.ch/ \
http://freebsd.unixfreunde.de/sources/ \
@@ -142,15 +143,21 @@ BROKEN= Does not compile on FreeBSD 6.X
KMK_ARCH= freebsd.x86
PLIST_SUB+= I386=""
.else
-.if !exists(/usr/lib32)
-IGNORE= requires 32-bit libraries installed under /usr/lib32
-.endif
KMK_ARCH= freebsd.${ARCH}
PLIST_SUB+= I386="@comment "
.endif
.include <bsd.port.pre.mk>
+pre-everything::
+.if ${ARCH} == "amd64"
+.if !exists(/usr/lib32)
+ @${ECHO} 'Requires 32-bit libraries installed under /usr/lib32.'
+ @${ECHO} 'Do: cd /usr/src; make build32 install32; ldconfig -v -m -R /usr/lib32'
+ @${FALSE}
+.endif
+.endif
+
post-patch:
@${ECHO} 'VBOX_PATH_APP_PRIVATE_ARCH = ${PREFIX}/lib/virtualbox' > ${WRKSRC}/LocalConfig.kmk
@${ECHO} 'VBOX_PATH_SHARED_LIBS = ${PREFIX}/lib/virtualbox' >> ${WRKSRC}/LocalConfig.kmk
diff --git a/emulators/virtualbox-ose-kmod/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h b/emulators/virtualbox-ose-kmod/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
new file mode 100644
index 000000000000..1924d8dd90ef
--- /dev/null
+++ b/emulators/virtualbox-ose-kmod/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
@@ -0,0 +1,28 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (working copy)
+@@ -206,6 +206,14 @@
+ hook_p output;
+ /** 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,6 +249,8 @@
+ # endif
+ #elif defined(RT_OS_LINUX)
+ uint8_t abPadding[320];
++#elif defined(RT_OS_FREEBSD)
++ uint8_t abPadding[256];
+ #else
+ uint8_t abPadding[128];
+ #endif
diff --git a/emulators/virtualbox-ose-kmod/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c b/emulators/virtualbox-ose-kmod/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
new file mode 100644
index 000000000000..bc23fb14a545
--- /dev/null
+++ b/emulators/virtualbox-ose-kmod/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
@@ -0,0 +1,375 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (working copy)
+@@ -43,6 +43,8 @@
+ #include <sys/socket.h>
+ #include <sys/sockio.h>
+ #include <sys/syscallsubr.h>
++#include <sys/queue.h>
++#include <sys/taskqueue.h>
+
+ #include <net/if.h>
+ #include <net/if_var.h>
+@@ -78,8 +80,6 @@
+ static ng_rcvdata_t ng_vboxnetflt_rcvdata;
+ 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 */
+ #define NG_VBOXNETFLT_NODE_TYPE "vboxnetflt"
+@@ -112,8 +112,8 @@
+ {
+ .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,
+ .newhook = ng_vboxnetflt_newhook,
+@@ -267,16 +267,12 @@
+ if (strcmp(name, NG_VBOXNETFLT_HOOK_IN) == 0)
+ {
+ #if __FreeBSD_version >= 800000
+- NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_in);
+ NG_HOOK_SET_TO_INBOUND(hook);
+ #endif
+ pThis->u.s.input = hook;
+ }
+ 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;
+ }
+ else
+@@ -310,161 +306,171 @@
+
+ /**
+ * 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 ifnet *ifp = pThis->u.s.ifp;
+ struct mbuf *m;
++ struct m_tag *mtag;
++ bool fActive;
+
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++
++ NGI_GET_M(item, m);
++ NG_FREE_ITEM(item);
++
++ /* 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)
++ {
++ m_tag_unlink(m, mtag);
++ m_tag_free(mtag);
++ }
++
++ /*
++ * Handle incoming hook. This is connected to the
++ * input path of the interface, thus handling incoming frames.
++ */
+ if (pThis->u.s.input == hook)
+- return ng_vboxnetflt_rcv_in(hook, item);
++ {
++ 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)
+- return ng_vboxnetflt_rcv_out(hook, item);
++ {
++ 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
+ {
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
++ m_freem(m);
+ }
+ return (0);
+ }
+
++static int ng_vboxnetflt_shutdown(node_p node)
++{
++ PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
++ bool fActive;
++
++ /* Prevent node shutdown if we're active */
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++ if (fActive)
++ return (EBUSY);
++ NG_NODE_UNREF(node);
++ return (0);
++}
++
++static int ng_vboxnetflt_disconnect(hook_p hook)
++{
++ return (0);
++}
++
+ /**
+- * Handle incoming hook. This is connected to the
+- * input path of the interface, thus handling incoming frames.
++ * Input processing task, handles incoming frames
+ */
+-static int ng_vboxnetflt_rcv_in(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDinput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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;
++ bool fDropIt = false, fActive;
+ PINTNETSG pSG;
+
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
+-
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (!fActive)
+- goto out;
+-
+- 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;
+- }
+ vboxNetFltRetain(pThis, true /* fBusy */);
+-
+- for (m0 = m; m0 != NULL; m0 = m0->m_next)
++ for (;;)
+ {
+- if (m0->m_len > 0)
+- cSegs++;
+- }
++ 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++;
++ 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);
++ /* 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 */);
+-
+-out:
+- /* Only deliver it to the host stack if the destination weren't a guest */
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+- ether_demux(ifp, m);
+- return (0);
+ }
+
+ /**
+- * Handle mbufs on the outgoing hook, frames going to the interface
++ * Output processing task, handles outgoing frames
+ */
+-static int ng_vboxnetflt_rcv_out(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDoutput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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)
++ for (;;)
+ {
+- m_tag_unlink(m, mtag);
+- m_tag_free(mtag);
+- goto out;
+- }
++ 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++;
+- }
++ 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++;
++ 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);
++ /* 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:
++ if (fDropIt)
++ m_freem(m);
++ else
++ ether_output_frame(ifp, m);
++ }
+ vboxNetFltRelease(pThis, true /* fBusy */);
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+-
+- return ether_output_frame(ifp, m);
+ }
+
+-static int ng_vboxnetflt_shutdown(node_p node)
+-{
+- PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
+- bool fActive;
+-
+- /* Prevent node shutdown if we're active */
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (fActive)
+- return (EBUSY);
+- NG_NODE_UNREF(node);
+- return (0);
+-}
+-
+-static int ng_vboxnetflt_disconnect(hook_p hook)
+-{
+- return (0);
+-}
+-
+ /**
+ * Called to deliver a frame to either the host, the wire or both.
+ */
+@@ -536,13 +542,23 @@
+
+ /* 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);
+ ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.ifp, ifp);
+ pThis->u.s.node = node;
+ 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);
+
+ NG_NODE_SET_PRIVATE(node, pThis);
+@@ -571,7 +587,10 @@
+ }
+
+ if (ifp0 != NULL)
++ {
++ vboxNetFltOsDeleteInstance(pThis);
+ vboxNetFltOsInitInstance(pThis, NULL);
++ }
+
+ return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
+ }
+@@ -579,6 +598,12 @@
+ 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)
+ ng_rmnode_self(pThis->u.s.node);
+ pThis->u.s.node = NULL;
diff --git a/emulators/virtualbox-ose-kmod/pkg-plist b/emulators/virtualbox-ose-kmod/pkg-plist
index 701bcf61f230..bdafc64fb6ee 100644
--- a/emulators/virtualbox-ose-kmod/pkg-plist
+++ b/emulators/virtualbox-ose-kmod/pkg-plist
@@ -592,7 +592,7 @@ include/virtualbox/xpcom/xpcom-config.h
%%QT4%%@dirrmtry share/icons
%%QT4%%@dirrmtry share/applications
@dirrm lib/virtualbox/components
-@dirrm lib/virtualbox/additions
+%%GUESTADDITIONS%%@dirrm lib/virtualbox/additions
@dirrm lib/virtualbox
@cwd /
%%KMODDIR%%/vboxdrv.ko
diff --git a/emulators/virtualbox-ose-legacy/Makefile b/emulators/virtualbox-ose-legacy/Makefile
index 3538d0054d94..a1a5891255f7 100644
--- a/emulators/virtualbox-ose-legacy/Makefile
+++ b/emulators/virtualbox-ose-legacy/Makefile
@@ -7,6 +7,7 @@
PORTNAME= virtualbox
DISTVERSION= 3.0.51r22902
+PORTREVISION= 1
CATEGORIES= emulators kld
MASTER_SITES= http://tmp.chruetertee.ch/ \
http://freebsd.unixfreunde.de/sources/ \
@@ -142,15 +143,21 @@ BROKEN= Does not compile on FreeBSD 6.X
KMK_ARCH= freebsd.x86
PLIST_SUB+= I386=""
.else
-.if !exists(/usr/lib32)
-IGNORE= requires 32-bit libraries installed under /usr/lib32
-.endif
KMK_ARCH= freebsd.${ARCH}
PLIST_SUB+= I386="@comment "
.endif
.include <bsd.port.pre.mk>
+pre-everything::
+.if ${ARCH} == "amd64"
+.if !exists(/usr/lib32)
+ @${ECHO} 'Requires 32-bit libraries installed under /usr/lib32.'
+ @${ECHO} 'Do: cd /usr/src; make build32 install32; ldconfig -v -m -R /usr/lib32'
+ @${FALSE}
+.endif
+.endif
+
post-patch:
@${ECHO} 'VBOX_PATH_APP_PRIVATE_ARCH = ${PREFIX}/lib/virtualbox' > ${WRKSRC}/LocalConfig.kmk
@${ECHO} 'VBOX_PATH_SHARED_LIBS = ${PREFIX}/lib/virtualbox' >> ${WRKSRC}/LocalConfig.kmk
diff --git a/emulators/virtualbox-ose-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h b/emulators/virtualbox-ose-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
new file mode 100644
index 000000000000..1924d8dd90ef
--- /dev/null
+++ b/emulators/virtualbox-ose-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
@@ -0,0 +1,28 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (working copy)
+@@ -206,6 +206,14 @@
+ hook_p output;
+ /** 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,6 +249,8 @@
+ # endif
+ #elif defined(RT_OS_LINUX)
+ uint8_t abPadding[320];
++#elif defined(RT_OS_FREEBSD)
++ uint8_t abPadding[256];
+ #else
+ uint8_t abPadding[128];
+ #endif
diff --git a/emulators/virtualbox-ose-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c b/emulators/virtualbox-ose-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
new file mode 100644
index 000000000000..bc23fb14a545
--- /dev/null
+++ b/emulators/virtualbox-ose-legacy/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
@@ -0,0 +1,375 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (working copy)
+@@ -43,6 +43,8 @@
+ #include <sys/socket.h>
+ #include <sys/sockio.h>
+ #include <sys/syscallsubr.h>
++#include <sys/queue.h>
++#include <sys/taskqueue.h>
+
+ #include <net/if.h>
+ #include <net/if_var.h>
+@@ -78,8 +80,6 @@
+ static ng_rcvdata_t ng_vboxnetflt_rcvdata;
+ 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 */
+ #define NG_VBOXNETFLT_NODE_TYPE "vboxnetflt"
+@@ -112,8 +112,8 @@
+ {
+ .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,
+ .newhook = ng_vboxnetflt_newhook,
+@@ -267,16 +267,12 @@
+ if (strcmp(name, NG_VBOXNETFLT_HOOK_IN) == 0)
+ {
+ #if __FreeBSD_version >= 800000
+- NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_in);
+ NG_HOOK_SET_TO_INBOUND(hook);
+ #endif
+ pThis->u.s.input = hook;
+ }
+ 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;
+ }
+ else
+@@ -310,161 +306,171 @@
+
+ /**
+ * 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 ifnet *ifp = pThis->u.s.ifp;
+ struct mbuf *m;
++ struct m_tag *mtag;
++ bool fActive;
+
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++
++ NGI_GET_M(item, m);
++ NG_FREE_ITEM(item);
++
++ /* 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)
++ {
++ m_tag_unlink(m, mtag);
++ m_tag_free(mtag);
++ }
++
++ /*
++ * Handle incoming hook. This is connected to the
++ * input path of the interface, thus handling incoming frames.
++ */
+ if (pThis->u.s.input == hook)
+- return ng_vboxnetflt_rcv_in(hook, item);
++ {
++ 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)
+- return ng_vboxnetflt_rcv_out(hook, item);
++ {
++ 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
+ {
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
++ m_freem(m);
+ }
+ return (0);
+ }
+
++static int ng_vboxnetflt_shutdown(node_p node)
++{
++ PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
++ bool fActive;
++
++ /* Prevent node shutdown if we're active */
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++ if (fActive)
++ return (EBUSY);
++ NG_NODE_UNREF(node);
++ return (0);
++}
++
++static int ng_vboxnetflt_disconnect(hook_p hook)
++{
++ return (0);
++}
++
+ /**
+- * Handle incoming hook. This is connected to the
+- * input path of the interface, thus handling incoming frames.
++ * Input processing task, handles incoming frames
+ */
+-static int ng_vboxnetflt_rcv_in(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDinput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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;
++ bool fDropIt = false, fActive;
+ PINTNETSG pSG;
+
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
+-
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (!fActive)
+- goto out;
+-
+- 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;
+- }
+ vboxNetFltRetain(pThis, true /* fBusy */);
+-
+- for (m0 = m; m0 != NULL; m0 = m0->m_next)
++ for (;;)
+ {
+- if (m0->m_len > 0)
+- cSegs++;
+- }
++ 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++;
++ 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);
++ /* 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 */);
+-
+-out:
+- /* Only deliver it to the host stack if the destination weren't a guest */
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+- ether_demux(ifp, m);
+- return (0);
+ }
+
+ /**
+- * Handle mbufs on the outgoing hook, frames going to the interface
++ * Output processing task, handles outgoing frames
+ */
+-static int ng_vboxnetflt_rcv_out(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDoutput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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)
++ for (;;)
+ {
+- m_tag_unlink(m, mtag);
+- m_tag_free(mtag);
+- goto out;
+- }
++ 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++;
+- }
++ 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++;
++ 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);
++ /* 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:
++ if (fDropIt)
++ m_freem(m);
++ else
++ ether_output_frame(ifp, m);
++ }
+ vboxNetFltRelease(pThis, true /* fBusy */);
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+-
+- return ether_output_frame(ifp, m);
+ }
+
+-static int ng_vboxnetflt_shutdown(node_p node)
+-{
+- PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
+- bool fActive;
+-
+- /* Prevent node shutdown if we're active */
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (fActive)
+- return (EBUSY);
+- NG_NODE_UNREF(node);
+- return (0);
+-}
+-
+-static int ng_vboxnetflt_disconnect(hook_p hook)
+-{
+- return (0);
+-}
+-
+ /**
+ * Called to deliver a frame to either the host, the wire or both.
+ */
+@@ -536,13 +542,23 @@
+
+ /* 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);
+ ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.ifp, ifp);
+ pThis->u.s.node = node;
+ 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);
+
+ NG_NODE_SET_PRIVATE(node, pThis);
+@@ -571,7 +587,10 @@
+ }
+
+ if (ifp0 != NULL)
++ {
++ vboxNetFltOsDeleteInstance(pThis);
+ vboxNetFltOsInitInstance(pThis, NULL);
++ }
+
+ return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
+ }
+@@ -579,6 +598,12 @@
+ 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)
+ ng_rmnode_self(pThis->u.s.node);
+ pThis->u.s.node = NULL;
diff --git a/emulators/virtualbox-ose-legacy/pkg-plist b/emulators/virtualbox-ose-legacy/pkg-plist
index 701bcf61f230..bdafc64fb6ee 100644
--- a/emulators/virtualbox-ose-legacy/pkg-plist
+++ b/emulators/virtualbox-ose-legacy/pkg-plist
@@ -592,7 +592,7 @@ include/virtualbox/xpcom/xpcom-config.h
%%QT4%%@dirrmtry share/icons
%%QT4%%@dirrmtry share/applications
@dirrm lib/virtualbox/components
-@dirrm lib/virtualbox/additions
+%%GUESTADDITIONS%%@dirrm lib/virtualbox/additions
@dirrm lib/virtualbox
@cwd /
%%KMODDIR%%/vboxdrv.ko
diff --git a/emulators/virtualbox-ose/Makefile b/emulators/virtualbox-ose/Makefile
index 3538d0054d94..a1a5891255f7 100644
--- a/emulators/virtualbox-ose/Makefile
+++ b/emulators/virtualbox-ose/Makefile
@@ -7,6 +7,7 @@
PORTNAME= virtualbox
DISTVERSION= 3.0.51r22902
+PORTREVISION= 1
CATEGORIES= emulators kld
MASTER_SITES= http://tmp.chruetertee.ch/ \
http://freebsd.unixfreunde.de/sources/ \
@@ -142,15 +143,21 @@ BROKEN= Does not compile on FreeBSD 6.X
KMK_ARCH= freebsd.x86
PLIST_SUB+= I386=""
.else
-.if !exists(/usr/lib32)
-IGNORE= requires 32-bit libraries installed under /usr/lib32
-.endif
KMK_ARCH= freebsd.${ARCH}
PLIST_SUB+= I386="@comment "
.endif
.include <bsd.port.pre.mk>
+pre-everything::
+.if ${ARCH} == "amd64"
+.if !exists(/usr/lib32)
+ @${ECHO} 'Requires 32-bit libraries installed under /usr/lib32.'
+ @${ECHO} 'Do: cd /usr/src; make build32 install32; ldconfig -v -m -R /usr/lib32'
+ @${FALSE}
+.endif
+.endif
+
post-patch:
@${ECHO} 'VBOX_PATH_APP_PRIVATE_ARCH = ${PREFIX}/lib/virtualbox' > ${WRKSRC}/LocalConfig.kmk
@${ECHO} 'VBOX_PATH_SHARED_LIBS = ${PREFIX}/lib/virtualbox' >> ${WRKSRC}/LocalConfig.kmk
diff --git a/emulators/virtualbox-ose/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h b/emulators/virtualbox-ose/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
new file mode 100644
index 000000000000..1924d8dd90ef
--- /dev/null
+++ b/emulators/virtualbox-ose/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
@@ -0,0 +1,28 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (working copy)
+@@ -206,6 +206,14 @@
+ hook_p output;
+ /** 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,6 +249,8 @@
+ # endif
+ #elif defined(RT_OS_LINUX)
+ uint8_t abPadding[320];
++#elif defined(RT_OS_FREEBSD)
++ uint8_t abPadding[256];
+ #else
+ uint8_t abPadding[128];
+ #endif
diff --git a/emulators/virtualbox-ose/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c b/emulators/virtualbox-ose/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
new file mode 100644
index 000000000000..bc23fb14a545
--- /dev/null
+++ b/emulators/virtualbox-ose/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
@@ -0,0 +1,375 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (working copy)
+@@ -43,6 +43,8 @@
+ #include <sys/socket.h>
+ #include <sys/sockio.h>
+ #include <sys/syscallsubr.h>
++#include <sys/queue.h>
++#include <sys/taskqueue.h>
+
+ #include <net/if.h>
+ #include <net/if_var.h>
+@@ -78,8 +80,6 @@
+ static ng_rcvdata_t ng_vboxnetflt_rcvdata;
+ 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 */
+ #define NG_VBOXNETFLT_NODE_TYPE "vboxnetflt"
+@@ -112,8 +112,8 @@
+ {
+ .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,
+ .newhook = ng_vboxnetflt_newhook,
+@@ -267,16 +267,12 @@
+ if (strcmp(name, NG_VBOXNETFLT_HOOK_IN) == 0)
+ {
+ #if __FreeBSD_version >= 800000
+- NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_in);
+ NG_HOOK_SET_TO_INBOUND(hook);
+ #endif
+ pThis->u.s.input = hook;
+ }
+ 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;
+ }
+ else
+@@ -310,161 +306,171 @@
+
+ /**
+ * 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 ifnet *ifp = pThis->u.s.ifp;
+ struct mbuf *m;
++ struct m_tag *mtag;
++ bool fActive;
+
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++
++ NGI_GET_M(item, m);
++ NG_FREE_ITEM(item);
++
++ /* 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)
++ {
++ m_tag_unlink(m, mtag);
++ m_tag_free(mtag);
++ }
++
++ /*
++ * Handle incoming hook. This is connected to the
++ * input path of the interface, thus handling incoming frames.
++ */
+ if (pThis->u.s.input == hook)
+- return ng_vboxnetflt_rcv_in(hook, item);
++ {
++ 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)
+- return ng_vboxnetflt_rcv_out(hook, item);
++ {
++ 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
+ {
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
++ m_freem(m);
+ }
+ return (0);
+ }
+
++static int ng_vboxnetflt_shutdown(node_p node)
++{
++ PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
++ bool fActive;
++
++ /* Prevent node shutdown if we're active */
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++ if (fActive)
++ return (EBUSY);
++ NG_NODE_UNREF(node);
++ return (0);
++}
++
++static int ng_vboxnetflt_disconnect(hook_p hook)
++{
++ return (0);
++}
++
+ /**
+- * Handle incoming hook. This is connected to the
+- * input path of the interface, thus handling incoming frames.
++ * Input processing task, handles incoming frames
+ */
+-static int ng_vboxnetflt_rcv_in(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDinput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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;
++ bool fDropIt = false, fActive;
+ PINTNETSG pSG;
+
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
+-
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (!fActive)
+- goto out;
+-
+- 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;
+- }
+ vboxNetFltRetain(pThis, true /* fBusy */);
+-
+- for (m0 = m; m0 != NULL; m0 = m0->m_next)
++ for (;;)
+ {
+- if (m0->m_len > 0)
+- cSegs++;
+- }
++ 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++;
++ 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);
++ /* 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 */);
+-
+-out:
+- /* Only deliver it to the host stack if the destination weren't a guest */
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+- ether_demux(ifp, m);
+- return (0);
+ }
+
+ /**
+- * Handle mbufs on the outgoing hook, frames going to the interface
++ * Output processing task, handles outgoing frames
+ */
+-static int ng_vboxnetflt_rcv_out(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDoutput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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)
++ for (;;)
+ {
+- m_tag_unlink(m, mtag);
+- m_tag_free(mtag);
+- goto out;
+- }
++ 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++;
+- }
++ 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++;
++ 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);
++ /* 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:
++ if (fDropIt)
++ m_freem(m);
++ else
++ ether_output_frame(ifp, m);
++ }
+ vboxNetFltRelease(pThis, true /* fBusy */);
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+-
+- return ether_output_frame(ifp, m);
+ }
+
+-static int ng_vboxnetflt_shutdown(node_p node)
+-{
+- PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
+- bool fActive;
+-
+- /* Prevent node shutdown if we're active */
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (fActive)
+- return (EBUSY);
+- NG_NODE_UNREF(node);
+- return (0);
+-}
+-
+-static int ng_vboxnetflt_disconnect(hook_p hook)
+-{
+- return (0);
+-}
+-
+ /**
+ * Called to deliver a frame to either the host, the wire or both.
+ */
+@@ -536,13 +542,23 @@
+
+ /* 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);
+ ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.ifp, ifp);
+ pThis->u.s.node = node;
+ 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);
+
+ NG_NODE_SET_PRIVATE(node, pThis);
+@@ -571,7 +587,10 @@
+ }
+
+ if (ifp0 != NULL)
++ {
++ vboxNetFltOsDeleteInstance(pThis);
+ vboxNetFltOsInitInstance(pThis, NULL);
++ }
+
+ return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
+ }
+@@ -579,6 +598,12 @@
+ 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)
+ ng_rmnode_self(pThis->u.s.node);
+ pThis->u.s.node = NULL;
diff --git a/emulators/virtualbox-ose/pkg-plist b/emulators/virtualbox-ose/pkg-plist
index 701bcf61f230..bdafc64fb6ee 100644
--- a/emulators/virtualbox-ose/pkg-plist
+++ b/emulators/virtualbox-ose/pkg-plist
@@ -592,7 +592,7 @@ include/virtualbox/xpcom/xpcom-config.h
%%QT4%%@dirrmtry share/icons
%%QT4%%@dirrmtry share/applications
@dirrm lib/virtualbox/components
-@dirrm lib/virtualbox/additions
+%%GUESTADDITIONS%%@dirrm lib/virtualbox/additions
@dirrm lib/virtualbox
@cwd /
%%KMODDIR%%/vboxdrv.ko
diff --git a/emulators/virtualbox/Makefile b/emulators/virtualbox/Makefile
index 3538d0054d94..a1a5891255f7 100644
--- a/emulators/virtualbox/Makefile
+++ b/emulators/virtualbox/Makefile
@@ -7,6 +7,7 @@
PORTNAME= virtualbox
DISTVERSION= 3.0.51r22902
+PORTREVISION= 1
CATEGORIES= emulators kld
MASTER_SITES= http://tmp.chruetertee.ch/ \
http://freebsd.unixfreunde.de/sources/ \
@@ -142,15 +143,21 @@ BROKEN= Does not compile on FreeBSD 6.X
KMK_ARCH= freebsd.x86
PLIST_SUB+= I386=""
.else
-.if !exists(/usr/lib32)
-IGNORE= requires 32-bit libraries installed under /usr/lib32
-.endif
KMK_ARCH= freebsd.${ARCH}
PLIST_SUB+= I386="@comment "
.endif
.include <bsd.port.pre.mk>
+pre-everything::
+.if ${ARCH} == "amd64"
+.if !exists(/usr/lib32)
+ @${ECHO} 'Requires 32-bit libraries installed under /usr/lib32.'
+ @${ECHO} 'Do: cd /usr/src; make build32 install32; ldconfig -v -m -R /usr/lib32'
+ @${FALSE}
+.endif
+.endif
+
post-patch:
@${ECHO} 'VBOX_PATH_APP_PRIVATE_ARCH = ${PREFIX}/lib/virtualbox' > ${WRKSRC}/LocalConfig.kmk
@${ECHO} 'VBOX_PATH_SHARED_LIBS = ${PREFIX}/lib/virtualbox' >> ${WRKSRC}/LocalConfig.kmk
diff --git a/emulators/virtualbox/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h b/emulators/virtualbox/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
new file mode 100644
index 000000000000..1924d8dd90ef
--- /dev/null
+++ b/emulators/virtualbox/files/patch-src-VBox-HostDrivers-VBoxNetFlt-VBoxNetFltInternal.h
@@ -0,0 +1,28 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h (working copy)
+@@ -206,6 +206,14 @@
+ hook_p output;
+ /** 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,6 +249,8 @@
+ # endif
+ #elif defined(RT_OS_LINUX)
+ uint8_t abPadding[320];
++#elif defined(RT_OS_FREEBSD)
++ uint8_t abPadding[256];
+ #else
+ uint8_t abPadding[128];
+ #endif
diff --git a/emulators/virtualbox/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c b/emulators/virtualbox/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
new file mode 100644
index 000000000000..bc23fb14a545
--- /dev/null
+++ b/emulators/virtualbox/files/patch-src-VBox-HostDrivers-VBoxNetFlt-freebsd-VBoxNetFlt-freebsd.c
@@ -0,0 +1,375 @@
+Index: src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c
+===================================================================
+--- src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (revision 23391)
++++ src/VBox/HostDrivers/VBoxNetFlt/freebsd/VBoxNetFlt-freebsd.c (working copy)
+@@ -43,6 +43,8 @@
+ #include <sys/socket.h>
+ #include <sys/sockio.h>
+ #include <sys/syscallsubr.h>
++#include <sys/queue.h>
++#include <sys/taskqueue.h>
+
+ #include <net/if.h>
+ #include <net/if_var.h>
+@@ -78,8 +80,6 @@
+ static ng_rcvdata_t ng_vboxnetflt_rcvdata;
+ 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 */
+ #define NG_VBOXNETFLT_NODE_TYPE "vboxnetflt"
+@@ -112,8 +112,8 @@
+ {
+ .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,
+ .newhook = ng_vboxnetflt_newhook,
+@@ -267,16 +267,12 @@
+ if (strcmp(name, NG_VBOXNETFLT_HOOK_IN) == 0)
+ {
+ #if __FreeBSD_version >= 800000
+- NG_HOOK_SET_RCVDATA(hook, ng_vboxnetflt_rcv_in);
+ NG_HOOK_SET_TO_INBOUND(hook);
+ #endif
+ pThis->u.s.input = hook;
+ }
+ 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;
+ }
+ else
+@@ -310,161 +306,171 @@
+
+ /**
+ * 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 ifnet *ifp = pThis->u.s.ifp;
+ struct mbuf *m;
++ struct m_tag *mtag;
++ bool fActive;
+
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++
++ NGI_GET_M(item, m);
++ NG_FREE_ITEM(item);
++
++ /* 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)
++ {
++ m_tag_unlink(m, mtag);
++ m_tag_free(mtag);
++ }
++
++ /*
++ * Handle incoming hook. This is connected to the
++ * input path of the interface, thus handling incoming frames.
++ */
+ if (pThis->u.s.input == hook)
+- return ng_vboxnetflt_rcv_in(hook, item);
++ {
++ 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)
+- return ng_vboxnetflt_rcv_out(hook, item);
++ {
++ 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
+ {
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
++ m_freem(m);
+ }
+ return (0);
+ }
+
++static int ng_vboxnetflt_shutdown(node_p node)
++{
++ PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
++ bool fActive;
++
++ /* Prevent node shutdown if we're active */
++ fActive = ASMAtomicUoReadBool(&pThis->fActive);
++ if (fActive)
++ return (EBUSY);
++ NG_NODE_UNREF(node);
++ return (0);
++}
++
++static int ng_vboxnetflt_disconnect(hook_p hook)
++{
++ return (0);
++}
++
+ /**
+- * Handle incoming hook. This is connected to the
+- * input path of the interface, thus handling incoming frames.
++ * Input processing task, handles incoming frames
+ */
+-static int ng_vboxnetflt_rcv_in(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDinput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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;
++ bool fDropIt = false, fActive;
+ PINTNETSG pSG;
+
+- NGI_GET_M(item, m);
+- NG_FREE_ITEM(item);
+-
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (!fActive)
+- goto out;
+-
+- 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;
+- }
+ vboxNetFltRetain(pThis, true /* fBusy */);
+-
+- for (m0 = m; m0 != NULL; m0 = m0->m_next)
++ for (;;)
+ {
+- if (m0->m_len > 0)
+- cSegs++;
+- }
++ 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++;
++ 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);
++ /* 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 */);
+-
+-out:
+- /* Only deliver it to the host stack if the destination weren't a guest */
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+- ether_demux(ifp, m);
+- return (0);
+ }
+
+ /**
+- * Handle mbufs on the outgoing hook, frames going to the interface
++ * Output processing task, handles outgoing frames
+ */
+-static int ng_vboxnetflt_rcv_out(hook_p hook, item_p item)
++static void vboxNetFltFreeBSDoutput(void *arg, int pending)
+ {
++ PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)arg;
+ 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)
++ for (;;)
+ {
+- m_tag_unlink(m, mtag);
+- m_tag_free(mtag);
+- goto out;
+- }
++ 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++;
+- }
++ 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++;
++ 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);
++ /* 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:
++ if (fDropIt)
++ m_freem(m);
++ else
++ ether_output_frame(ifp, m);
++ }
+ vboxNetFltRelease(pThis, true /* fBusy */);
+- if (fDropIt)
+- {
+- m_freem(m);
+- return (0);
+- }
+-
+- return ether_output_frame(ifp, m);
+ }
+
+-static int ng_vboxnetflt_shutdown(node_p node)
+-{
+- PVBOXNETFLTINS pThis = NG_NODE_PRIVATE(node);
+- bool fActive;
+-
+- /* Prevent node shutdown if we're active */
+- fActive = ASMAtomicUoReadBool(&pThis->fActive);
+- if (fActive)
+- return (EBUSY);
+- NG_NODE_UNREF(node);
+- return (0);
+-}
+-
+-static int ng_vboxnetflt_disconnect(hook_p hook)
+-{
+- return (0);
+-}
+-
+ /**
+ * Called to deliver a frame to either the host, the wire or both.
+ */
+@@ -536,13 +542,23 @@
+
+ /* 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);
+ ASMAtomicUoWritePtr((void * volatile *)&pThis->u.s.ifp, ifp);
+ pThis->u.s.node = node;
+ 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);
+
+ NG_NODE_SET_PRIVATE(node, pThis);
+@@ -571,7 +587,10 @@
+ }
+
+ if (ifp0 != NULL)
++ {
++ vboxNetFltOsDeleteInstance(pThis);
+ vboxNetFltOsInitInstance(pThis, NULL);
++ }
+
+ return !ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost);
+ }
+@@ -579,6 +598,12 @@
+ 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)
+ ng_rmnode_self(pThis->u.s.node);
+ pThis->u.s.node = NULL;
diff --git a/emulators/virtualbox/pkg-plist b/emulators/virtualbox/pkg-plist
index 701bcf61f230..bdafc64fb6ee 100644
--- a/emulators/virtualbox/pkg-plist
+++ b/emulators/virtualbox/pkg-plist
@@ -592,7 +592,7 @@ include/virtualbox/xpcom/xpcom-config.h
%%QT4%%@dirrmtry share/icons
%%QT4%%@dirrmtry share/applications
@dirrm lib/virtualbox/components
-@dirrm lib/virtualbox/additions
+%%GUESTADDITIONS%%@dirrm lib/virtualbox/additions
@dirrm lib/virtualbox
@cwd /
%%KMODDIR%%/vboxdrv.ko