summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2022-10-31 08:15:38 +0000
committervboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2022-10-31 08:15:38 +0000
commit117bc8ff117ba31749d09a393a790a40facb542c (patch)
tree239af439ccfeff7728e9930eecb42fe0fb229912
parent9bad036d9b5b9c0a5327b6e3ba3ee8ef01537f04 (diff)
downloadVirtualBox-svn-117bc8ff117ba31749d09a393a790a40facb542c.tar.gz
NetworkServices/IntNetSwitch,Devices/Network/DrvIntNet,Devices/Network/SrvIntNetR0: Don't require a dedicated waiting thread to get notified when there is something to receive but make it possible to register a callback which is called and sends an IPC message instead, bugref:10297
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@97338 cfe28804-0f27-0410-a406-dd0f0b0b656f
-rw-r--r--include/VBox/intnet.h29
-rw-r--r--src/VBox/Devices/Network/DrvIntNet.cpp27
-rw-r--r--src/VBox/Devices/Network/SrvIntNetR0.cpp109
-rw-r--r--src/VBox/Devices/Network/testcase/tstIntNetR0.cpp8
-rw-r--r--src/VBox/NetworkServices/IntNetSwitch/Makefile.kmk3
-rw-r--r--src/VBox/NetworkServices/IntNetSwitch/VBoxIntNetSwitch.cpp (renamed from src/VBox/NetworkServices/IntNetSwitch/main.cpp)131
6 files changed, 196 insertions, 111 deletions
diff --git a/include/VBox/intnet.h b/include/VBox/intnet.h
index 451db665c63..da046e37f00 100644
--- a/include/VBox/intnet.h
+++ b/include/VBox/intnet.h
@@ -50,7 +50,17 @@ RT_C_DECLS_BEGIN
/** The userspace internal network service identifier. */
#if defined(RT_OS_DARWIN) && defined(VBOX_WITH_INTNET_SERVICE_IN_R3)
-# define INTNET_R3_SVC_NAME "org.virtualbox.intnet"
+/** The XPC service identififer. */
+# define INTNET_R3_SVC_NAME "org.virtualbox.intnet"
+/** The high 32 bits pattern for the "rc" status code field to recognize errors
+ * where xpc_dictionary_get_int64() might return 0 which could be confused with VINF_SUCCESS. */
+# define INTNET_R3_SVC_RC_PATTERN ((uint64_t)RT_MAKE_U32_FROM_U8('V', 'B', 'O', 'X'))
+/** Constructs a signd 64bit value for the given 32-bit status code. */
+# define INTNET_R3_SVC_SET_RC(a_rc) ((INTNET_R3_SVC_RC_PATTERN << 32) | (uint64_t)(a_rc))
+/** Gets the status code from the given 64-bit signed status code value. */
+# define INTNET_R3_SVC_GET_RC(a_RcVal) ((int32_t)(a_RcVal))
+/** Checks whether the given 64-bit signed status code value encodes a valid IPRT/VBOX status code. */
+# define INTNET_R3_SVC_IS_VALID_RC(a_RcVal) (((a_RcVal) >> 32) == INTNET_R3_SVC_RC_PATTERN)
#endif
@@ -1316,6 +1326,23 @@ INTNETR0DECL(int) IntNetR0IfAbortWait(INTNETIFHANDLE hIf, PSUPDRVSESSION p
/** @} */
#endif /* IN_RING0 */
+/**
+ * Callback function for use with IntNetR3Open to signalling incoming data.
+ *
+ * @param hIf Interface handle.
+ * @param pvUser User parameter.
+ */
+typedef DECLCALLBACKTYPE(void, FNINTNETIFRECVAVAIL,(INTNETIFHANDLE hIf, void *pvUser));
+/** Pointer to a FNINTNETIFRECVAVAIL callback. */
+typedef FNINTNETIFRECVAVAIL *PFNINTNETIFRECVAVAIL;
+
+#if defined(VBOX_WITH_INTNET_SERVICE_IN_R3) && defined(IN_RING3)
+INTNETR3DECL(int) IntNetR3Open(PSUPDRVSESSION pSession, const char *pszNetwork,
+ INTNETTRUNKTYPE enmTrunkType, const char *pszTrunk, uint32_t fFlags,
+ uint32_t cbSend, uint32_t cbRecv, PFNINTNETIFRECVAVAIL pfnRecvAvail,
+ void *pvUserRecvAvail, PINTNETIFHANDLE phIf);
+#endif
+
RT_C_DECLS_END
#endif /* !VBOX_INCLUDED_intnet_h */
diff --git a/src/VBox/Devices/Network/DrvIntNet.cpp b/src/VBox/Devices/Network/DrvIntNet.cpp
index 54cb251613e..5673fb91ca9 100644
--- a/src/VBox/Devices/Network/DrvIntNet.cpp
+++ b/src/VBox/Devices/Network/DrvIntNet.cpp
@@ -248,15 +248,20 @@ static int drvR3IntNetCallSvc(PDRVINTNET pThis, uint32_t uOperation, void *pvArg
xpc_dictionary_set_uint64(hObj, "req-id", uOperation);
xpc_dictionary_set_data(hObj, "req", pvArg, cbArg);
xpc_object_t hObjReply = xpc_connection_send_message_with_reply_sync(pThis->hXpcCon, hObj);
- int rc = (int)xpc_dictionary_get_int64(hObjReply, "rc");
+ uint64_t u64Rc = xpc_dictionary_get_uint64(hObjReply, "rc");
+ if (INTNET_R3_SVC_IS_VALID_RC(u64Rc))
+ {
+ size_t cbReply = 0;
+ const void *pvData = xpc_dictionary_get_data(hObjReply, "reply", &cbReply);
+ AssertRelease(cbReply == cbArg);
+ memcpy(pvArg, pvData, cbArg);
+ xpc_release(hObjReply);
- size_t cbReply = 0;
- const void *pvData = xpc_dictionary_get_data(hObjReply, "reply", &cbReply);
- AssertRelease(cbReply == cbArg);
- memcpy(pvArg, pvData, cbArg);
- xpc_release(hObjReply);
+ return INTNET_R3_SVC_GET_RC(u64Rc);
+ }
- return rc;
+ xpc_release(hObjReply);
+ return VERR_INVALID_STATE;
}
else
#endif
@@ -315,7 +320,12 @@ static int drvR3IntNetMapBufferPointers(PDRVINTNET pThis)
xpc_dictionary_set_uint64(hObj, "req-id", VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS);
xpc_dictionary_set_data(hObj, "req", &GetBufferPtrsReq, sizeof(GetBufferPtrsReq));
xpc_object_t hObjReply = xpc_connection_send_message_with_reply_sync(pThis->hXpcCon, hObj);
- rc = (int)xpc_dictionary_get_int64(hObjReply, "rc");
+ uint64_t u64Rc = xpc_dictionary_get_uint64(hObjReply, "rc");
+ if (INTNET_R3_SVC_IS_VALID_RC(u64Rc))
+ rc = INTNET_R3_SVC_GET_RC(u64Rc);
+ else
+ rc = VERR_INVALID_STATE;
+
if (RT_SUCCESS(rc))
{
/* Get the shared memory object. */
@@ -326,6 +336,7 @@ static int drvR3IntNetMapBufferPointers(PDRVINTNET pThis)
else
pThis->cbBuf = cbMem;
}
+
xpc_release(hObjReply);
}
else
diff --git a/src/VBox/Devices/Network/SrvIntNetR0.cpp b/src/VBox/Devices/Network/SrvIntNetR0.cpp
index 25e4997dd27..e19afefa14b 100644
--- a/src/VBox/Devices/Network/SrvIntNetR0.cpp
+++ b/src/VBox/Devices/Network/SrvIntNetR0.cpp
@@ -244,11 +244,18 @@ typedef struct INTNETIF
PINTNETBUF pIntBufDefault;
/** Pointer to ring-3 mapping of the default exchange buffer. */
R3PTRTYPE(PINTNETBUF) pIntBufDefaultR3;
+#if !defined(VBOX_WITH_INTNET_SERVICE_IN_R3) || !defined(IN_RING3)
/** Event semaphore which a receiver/consumer thread will sleep on while
* waiting for data to arrive. */
RTSEMEVENT volatile hRecvEvent;
/** Number of threads sleeping on the event semaphore. */
uint32_t volatile cSleepers;
+#else
+ /** The callback to call when there is something to receive/consume. */
+ PFNINTNETIFRECVAVAIL pfnRecvAvail;
+ /** Opaque user data to pass to the receive avail callback (pfnRecvAvail). */
+ void *pvUserRecvAvail;
+#endif
/** The interface handle.
* When this is INTNET_HANDLE_INVALID a sleeper which is waking up
* should return with the appropriate error condition. */
@@ -2832,6 +2839,19 @@ static int intnetR0RingWriteFrame(PINTNETRINGBUF pRingBuf, PCINTNETSG pSG, PCRTM
}
+/**
+ * Notifies consumers of incoming data from @a pIf that data is available.
+ */
+DECL_FORCE_INLINE(void) intnetR0IfNotifyRecv(PINTNETIF pIf)
+{
+#if !defined(VBOX_WITH_INTNET_SERVICE_IN_R3) || !defined(IN_RING3)
+ RTSemEventSignal(pIf->hRecvEvent);
+#else
+ pIf->pfnRecvAvail(pIf->hIf, pIf->pvUserRecvAvail);
+#endif
+}
+
+
/**
* Sends a frame to a specific interface.
*
@@ -2851,7 +2871,7 @@ static void intnetR0IfSend(PINTNETIF pIf, PINTNETIF pIfSender, PINTNETSG pSG, PC
if (RT_SUCCESS(rc))
{
pIf->cYields = 0;
- RTSemEventSignal(pIf->hRecvEvent);
+ intnetR0IfNotifyRecv(pIf);
return;
}
@@ -2869,7 +2889,7 @@ static void intnetR0IfSend(PINTNETIF pIf, PINTNETIF pIfSender, PINTNETSG pSG, PC
unsigned cYields = 2;
while (--cYields > 0)
{
- RTSemEventSignal(pIf->hRecvEvent);
+ intnetR0IfNotifyRecv(pIf);
RTThreadYield();
RTSpinlockAcquire(pIf->hRecvInSpinlock);
@@ -2878,7 +2898,7 @@ static void intnetR0IfSend(PINTNETIF pIf, PINTNETIF pIfSender, PINTNETSG pSG, PC
if (RT_SUCCESS(rc))
{
STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatYieldsOk);
- RTSemEventSignal(pIf->hRecvEvent);
+ intnetR0IfNotifyRecv(pIf);
return;
}
pIf->cYields++;
@@ -2888,7 +2908,7 @@ static void intnetR0IfSend(PINTNETIF pIf, PINTNETIF pIfSender, PINTNETSG pSG, PC
/* ok, the frame is lost. */
STAM_REL_COUNTER_INC(&pIf->pIntBuf->cStatLost);
- RTSemEventSignal(pIf->hRecvEvent);
+ intnetR0IfNotifyRecv(pIf);
}
@@ -4666,7 +4686,11 @@ INTNETR0DECL(int) IntNetR0IfWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, ui
return VERR_INVALID_HANDLE;
}
- const RTSEMEVENT hRecvEvent = pIf->hRecvEvent;
+#if defined(VBOX_WITH_INTNET_SERVICE_IN_R3) && defined(IN_RING3)
+ AssertReleaseFailed(); /* Should never be called. */
+ return VERR_NOT_SUPPORTED;
+#else
+ const RTSEMEVENT hRecvEvent = pIf->hRecvEvent;
const bool fNoMoreWaits = ASMAtomicUoReadBool(&pIf->fNoMoreWaits);
RTNATIVETHREAD hDtorThrd;
ASMAtomicReadHandle(&pIf->hDestructorThread, &hDtorThrd);
@@ -4720,6 +4744,7 @@ INTNETR0DECL(int) IntNetR0IfWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, ui
Log4(("IntNetR0IfWait: returns %Rrc\n", rc));
return rc;
+#endif
}
@@ -4764,6 +4789,10 @@ INTNETR0DECL(int) IntNetR0IfAbortWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSessio
return VERR_INVALID_HANDLE;
}
+#if defined(VBOX_WITH_INTNET_SERVICE_IN_R3) && defined(IN_RING3)
+ AssertReleaseFailed();
+ return VERR_NOT_SUPPORTED;
+#else
const RTSEMEVENT hRecvEvent = pIf->hRecvEvent;
RTNATIVETHREAD hDtorThrd;
ASMAtomicReadHandle(&pIf->hDestructorThread, &hDtorThrd);
@@ -4806,6 +4835,7 @@ INTNETR0DECL(int) IntNetR0IfAbortWait(INTNETIFHANDLE hIf, PSUPDRVSESSION pSessio
Log4(("IntNetR0IfWait: returns %Rrc\n", VINF_SUCCESS));
return VINF_SUCCESS;
+#endif
}
@@ -4850,6 +4880,7 @@ INTNETR0DECL(int) IntNetR0IfClose(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession)
/* Mark the handle as freed so intnetR0IfDestruct won't free it again. */
ASMAtomicWriteU32(&pIf->hIf, INTNET_HANDLE_INVALID);
+#if !defined(VBOX_WITH_INTNET_SERVICE_IN_R3) || !defined(IN_RING3)
/*
* Signal the event semaphore to wake up any threads in IntNetR0IfWait
* and give them a moment to get out and release the interface.
@@ -4861,6 +4892,7 @@ INTNETR0DECL(int) IntNetR0IfClose(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession)
RTThreadYield();
}
RTSemEventSignal(pIf->hRecvEvent);
+#endif
/*
* Release the references to the interface object (handle + free lookup).
@@ -4999,6 +5031,7 @@ static DECLCALLBACK(void) intnetR0IfDestruct(void *pvObj, void *pvUser1, void *p
RTSemMutexRelease(pIntNet->hMtxCreateOpenDestroy);
+#if !defined(VBOX_WITH_INTNET_SERVICE_IN_R3) || !defined(IN_RING3)
/*
* Wakeup anyone waiting on this interface. (Kind of unlikely, but perhaps
* not quite impossible.)
@@ -5030,6 +5063,7 @@ static DECLCALLBACK(void) intnetR0IfDestruct(void *pvObj, void *pvUser1, void *p
RTSemEventDestroy(hRecvEvent);
pIf->hRecvEvent = NIL_RTSEMEVENT;
}
+#endif
/*
* Unmap user buffer.
@@ -5079,17 +5113,19 @@ static DECLCALLBACK(int) intnetR0TrunkReconnectThread(RTTHREAD hThread, void *pv
* opened so the interface destructor can close it.
*
* @returns VBox status code.
- * @param pNetwork The network, referenced. The reference is consumed on
- * success.
- * @param pSession The session handle.
- * @param cbSend The size of the send buffer.
- * @param cbRecv The size of the receive buffer.
- * @param fFlags The open network flags.
- * @param phIf Where to store the interface handle.
+ * @param pNetwork The network, referenced. The reference is consumed
+ * on success.
+ * @param pSession The session handle.
+ * @param cbSend The size of the send buffer.
+ * @param cbRecv The size of the receive buffer.
+ * @param fFlags The open network flags.
+ * @param pfnRecvAvail The receive available callback to call instead of
+ * signalling the semaphore (R3 service only).
+ * @param pvUser The opaque user data to pass to the callback.
+ * @param phIf Where to store the interface handle.
*/
-static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSession,
- unsigned cbSend, unsigned cbRecv, uint32_t fFlags,
- PINTNETIFHANDLE phIf)
+static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSession, unsigned cbSend, unsigned cbRecv,
+ uint32_t fFlags, PFNINTNETIFRECVAVAIL pfnRecvAvail, void *pvUser, PINTNETIFHANDLE phIf)
{
LogFlow(("intnetR0NetworkCreateIf: pNetwork=%p pSession=%p cbSend=%u cbRecv=%u fFlags=%#x phIf=%p\n",
pNetwork, pSession, cbSend, cbRecv, fFlags, phIf));
@@ -5099,6 +5135,11 @@ static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSess
*/
AssertPtr(pNetwork);
AssertPtr(phIf);
+#if !defined(VBOX_WITH_INTNET_SERVICE_IN_R3) || !defined(IN_RING3)
+ Assert(pfnRecvAvail == NULL);
+ Assert(pvUser == NULL);
+ RT_NOREF(pfnRecvAvail, pvUser);
+#endif
/*
* Adjust the flags with defaults for the interface policies.
@@ -5135,7 +5176,12 @@ static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSess
//pIf->pIntBufR3 = NIL_RTR3PTR;
//pIf->pIntBufDefault = 0;
//pIf->pIntBufDefaultR3 = NIL_RTR3PTR;
+#if !defined(VBOX_WITH_INTNET_SERVICE_IN_R3) || !defined(IN_RING3)
pIf->hRecvEvent = NIL_RTSEMEVENT;
+#else
+ pIf->pfnRecvAvail = pfnRecvAvail;
+ pIf->pvUserRecvAvail = pvUser;
+#endif
//pIf->cSleepers = 0;
pIf->hIf = INTNET_HANDLE_INVALID;
pIf->hDestructorThread = NIL_RTNATIVETHREAD;
@@ -5153,8 +5199,10 @@ static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSess
!!(pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE));
if (RT_SUCCESS(rc))
rc = intnetR0AllocDstTab(pNetwork->MacTab.cEntriesAllocated, (PINTNETDSTTAB *)&pIf->pDstTab);
+#if !defined(VBOX_WITH_INTNET_SERVICE_IN_R3) || !defined(IN_RING3)
if (RT_SUCCESS(rc))
rc = RTSemEventCreate((PRTSEMEVENT)&pIf->hRecvEvent);
+#endif
if (RT_SUCCESS(rc))
rc = RTSpinlockCreate(&pIf->hRecvInSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "hRecvInSpinlock");
if (RT_SUCCESS(rc))
@@ -5247,8 +5295,13 @@ static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSess
RTSpinlockDestroy(pIf->hRecvInSpinlock);
pIf->hRecvInSpinlock = NIL_RTSPINLOCK;
+#if !defined(VBOX_WITH_INTNET_SERVICE_IN_R3) || !defined(IN_RING3)
RTSemEventDestroy(pIf->hRecvEvent);
pIf->hRecvEvent = NIL_RTSEMEVENT;
+#else
+ pIf->pfnRecvAvail = NULL;
+ pIf->pvUserRecvAvail = NULL;
+#endif
RTMemFree(pIf->pDstTab);
for (int i = kIntNetAddrType_Invalid + 1; i < kIntNetAddrType_End; i++)
intnetR0IfAddrCacheDestroy(&pIf->aAddrCache[i]);
@@ -6593,14 +6646,19 @@ static int intnetR0CreateNetwork(PINTNET pIntNet, PSUPDRVSESSION pSession, const
* @param enmTrunkType The trunk type.
* @param pszTrunk The trunk name. Its meaning is specific to the type.
* @param fFlags Flags, see INTNET_OPEN_FLAGS_*.
- * @param fRestrictAccess Whether new participants should be subjected to access check or not.
+ * @param fRestrictAccess Whether new participants should be subjected to
+ * access check or not.
* @param cbSend The send buffer size.
* @param cbRecv The receive buffer size.
+ * @param pfnRecvAvail The receive available callback to call instead of
+ * signalling the semaphore (R3 service only).
+ * @param pvUser The opaque user data to pass to the callback.
* @param phIf Where to store the handle to the network interface.
*/
INTNETR0DECL(int) IntNetR0Open(PSUPDRVSESSION pSession, const char *pszNetwork,
INTNETTRUNKTYPE enmTrunkType, const char *pszTrunk, uint32_t fFlags,
- uint32_t cbSend, uint32_t cbRecv, PINTNETIFHANDLE phIf)
+ uint32_t cbSend, uint32_t cbRecv, PFNINTNETIFRECVAVAIL pfnRecvAvail, void *pvUser,
+ PINTNETIFHANDLE phIf)
{
LogFlow(("IntNetR0Open: pSession=%p pszNetwork=%p:{%s} enmTrunkType=%d pszTrunk=%p:{%s} fFlags=%#x cbSend=%u cbRecv=%u phIf=%p\n",
pSession, pszNetwork, pszNetwork, enmTrunkType, pszTrunk, pszTrunk, fFlags, cbSend, cbRecv, phIf));
@@ -6674,7 +6732,7 @@ INTNETR0DECL(int) IntNetR0Open(PSUPDRVSESSION pSession, const char *pszNetwork,
rc = intnetR0OpenNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork);
if (RT_SUCCESS(rc))
{
- rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, fFlags, phIf);
+ rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, fFlags, pfnRecvAvail, pvUser, phIf);
if (RT_SUCCESS(rc))
{
intnetR0AdaptOpenNetworkFlags(pNetwork, fFlags);
@@ -6688,7 +6746,7 @@ INTNETR0DECL(int) IntNetR0Open(PSUPDRVSESSION pSession, const char *pszNetwork,
rc = intnetR0CreateNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork);
if (RT_SUCCESS(rc))
{
- rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, fFlags, phIf);
+ rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, fFlags, pfnRecvAvail, pvUser, phIf);
if (RT_FAILURE(rc))
SUPR0ObjRelease(pNetwork->pvObj, pSession);
}
@@ -6712,8 +6770,19 @@ INTNETR0DECL(int) IntNetR0OpenReq(PSUPDRVSESSION pSession, PINTNETOPENREQ pReq)
if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
return VERR_INVALID_PARAMETER;
return IntNetR0Open(pSession, &pReq->szNetwork[0], pReq->enmTrunkType, pReq->szTrunk,
- pReq->fFlags, pReq->cbSend, pReq->cbRecv, &pReq->hIf);
+ pReq->fFlags, pReq->cbSend, pReq->cbRecv, NULL /*pfnRecvAvail*/, NULL /*pvUser*/, &pReq->hIf);
+}
+
+
+#if defined(VBOX_WITH_INTNET_SERVICE_IN_R3) && defined(IN_RING3)
+INTNETR3DECL(int) IntNetR3Open(PSUPDRVSESSION pSession, const char *pszNetwork,
+ INTNETTRUNKTYPE enmTrunkType, const char *pszTrunk, uint32_t fFlags,
+ uint32_t cbSend, uint32_t cbRecv, PFNINTNETIFRECVAVAIL pfnRecvAvail, void *pvUser,
+ PINTNETIFHANDLE phIf)
+{
+ return IntNetR0Open(pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, cbSend, cbRecv, pfnRecvAvail, pvUser, phIf);
}
+#endif
/**
diff --git a/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp b/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp
index c67643a37e7..9f087a31558 100644
--- a/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp
+++ b/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp
@@ -446,16 +446,16 @@ typedef TSTSTATE *PTSTSTATE;
static int tstOpenInterfaces(PTSTSTATE pThis, const char *pszNetwork, uint32_t cbSend, uint32_t cbRecv)
{
pThis->hIf0 = INTNET_HANDLE_INVALID;
- RTTESTI_CHECK_RC_OK_RET(IntNetR0Open(g_pSession, pszNetwork, kIntNetTrunkType_None, "",
- 0/*fFlags*/, cbSend, cbRecv, &pThis->hIf0), rcCheck);
+ RTTESTI_CHECK_RC_OK_RET(IntNetR0Open(g_pSession, pszNetwork, kIntNetTrunkType_None, "", 0/*fFlags*/, cbSend, cbRecv,
+ NULL /*pfnRecvAvail*/, NULL /*pvUser*/, &pThis->hIf0), rcCheck);
RTTESTI_CHECK_RET(pThis->hIf0 != INTNET_HANDLE_INVALID, VERR_INTERNAL_ERROR);
RTTESTI_CHECK_RC_RET(IntNetR0IfGetBufferPtrs(pThis->hIf0, g_pSession, &pThis->pBuf0, NULL), VINF_SUCCESS, rcCheck);
RTTESTI_CHECK_RET(pThis->pBuf0, VERR_INTERNAL_ERROR);
pThis->hIf1 = INTNET_HANDLE_INVALID;
- RTTESTI_CHECK_RC_OK_RET(IntNetR0Open(g_pSession, pszNetwork, kIntNetTrunkType_None, "",
- 0/*fFlags*/, cbSend, cbRecv, &pThis->hIf1), rcCheck);
+ RTTESTI_CHECK_RC_OK_RET(IntNetR0Open(g_pSession, pszNetwork, kIntNetTrunkType_None, "", 0/*fFlags*/, cbSend, cbRecv,
+ NULL /*pfnRecvAvail*/, NULL /*pvUser*/, &pThis->hIf1), rcCheck);
RTTESTI_CHECK_RET(pThis->hIf1 != INTNET_HANDLE_INVALID, VERR_INTERNAL_ERROR);
RTTESTI_CHECK_RC_RET(IntNetR0IfGetBufferPtrs(pThis->hIf1, g_pSession, &pThis->pBuf1, NULL), VINF_SUCCESS, rcCheck);
RTTESTI_CHECK_RET(pThis->pBuf1, VERR_INTERNAL_ERROR);
diff --git a/src/VBox/NetworkServices/IntNetSwitch/Makefile.kmk b/src/VBox/NetworkServices/IntNetSwitch/Makefile.kmk
index 76996ab9b2c..e48e89494fd 100644
--- a/src/VBox/NetworkServices/IntNetSwitch/Makefile.kmk
+++ b/src/VBox/NetworkServices/IntNetSwitch/Makefile.kmk
@@ -39,9 +39,10 @@ VBoxIntNetSwitch_DEFS = KBUILD_TYPE="$(KBUILD_TYPE)"
else
VBoxIntNetSwitch_DEFS = KBUILD_TYPE=\"$(KBUILD_TYPE)\"
endif
+VBoxIntNetSwitch_DEFS += VBOX_WITH_INTNET_SERVICE_IN_R3
VBoxIntNetSwitch_INST.darwin = $(VBoxIntNetSwitch.xpc_INST)/MacOS/
VBoxIntNetSwitch_SOURCES = \
- main.cpp \
+ VBoxIntNetSwitch.cpp \
SrvIntNetWrapper.cpp
VBoxIntNetSwitch_LIBS = $(LIB_RUNTIME)
VBoxIntNetSwitch_LDFLAGS.darwin = \
diff --git a/src/VBox/NetworkServices/IntNetSwitch/main.cpp b/src/VBox/NetworkServices/IntNetSwitch/VBoxIntNetSwitch.cpp
index fe946946b6a..1cb3c3db271 100644
--- a/src/VBox/NetworkServices/IntNetSwitch/main.cpp
+++ b/src/VBox/NetworkServices/IntNetSwitch/VBoxIntNetSwitch.cpp
@@ -52,6 +52,11 @@
/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+
+/*********************************************************************************************************************************
* Structures and Typedefs *
*********************************************************************************************************************************/
@@ -115,14 +120,12 @@ typedef struct SUPDRVSESSION
PSUPDRVUSAGE volatile pUsage;
/** The XPC connection handle for this session. */
xpc_connection_t hXpcCon;
- /** The receive wait thread. */
- RTTHREAD hThrdRecv;
/** The intnet interface handle to wait on. */
INTNETIFHANDLE hIfWait;
- /** The event semaphore for the receive thread. */
- RTSEMEVENT hEvtRecv;
- /** Flag whether to terminate the receive thread. */
- bool volatile fTerminate;
+ /** Flag whether a receive wait was initiated. */
+ bool volatile fRecvWait;
+ /** Flag whether there is something to receive. */
+ bool volatile fRecvAvail;
} SUPDRVSESSION;
@@ -356,24 +359,12 @@ static uint32_t intnetR3SessionDestroy(PSUPDRVSESSION pSession)
{
PSUPDRVDEVEXT pDevExt = pSession->pDevExt;
uint32_t cRefs = ASMAtomicDecU32(&pDevExt->cRefs);
+ xpc_transaction_end();
xpc_connection_set_context(pSession->hXpcCon, NULL);
xpc_connection_cancel(pSession->hXpcCon);
pSession->hXpcCon = NULL;
- xpc_transaction_end();
-
- /* Tear down the receive wait thread. */
- ASMAtomicXchgBool(&pSession->fTerminate, true);
- RTSemEventSignal(pSession->hEvtRecv);
-
- if (pSession->hThrdRecv != NIL_RTTHREAD)
- {
- int rc = RTThreadWait(pSession->hThrdRecv, 5000, NULL);
- AssertRC(rc);
- pSession->hThrdRecv = NIL_RTTHREAD;
- }
- RTSemEventDestroy(pSession->hEvtRecv);
- pSession->hEvtRecv = NIL_RTSEMEVENT;
+ ASMAtomicXchgBool(&pSession->fRecvAvail, true);
if (pSession->pUsage)
{
@@ -421,7 +412,7 @@ static uint32_t intnetR3SessionDestroy(PSUPDRVSESSION pSession)
}
RTCritSectLeave(&pDevExt->CritSect);
- AssertMsg(!pSession->pUsage, ("Some buster reregistered an object during desturction!\n"));
+ AssertMsg(!pSession->pUsage, ("Some buster reregistered an object during destruction!\n"));
}
RTMemFree(pSession);
@@ -430,42 +421,21 @@ static uint32_t intnetR3SessionDestroy(PSUPDRVSESSION pSession)
/**
- * Asynchronous I/O thread for handling receive.
- *
- * @returns VINF_SUCCESS (ignored).
- * @param hThreadSelf Thread handle.
- * @param pvUser Pointer to a DRVINTNET structure.
+ * Data available in th receive buffer callback.
*/
-static DECLCALLBACK(int) intnetR3RecvThread(RTTHREAD hThreadSelf, void *pvUser)
+static DECLCALLBACK(void) intnetR3RecvAvail(INTNETIFHANDLE hIf, void *pvUser)
{
- RT_NOREF(hThreadSelf);
+ RT_NOREF(hIf);
PSUPDRVSESSION pSession = (PSUPDRVSESSION)pvUser;
- for (;;)
+ if (ASMAtomicXchgBool(&pSession->fRecvWait, false))
{
- if (pSession->fTerminate)
- break;
-
- RTSemEventWait(pSession->hEvtRecv, RT_INDEFINITE_WAIT);
- if (pSession->fTerminate)
- break;
-
- int rc = IntNetR0IfWait(pSession->hIfWait, pSession, 30000); /* 30s - don't wait forever, timeout now and then. */
- if (RT_SUCCESS(rc))
- {
- /* Send an empty message. */
- xpc_object_t hObjPoke = xpc_dictionary_create(NULL, NULL, 0);
- xpc_connection_send_message(pSession->hXpcCon, hObjPoke);
- }
- else if ( rc != VERR_TIMEOUT
- && rc != VERR_INTERRUPTED)
- {
- LogFlow(("intnetR3RecvThread: returns %Rrc\n", rc));
- return rc;
- }
+ /* Send an empty message. */
+ xpc_object_t hObjPoke = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_connection_send_message(pSession->hXpcCon, hObjPoke);
}
-
- return VINF_SUCCESS;
+ else
+ ASMAtomicXchgBool(&pSession->fRecvAvail, true);
}
@@ -499,7 +469,9 @@ static void intnetR3RequestProcess(xpc_connection_t hCon, xpc_object_t hObj, PSU
{
if (cbReq == sizeof(INTNETOPENREQ))
{
- rc = IntNetR0OpenReq(pSession, &ReqReply.OpenReq);
+ rc = IntNetR3Open(pSession, &ReqReply.OpenReq.szNetwork[0], ReqReply.OpenReq.enmTrunkType, ReqReply.OpenReq.szTrunk,
+ ReqReply.OpenReq.fFlags, ReqReply.OpenReq.cbSend, ReqReply.OpenReq.cbRecv,
+ intnetR3RecvAvail, pSession, &ReqReply.OpenReq.hIf);
cbReply = sizeof(INTNETOPENREQ);
}
else
@@ -524,10 +496,16 @@ static void intnetR3RequestProcess(xpc_connection_t hCon, xpc_object_t hObj, PSU
rc = IntNetR0IfGetBufferPtrsReq(pSession, &ReqReply.IfGetBufferPtrsReq);
/* This is special as we need to return a shared memory segment. */
xpc_object_t hObjReply = xpc_dictionary_create_reply(hObj);
- xpc_dictionary_set_int64(hObjReply, "rc", rc);
xpc_object_t hObjShMem = xpc_shmem_create(ReqReply.IfGetBufferPtrsReq.pRing3Buf, ReqReply.IfGetBufferPtrsReq.pRing3Buf->cbBuf);
- xpc_dictionary_set_value(hObjReply, "buf-ptr", hObjShMem);
- xpc_release(hObjShMem);
+ if (hObjShMem)
+ {
+ xpc_dictionary_set_value(hObjReply, "buf-ptr", hObjShMem);
+ xpc_release(hObjShMem);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ xpc_dictionary_set_uint64(hObjReply, "rc", INTNET_R3_SVC_SET_RC(rc));
xpc_connection_send_message(hCon, hObjReply);
return;
}
@@ -583,8 +561,15 @@ static void intnetR3RequestProcess(xpc_connection_t hCon, xpc_object_t hObj, PSU
{
if (cbReq == sizeof(INTNETIFWAITREQ))
{
- pSession->hIfWait = ReqReply.IfWaitReq.hIf; /* Asynchronous. */
- rc = RTSemEventSignal(pSession->hEvtRecv);
+ ASMAtomicXchgBool(&pSession->fRecvWait, true);
+ if (ASMAtomicXchgBool(&pSession->fRecvAvail, false))
+ {
+ ASMAtomicXchgBool(&pSession->fRecvWait, false);
+
+ /* Send an empty message. */
+ xpc_object_t hObjPoke = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_connection_send_message(pSession->hXpcCon, hObjPoke);
+ }
return;
}
else
@@ -595,7 +580,13 @@ static void intnetR3RequestProcess(xpc_connection_t hCon, xpc_object_t hObj, PSU
{
if (cbReq == sizeof(INTNETIFABORTWAITREQ))
{
- rc = IntNetR0IfAbortWaitReq(pSession, &ReqReply.IfAbortWaitReq);
+ ASMAtomicXchgBool(&pSession->fRecvWait, false);
+ if (ASMAtomicXchgBool(&pSession->fRecvAvail, false))
+ {
+ /* Send an empty message. */
+ xpc_object_t hObjPoke = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_connection_send_message(pSession->hXpcCon, hObjPoke);
+ }
cbReply = sizeof(INTNETIFABORTWAITREQ);
}
else
@@ -608,7 +599,7 @@ static void intnetR3RequestProcess(xpc_connection_t hCon, xpc_object_t hObj, PSU
}
xpc_object_t hObjReply = xpc_dictionary_create_reply(hObj);
- xpc_dictionary_set_int64(hObjReply, "rc", rc);
+ xpc_dictionary_set_uint64(hObjReply, "rc", INTNET_R3_SVC_SET_RC(rc));
xpc_dictionary_set_data(hObjReply, "reply", &ReqReply, cbReply);
xpc_connection_send_message(hCon, hObjReply);
}
@@ -645,24 +636,10 @@ DECLCALLBACK(void) xpcConnHandler(xpc_connection_t hXpcCon)
pSession->pDevExt = &g_DevExt;
pSession->hXpcCon = hXpcCon;
- int rc = RTSemEventCreate(&pSession->hEvtRecv);
- if (RT_SUCCESS(rc))
- {
- rc = RTThreadCreate(&pSession->hThrdRecv, intnetR3RecvThread, pSession, 0,
- RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "INTNET-RECV");
- if (RT_SUCCESS(rc))
- {
- xpc_connection_set_context(hXpcCon, pSession);
- xpc_connection_resume(hXpcCon);
- xpc_transaction_begin();
- ASMAtomicIncU32(&g_DevExt.cRefs);
- return;
- }
-
- RTSemEventDestroy(pSession->hEvtRecv);
- }
-
- RTMemFree(pSession);
+ xpc_connection_set_context(hXpcCon, pSession);
+ xpc_connection_activate(hXpcCon);
+ xpc_transaction_begin();
+ ASMAtomicIncU32(&g_DevExt.cRefs);
}
}