Changeset 22341 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Aug 19, 2009 10:45:59 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvNAT.cpp
r22277 r22341 118 118 x.s_addr = def; \ 119 119 }while(0) 120 121 #define QUEUE_SIZE 50 120 122 121 123 /******************************************************************************* … … 150 152 PRTREQQUEUE pReqQueue; 151 153 /* Send queue */ 154 #ifndef SLIRP_SPLIT_CAN_OUTPUT 152 155 PPDMQUEUE pSendQueue; 153 154 RTSEMEVENT semStatus; 156 #endif 157 155 158 #ifdef VBOX_WITH_SLIRP_MT 156 159 PPDMTHREAD pGuestThread; … … 171 174 PPDMTHREAD thrNATRx; 172 175 RTSEMEVENT semNATRx; 173 bool fCanOutput;174 176 STAMCOUNTER StatNATRxWakeups; 177 PRTREQQUEUE pGuestQueue; 175 178 #endif 176 179 } DRVNAT; … … 178 181 typedef DRVNAT *PDRVNAT; 179 182 180 #ifdef SLIRP_SPLIT_CAN_OUTPUT181 static DECLCALLBACK(int) drvNATRx(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)182 {183 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);184 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)185 return VINF_SUCCESS;186 while (pThread->enmState == PDMTHREADSTATE_RUNNING)187 {188 int rc;189 bool fHaveRxBuffers;190 do {191 rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, 0);192 fHaveRxBuffers = RT_SUCCESS(rc);193 if (!fHaveRxBuffers) RTThreadSleep(2);194 } while (!fHaveRxBuffers && pThread->enmState == PDMTHREADSTATE_RUNNING);195 196 if (!pThis->fCanOutput && fHaveRxBuffers)197 {198 int rc;199 pThis->fCanOutput = fHaveRxBuffers;200 /*we need inform NAT thread*/201 #ifndef RT_OS_WINDOWS202 /* kick select() */203 rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL);204 AssertRC(rc);205 #else206 /* kick WSAWaitForMultipleEvents */207 rc = WSASetEvent(pThis->hWakeupEvent);208 AssertRelease(rc == TRUE);209 #endif210 }211 pThis->fCanOutput = fHaveRxBuffers;212 RTSemEventWait(pThis->semNATRx, RT_INDEFINITE_WAIT);213 }214 return VINF_SUCCESS;215 }216 217 218 static DECLCALLBACK(int) drvNATRxWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)219 {220 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);221 int rc = RTSemEventSignal(pThis->semNATRx);222 STAM_COUNTER_INC(&pThis->StatNATRxWakeups);223 AssertReleaseRC(rc);224 return VINF_SUCCESS;225 }226 #endif227 228 183 /** 229 184 * NAT queue item. 230 185 */ 231 enum232 {233 SLIRP_CHECK,234 SLIRP_SEND235 };236 237 186 typedef struct DRVNATQUEUITEM 238 187 { … … 248 197 typedef DRVNATQUEUITEM *PDRVNATQUEUITEM; 249 198 199 200 static void drvNATNotifyNATThr(PDRVNAT pThis); 201 202 #ifdef SLIRP_SPLIT_CAN_OUTPUT 203 static DECLCALLBACK(int) drvNATRx(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 204 { 205 uint16_t iSendCounter = 0; 206 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 207 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 208 return VINF_SUCCESS; 209 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 210 { 211 RTReqProcess(pThis->pGuestQueue, 0); 212 RTSemEventWait(pThis->semNATRx, RT_INDEFINITE_WAIT); 213 } 214 return VINF_SUCCESS; 215 } 216 217 218 static DECLCALLBACK(int) drvNATRxWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 219 { 220 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 221 int rc = RTSemEventSignal(pThis->semNATRx); 222 STAM_COUNTER_INC(&pThis->StatNATRxWakeups); 223 AssertReleaseRC(rc); 224 return VINF_SUCCESS; 225 } 226 227 static DECLCALLBACK(void) drvNATRxWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb) 228 { 229 int rc; 230 if (RT_FAILURE(pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT))) 231 { 232 AssertMsgFailed(("No RX available even on indefinite wait")); 233 } 234 rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb); 235 RTMemFree(pu8Buf); 236 AssertRC(rc); 237 } 238 #endif 239 250 240 /** Converts a pointer to NAT::INetworkConnector to a PRDVNAT. */ 251 241 #define PDMINETWORKCONNECTOR_2_DRVNAT(pInterface) ( (PDRVNAT)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAT, INetworkConnector)) ) … … 311 301 rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */ 312 302 AssertReleaseRC(rc); 303 drvNATNotifyNATThr(pThis); 304 LogFlow(("drvNATSend: end\n")); 305 return VINF_SUCCESS; 306 } 307 308 static void drvNATNotifyNATThr(PDRVNAT pThis) 309 { 310 int rc; 313 311 #ifndef RT_OS_WINDOWS 314 312 /* kick select() */ 315 313 rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL); 316 AssertRC(rc);317 314 #else 318 315 /* kick WSAWaitForMultipleEvents */ 319 316 rc = WSASetEvent(pThis->hWakeupEvent); 320 AssertRelease(rc == TRUE); 321 #endif 322 323 LogFlow(("drvNATSend: end\n")); 324 return VINF_SUCCESS; 325 } 326 317 #endif 318 AssertReleaseRC(rc); 319 } 327 320 328 321 /** … … 396 389 if (RT_LIKELY(rc == VERR_TIMEOUT)) 397 390 { 398 #ifndef RT_OS_WINDOWS 399 /* kick select() */ 400 rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL); 401 AssertRC(rc); 402 #else 403 /* kick WSAWaitForMultipleEvents() */ 404 rc = WSASetEvent(pThis->hWakeupEvent); 405 AssertRelease(rc == TRUE); 406 #endif 391 drvNATNotifyNATThr(pThis); 407 392 rc = RTReqWait(pReq, RT_INDEFINITE_WAIT); 408 393 AssertReleaseRC(rc); … … 443 428 { 444 429 nFDs = -1; 445 446 430 /* 447 431 * To prevent concurent execution of sending/receving threads … … 524 508 continue; 525 509 } 526 527 510 /* poll the sockets in any case */ 528 511 Log2(("%s: poll\n", __FUNCTION__)); … … 538 521 # endif 539 522 #endif /* RT_OS_WINDOWS */ 540 #ifdef SLIRP_SPLIT_CAN_OUTPUT541 if (!pThis->fCanOutput)542 drvNATRxWakeup(pThis->pDrvIns, pThis->thrNATRx);543 #endif544 523 } 545 524 … … 548 527 549 528 550 /**551 * Unblock the send thread so it can respond to a state change.552 *553 * @returns VBox status code.554 * @param pDevIns The pcnet device instance.555 * @param pThread The send thread.556 */557 static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)558 {559 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);560 561 #ifndef RT_OS_WINDOWS562 /* kick select() */563 int rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL);564 AssertRC(rc);565 #else /* !RT_OS_WINDOWS */566 /* kick WSAWaitForMultipleEvents() */567 WSASetEvent(pThis->hWakeupEvent);568 #endif /* RT_OS_WINDOWS */569 570 return VINF_SUCCESS;571 }572 573 #ifdef VBOX_WITH_SLIRP_MT574 575 static DECLCALLBACK(int) drvNATAsyncIoGuest(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)576 {577 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);578 579 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)580 return VINF_SUCCESS;581 while (pThread->enmState == PDMTHREADSTATE_RUNNING)582 {583 slirp_process_queue(pThis->pNATState);584 }585 return VINF_SUCCESS;586 }587 588 589 static DECLCALLBACK(int) drvNATAsyncIoGuestWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)590 {591 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);592 593 return VINF_SUCCESS;594 }595 596 #endif /* VBOX_WITH_SLIRP_MT */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 */ 597 576 598 577 /** … … 603 582 int slirp_can_output(void *pvUser) 604 583 { 605 #ifdef SLIRP_SPLIT_CAN_OUTPUT606 PDRVNAT pThis = (PDRVNAT)pvUser;607 return pThis->fCanOutput;608 #else609 584 return 1; 610 #endif611 585 } 612 586 … … 628 602 Assert(pThis); 629 603 604 #ifndef SLIRP_SPLIT_CAN_OUTPUT 630 605 PDRVNATQUEUITEM pItem = (PDRVNATQUEUITEM)PDMQueueAlloc(pThis->pSendQueue); 631 606 if (pItem) … … 649 624 STAM_COUNTER_INC(&pThis->StatQueuePktDropped); 650 625 RTMemFree((void *)pu8Buf); 651 } 652 653 626 #else 627 PRTREQ pReq = NULL; 628 /* don't queue new requests when the NAT thread is about to stop */ 629 if (pThis->pThread->enmState != PDMTHREADSTATE_RUNNING) 630 return; 631 int rc = RTReqAlloc(pThis->pGuestQueue, &pReq, RTREQTYPE_INTERNAL); 632 AssertReleaseRC(rc); 633 pReq->u.Internal.pfn = (PFNRT)drvNATRxWorker; 634 pReq->u.Internal.cArgs = 3; 635 pReq->u.Internal.aArgs[0] = (uintptr_t)pThis; 636 pReq->u.Internal.aArgs[1] = (uintptr_t)pu8Buf; 637 pReq->u.Internal.aArgs[2] = (uintptr_t)cb; 638 pReq->fFlags = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT; 639 rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */ 640 AssertReleaseRC(rc); 641 drvNATRxWakeup(pThis->pDrvIns, pThis->thrNATRx); 642 STAM_COUNTER_INC(&pThis->StatQueuePktSent); 643 #endif 644 } 645 646 647 #ifndef SLIRP_SPLIT_CAN_OUTPUT 654 648 /** 655 649 * Queue callback for processing a queued item. … … 668 662 Log(("drvNATQueueConsumer(pItem:%p, pu8Buf:%p, cb:%d)\n", pItem, pItem->pu8Buf, pItem->cb)); 669 663 Log2(("drvNATQueueConsumer: pu8Buf:\n%.Rhxd\n", pItem->pu8Buf)); 670 #ifndef SLIRP_SPLIT_CAN_OUTPUT671 664 if (RT_FAILURE(pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, 0))) 672 665 { … … 674 667 return false; 675 668 } 676 #else677 if (RT_FAILURE(pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, 0)))678 {679 drvNATRxWakeup(pThis->pDrvIns, pThis->thrNATRx);680 STAM_COUNTER_INC(&pThis->StatConsumerFalse);681 return false;682 }683 #endif684 669 rc = pThis->pPort->pfnReceive(pThis->pPort, pItem->pu8Buf, pItem->cb); 685 670 RTMemFree((void *)pItem->pu8Buf); … … 689 674 return RT_SUCCESS(rc); 690 675 } 676 #endif 691 677 692 678 … … 1008 994 } 1009 995 1010 rc = PDMDrvHlpPDMQueueCreate(pDrvIns, sizeof(DRVNATQUEUITEM), 50, 0, 996 997 #ifndef SLIRP_SPLIT_CAN_OUTPUT 998 rc = PDMDrvHlpPDMQueueCreate(pDrvIns, sizeof(DRVNATQUEUITEM), QUEUE_SIZE, 0, 1011 999 drvNATQueueConsumer, "NAT", &pThis->pSendQueue); 1012 1000 if (RT_FAILURE(rc)) … … 1015 1003 return rc; 1016 1004 } 1017 1018 rc = RTSemEventCreate(&pThis->semStatus); 1019 AssertRC(rc); 1020 #ifdef SLIRP_SPLIT_CAN_OUTPUT 1021 pThis->fCanOutput = false; 1005 #else 1006 rc = RTReqCreateQueue(&pThis->pGuestQueue); 1007 if (RT_FAILURE(rc)) 1008 { 1009 LogRel(("NAT: Can't create request queue\n")); 1010 return rc; 1011 } 1022 1012 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->thrNATRx, pThis, drvNATRx, 1023 1013 drvNATRxWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX");
Note:
See TracChangeset
for help on using the changeset viewer.