Changeset 22360 in vbox
- Timestamp:
- Aug 20, 2009 9:18:13 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvNAT.cpp
r22354 r22360 148 148 char *pszNextServer; 149 149 /* polling thread */ 150 PPDMTHREAD p Thread;150 PPDMTHREAD pSlirpThread; 151 151 /** Queue for NAT-thread-external events. */ 152 PRTREQQUEUE p ReqQueue;152 PRTREQQUEUE pSlirpReqQueue; 153 153 /* Send queue */ 154 154 #ifndef SLIRP_SPLIT_CAN_OUTPUT … … 172 172 STAMCOUNTER StatConsumerFalse; 173 173 #ifdef SLIRP_SPLIT_CAN_OUTPUT 174 PPDMTHREAD thrNATRx;175 RTSEMEVENT semNATRx;176 STAMCOUNTER StatNATR xWakeups;177 PRTREQQUEUE p GuestQueue;174 PPDMTHREAD pRecvThread; 175 RTSEMEVENT EventRecv; 176 STAMCOUNTER StatNATRecvWakeups; 177 PRTREQQUEUE pRecvReqQueue; 178 178 #endif 179 179 } DRVNAT; … … 198 198 199 199 200 static void drvNATNotifyNATThr(PDRVNAT pThis); 200 static void drvNATNotifyNATThread(PDRVNAT pThis); 201 202 203 /** Converts a pointer to NAT::INetworkConnector to a PRDVNAT. */ 204 #define PDMINETWORKCONNECTOR_2_DRVNAT(pInterface) ( (PDRVNAT)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAT, INetworkConnector)) ) 205 201 206 202 207 #ifdef SLIRP_SPLIT_CAN_OUTPUT 203 static DECLCALLBACK(int) drvNATR x(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)208 static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 204 209 { 205 uint16_t iSendCounter = 0;206 210 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 211 207 212 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 208 213 return VINF_SUCCESS; 214 209 215 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 210 216 { 211 RTReqProcess(pThis->p GuestQueue, 0);212 RTSemEventWait(pThis-> semNATRx, RT_INDEFINITE_WAIT);217 RTReqProcess(pThis->pRecvReqQueue, 0); 218 RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT); 213 219 } 214 220 return VINF_SUCCESS; … … 216 222 217 223 218 static DECLCALLBACK(int) drvNATR xWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)224 static DECLCALLBACK(int) drvNATRecvWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 219 225 { 220 226 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 221 int rc = RTSemEventSignal(pThis-> semNATRx);222 STAM_COUNTER_INC(&pThis->StatNATR xWakeups);227 int rc = RTSemEventSignal(pThis->EventRecv); 228 STAM_COUNTER_INC(&pThis->StatNATRecvWakeups); 223 229 AssertReleaseRC(rc); 224 230 return VINF_SUCCESS; 225 231 } 226 232 227 static DECLCALLBACK(void) drvNATR xWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb)233 static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb) 228 234 { 229 235 int rc; … … 237 243 } 238 244 #endif 239 240 /** Converts a pointer to NAT::INetworkConnector to a PRDVNAT. */241 #define PDMINETWORKCONNECTOR_2_DRVNAT(pInterface) ( (PDRVNAT)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAT, INetworkConnector)) )242 243 245 244 246 /** … … 273 275 int rc; 274 276 void *buf; 277 275 278 /* don't queue new requests when the NAT thread is about to stop */ 276 if (pThis->p Thread->enmState != PDMTHREADSTATE_RUNNING)279 if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING) 277 280 return VINF_SUCCESS; 281 278 282 #ifndef VBOX_WITH_SLIRP_MT 279 rc = RTReqAlloc(pThis->p ReqQueue, &pReq, RTREQTYPE_INTERNAL);283 rc = RTReqAlloc(pThis->pSlirpReqQueue, &pReq, RTREQTYPE_INTERNAL); 280 284 #else 281 285 rc = RTReqAlloc((PRTREQQUEUE)slirp_get_queue(pThis->pNATState), &pReq, RTREQTYPE_INTERNAL); … … 301 305 rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */ 302 306 AssertReleaseRC(rc); 303 drvNATNotifyNATThr (pThis);307 drvNATNotifyNATThread(pThis); 304 308 LogFlow(("drvNATSend: end\n")); 305 309 return VINF_SUCCESS; 306 310 } 307 311 308 static void drvNATNotifyNATThr(PDRVNAT pThis) 312 313 /** 314 * Get the NAT thread out of poll/WSAWaitForMultipleEvents 315 */ 316 static void drvNATNotifyNATThread(PDRVNAT pThis) 309 317 { 310 318 int rc; … … 319 327 } 320 328 329 321 330 /** 322 331 * Set promiscuous mode. … … 376 385 377 386 PRTREQ pReq = NULL; 387 378 388 /* don't queue new requests when the NAT thread is about to stop */ 379 if (pThis->p Thread->enmState != PDMTHREADSTATE_RUNNING)389 if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING) 380 390 return; 381 int rc = RTReqAlloc(pThis->pReqQueue, &pReq, RTREQTYPE_INTERNAL); 391 392 int rc = RTReqAlloc(pThis->pSlirpReqQueue, &pReq, RTREQTYPE_INTERNAL); 382 393 AssertReleaseRC(rc); 383 394 pReq->u.Internal.pfn = (PFNRT)drvNATNotifyLinkChangedWorker; … … 389 400 if (RT_LIKELY(rc == VERR_TIMEOUT)) 390 401 { 391 drvNATNotifyNATThr (pThis);402 drvNATNotifyNATThread(pThis); 392 403 rc = RTReqWait(pReq, RT_INDEFINITE_WAIT); 393 404 AssertReleaseRC(rc); … … 398 409 } 399 410 400 411 /** 412 * NAT thread handling the slirp stuff. The slirp implementation is single-threaded 413 * so we execute this enginre in a dedicated thread. We take care that this thread 414 * does not become the bottleneck: If the guest wants to send, a request is enqueued 415 * into the pSlirpReqQueue and handled asynchronously by this thread. If this thread 416 * wants to deliver packets to the guest, it enqueues a request into pRecvReqQueue 417 * which is later handled by the Recv thread. 418 */ 401 419 static DECLCALLBACK(int) drvNATAsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 402 420 { … … 487 505 } 488 506 /* process _all_ outstanding requests but don't wait */ 489 RTReqProcess(pThis->p ReqQueue, 0);507 RTReqProcess(pThis->pSlirpReqQueue, 0); 490 508 RTMemFree(polls); 491 509 #else /* RT_OS_WINDOWS */ … … 512 530 slirp_select_poll(pThis->pNATState, /* fTimeout=*/false, /* fIcmp=*/(event == WSA_WAIT_EVENT_0)); 513 531 /* process _all_ outstanding requests but don't wait */ 514 RTReqProcess(pThis->p ReqQueue, 0);532 RTReqProcess(pThis->pSlirpReqQueue, 0); 515 533 # ifdef VBOX_NAT_DELAY_HACK 516 534 if (cBreak++ > 128) … … 527 545 528 546 529 /** 530 * Unblock the send thread so it can respond to a state change. 531 * 532 * @returns VBox status code. 533 * @param pDevIns The pcnet device instance. 534 * @param pThread The send thread. 535 */ 536 static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 537 { 538 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 539 540 #ifndef RT_OS_WINDOWS 541 /* kick select() */ 542 int rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL); 543 AssertRC(rc); 544 #else /* !RT_OS_WINDOWS */ 545 /* kick WSAWaitForMultipleEvents() */ 546 WSASetEvent(pThis->hWakeupEvent); 547 #endif /* RT_OS_WINDOWS */ 548 549 return VINF_SUCCESS; 550 } 551 552 #ifdef VBOX_WITH_SLIRP_MT 553 554 static DECLCALLBACK(int) drvNATAsyncIoGuest(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 555 { 556 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 557 558 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 559 return VINF_SUCCESS; 560 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 561 { 562 slirp_process_queue(pThis->pNATState); 563 } 564 return VINF_SUCCESS; 565 } 566 567 568 static DECLCALLBACK(int) drvNATAsyncIoGuestWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 569 { 570 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 571 572 return VINF_SUCCESS; 573 } 574 575 #endif /* VBOX_WITH_SLIRP_MT */ 547 /** 548 * Unblock the send thread so it can respond to a state change. 549 * 550 * @returns VBox status code. 551 * @param pDevIns The pcnet device instance. 552 * @param pThread The send thread. 553 */ 554 static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 555 { 556 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 557 558 drvNATNotifyNATThread(pThis); 559 return VINF_SUCCESS; 560 } 561 562 #ifdef VBOX_WITH_SLIRP_MT 563 564 static DECLCALLBACK(int) drvNATAsyncIoGuest(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 565 { 566 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 567 568 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 569 return VINF_SUCCESS; 570 571 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 572 slirp_process_queue(pThis->pNATState); 573 574 return VINF_SUCCESS; 575 } 576 577 578 static DECLCALLBACK(int) drvNATAsyncIoGuestWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 579 { 580 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 581 582 return VINF_SUCCESS; 583 } 584 585 #endif /* VBOX_WITH_SLIRP_MT */ 586 576 587 577 588 /** … … 591 602 { 592 603 PDRVNAT pThis = (PDRVNAT)pvUser; 604 Assert(pThis); 593 605 594 606 LogFlow(("slirp_output BEGIN %x %d\n", pu8Buf, cb)); 595 607 Log2(("slirp_output: pu8Buf=%p cb=%#x (pThis=%p)\n%.*Rhxd\n", pu8Buf, cb, pThis, cb, pu8Buf)); 596 597 /** @todo r-bird: Why do you reset the counters every time? You won't ever count598 * higher than ONE then. If you want to record what happened to the last599 * queued item, use a U8/bool instead to two 64-bit values. */600 //STAM_COUNTER_RESET(&pThis->StatQueuePktDropped);601 //STAM_COUNTER_RESET(&pThis->StatQueuePktSent);602 Assert(pThis);603 608 604 609 #ifndef SLIRP_SPLIT_CAN_OUTPUT … … 626 631 #else 627 632 PRTREQ pReq = NULL; 633 628 634 /* don't queue new requests when the NAT thread is about to stop */ 629 if (pThis->p Thread->enmState != PDMTHREADSTATE_RUNNING)635 if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING) 630 636 return; 631 int rc = RTReqAlloc(pThis->pGuestQueue, &pReq, RTREQTYPE_INTERNAL); 637 638 int rc = RTReqAlloc(pThis->pRecvReqQueue, &pReq, RTREQTYPE_INTERNAL); 632 639 AssertReleaseRC(rc); 633 pReq->u.Internal.pfn = (PFNRT)drvNATR xWorker;640 pReq->u.Internal.pfn = (PFNRT)drvNATRecvWorker; 634 641 pReq->u.Internal.cArgs = 3; 635 642 pReq->u.Internal.aArgs[0] = (uintptr_t)pThis; … … 639 646 rc = RTReqQueue(pReq, 0); 640 647 AssertReleaseRC(rc); 641 drvNATR xWakeup(pThis->pDrvIns, pThis->thrNATRx);648 drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread); 642 649 STAM_COUNTER_INC(&pThis->StatQueuePktSent); 643 650 #endif … … 970 977 " queue", "/Drivers/NAT%u/PDMConsumerFalse", pDrvIns->iInstance); 971 978 # ifdef SLIRP_SPLIT_CAN_OUTPUT 972 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatNATR xWakeups, STAMTYPE_COUNTER,979 PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatNATRecvWakeups, STAMTYPE_COUNTER, 973 980 STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "counting wakeups of NATRX" 974 " thread", "/Drivers/NAT%u/NATR xWakeups", pDrvIns->iInstance);981 " thread", "/Drivers/NAT%u/NATRecvWakeups", pDrvIns->iInstance); 975 982 # endif 976 983 #endif … … 987 994 NULL, NULL, NULL, NULL, NULL, drvNATLoadDone); 988 995 AssertRC(rc2); 989 rc = RTReqCreateQueue(&pThis->p ReqQueue);996 rc = RTReqCreateQueue(&pThis->pSlirpReqQueue); 990 997 if (RT_FAILURE(rc)) 991 998 { … … 1004 1011 } 1005 1012 #else 1006 rc = RTReqCreateQueue(&pThis->p GuestQueue);1013 rc = RTReqCreateQueue(&pThis->pRecvReqQueue); 1007 1014 if (RT_FAILURE(rc)) 1008 1015 { … … 1010 1017 return rc; 1011 1018 } 1012 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis-> thrNATRx, pThis, drvNATRx,1013 drvNATR xWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX");1019 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvNATRecv, 1020 drvNATRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX"); 1014 1021 AssertReleaseRC(rc); 1015 rc = RTSemEventCreate(&pThis-> semNATRx);1022 rc = RTSemEventCreate(&pThis->EventRecv); 1016 1023 #endif 1017 1024 … … 1035 1042 #endif 1036 1043 1037 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->p Thread, pThis, drvNATAsyncIoThread,1044 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pSlirpThread, pThis, drvNATAsyncIoThread, 1038 1045 drvNATAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "NAT"); 1039 1046 AssertReleaseRC(rc);
Note:
See TracChangeset
for help on using the changeset viewer.