VirtualBox

Changeset 13986 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Nov 9, 2008 8:49:02 PM (16 years ago)
Author:
vboxsync
Message:

NAT: simplified synchronization

File:
1 edited

Legend:

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

    r13984 r13986  
    2828#define __STDC_LIMIT_MACROS
    2929#define __STDC_CONSTANT_MACROS
    30 #ifndef VBOX_NAT_SOURCES
    3130#include "Network/slirp/libslirp.h"
    32 #else
    33 #include <sys/types.h>
    34 #include <sys/socket.h>
    35 
    36 #include <netinet/in.h>
    37 
    38 #include <errno.h>
    39 
    40 #include <unistd.h>
    41 
    42 #include <fcntl.h>
    43 
    44 #include <string.h>
    45 
    46 #endif
    4731#include <VBox/pdmdrv.h>
    4832#include <iprt/assert.h>
     
    5135#include <iprt/critsect.h>
    5236#include <iprt/cidr.h>
     37#include <iprt/stream.h>
    5338
    5439#include "Builtins.h"
    5540
    56 #ifdef VBOX_NAT_SOURCES
    57 #include "Network/nat/nat.h"
    58 #endif
    5941#ifdef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC
    60 #include <unistd.h>
    61 #include <errno.h>
    62 #include<iprt/semaphore.h>
     42# include <unistd.h>
     43# include <errno.h>
     44# include<iprt/semaphore.h>
    6345#endif
    6446
     
    8769    PDMNETWORKLINKSTATE     enmLinkState;
    8870    /** NAT state for this instance. */
    89 #ifndef VBOX_NAT_SOURCES
    9071    PNATState               pNATState;
    91 #endif
    9272    /** TFTP directory prefix. */
    9373    char                    *pszTFTPPrefix;
     
    9878    PPDMTHREAD              pThread;
    9979    /*used for wakep of poling thread*/
    100     RTSEMEVENT               semIOmutex;
    101     RTSEMEVENT           semSndMutex;
     80    RTSEMEVENT              semSndMutex;
    10281#ifndef RT_OS_WINDOWS
    10382    /** The write end of the control pipe. */
     
    10786#else
    10887#endif
    109     char                   cBuffer[1600];
     88    /** Send buffer */
     89    char                    cBuffer[1600];
    11090    size_t                  sBufferSize;
    11191#endif
     
    11696
    11797
    118 /*******************************************************************************
    119 *   Global Variables                                                           *
    120 *******************************************************************************/
    121 #if 0
    122 /** If set the thread should terminate. */
    123 static bool             g_fThreadTerm = false;
    124 /** The thread id of the select thread (drvNATSelectThread()). */
    125 static RTTHREAD         g_ThreadSelect;
    126 #endif
    127 
    128 
    129 /*******************************************************************************
    130 *   Internal Functions                                                         *
    131 *******************************************************************************/
    132 
    133 
    134 #ifdef VBOX_NAT_SOURCES
    135 /*
    136  * Sends data to guest called from NAT glue code
    137  */
    138 static DECLCALLBACK(void) drvNATOutput(const void * data, const uint8_t *msg, int size)
    139 {
    140         PDRVNAT pThis = (PDRVNAT)(void *)data;
    141         LogFlow(("output: pvBuf=%p cb=%#x\n", msg, size));
    142         int rc =  pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, 0);
    143         if (RT_SUCCESS(rc))
    144                 pThis->pPort->pfnReceive(pThis->pPort, msg, size);
    145         LogFlow(("output: exit\n"));
    146 }
    147 
    148 #endif
    14998
    15099/**
     
    162111
    163112    LogFlow(("drvNATSend: pvBuf=%p cb=%#x\n", pvBuf, cb));
    164     Log2(("drvNATSend: pvBuf=%p cb=%#x\n"
    165           "%.*Vhxd\n",
    166           pvBuf, cb, cb, pvBuf));
     113    Log2(("drvNATSend: pvBuf=%p cb=%#x\n%.*Rhxd\n", pvBuf, cb, cb, pvBuf));
    167114
    168115#ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC
     
    173120    memcpy(pThis->cBuffer,pvBuf, cb);
    174121    pThis->sBufferSize = cb;
    175     int rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL);
     122    int rc = RTFileWrite(pThis->PipeWrite, "1", 2, NULL);
    176123    AssertRC(rc);
    177124    RTSemEventWait(pThis->semSndMutex, RT_INDEFINITE_WAIT);
     
    181128    Assert(pThis->enmLinkState == PDMNETWORKLINKSTATE_UP);
    182129    if (pThis->enmLinkState == PDMNETWORKLINKSTATE_UP) {
    183 #ifndef VBOX_NAT_SOURCES
    184130        slirp_input(pThis->pNATState, (uint8_t *)pvBuf, cb);
    185 #else
    186         ether_chk(pThis, pvBuf, cb);
    187 #endif
    188131    }
    189132    RTCritSectLeave(&pThis->CritSect);
     
    234177        case PDMNETWORKLINKSTATE_UP:
    235178            LogRel(("NAT: link up\n"));
    236 #ifndef VBOX_NAT_SOURCES
    237179            slirp_link_up(pThis->pNATState);
    238 #endif
    239180            break;
    240181
     
    242183        case PDMNETWORKLINKSTATE_DOWN_RESUME:
    243184            LogRel(("NAT: link down\n"));
    244 #ifndef VBOX_NAT_SOURCES
    245185            slirp_link_down(pThis->pNATState);
    246 #endif
    247186            break;
    248187
     
    274213    AssertReleaseRC(rc);
    275214
    276 #ifndef VBOX_NAT_SOURCES
    277215    slirp_select_fill(pThis->pNATState, &cFDs, &ReadFDs, &WriteFDs, &XcptFDs);
    278 #else
    279     nat_select_fill(NULL, &cFDs, &ReadFDs, &WriteFDs, &XcptFDs);
    280 #endif
    281216
    282217    struct timeval tv = {0, 0}; /* no wait */
    283218    int cReadFDs = select(cFDs + 1, &ReadFDs, &WriteFDs, &XcptFDs, &tv);
    284 #ifndef VBOX_NAT_SOURCES
    285219    if (cReadFDs >= 0)
    286220        slirp_select_poll(pThis->pNATState, &ReadFDs, &WriteFDs, &XcptFDs);
    287 #else
    288     if (cReadFDs >= 0) {
    289         nat_select_poll(pThis, &ReadFDs, &WriteFDs, &XcptFDs);
    290     }
    291 #endif
    292221
    293222    RTCritSectLeave(&pThis->CritSect);
     
    306235    LogFlow(("drvNATAsyncIoThread: pThis=%p\n", pThis));
    307236
    308 
    309237    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
    310238        return VINF_SUCCESS;
     239
    311240    /*
    312241     * Polling loop.
     
    324253        slirp_select_fill(pThis->pNATState, &cFDs, &ReadFDs, &WriteFDs, &XcptFDs);
    325254
    326         struct timeval tv = {0, 200}; /* 2 millis wait */
    327 
    328         FD_SET(pThis->PipeRead, &ReadFDs); /*Linux only*/
    329         cFDs = (pThis->PipeRead < cFDs ? cFDs:pThis->PipeRead);
     255        struct timeval tv = {0, 2000}; /* 2ms for the fast timer */
     256
     257        FD_SET(pThis->PipeRead, &ReadFDs); /* Linux only */
     258        cFDs = ((int)pThis->PipeRead < cFDs ? cFDs:pThis->PipeRead);
    330259        int cReadFDs = select(cFDs + 1, &ReadFDs, &WriteFDs, &XcptFDs, &tv);
    331 
    332         if (cReadFDs >= 0) {
     260        if (cReadFDs >= 0)
     261        {
    333262            slirp_select_poll(pThis->pNATState, &ReadFDs, &WriteFDs, &XcptFDs);
    334263
    335             if (FD_ISSET(pThis->PipeRead, &ReadFDs)) {
     264            if (FD_ISSET(pThis->PipeRead, &ReadFDs))
     265            {
    336266                /* drain the pipe */
    337                 char ch;
     267                char ch[2];
    338268                size_t cbRead;
    339                 RTFileRead(pThis->PipeRead, &ch, 1, &cbRead);
    340                 slirp_input(pThis->pNATState, (uint8_t *)pThis->cBuffer, pThis->sBufferSize);
    341                 RTSemEventSignal(pThis->semSndMutex);
     269                RTFileRead(pThis->PipeRead, &ch, 2, &cbRead);
     270                switch (ch[0])
     271                {
     272                    case '1':
     273                        slirp_input(pThis->pNATState, (uint8_t *)pThis->cBuffer, pThis->sBufferSize);
     274                        RTSemEventSignal(pThis->semSndMutex);
     275                        break;
     276                    case '2':
     277                        break;
     278                }
    342279            }
    343280        }
    344 #if 0
    345         if (cReadFDs == 0) {
    346             rc = RTSemEventWait(pThis->semIOmutex, RT_INDEFINITE_WAIT);
    347             AssertReleaseRC(rc);
    348         }
    349 #endif
    350281    }
    351282
     
    362293static DECLCALLBACK(int) drvNATAsyncIoWakeup(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    363294{
    364 #if 0
    365295    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    366     int rc = RTSemEventSignal(pThis->semIOmutex);
    367     AssertReleaseRC(rc);
    368 #endif
    369     return (VINF_SUCCESS);
    370 }
    371 
    372 #endif
    373 
    374 #ifndef VBOX_NAT_SOURCES
     296
     297    int rc = RTFileWrite(pThis->PipeWrite, "2", 2, NULL);
     298    AssertRC(rc);
     299    RTSemEventSignal(pThis->semSndMutex);
     300    return VINF_SUCCESS;
     301}
     302
     303#endif
     304
    375305/**
    376306 * Function called by slirp to check if it's possible to feed incoming data to the network port.
     
    403333
    404334    LogFlow(("slirp_output BEGIN %x %d\n", pu8Buf, cb));
    405     Log2(("slirp_output: pu8Buf=%p cb=%#x (pThis=%p)\n"
    406           "%.*Vhxd\n",
    407           pu8Buf, cb, pThis,
    408           cb, pu8Buf));
     335    Log2(("slirp_output: pu8Buf=%p cb=%#x (pThis=%p)\n%.*Rhxd\n", pu8Buf, cb, pThis, cb, pu8Buf));
    409336
    410337    Assert(pThis);
     
    420347    LogFlow(("slirp_output END %x %d\n", pu8Buf, cb));
    421348}
    422 #endif
    423349
    424350/**
     
    465391    AssertReleaseRC(rc);
    466392#endif
    467 #ifndef VBOX_NAT_SOURCES
    468393    slirp_term(pThis->pNATState);
    469394    pThis->pNATState = NULL;
    470 #endif
    471395#ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC
    472396    RTCritSectLeave(&pThis->CritSect);
     
    487411static int drvNATConstructRedir(unsigned iInstance, PDRVNAT pThis, PCFGMNODE pCfgHandle, RTIPV4ADDR Network)
    488412{
    489 #ifndef VBOX_NAT_SOURCES
    490413    /*
    491414     * Enumerate redirections.
     
    545468        struct in_addr GuestIP;
    546469        if (!inet_aton(szGuestIP, &GuestIP))
    547             return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_GUEST_IP, RT_SRC_POS, N_("NAT#%d: configuration error: invalid \"GuestIP\"=\"%s\", inet_aton failed"), iInstance, szGuestIP);
     470            return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_GUEST_IP, RT_SRC_POS,
     471                                       N_("NAT#%d: configuration error: invalid \"GuestIP\"=\"%s\", inet_aton failed"), iInstance, szGuestIP);
    548472
    549473        /*
     
    552476        Log(("drvNATConstruct: Redir %d -> %s:%d\n", iHostPort, szGuestIP, iGuestPort));
    553477        if (slirp_redir(pThis->pNATState, fUDP, iHostPort, GuestIP, iGuestPort) < 0)
    554             return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_SETUP, RT_SRC_POS, N_("NAT#%d: configuration error: failed to set up redirection of %d to %s:%d. Probably a conflict with existing services or other rules"), iInstance, iHostPort, szGuestIP, iGuestPort);
     478            return PDMDrvHlpVMSetError(pThis->pDrvIns, VERR_NAT_REDIR_SETUP, RT_SRC_POS,
     479                                       N_("NAT#%d: configuration error: failed to set up redirection of %d to %s:%d. Probably a conflict with existing services or other rules"), iInstance, iHostPort, szGuestIP, iGuestPort);
    555480    } /* for each redir rule */
    556 #endif
    557481
    558482    return VINF_SUCCESS;
     
    564488static void drvNATSetMac(PDRVNAT pThis)
    565489{
    566 #ifndef VBOX_NAT_SOURCES
    567490    if (pThis->pConfig)
    568491    {
     
    571494        slirp_set_ethaddr(pThis->pNATState, Mac.au8);
    572495    }
    573 #endif
    574496}
    575497
     
    625547     */
    626548    pThis->pDrvIns                      = pDrvIns;
    627 #ifndef VBOX_NAT_SOURCES
    628549    pThis->pNATState                    = NULL;
    629 #endif
    630550    pThis->pszTFTPPrefix                = NULL;
    631551    pThis->pszBootFile                  = NULL;
     
    690610        return rc;
    691611#endif
    692 #if 0
    693     rc = RTSemEventCreate(&g_EventSem);
     612    /*
     613     * Initialize slirp.
     614     */
     615    rc = slirp_init(&pThis->pNATState, &szNetAddr[0], Netmask, fPassDomain, pThis->pszTFTPPrefix, pThis->pszBootFile, pThis);
    694616    if (RT_SUCCESS(rc))
    695617    {
    696         /*
    697          * Start the select thread. (it'll block on the sem)
    698          */
    699         g_fThreadTerm = false;
    700         rc = RTThreadCreate(&g_ThreadSelect, drvNATSelectThread, 0, NULL, "NATSEL");
    701         if (RT_SUCCESS(rc))
     618        int rc2 = drvNATConstructRedir(pDrvIns->iInstance, pThis, pCfgHandle, Network);
     619        if (RT_SUCCESS(rc2))
    702620        {
    703 #endif
    704 #ifndef VBOX_NAT_SOURCES
    705621            /*
    706              * Initialize slirp.
     622             * Register a load done notification to get the MAC address into the slirp
     623             * engine after we loaded a guest state.
    707624             */
    708             rc = slirp_init(&pThis->pNATState, &szNetAddr[0], Netmask, fPassDomain, pThis->pszTFTPPrefix, pThis->pszBootFile, pThis);
    709             if (RT_SUCCESS(rc))
     625            rc2 = PDMDrvHlpSSMRegister(pDrvIns, pDrvIns->pDrvReg->szDriverName,
     626                                       pDrvIns->iInstance, 0, 0,
     627                                       NULL, NULL, NULL, NULL, NULL, drvNATLoadDone);
     628            AssertRC(rc2);
     629#ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC
     630            pDrvIns->pDrvHlp->pfnPDMPollerRegister(pDrvIns, drvNATPoller);
     631#else
     632            rc = RTSemEventCreate(&pThis->semSndMutex);
     633            AssertReleaseRC(rc);
     634
     635            /*
     636             * Create the control pipe.
     637             * XXX: Linux only
     638             */
     639            int fds[2];
     640            if (pipe(&fds[0]) != 0) /** @todo RTPipeCreate() or something... */
    710641            {
    711                 int rc2 = drvNATConstructRedir(pDrvIns->iInstance, pThis, pCfgHandle, Network);
    712                 if (RT_SUCCESS(rc2))
    713                 {
    714                     /*
    715                      * Register a load done notification to get the MAC address into the slirp
    716                      * engine after we loaded a guest state.
    717                      */
    718                     rc2 = PDMDrvHlpSSMRegister(pDrvIns, pDrvIns->pDrvReg->szDriverName,
    719                                                pDrvIns->iInstance, 0, 0,
    720                                                NULL, NULL, NULL, NULL, NULL, drvNATLoadDone);
    721                     AssertRC(rc2);
    722 #ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC
    723                     pDrvIns->pDrvHlp->pfnPDMPollerRegister(pDrvIns, drvNATPoller);
    724 #else
    725 
    726                     rc = RTSemEventCreate(&pThis->semIOmutex);
    727                     AssertReleaseRC(rc);
    728                     rc = RTSemEventCreate(&pThis->semSndMutex);
    729                     AssertReleaseRC(rc);
    730 
    731                     /*
    732                      * Create the control pipe.
    733                      * XXX: Linux only
    734                      */
    735                     int fds[2];
    736                     if (pipe(&fds[0]) != 0) /** @todo RTPipeCreate() or something... */
    737                     {
    738                         int rc = RTErrConvertFromErrno(errno);
    739                         AssertRC(rc);
    740                         return rc;
    741                     }
    742                     pThis->PipeRead = fds[0];
    743                     pThis->PipeWrite = fds[1];
    744 
    745                     rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvNATAsyncIoThread, drvNATAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "NAT");
    746                     AssertReleaseRC(rc);
    747 #endif
    748 
    749                     pThis->enmLinkState = PDMNETWORKLINKSTATE_UP;
    750 #if 0
    751                     RTSemEventSignal(g_EventSem);
    752                     RTThreadSleep(0);
    753 #endif
    754                     /* might return VINF_NAT_DNS */
    755                     return rc;
    756                 }
    757                 /* failure path */
    758                 rc = rc2;
    759                 slirp_term(pThis->pNATState);
    760                 pThis->pNATState = NULL;
     642                int rc = RTErrConvertFromErrno(errno);
     643                AssertRC(rc);
     644                return rc;
    761645            }
    762             else
    763             {
    764               PDMDRV_SET_ERROR(pDrvIns, rc, N_("Unknown error during NAT networking setup: "));
    765               AssertMsgFailed(("Add error message for rc=%d (%Rrc)\n", rc, rc));
    766             }
    767 #else
    768         pDrvIns->pDrvHlp->pfnPDMPollerRegister(pDrvIns, drvNATPoller);
    769         pThis->enmLinkState = PDMNETWORKLINKSTATE_UP;
    770         struct nat_output_callbacks cb;
    771         cb.noc_guest_out = drvNATOutput;
    772         nat_init(&cb, pDrvIns);
    773 #endif
    774 #if 0
    775             g_fThreadTerm = true;
    776             RTSemEventSignal(g_EventSem);
    777             RTThreadSleep(0);
     646            pThis->PipeRead = fds[0];
     647            pThis->PipeWrite = fds[1];
     648
     649            rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvNATAsyncIoThread, drvNATAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "NAT");
     650            AssertReleaseRC(rc);
     651#endif
     652
     653            pThis->enmLinkState = PDMNETWORKLINKSTATE_UP;
     654
     655            /* might return VINF_NAT_DNS */
     656            return rc;
    778657        }
    779         RTSemEventDestroy(g_EventSem);
    780         g_EventSem = NULL;
     658        /* failure path */
     659        rc = rc2;
     660        slirp_term(pThis->pNATState);
     661        pThis->pNATState = NULL;
    781662    }
    782 #endif
     663    else
     664    {
     665        PDMDRV_SET_ERROR(pDrvIns, rc, N_("Unknown error during NAT networking setup: "));
     666        AssertMsgFailed(("Add error message for rc=%d (%Rrc)\n", rc, rc));
     667    }
     668
    783669#ifndef VBOX_WITH_SIMPLEFIED_SLIRP_SYNC
    784670    RTCritSectDelete(&pThis->CritSect);
     
    786672    return rc;
    787673}
    788 
    789 
    790674
    791675
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