Changeset 23462 in vbox for trunk/src/VBox/Devices/Network/DrvNAT.cpp
- Timestamp:
- Oct 1, 2009 5:42:19 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvNAT.cpp
r23163 r23462 166 166 /** thread delivering packets for receiving by the guest */ 167 167 PPDMTHREAD pRecvThread; 168 /** thread delivering urg packets for receiving by the guest */ 169 PPDMTHREAD pUrgRecvThread; 168 170 /** event to wakeup the guest receive thread */ 169 171 RTSEMEVENT EventRecv; 172 /** event to wakeup the guest urgent receive thread */ 173 RTSEMEVENT EventUrgRecv; 170 174 /** Receive Req queue (deliver packets to the guest) */ 171 175 PRTREQQUEUE pRecvReqQueue; 176 /** Receive Urgent Req queue (deliver packets to the guest) */ 177 PRTREQQUEUE pUrgRecvReqQueue; 178 179 /* makes access to device func RecvAvail and Recv atomical */ 180 RTCRITSECT csDevAccess; 181 volatile uint32_t cUrgPkt; 182 volatile uint32_t cPkt; 183 PTMTIMERR3 pTmrSlow; 184 PTMTIMERR3 pTmrFast; 172 185 } DRVNAT; 173 186 AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8); … … 193 206 194 207 static void drvNATNotifyNATThread(PDRVNAT pThis); 208 static DECLCALLBACK(void) drvNATSlowTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser); 209 static DECLCALLBACK(void) drvNATFast(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser); 195 210 196 211 … … 198 213 #define PDMINETWORKCONNECTOR_2_DRVNAT(pInterface) ( (PDRVNAT)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAT, INetworkConnector)) ) 199 214 215 static DECLCALLBACK(void) drvNATSlowTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser) 216 { 217 Assert(pvUser); 218 PDRVNAT pThis = (PDRVNAT)pvUser; 219 drvNATNotifyNATThread(pThis); 220 } 221 222 static DECLCALLBACK(void) drvNATFastTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser) 223 { 224 Assert(pvUser); 225 PDRVNAT pThis = (PDRVNAT)pvUser; 226 drvNATNotifyNATThread(pThis); 227 } 200 228 201 229 202 230 static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 203 231 { 204 232 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 205 233 … … 210 238 { 211 239 RTReqProcess(pThis->pRecvReqQueue, 0); 212 RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT); 240 if (ASMAtomicReadU32(&pThis->cPkt) == 0) 241 RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT); 213 242 } 214 243 return VINF_SUCCESS; … … 226 255 } 227 256 228 229 static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb) 257 static DECLCALLBACK(int) drvNATUrgRecv(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 258 { 259 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 260 261 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING) 262 return VINF_SUCCESS; 263 264 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 265 { 266 RTReqProcess(pThis->pUrgRecvReqQueue, 0); 267 if (ASMAtomicReadU32(&pThis->cUrgPkt) == 0) 268 RTSemEventWait(pThis->EventUrgRecv, RT_INDEFINITE_WAIT); 269 } 270 return VINF_SUCCESS; 271 } 272 static DECLCALLBACK(int) drvNATUrgRecvWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread) 273 { 274 PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT); 275 int rc = RTSemEventSignal(pThis->EventUrgRecv); 276 277 AssertReleaseRC(rc); 278 return VINF_SUCCESS; 279 } 280 281 static DECLCALLBACK(void) drvNATUrgRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, void *pvArg) 282 { 283 int rc = RTCritSectEnter(&pThis->csDevAccess); 284 AssertReleaseRC(rc); 285 rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT); 286 if (RT_SUCCESS(rc)) 287 { 288 rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb); 289 rc = RTCritSectLeave(&pThis->csDevAccess); 290 AssertReleaseRC(rc); 291 slirp_ext_m_free(pThis->pNATState, pvArg); 292 } 293 else if ( RT_FAILURE(rc) 294 && ( rc == VERR_TIMEOUT 295 || rc == VERR_INTERRUPTED)) 296 { 297 rc = RTCritSectLeave(&pThis->csDevAccess); 298 slirp_ext_m_free(pThis->pNATState, pvArg); 299 } 300 else 301 { 302 rc = RTCritSectLeave(&pThis->csDevAccess); 303 slirp_ext_m_free(pThis->pNATState, pvArg); 304 AssertReleaseRC(rc); 305 } 306 if (ASMAtomicDecU32(&pThis->cUrgPkt) == 0) 307 { 308 drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread); 309 drvNATNotifyNATThread(pThis); 310 } 311 } 312 313 314 static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, void *pvArg) 230 315 { 231 316 STAM_PROFILE_START(&pThis->StatNATRecv, a); 232 317 233 318 STAM_PROFILE_START(&pThis->StatNATRecvWait, b); 234 int rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT); 235 AssertMsgRC(rc, ("NAT: No RX available even on indefinite wait; rc=%Rrc", rc)); 319 320 while(ASMAtomicReadU32(&pThis->cUrgPkt) != 0) 321 RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT); 322 323 int rc = RTCritSectEnter(&pThis->csDevAccess); 324 rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT); 325 if (RT_SUCCESS(rc)) 326 { 327 rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb); 328 AssertReleaseRC(rc); 329 rc = RTCritSectLeave(&pThis->csDevAccess); 330 AssertReleaseRC(rc); 331 slirp_ext_m_free(pThis->pNATState, pvArg); 332 } 333 else if ( RT_FAILURE(rc) 334 && ( rc == VERR_TIMEOUT 335 || rc == VERR_INTERRUPTED)) 336 { 337 rc = RTCritSectLeave(&pThis->csDevAccess); 338 AssertReleaseRC(rc); 339 slirp_ext_m_free(pThis->pNATState, pvArg); 340 } 341 else 342 { 343 rc = RTCritSectLeave(&pThis->csDevAccess); 344 slirp_ext_m_free(pThis->pNATState, pvArg); 345 AssertReleaseRC(rc); 346 } 347 ASMAtomicDecU32(&pThis->cPkt); 348 349 drvNATNotifyNATThread(pThis); 236 350 237 351 STAM_PROFILE_STOP(&pThis->StatNATRecvWait, b); 238 239 rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb);240 AssertRC(rc);241 RTMemFree(pu8Buf);242 243 352 STAM_PROFILE_STOP(&pThis->StatNATRecv, a); 244 353 } … … 248 357 * @thread "NAT" thread. 249 358 */ 250 static void drvNATSendWorker(PDRVNAT pThis, constvoid *pvBuf, size_t cb)359 static void drvNATSendWorker(PDRVNAT pThis, void *pvBuf, size_t cb) 251 360 { 252 361 Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP); 253 362 if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP) 254 slirp_input(pThis->pNATState, (uint8_t *)pvBuf, cb);363 slirp_input(pThis->pNATState, pvBuf); 255 364 } 256 365 … … 288 397 289 398 /* @todo: Here we should get mbuf instead temporal buffer */ 399 #if 0 290 400 buf = RTMemAlloc(cb); 291 401 if (buf == NULL) … … 295 405 } 296 406 memcpy(buf, pvBuf, cb); 407 #else 408 void *pvmBuf = slirp_ext_m_get(pThis->pNATState); 409 Assert(pvmBuf); 410 slirp_ext_m_append(pThis->pNATState, pvmBuf, (uint8_t *)pvBuf, cb); 411 #endif 297 412 298 413 pReq->u.Internal.pfn = (PFNRT)drvNATSendWorker; 299 pReq->u.Internal.cArgs = 3;414 pReq->u.Internal.cArgs = 2; 300 415 pReq->u.Internal.aArgs[0] = (uintptr_t)pThis; 301 pReq->u.Internal.aArgs[1] = (uintptr_t)buf; 302 pReq->u.Internal.aArgs[2] = (uintptr_t)cb; 416 pReq->u.Internal.aArgs[1] = (uintptr_t)pvmBuf; 303 417 pReq->fFlags = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT; 304 418 … … 459 573 /* don't pass the managemant pipe */ 460 574 slirp_select_fill(pThis->pNATState, &nFDs, &polls[1]); 575 #if 0 461 576 ms = slirp_get_timeout_ms(pThis->pNATState); 577 #else 578 ms = 0; 579 #endif 462 580 463 581 polls[0].fd = pThis->PipeRead; … … 509 627 #else /* RT_OS_WINDOWS */ 510 628 slirp_select_fill(pThis->pNATState, &nFDs); 629 #if 0 511 630 ms = slirp_get_timeout_ms(pThis->pNATState); 631 #else 632 ms = 0; 633 #endif 512 634 struct timeval tv = { 0, ms*1000 }; 513 635 event = WSAWaitForMultipleEvents(nFDs, phEvents, FALSE, ms ? ms : WSA_INFINITE, FALSE); … … 585 707 #endif /* VBOX_WITH_SLIRP_MT */ 586 708 709 void slirp_arm_fast_timer(void *pvUser) 710 { 711 PDRVNAT pThis = (PDRVNAT)pvUser; 712 Assert(pThis); 713 TMTimerSetMillies(pThis->pTmrFast, 2); 714 } 715 716 void slirp_arm_slow_timer(void *pvUser) 717 { 718 PDRVNAT pThis = (PDRVNAT)pvUser; 719 Assert(pThis); 720 TMTimerSetMillies(pThis->pTmrSlow, 500); 721 } 587 722 588 723 /** … … 596 731 } 597 732 598 /** 599 * Function called by slirp to feed incoming data to the network port. 600 */ 601 void slirp_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb) 733 void slirp_push_recv_thread(void *pvUser) 602 734 { 603 735 PDRVNAT pThis = (PDRVNAT)pvUser; 604 736 Assert(pThis); 605 606 LogFlow(("slirp_output BEGIN %x %d\n", pu8Buf, cb)); 607 Log2(("slirp_output: pu8Buf=%p cb=%#x (pThis=%p)\n%.*Rhxd\n", pu8Buf, cb, pThis, cb, pu8Buf)); 737 drvNATUrgRecvWakeup(pThis->pDrvIns, pThis->pUrgRecvThread); 738 } 739 740 void slirp_urg_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb) 741 { 742 PDRVNAT pThis = (PDRVNAT)pvUser; 743 Assert(pThis); 744 ASMAtomicIncU32(&pThis->cUrgPkt); 608 745 609 746 PRTREQ pReq = NULL; … … 613 750 return; 614 751 615 int rc = RTReqAlloc(pThis->p RecvReqQueue, &pReq, RTREQTYPE_INTERNAL);752 int rc = RTReqAlloc(pThis->pUrgRecvReqQueue, &pReq, RTREQTYPE_INTERNAL); 616 753 AssertReleaseRC(rc); 617 pReq->u.Internal.pfn = (PFNRT)drvNAT RecvWorker;618 pReq->u.Internal.cArgs = 3;754 pReq->u.Internal.pfn = (PFNRT)drvNATUrgRecvWorker; 755 pReq->u.Internal.cArgs = 4; 619 756 pReq->u.Internal.aArgs[0] = (uintptr_t)pThis; 620 757 pReq->u.Internal.aArgs[1] = (uintptr_t)pu8Buf; 621 758 pReq->u.Internal.aArgs[2] = (uintptr_t)cb; 759 pReq->u.Internal.aArgs[3] = (uintptr_t)pvArg; 760 pReq->fFlags = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT; 761 rc = RTReqQueue(pReq, 0); 762 AssertReleaseRC(rc); 763 drvNATUrgRecvWakeup(pThis->pDrvIns, pThis->pUrgRecvThread); 764 } 765 766 /** 767 * Function called by slirp to feed incoming data to the network port. 768 */ 769 void slirp_output(void *pvUser, void *pvArg, const uint8_t *pu8Buf, int cb) 770 { 771 PDRVNAT pThis = (PDRVNAT)pvUser; 772 Assert(pThis); 773 774 LogFlow(("slirp_output BEGIN %x %d\n", pu8Buf, cb)); 775 Log2(("slirp_output: pu8Buf=%p cb=%#x (pThis=%p)\n%.*Rhxd\n", pu8Buf, cb, pThis, cb, pu8Buf)); 776 777 PRTREQ pReq = NULL; 778 779 /* don't queue new requests when the NAT thread is about to stop */ 780 if (pThis->pSlirpThread->enmState != PDMTHREADSTATE_RUNNING) 781 return; 782 783 int rc = RTReqAlloc(pThis->pRecvReqQueue, &pReq, RTREQTYPE_INTERNAL); 784 AssertReleaseRC(rc); 785 ASMAtomicIncU32(&pThis->cPkt); 786 pReq->u.Internal.pfn = (PFNRT)drvNATRecvWorker; 787 pReq->u.Internal.cArgs = 4; 788 pReq->u.Internal.aArgs[0] = (uintptr_t)pThis; 789 pReq->u.Internal.aArgs[1] = (uintptr_t)pu8Buf; 790 pReq->u.Internal.aArgs[2] = (uintptr_t)cb; 791 pReq->u.Internal.aArgs[3] = (uintptr_t)pvArg; 622 792 pReq->fFlags = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT; 623 793 rc = RTReqQueue(pReq, 0); … … 951 1121 return rc; 952 1122 } 1123 rc = RTReqCreateQueue(&pThis->pUrgRecvReqQueue); 1124 if (RT_FAILURE(rc)) 1125 { 1126 LogRel(("NAT: Can't create request queue\n")); 1127 return rc; 1128 } 953 1129 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvNATRecv, 954 1130 drvNATRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX"); 955 1131 AssertReleaseRC(rc); 956 1132 rc = RTSemEventCreate(&pThis->EventRecv); 1133 1134 rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pUrgRecvThread, pThis, drvNATUrgRecv, 1135 drvNATUrgRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATURGRX"); 1136 AssertReleaseRC(rc); 1137 rc = RTSemEventCreate(&pThis->EventRecv); 1138 rc = RTSemEventCreate(&pThis->EventUrgRecv); 1139 rc = RTCritSectInit(&pThis->csDevAccess); 1140 rc = PDMDrvHlpTMTimerCreate(pThis->pDrvIns, TMCLOCK_REAL/*enmClock*/, drvNATSlowTimer, 1141 pThis, TMTIMER_FLAGS_NO_CRIT_SECT/*flags*/, "NATSlowTmr", &pThis->pTmrSlow); 1142 rc = PDMDrvHlpTMTimerCreate(pThis->pDrvIns, TMCLOCK_REAL/*enmClock*/, drvNATFastTimer, 1143 pThis, TMTIMER_FLAGS_NO_CRIT_SECT/*flags*/, "NATFastTmr", &pThis->pTmrFast); 957 1144 958 1145 #ifndef RT_OS_WINDOWS
Note:
See TracChangeset
for help on using the changeset viewer.