VirtualBox

Ignore:
Timestamp:
Oct 1, 2009 5:42:19 AM (15 years ago)
Author:
vboxsync
Message:

NAT: Big changeset:

  1. mbuf_zone has been inroduced.
  2. IPRT timers replaces Slirp's one making poll/WSAWaitForMultipleEvents blocking.
  3. UrgRecv(Thread,Req) introduced for transfering ICMP errors/ARP with highter priority.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DrvNAT.cpp

    r23163 r23462  
    166166    /** thread delivering packets for receiving by the guest */
    167167    PPDMTHREAD              pRecvThread;
     168    /** thread delivering urg packets for receiving by the guest */
     169    PPDMTHREAD              pUrgRecvThread;
    168170    /** event to wakeup the guest receive thread */
    169171    RTSEMEVENT              EventRecv;
     172    /** event to wakeup the guest urgent receive thread */
     173    RTSEMEVENT              EventUrgRecv;
    170174    /** Receive Req queue (deliver packets to the guest) */
    171175    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;
    172185} DRVNAT;
    173186AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8);
     
    193206
    194207static void drvNATNotifyNATThread(PDRVNAT pThis);
     208static DECLCALLBACK(void) drvNATSlowTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser);
     209static DECLCALLBACK(void) drvNATFast(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser);
    195210
    196211
     
    198213#define PDMINETWORKCONNECTOR_2_DRVNAT(pInterface)   ( (PDRVNAT)((uintptr_t)pInterface - RT_OFFSETOF(DRVNAT, INetworkConnector)) )
    199214
     215static DECLCALLBACK(void) drvNATSlowTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser)
     216{
     217    Assert(pvUser);
     218    PDRVNAT pThis = (PDRVNAT)pvUser;
     219    drvNATNotifyNATThread(pThis);
     220}
     221
     222static DECLCALLBACK(void) drvNATFastTimer(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser)
     223{
     224    Assert(pvUser);
     225    PDRVNAT pThis = (PDRVNAT)pvUser;
     226    drvNATNotifyNATThread(pThis);
     227}
    200228
    201229
    202230static DECLCALLBACK(int) drvNATRecv(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    203  {
     231{
    204232    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    205233
     
    210238    {
    211239        RTReqProcess(pThis->pRecvReqQueue, 0);
    212         RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
     240        if (ASMAtomicReadU32(&pThis->cPkt) == 0)
     241            RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
    213242    }
    214243    return VINF_SUCCESS;
     
    226255}
    227256
    228 
    229 static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb)
     257static 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}
     272static 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
     281static 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
     314static DECLCALLBACK(void) drvNATRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, void *pvArg)
    230315{
    231316    STAM_PROFILE_START(&pThis->StatNATRecv, a);
    232317
    233318    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);
    236350
    237351    STAM_PROFILE_STOP(&pThis->StatNATRecvWait, b);
    238 
    239     rc = pThis->pPort->pfnReceive(pThis->pPort, pu8Buf, cb);
    240     AssertRC(rc);
    241     RTMemFree(pu8Buf);
    242 
    243352    STAM_PROFILE_STOP(&pThis->StatNATRecv, a);
    244353}
     
    248357 * @thread "NAT" thread.
    249358 */
    250 static void drvNATSendWorker(PDRVNAT pThis, const void *pvBuf, size_t cb)
     359static void drvNATSendWorker(PDRVNAT pThis, void *pvBuf, size_t cb)
    251360{
    252361    Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP);
    253362    if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP)
    254         slirp_input(pThis->pNATState, (uint8_t *)pvBuf, cb);
     363        slirp_input(pThis->pNATState, pvBuf);
    255364}
    256365
     
    288397
    289398    /* @todo: Here we should get mbuf instead temporal buffer */
     399#if 0
    290400    buf = RTMemAlloc(cb);
    291401    if (buf == NULL)
     
    295405    }
    296406    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
    297412
    298413    pReq->u.Internal.pfn      = (PFNRT)drvNATSendWorker;
    299     pReq->u.Internal.cArgs    = 3;
     414    pReq->u.Internal.cArgs    = 2;
    300415    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;
    303417    pReq->fFlags              = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT;
    304418
     
    459573        /* don't pass the managemant pipe */
    460574        slirp_select_fill(pThis->pNATState, &nFDs, &polls[1]);
     575#if 0
    461576        ms = slirp_get_timeout_ms(pThis->pNATState);
     577#else
     578        ms = 0;
     579#endif
    462580
    463581        polls[0].fd = pThis->PipeRead;
     
    509627#else /* RT_OS_WINDOWS */
    510628        slirp_select_fill(pThis->pNATState, &nFDs);
     629#if 0
    511630        ms = slirp_get_timeout_ms(pThis->pNATState);
     631#else
     632        ms = 0;
     633#endif
    512634        struct timeval tv = { 0, ms*1000 };
    513635        event = WSAWaitForMultipleEvents(nFDs, phEvents, FALSE, ms ? ms : WSA_INFINITE, FALSE);
     
    585707#endif /* VBOX_WITH_SLIRP_MT */
    586708
     709void slirp_arm_fast_timer(void *pvUser)
     710{
     711    PDRVNAT pThis = (PDRVNAT)pvUser;
     712    Assert(pThis);
     713    TMTimerSetMillies(pThis->pTmrFast, 2);
     714}
     715
     716void slirp_arm_slow_timer(void *pvUser)
     717{
     718    PDRVNAT pThis = (PDRVNAT)pvUser;
     719    Assert(pThis);
     720    TMTimerSetMillies(pThis->pTmrSlow, 500);
     721}
    587722
    588723/**
     
    596731}
    597732
    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)
     733void slirp_push_recv_thread(void *pvUser)
    602734{
    603735    PDRVNAT pThis = (PDRVNAT)pvUser;
    604736    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
     740void 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);
    608745
    609746    PRTREQ pReq = NULL;
     
    613750        return;
    614751
    615     int rc = RTReqAlloc(pThis->pRecvReqQueue, &pReq, RTREQTYPE_INTERNAL);
     752    int rc = RTReqAlloc(pThis->pUrgRecvReqQueue, &pReq, RTREQTYPE_INTERNAL);
    616753    AssertReleaseRC(rc);
    617     pReq->u.Internal.pfn      = (PFNRT)drvNATRecvWorker;
    618     pReq->u.Internal.cArgs    = 3;
     754    pReq->u.Internal.pfn      = (PFNRT)drvNATUrgRecvWorker;
     755    pReq->u.Internal.cArgs    = 4;
    619756    pReq->u.Internal.aArgs[0] = (uintptr_t)pThis;
    620757    pReq->u.Internal.aArgs[1] = (uintptr_t)pu8Buf;
    621758    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 */
     769void 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;
    622792    pReq->fFlags              = RTREQFLAGS_VOID|RTREQFLAGS_NO_WAIT;
    623793    rc = RTReqQueue(pReq, 0);
     
    9511121                return rc;
    9521122            }
     1123            rc = RTReqCreateQueue(&pThis->pUrgRecvReqQueue);
     1124            if (RT_FAILURE(rc))
     1125            {
     1126                LogRel(("NAT: Can't create request queue\n"));
     1127                return rc;
     1128            }
    9531129            rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvNATRecv,
    9541130                                          drvNATRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX");
    9551131            AssertReleaseRC(rc);
    9561132            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);
    9571144
    9581145#ifndef RT_OS_WINDOWS
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette