diff options
-rw-r--r-- | include/VBox/intnet.h | 29 | ||||
-rw-r--r-- | src/VBox/Devices/Network/DrvIntNet.cpp | 27 | ||||
-rw-r--r-- | src/VBox/Devices/Network/SrvIntNetR0.cpp | 109 | ||||
-rw-r--r-- | src/VBox/Devices/Network/testcase/tstIntNetR0.cpp | 8 | ||||
-rw-r--r-- | src/VBox/NetworkServices/IntNetSwitch/Makefile.kmk | 3 | ||||
-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); } } |