- Timestamp:
- Nov 14, 2008 1:00:50 PM (16 years ago)
- Location:
- trunk/src/VBox/Devices/Network
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvNAT.cpp
r14202 r14204 44 44 # endif 45 45 # include <errno.h> 46 # include<iprt/semaphore.h> 46 # include <iprt/semaphore.h> 47 # include <iprt/req.h> 47 48 #endif 48 49 … … 77 78 char *pszBootFile; 78 79 #ifdef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC 79 /* polling thread*/80 /* polling thread */ 80 81 PPDMTHREAD pThread; 81 /*used for wakep of poling thread*/ 82 RTSEMEVENT semSndMutex; 83 RTSEMEVENT semLinkMutex; 84 #ifndef RT_OS_WINDOWS 82 /** Queue for NAT-thread-external events. */ 83 PRTREQQUEUE pReqQueue; 84 # ifndef RT_OS_WINDOWS 85 85 /** The write end of the control pipe. */ 86 86 RTFILE PipeWrite; 87 87 /** The read end of the control pipe. */ 88 88 RTFILE PipeRead; 89 #else 90 /*for send event from guest*/ 91 HANDLE hSendEvent; 92 HANDLE hNetEvent; 93 #endif 94 /** Send buffer */ 95 char cBuffer[1600]; 96 size_t sBufferSize; 89 # else 90 /** for external notification */ 91 HANDLE hWakeupEvent; 92 # endif 97 93 #endif 98 94 } DRVNAT, *PDRVNAT; … … 102 98 103 99 100 /** 101 * Worker function for drvNATSend(). 102 * @thread "NAT" thread. 103 */ 104 static void drvNATSendWorker(PDRVNAT pThis, const void *pvBuf, size_t cb) 105 { 106 Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP); 107 if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP) 108 slirp_input(pThis->pNATState, (uint8_t *)pvBuf, cb); 109 } 104 110 105 111 /** … … 121 127 #ifdef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC 122 128 129 PRTREQ pReq = NULL; 123 130 int rc; 124 /*notify select to wakeup*/ 125 AssertRelease(cb <= sizeof(pThis->cBuffer)); 126 memcpy(pThis->cBuffer, pvBuf, cb); 127 pThis->sBufferSize = cb; 131 /* don't queue new requests when the NAT thread is about to stop */ 132 if (pThis->pThread->enmState != PDMTHREADSTATE_RUNNING) 133 return VINF_SUCCESS; 134 rc = RTReqAlloc(pThis->pReqQueue, &pReq, RTREQTYPE_INTERNAL); 135 AssertReleaseRC(rc); 136 pReq->u.Internal.pfn = (PFNRT)drvNATSendWorker; 137 pReq->u.Internal.cArgs = 3; 138 pReq->u.Internal.aArgs[0] = (uintptr_t)pThis; 139 pReq->u.Internal.aArgs[1] = (uintptr_t)pvBuf; 140 pReq->u.Internal.aArgs[2] = (uintptr_t)cb; 141 pReq->fFlags = RTREQFLAGS_VOID; 142 rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */ 143 if (RT_LIKELY(rc == VERR_TIMEOUT)) 144 { 128 145 # ifndef RT_OS_WINDOWS 129 rc = RTFileWrite(pThis->PipeWrite, "1", 2, NULL); 130 AssertRC(rc); 146 /* kick select() */ 147 rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL); 148 AssertRC(rc); 131 149 # else 132 rc = WSASetEvent(pThis->hSendEvent); 133 AssertRelease(rc == TRUE); 150 /* kick WSAWaitForMultipleEvents */ 151 rc = WSASetEvent(pThis->hWakeupEvent); 152 AssertRelease(rc == TRUE); 134 153 # endif 135 RTSemEventWait(pThis->semSndMutex, RT_INDEFINITE_WAIT); 136 137 #else /* ! VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */ 154 rc = RTReqWait(pReq, RT_INDEFINITE_WAIT); 155 AssertReleaseRC(rc); 156 } 157 else 158 AssertReleaseRC(rc); 159 RTReqFree(pReq); 160 161 #else /* !VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */ 138 162 139 163 int rc = RTCritSectEnter(&pThis->CritSect); 140 164 AssertReleaseRC(rc); 141 165 142 Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP); 143 if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP) 144 slirp_input(pThis->pNATState, (uint8_t *)pvBuf, cb); 166 drvNATSendWorker(pThis, pvBuf, cb); 145 167 146 168 RTCritSectLeave(&pThis->CritSect); … … 169 191 } 170 192 171 172 /** 173 * Notification on link status changes. 174 * 175 * @param pInterface Pointer to the interface structure containing the called function pointer. 176 * @param enmLinkState The new link state. 177 * @thread EMT 178 */ 179 static DECLCALLBACK(void) drvNATNotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState) 180 { 181 PDRVNAT pThis = PDMINETWORKCONNECTOR_2_DRVNAT(pInterface); 182 int rc; 183 184 LogFlow(("drvNATNotifyLinkChanged: enmLinkState=%d\n", enmLinkState)); 185 186 LogRel(("drvNATNotifyLinkChanged\n")); 187 #ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC 188 rc = RTCritSectEnter(&pThis->CritSect); 189 AssertReleaseRC(rc); 190 #endif 193 /** 194 * Worker function for drvNATNotifyLinkChanged(). 195 * @thread "NAT" thread. 196 */ 197 static void drvNATNotifyLinkChangedWorker(PDRVNAT pThis, PDMNETWORKLINKSTATE enmLinkState) 198 { 191 199 pThis->enmLinkState = enmLinkState; 192 200 … … 195 203 case PDMNETWORKLINKSTATE_UP: 196 204 LogRel(("NAT: link up\n")); 197 #ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC198 205 slirp_link_up(pThis->pNATState); 199 #else /* VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */200 # ifndef RT_OS_WINDOWS201 rc = RTFileWrite(pThis->PipeWrite, "2", 2, NULL);202 AssertRC(rc);203 # else204 WSASetEvent(pThis->hNetEvent);205 # endif206 #endif /* VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */207 206 break; 208 207 … … 210 209 case PDMNETWORKLINKSTATE_DOWN_RESUME: 211 210 LogRel(("NAT: link down\n")); 212 #ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC213 211 slirp_link_down(pThis->pNATState); 214 #else /* VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */215 # ifndef RT_OS_WINDOWS216 rc = RTFileWrite(pThis->PipeWrite, "2", 2, NULL);217 AssertRC(rc);218 # else219 WSASetEvent(pThis->hNetEvent);220 RTSemEventWait(pThis->semLinkMutex, RT_INDEFINITE_WAIT);221 # endif222 #endif /* VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */223 212 break; 224 213 … … 226 215 AssertMsgFailed(("drvNATNotifyLinkChanged: unexpected link state %d\n", enmLinkState)); 227 216 } 217 } 218 219 /** 220 * Notification on link status changes. 221 * 222 * @param pInterface Pointer to the interface structure containing the called function pointer. 223 * @param enmLinkState The new link state. 224 * @thread EMT 225 */ 226 static DECLCALLBACK(void) drvNATNotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState) 227 { 228 PDRVNAT pThis = PDMINETWORKCONNECTOR_2_DRVNAT(pInterface); 229 230 LogFlow(("drvNATNotifyLinkChanged: enmLinkState=%d\n", enmLinkState)); 231 232 #ifdef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC 233 234 PRTREQ pReq = NULL; 235 bool fWait; 236 /* don't queue new requests when the NAT thread is about to stop */ 237 if (pThis->pThread->enmState != PDMTHREADSTATE_RUNNING) 238 return; 239 int rc = RTReqAlloc(pThis->pReqQueue, &pReq, RTREQTYPE_INTERNAL); 240 AssertReleaseRC(rc); 241 pReq->u.Internal.pfn = (PFNRT)drvNATNotifyLinkChangedWorker; 242 pReq->u.Internal.cArgs = 2; 243 pReq->u.Internal.aArgs[0] = (uintptr_t)pThis; 244 pReq->u.Internal.aArgs[1] = (uintptr_t)enmLinkState; 245 pReq->fFlags = RTREQFLAGS_VOID; 246 rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */ 247 if (RT_LIKELY(rc == VERR_TIMEOUT)) 248 { 249 # ifndef RT_OS_WINDOWS 250 /* kick select() */ 251 rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL); 252 AssertRC(rc); 253 # else 254 /* kick WSAWaitForMultipleEvents() */ 255 rc = WSASetEvent(pThis->hWakeupEvent); 256 AssertRelease(rc == TRUE); 257 # endif 258 rc = RTReqWait(pReq, RT_INDEFINITE_WAIT); 259 AssertReleaseRC(rc); 260 } 261 else 262 AssertReleaseRC(rc); 263 RTReqFree(pReq); 264 265 #else /* !VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */ 266 267 int rc = RTCritSectEnter(&pThis->CritSect); 268 AssertReleaseRC(rc); 269 drvNATNotifyLinkChangedWorker(pThis, enmLinkState); 270 RTCritSectLeave(&pThis->CritSect); 271 272 #endif /* VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */ 273 } 274 275 228 276 #ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC 229 RTCritSectLeave(&pThis->CritSect); 230 #endif 231 } 232 233 234 #ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC 277 235 278 /** 236 279 * Poller callback. … … 259 302 RTCritSectLeave(&pThis->CritSect); 260 303 } 261 #else 304 305 #else /* VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */ 262 306 263 307 static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) … … 287 331 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 288 332 { 289 290 333 FD_ZERO(&ReadFDs); 291 334 FD_ZERO(&WriteFDs); … … 308 351 { 309 352 /* drain the pipe */ 310 char ch[ 2];353 char ch[1]; 311 354 size_t cbRead; 312 RTFileRead(pThis->PipeRead, &ch, 2, &cbRead); 313 switch (ch[0]) 314 { 315 case '1': 316 /* called from drvNATSend */ 317 slirp_input(pThis->pNATState, (uint8_t *)pThis->cBuffer, pThis->sBufferSize); 318 RTSemEventSignal(pThis->semSndMutex); 319 break; 320 case '2': 321 /* wakeup only */ 322 break; 323 } 355 RTFileRead(pThis->PipeRead, &ch, 1, &cbRead); 324 356 } 357 /* process _all_ outstanding requests but don't wait */ 358 while (RT_SUCCESS(RTReqProcess(pThis->pReqQueue, 0))) 359 ; 325 360 } 326 361 # else /* RT_OS_WINDOWS */ … … 336 371 if (event == WSA_WAIT_TIMEOUT) 337 372 { 373 /* only check for slow/fast timers */ 338 374 slirp_select_poll(pThis->pNATState, NULL, NULL, NULL); 339 375 continue; 340 376 } 341 377 342 /* 343 * see WSAWaitForMultipleEvents documentation: return value is a minimal index in array 344 */ 345 if ((event - WSA_WAIT_EVENT_0) >= VBOX_SEND_EVENT_INDEX) 346 slirp_select_poll(pThis->pNATState, &ReadFDs, &WriteFDs, &XcptFDs); 347 348 if ((event - WSA_WAIT_EVENT_0) == VBOX_SEND_EVENT_INDEX) 349 { 350 /** XXX distinguish between drvNATSend and wakeup only */ 351 slirp_input(pThis->pNATState, (uint8_t *)&pThis->cBuffer[0], pThis->sBufferSize); 352 WSAResetEvent(pThis->hSendEvent); 353 RTSemEventSignal(pThis->semSndMutex); 354 } 355 if ((event - WSA_WAIT_EVENT_0) == VBOX_NET_EVENT_INDEX) 356 { 357 switch(pThis->enmLinkState) 358 { 359 case PDMNETWORKLINKSTATE_UP: 360 slirp_link_up(pThis->pNATState); 361 break; 362 case PDMNETWORKLINKSTATE_DOWN: 363 case PDMNETWORKLINKSTATE_DOWN_RESUME: 364 slirp_link_down(pThis->pNATState); 365 break; 366 } 367 WSAResetEvent(pThis->hNetEvent); 368 RTSemEventSignal(pThis->semLinkMutex); 369 break; 370 } 378 /* poll the sockets in any case */ 379 slirp_select_poll(pThis->pNATState, &ReadFDs, &WriteFDs, &XcptFDs); 380 /* process _all_ outstanding requests but don't wait */ 381 while (RT_SUCCESS(RTReqProcess(This->pReqQueue, 0))) 382 ; 371 383 # endif /* RT_OS_WINDOWS */ 372 384 } … … 387 399 388 400 # ifndef RT_OS_WINDOWS 389 int rc = RTFileWrite(pThis->PipeWrite, "2", 2, NULL); 401 /* kick select() */ 402 int rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL); 390 403 AssertRC(rc); 391 404 # else 392 WSASetEvent(pThis->hNetEvent); 405 /* kick WSAWaitForMultipleEvents() */ 406 WSASetEvent(pThis->hNetEvent); 393 407 # endif 394 RTSemEventSignal(pThis->semSndMutex); 408 395 409 return VINF_SUCCESS; 396 410 } 397 411 398 #endif 412 #endif /* VBOX_WITH_SIMPLEFIED_SLIRP_SYNC */ 413 399 414 400 415 /** … … 491 506 RTCritSectLeave(&pThis->CritSect); 492 507 RTCritSectDelete(&pThis->CritSect); 493 #else494 RTSemEventDestroy(pThis->semLinkMutex);495 RTSemEventDestroy(pThis->semSndMutex);496 508 #endif 497 509 } … … 726 738 pDrvIns->pDrvHlp->pfnPDMPollerRegister(pDrvIns, drvNATPoller); 727 739 #else 728 rc = RTSemEventCreate(&pThis->semLinkMutex); 729 AssertReleaseRC(rc); 730 rc = RTSemEventCreate(&pThis->semSndMutex); 731 AssertReleaseRC(rc); 740 rc = RTReqCreateQueue(&pThis->pReqQueue); 741 if (RT_FAILURE(rc)) 742 return rc; 732 743 733 744 # ifndef RT_OS_WINDOWS … … 745 756 pThis->PipeWrite = fds[1]; 746 757 # else 747 pThis->hSendEvent = WSACreateEvent(); 748 pThis->hNetEvent = WSACreateEvent(); 749 slirp_register_external_event(pThis->pNATState, pThis->hSendEvent, VBOX_SEND_EVENT_INDEX); 750 slirp_register_external_event(pThis->pNATState, pThis->hNetEvent, VBOX_NET_EVENT_INDEX); 758 pThis->hSendWakeup = CreateEvent(NULL, FALSE, FALSE, NULL); /* auto-reset event */ 759 slirp_register_external_event(pThis->pNATState, pThis->hWakeupEvent, VBOX_WAKEUP_EVENT_INDEX); 751 760 # endif 752 761 -
trunk/src/VBox/Devices/Network/slirp/libslirp.h
r14196 r14204 51 51 52 52 #if defined(VBOX_WITH_SIMPLEFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS) 53 #define VBOX_NET_EVENT_INDEX 0 54 #define VBOX_SEND_EVENT_INDEX 1 55 #define VBOX_SOCKET_EVENT_INDEX 2 53 /** 54 * This event is for 55 * - slirp_input 56 * - slirp_link_up 57 * - slirp_link_down 58 * - wakeup 59 * 60 * The event index should be smaller than VBOX_SOCKET_EVENT_INDEX to ensure 61 * that we can detect if that event was set (WSAWaitForMultipleEvents() 62 * returns the index of the first active event). 63 */ 64 #define VBOX_WAKEUP_EVENT_INDEX 0 65 66 /* 67 * UDP/TCP socket state change (socket ready to receive, to send, ...) 68 */ 69 #define VBOX_SOCKET_EVENT_INDEX 1 70 71 /* 72 * The number of events for WSAWaitForMultipleEvents(). 73 */ 74 #define VBOX_EVENT_COUNT 2 75 56 76 HANDLE *slirp_get_events(PNATState pData); 57 77 void slirp_register_external_event(PNATState pData, HANDLE hEvent, int index); 58 78 #endif 79 59 80 #ifdef __cplusplus 60 81 } -
trunk/src/VBox/Devices/Network/slirp/slirp_state.h
r14200 r14204 117 117 struct socket *udp_last_so; 118 118 #if defined(VBOX_WITH_SIMPLEFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS) 119 #define VBOX_SOCKET_EVENT (pData->phEvents[VBOX_SOCKET_EVENT_INDEX]) 120 #define VBOX_EVENT_COUNT 3 119 # define VBOX_SOCKET_EVENT (pData->phEvents[VBOX_SOCKET_EVENT_INDEX]) 121 120 HANDLE phEvents[VBOX_EVENT_COUNT]; 122 121 #endif
Note:
See TracChangeset
for help on using the changeset viewer.