VirtualBox

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


Ignore:
Timestamp:
Sep 10, 2007 1:38:09 AM (17 years ago)
Author:
vboxsync
Message:

Compilable TAP driver for OS/2.

File:
1 edited

Legend:

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

    r4372 r4642  
    3232#include "Builtins.h"
    3333
     34#define INCL_BASE
     35#include <os2.h>
     36#include "DrvTAPOs2.h"
     37
    3438
    3539
     
    5054    PPDMDRVINS              pDrvIns;
    5155    /** TAP device file handle. */
    52     RTFILE                  FileDevice;
     56    RTFILE                  hDevice;
     57    /** Out LAN number. */
     58    int32_t                 iLan;
     59    /** The LAN number we're connected to. -1 if not connected. */
     60    int32_t                 iConnectedTo;
    5361    /** Receiver thread. */
    5462    PPDMTHREAD              pThread;
    55     /** We are waiting for more receive buffers. */
    56     uint32_t volatile       fOutOfSpace;
    5763    /** Event semaphore for blocking on receive. */
    5864    RTSEMEVENT              EventOutOfSpace;
     65    /** We are checking or waiting for more receive buffers. */
     66    bool volatile           fMaybeOutOfSpace;
     67    /** Set if the link is down.
     68     * When the link is down all incoming packets will be dropped. */
     69    bool volatile           fLinkDown;
     70    /** The log and thread name. */
     71    char                    szName[16];
     72    /** The \DEV\TAP$ device name. */
     73    char                    szDevice[32];
    5974
    6075#ifdef VBOX_WITH_STATISTICS
     
    98113static DECLCALLBACK(int) drvTAPOs2Send(PPDMINETWORKCONNECTOR pInterface, const void *pvBuf, size_t cb)
    99114{
    100     PDRVTAPOS2 pData = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
    101     STAM_COUNTER_INC(&pData->StatPktSent);
    102     STAM_COUNTER_ADD(&pData->StatPktSentBytes, cb);
    103     STAM_PROFILE_START(&pData->StatTransmit, a);
     115    PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
     116    STAM_COUNTER_INC(&pThis->StatPktSent);
     117    STAM_COUNTER_ADD(&pThis->StatPktSentBytes, cb);
     118    STAM_PROFILE_START(&pThis->StatTransmit, a);
    104119
    105120#ifdef LOG_ENABLED
    106121    uint64_t u64Now = RTTimeProgramNanoTS();
    107     LogFlow(("drvTAPOs2Send: %-4d bytes at %llu ns  deltas: r=%llu t=%llu\n",
    108              cb, u64Now, u64Now - pData->u64LastReceiveTS, u64Now - pData->u64LastTransferTS));
    109     pData->u64LastTransferTS = u64Now;
     122    LogFlow(("%s: Send: %-4d bytes at %RU64 ns  deltas: recv=%RU64 xmit=%RU64\n", pThis->szName,
     123             cb, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS));
     124    pThis->u64LastTransferTS = u64Now;
    110125#endif
    111     Log2(("drvTAPOs2Send: pvBuf=%p cb=%#x\n"
     126    Log2(("%s Send: pvBuf=%p cb=%#zx\n"
    112127          "%.*Vhxd\n",
    113           pvBuf, cb, cb, pvBuf));
    114 
    115     ULONG UnusedParms[10] = { 0,0,0,0, 0,0,0,0, 0,0 };
    116     ULONG cbParms = sizeof(UnusedParms);
     128          pThis->szName, pvBuf, cb, cb, pvBuf));
     129
     130    ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
     131    ULONG cbParm = sizeof(Parm);
    117132    ULONG cbData = cb;
    118     int rc = DosDevIOCtl(pData->FileDevice, PROT_CATEGORY, TAP_WRITE_PACKET,
    119                          &UnusedParms[0], cbParms, &cbParms,
    120                          pvBuf, cbData, &cbData);
    121     if (rc)
    122         rc = RTErrConvertFromOS2(rc);
    123 
    124     STAM_PROFILE_STOP(&pData->StatTransmit, a);
     133    int rc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_WRITE_PACKET,
     134                         &Parm[0], cbParm, &cbParm,
     135                         (void *)pvBuf, cbData, &cbData);
     136    if (RT_UNLIKELY(rc || Parm[0]))
     137    {
     138        static unsigned cComplaints = 0;
     139        if (cComplaints++ < 256)
     140            LogRel(("%s: send failed. rc=%d Parm={%ld,%ld} cb=%d\n",
     141                    pThis->szName, rc, Parm[0], Parm[1], cb));
     142        if (rc)
     143            rc = RTErrConvertFromOS2(rc);
     144        else
     145            rc = VERR_IO_GEN_FAILURE;
     146    }
     147    Log3(("%s: Send completed %d ns\n", pThis->szName, RTTimeProgramNanoTS() - pThis->u64LastTransferTS));
     148
     149    STAM_PROFILE_STOP(&pThis->StatTransmit, a);
    125150    AssertRC(rc);
    126151    return rc;
     
    140165static DECLCALLBACK(void) drvTAPOs2SetPromiscuousMode(PPDMINETWORKCONNECTOR pInterface, bool fPromiscuous)
    141166{
    142     LogFlow(("drvTAPOs2SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous));
    143     /* nothing to do */
     167    PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
     168    LogFlow(("%s: SetPromiscuousMode: fPromiscuous=%d\n", pThis->szName, fPromiscuous));
     169    NOREF(pThis);
     170    /** @todo is it always in promiscuous mode? */
    144171}
    145172
     
    154181static DECLCALLBACK(void) drvTAPOs2NotifyLinkChanged(PPDMINETWORKCONNECTOR pInterface, PDMNETWORKLINKSTATE enmLinkState)
    155182{
    156     LogFlow(("drvNATNotifyLinkChanged: enmLinkState=%d\n", enmLinkState));
    157     /** @todo take action on link down and up. Stop the polling and such like. */
     183    PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
     184    bool fLinkDown;
     185    switch (enmLinkState)
     186    {
     187        case PDMNETWORKLINKSTATE_DOWN:
     188        case PDMNETWORKLINKSTATE_DOWN_RESUME:
     189            fLinkDown = true;
     190            break;
     191        default:
     192            AssertMsgFailed(("enmLinkState=%d\n", enmLinkState));
     193        case PDMNETWORKLINKSTATE_UP:
     194            fLinkDown = false;
     195            break;
     196    }
     197    LogFlow(("%s: NotifyLinkChanged: enmLinkState=%d %d->%d\n", pThis->szName, pThis->fLinkDown, fLinkDown));
     198    ASMAtomicXchgBool(&pThis->fLinkDown, fLinkDown);
    158199}
    159200
     
    169210static DECLCALLBACK(void) drvTAPOs2NotifyCanReceive(PPDMINETWORKCONNECTOR pInterface)
    170211{
    171     PDRVTAPOS2 pData = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
    172 
    173     LogFlow(("drvTAPOs2NotifyCanReceive:\n"));
    174     /* ensure we wake up only once */
    175     if (ASMAtomicXchgU32(&pData->fOutOfSpace, false))
    176         RTSemEventSignal(pData->EventOutOfSpace);
    177 }
    178 
    179 
    180 /**
    181  * Asynchronous I/O thread for handling receive.
    182  *
    183  * @returns VINF_SUCCESS (ignored).
    184  * @param   pDrvIns         The driver instance.
    185  * @param   pThread         The PDM thread structure.
    186  */
    187 static DECLCALLBACK(int) drvTAPOs2AsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    188 {
    189     PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
    190     LogFlow(("drvTAPOs2AsyncIoThread: pData=%p\n", pData));
    191     Assert(pThread->enmState == PDMTHREADSTATE_INITIALIZING);
    192    
    193 
    194     /*
    195      * Outer loop.
    196      */
    197     for (;;)
     212    PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
     213
     214    /* don't waste time signalling the semaphore unnecessary */
     215    if (!pThis->fMaybeOutOfSpace)
     216        LogFlow(("%s: NotifyCanReceive: fMaybeOutOfSpace=false\n", pThis->szName));
     217    else
     218    {
     219        LogFlow(("%s: NotifyCanReceive: fMaybeOutOfSpace=true\n", pThis->szName));
     220        RTSemEventSignal(pThis->EventOutOfSpace);
     221    }
     222}
     223
     224
     225/**
     226 * Receiver thread.
     227 *
     228 * @returns VBox status code. Returning failure will naturally terminate the thread.
     229 * @param   pDrvIns     The pcnet device instance.
     230 * @param   pThread     The thread.
     231 */
     232static DECLCALLBACK(int) drvTAPOs2ReceiveThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     233{
     234    PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
     235
     236    /*
     237     * No initialization work to do, just return immediately.
     238     */
     239    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     240        return VINF_SUCCESS;
     241    Assert(pThread->enmState == PDMTHREADSTATE_RESUMING);
     242
     243    /*
     244     * Loop while the thread is running, quit immediately when
     245     * we're supposed to suspend or terminate.
     246     */
     247    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    198248    {
    199249        /*
    200          *
     250         * Read a frame, this will block for a while if nothing to read.
    201251         */
    202         PDMR3ThreadSuspend(pThread);
    203         if (pThread->enmState != PDMTHREADSTATE_RESUMING)
     252        char    abBuf[4096];
     253        ULONG   Parm[2] = { ~0UL, ~0UL };   /* mysterious output */
     254        ULONG   cbParm = sizeof(Parm);      /* this one is actually ignored... */
     255        ULONG   cbBuf = sizeof(abBuf);
     256
     257        int rc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_READ_PACKET,
     258                             &Parm[0], cbParm, &cbParm,
     259                             &abBuf[0], cbBuf, &cbBuf);
     260        if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    204261            break;
    205 
    206         {
    207         }
    208     }
    209 
    210 
    211 
    212 
    213     STAM_PROFILE_ADV_START(&pData->StatReceive, a);
    214 
    215     /*
    216      * Polling loop.
    217      */
    218     for (;;)
    219     {
    220         /*
    221          * Read/wait the frame.
    222          */
    223         char    achBuf[4096];
    224         ULONG   cbParm = ;
    225         ULONG   cbRead = 0;
    226         int     LanNumber;
    227 
    228         int rc = DosDevIOCtl(pData->FileDevice, PROT_CATEGORY, TAP_CANCEL_READ,
    229                              &UnusedParms[0], cbParm, &cbParm,
    230                              &achBuf[0], cbRead, &cbRead);
    231         if (rc == NO_ERROR)
     262        const size_t cbRead = Parm[1];
     263        if (    !rc
     264            &&  !Parm[0]
     265            &&  cbRead > 0 /* cbRead */)
    232266        {
    233267            AssertMsg(cbRead <= 1536, ("cbRead=%d\n", cbRead));
    234268
    235269            /*
    236              * Wait for the device to have space for this frame.
     270             * Wait for the device to have room for this frame.
    237271             */
    238             size_t cbMax = pData->pPort->pfnCanReceive(pData->pPort);
     272            ASMAtomicXchgBool(&pThis->fMaybeOutOfSpace, true);
     273            size_t cbMax = pThis->pPort->pfnCanReceive(pThis->pPort);
    239274            if (cbMax < cbRead)
    240275            {
    241                 /** @todo receive overflow handling needs serious improving! */
    242                 STAM_PROFILE_ADV_STOP(&pData->StatReceive, a);
    243                 STAM_PROFILE_START(&pData->StatRecvOverflows, b);
     276                STAM_PROFILE_ADV_STOP(&pThis->StatReceive, a);
     277                STAM_PROFILE_START(&pThis->StatRecvOverflows, b);
    244278                while (   cbMax < cbRead
    245                        && pData->enmState != ASYNCSTATE_TERMINATE)
     279                       && pThread->enmState == PDMTHREADSTATE_RUNNING)
    246280                {
    247                     LogFlow(("drvTAPOs2AsyncIoThread: cbMax=%d cbRead=%d waiting...\n", cbMax, cbRead));
    248 #if 1
    249                     /* We get signalled by the network driver. 50ms is just for sanity */
    250                     ASMAtomicXchgU32(&pData->fOutOfSpace, true);
    251                     RTSemEventWait(pData->EventOutOfSpace, 50);
    252 #else
    253                     RTThreadSleep(1);
    254 #endif
    255                     cbMax = pData->pPort->pfnCanReceive(pData->pPort);
     281                    LogFlow(("%s: ReceiveThread: cbMax=%d cbRead=%d waiting...\n", pThis->szName, cbMax, cbRead));
     282                    RTSemEventWait(pThis->EventOutOfSpace, 50);
     283                    cbMax = pThis->pPort->pfnCanReceive(pThis->pPort);
    256284                }
    257                 ASMAtomicXchgU32(&pData->fOutOfSpace, false);
    258                 STAM_PROFILE_STOP(&pData->StatRecvOverflows, b);
    259                 STAM_PROFILE_ADV_START(&pData->StatReceive, a);
    260                 if (pData->enmState == ASYNCSTATE_TERMINATE)
    261                     break;
     285                STAM_PROFILE_STOP(&pThis->StatRecvOverflows, b);
     286                STAM_PROFILE_ADV_START(&pThis->StatReceive, a);
    262287            }
     288            ASMAtomicXchgBool(&pThis->fMaybeOutOfSpace, false);
     289            if (pThread->enmState != PDMTHREADSTATE_RUNNING)
     290                break; /* just drop it, no big deal. */
    263291
    264292            /*
     
    267295#ifdef LOG_ENABLED
    268296            uint64_t u64Now = RTTimeProgramNanoTS();
    269             LogFlow(("drvTAPOs2AsyncIoThread: %-4d bytes at %llu ns  deltas: r=%llu t=%llu\n",
    270                      cbRead, u64Now, u64Now - pData->u64LastReceiveTS, u64Now - pData->u64LastTransferTS));
    271             pData->u64LastReceiveTS = u64Now;
     297            LogFlow(("%s: ReceiveThread: %-4d bytes at %RU64 ns  deltas: recv=%RU64 xmit=%RU64\n", pThis->szName,
     298                     cbRead, u64Now, u64Now - pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS));
     299            pThis->u64LastReceiveTS = u64Now;
    272300#endif
    273             Log2(("drvTAPOs2AsyncIoThread: cbRead=%#x\n"
     301            Log2(("%s: ReceiveThread: cbRead=%#x\n"
    274302                  "%.*Vhxd\n",
    275                   cbRead, cbRead, achBuf));
    276             STAM_COUNTER_INC(&pData->StatPktRecv);
    277             STAM_COUNTER_ADD(&pData->StatPktRecvBytes, cbRead);
    278             rc = pData->pPort->pfnReceive(pData->pPort, achBuf, cbRead);
     303                  pThis->szName, cbRead, cbRead, abBuf));
     304            STAM_COUNTER_INC(&pThis->StatPktRecv);
     305            STAM_COUNTER_ADD(&pThis->StatPktRecvBytes, cbRead);
     306            rc = pThis->pPort->pfnReceive(pThis->pPort, abBuf, cbRead);
    279307            AssertRC(rc);
    280308        }
    281         else
     309        /* we'll be returning ~1 per second with no data; rc=0 Parm[0] = 1, Parm[1] = 0. */
     310        else if (rc)
    282311        {
    283             LogFlow(("drvTAPOs2AsyncIoThread: DoDevIOCtl -> %Vrc\n", rc));
     312            LogFlow(("%s: ReceiveThread: DoDevIOCtl -> %s Parm={%ld, %ld}\n",
     313                     pThis->szName, rc, Parm[0], Parm[1]));
     314            rc = RTErrConvertFromOS2(rc);
    284315            if (rc == VERR_INVALID_HANDLE)
    285                 break;
     316                return rc;
    286317            RTThreadYield();
    287318        }
    288319    }
    289320
    290     LogFlow(("drvTAPOs2AsyncIoThread: returns %Vrc\n", VINF_SUCCESS));
    291     STAM_PROFILE_ADV_STOP(&pData->StatReceive, a);
     321    /* The thread is being suspended or terminated. */
     322    return VINF_SUCCESS;
     323}
     324
     325
     326/**
     327 * Unblock the send thread so it can respond to a state change.
     328 *
     329 * @returns VBox status code.
     330 * @param   pDrvIns     The pcnet device instance.
     331 * @param   pThread     The send thread.
     332 */
     333static DECLCALLBACK(int) drvTAPOs2WakeupReceiveThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
     334{
     335    PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
     336    LogFlow(("%s: WakeupReceiveThread\n", pThis->szName));
     337
     338    /* cancel any pending reads */
     339    ULONG   Parm[2] = { ~0UL, ~0UL };   /* mysterious output */
     340    ULONG   cbParm = sizeof(Parm);
     341    ULONG   Data = pThis->iLan;         /* right? */
     342    ULONG   cbData = sizeof(Data);
     343    int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_CANCEL_READ,
     344                          &Parm[0], cbParm, &cbParm,
     345                          &Data, cbData, &cbData);
     346    AssertMsg(orc == 0, ("%d\n", orc)); NOREF(orc);
     347
     348    /* wake it up if it's waiting for receive buffers. */
     349    if (pThis->fMaybeOutOfSpace)
     350        RTSemEventSignal(pThis->EventOutOfSpace);
     351
    292352    return VINF_SUCCESS;
    293353}
     
    306366{
    307367    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
    308     PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
     368    PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
    309369    switch (enmInterface)
    310370    {
     
    312372            return &pDrvIns->IBase;
    313373        case PDMINTERFACE_NETWORK_CONNECTOR:
    314             return &pData->INetworkConnector;
     374            return &pThis->INetworkConnector;
    315375        default:
    316376            return NULL;
     
    329389static DECLCALLBACK(void) drvTAPOs2Destruct(PPDMDRVINS pDrvIns)
    330390{
    331     LogFlow(("drvTAPOs2Destruct\n"));
    332     PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
    333 
    334     /*
    335      * Destroy the event semaphore.
    336      */
    337     if (pData->EventOutOfSpace != NIL_RTSEMEVENTMULTI)
    338     {
    339         rc = RTSemEventDestroy(pData->EventOutOfSpace);
     391    PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
     392    LogFlow(("%s: Destruct\n", pThis->szName));
     393
     394    /* PDM will destroy the thread for us, it's suspended right now. */
     395
     396    /*
     397     * Destroy the out-of-space event semaphore.
     398     */
     399    if (pThis->EventOutOfSpace != NIL_RTSEMEVENTMULTI)
     400    {
     401        int rc = RTSemEventDestroy(pThis->EventOutOfSpace);
    340402        AssertRC(rc);
    341         pData->EventOutOfSpace = NIL_RTSEMEVENTMULTI;
     403        pThis->EventOutOfSpace = NIL_RTSEMEVENTMULTI;
     404    }
     405
     406    /*
     407     * Disconnect from the lan if we made a connection and close it.
     408     */
     409    if (pThis->iConnectedTo != -1)
     410    {
     411        ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
     412        ULONG cbParm = sizeof(Parm);
     413        ULONG Data = pThis->iConnectedTo;
     414        ULONG cbData = sizeof(Data);
     415        int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_DISCONNECT_NIC,
     416                              &Parm, cbParm, &cbParm,
     417                              &Data, cbData, &cbData);
     418        if (    orc
     419            ||  Parm[0])
     420            LogRel(("%s: Failed to disconnect %d from %d! orc=%d Parm={%ld,%ld}\n",
     421                    pThis->szName, pThis->iLan, pThis->iConnectedTo, orc, Parm[0], Parm[1]));
     422        pThis->iConnectedTo = -1;
     423    }
     424
     425    if (pThis->hDevice != NIL_RTFILE)
     426    {
     427        int rc = RTFileClose(pThis->hDevice);
     428        AssertRC(rc);
     429        pThis->hDevice = NIL_RTFILE;
    342430    }
    343431}
     
    356444static DECLCALLBACK(int) drvTAPOs2Construct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
    357445{
    358     PDRVTAPOS2 pData = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
     446    PDRVTAPOS2 pThis = PDMINS2DATA(pDrvIns, PDRVTAPOS2);
    359447
    360448    /*
    361449     * Init the static parts.
    362450     */
    363     pData->pDrvIns                      = pDrvIns;
    364     pData->FileDevice                   = NIL_RTFILE;
    365     pData->Thread                       = NIL_RTTHREAD;
    366     pData->enmState                     = ASYNCSTATE_RUNNING;
     451    pThis->pDrvIns                      = pDrvIns;
     452    pThis->hDevice                      = NIL_RTFILE;
     453    pThis->iLan                         = -1;
     454    pThis->iConnectedTo                 = -1;
     455    pThis->pThread                      = NULL;
     456    RTStrPrintf(pThis->szName, sizeof(pThis->szName), "TAP%d", pDrvIns->iInstance);
    367457    /* IBase */
    368458    pDrvIns->IBase.pfnQueryInterface    = drvTAPOs2QueryInterface;
    369459    /* INetwork */
    370     pData->INetworkConnector.pfnSend                = drvTAPOs2Send;
    371     pData->INetworkConnector.pfnSetPromiscuousMode  = drvTAPOs2SetPromiscuousMode;
    372     pData->INetworkConnector.pfnNotifyLinkChanged   = drvTAPOs2NotifyLinkChanged;
    373     pData->INetworkConnector.pfnNotifyCanReceive    = drvTAPOs2NotifyCanReceive;
     460    pThis->INetworkConnector.pfnSend                = drvTAPOs2Send;
     461    pThis->INetworkConnector.pfnSetPromiscuousMode  = drvTAPOs2SetPromiscuousMode;
     462    pThis->INetworkConnector.pfnNotifyLinkChanged   = drvTAPOs2NotifyLinkChanged;
     463    pThis->INetworkConnector.pfnNotifyCanReceive    = drvTAPOs2NotifyCanReceive;
    374464
    375465    /*
    376466     * Validate the config.
    377467     */
    378     if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0InitProg\0TermProg\0FileHandle\0"))
     468    if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0LanNumber\0ConnectTo\0"))
    379469        return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, "");
    380470
     
    390480     * Query the network port interface.
    391481     */
    392     pData->pPort = (PPDMINETWORKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_PORT);
    393     if (!pData->pPort)
     482    pThis->pPort = (PPDMINETWORKPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_NETWORK_PORT);
     483    if (!pThis->pPort)
    394484        return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE,
    395485                                N_("Configuration error: The above device/driver didn't export the network port interface!"));
     
    398488     * Read the configuration.
    399489     */
    400     int32_t iFile;
    401     rc = CFGMR3QueryS32(pCfgHandle, "FileHandle", &iFile);
     490    rc = CFGMR3QueryString(pCfgHandle, "Device", &pThis->szDevice[0], sizeof(pThis->szDevice));
     491    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     492        strcpy(pThis->szDevice, "\\DEV\\TAP$");
     493    else if (VBOX_FAILURE(rc))
     494        return PDMDRV_SET_ERROR(pDrvIns, rc,
     495                                N_("Configuration error: Query for \"Device\" failed!"));
     496
     497    int32_t iConnectTo;
     498    rc = CFGMR3QueryS32(pCfgHandle, "ConnectTo", &iConnectTo);
     499    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     500        iConnectTo = -1;
     501    else if (VBOX_FAILURE(rc))
     502        return PDMDRV_SET_ERROR(pDrvIns, rc,
     503                                N_("Configuration error: Query for \"ConnectTo\" failed!"));
     504
     505    /*
     506     * Open the device.
     507     * Keep in mind that the destructor is always called!
     508     */
     509    rc = RTFileOpen(&pThis->hDevice, pThis->szDevice, RTFILE_O_DENY_NONE | RTFILE_O_READ);
    402510    if (VBOX_FAILURE(rc))
    403         return PDMDRV_SET_ERROR(pDrvIns, rc,
    404                                 N_("Configuration error: Query for \"FileHandle\" 32-bit signed integer failed!"));
    405     pData->FileDevice = (RTFILE)iFile;
    406     if (!RTFileIsValid(pData->FileDevice))
    407         return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_HANDLE, RT_SRC_POS,
    408                                    N_("The TAP file handle %RTfile is not valid!"), pData->FileDevice);
    409 
    410     /*
    411      * Make sure the descriptor is non-blocking and valid.
    412      *
    413      * We should actually query if it's a TAP device, but I haven't
    414      * found any way to do that.
    415      */
    416     if (fcntl(pData->FileDevice, F_SETFL, O_NONBLOCK) == -1)
    417         return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_IOCTL, RT_SRC_POS,
    418                                    N_("Configuration error: Failed to configure /dev/net/tun. errno=%d"), errno);
    419     Log(("drvTAPOs2Contruct: %d (from fd)\n", pData->FileDevice));
    420     rc = VINF_SUCCESS;
     511        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     512                                   N_("Failed to open tap device '%s'!"), pThis->szDevice);
     513
     514    ULONG Parm[2] = { ~0UL, ~0UL }; /* mysterious output */
     515    ULONG cbParm = sizeof(Parm);
     516    ULONG Data = ~0UL;
     517    ULONG cbData = sizeof(Data);
     518    int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_GET_LAN_NUMBER,
     519                          &Parm, cbParm, &cbParm,
     520                          &Data, cbData, &cbData);
     521    if (orc)
     522        rc = RTErrConvertFromOS2(orc);
     523    else if (Parm[0])
     524        rc = VERR_GENERAL_FAILURE;
     525    if (VBOX_FAILURE(rc))
     526        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     527                                   N_("Failed to query LanNumber! orc=%d Parm={%ld,%ld}\n"),
     528                                   orc, Parm[0], Parm[1]);
     529    pThis->iLan = (int32_t)Data;
     530    Log(("%s: iLan=%d Parm[1]=%ld\n", pThis->szName, pThis->iLan, Parm[1]));
     531
     532    /*
     533     * Connect it requested.
     534     */
     535    if (iConnectTo != -1)
     536    {
     537        if (iConnectTo == pThis->iLan)
     538            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     539                                       N_("Cannot connect to ourself (%d)"), iConnectTo);
     540
     541        Parm[0] = Parm[1] = ~0UL; /* mysterious output */
     542        cbParm = sizeof(Parm);
     543        Data = iConnectTo;
     544        cbData = sizeof(Data);
     545        int orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_CONNECT_NIC,
     546                              &Parm, cbParm, &cbParm,
     547                              &Data, cbData, &cbData);
     548        if (orc)
     549            rc = RTErrConvertFromOS2(orc);
     550        else if (Parm[0])
     551            rc = VERR_GENERAL_FAILURE;
     552        if (VBOX_FAILURE(rc))
     553            return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
     554                                       N_("Failed to connect %d to %d! orc=%d Parm={%ld,%ld}\n"),
     555                                       pThis->iLan, iConnectTo, orc, Parm[0], Parm[1]);
     556        Log(("%s: Connected to %d\n", pThis->szName, iConnectTo));
     557        pThis->iConnectedTo = iConnectTo;
     558    }
     559
     560    /*
     561     * Log the config.
     562     */
     563    Parm[0] = Parm[1] = ~0UL; /* mysterious output */
     564    PDMMAC Mac;
     565    cbParm = sizeof(Parm);
     566    cbData = sizeof(Mac);
     567    orc = DosDevIOCtl(pThis->hDevice, PROT_CATEGORY, TAP_READ_MAC_ADDRESS,
     568                      &Parm[0], cbParm, &cbParm,
     569                      &Mac, cbData, &cbData);
     570    if (    !orc
     571        &&  !Parm[0]
     572      /*&&  !Parm[1]?*/)
     573        LogRel(("%s: iLan=%d iConnectedTo=%d Mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
     574                pThis->szName, pThis->iLan, pThis->iConnectedTo,
     575                Mac.au8[0], Mac.au8[1], Mac.au8[2], Mac.au8[3], Mac.au8[4], Mac.au8[5]));
     576    else
     577        LogRel(("%s: iLan=%d iConnectedTo Mac=failed - orc=%d Parm={%ld,%ld}\n",
     578                pThis->szName, pThis->iLan, pThis->iConnectedTo, Parm[0], Parm[1]));
    421579
    422580    /*
    423581     * Create the out-of-space semaphore and the async receiver thread.
    424582     */
    425     rc = RTSemEventCreate(&pData->EventOutOfSpace);
     583    rc = RTSemEventCreate(&pThis->EventOutOfSpace);
    426584    AssertRCReturn(rc, rc);
    427585
    428     rc = PDMDrvHlpThreadCreate(pDrvIns, &pData->pThread, pData, drvTAPOs2AsyncIoThread, drvTAPOs2WakeupThread,
    429                                0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "TAP");
     586    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPOs2ReceiveThread, drvTAPOs2WakeupReceiveThread,
     587                                  0, RTTHREADTYPE_IO, pThis->szName);
    430588    AssertRCReturn(rc, rc);
    431589
     
    434592     * Statistics.
    435593     */
    436     PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatPktSent,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,        "Number of sent packets.",          "/Drivers/TAP%d/Packets/Sent", pDrvIns->iInstance);
    437     PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatPktSentBytes,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,             "Number of sent bytes.",            "/Drivers/TAP%d/Bytes/Sent", pDrvIns->iInstance);
    438     PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatPktRecv,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,        "Number of received packets.",      "/Drivers/TAP%d/Packets/Received", pDrvIns->iInstance);
    439     PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatPktRecvBytes,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,             "Number of received bytes.",        "/Drivers/TAP%d/Bytes/Received", pDrvIns->iInstance);
    440     PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatTransmit,      STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,    "Profiling packet transmit runs.",  "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);
    441     PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatReceive,       STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,    "Profiling packet receive runs.",   "/Drivers/TAP%d/Receive", pDrvIns->iInstance);
    442     PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatRecvOverflows, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.", "/Drivers/TAP%d/RecvOverflows", pDrvIns->iInstance);
     594    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSent,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,        "Number of sent packets.",          "/Drivers/TAP%d/Packets/Sent", pDrvIns->iInstance);
     595    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSentBytes,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,             "Number of sent bytes.",            "/Drivers/TAP%d/Bytes/Sent", pDrvIns->iInstance);
     596    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecv,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,        "Number of received packets.",      "/Drivers/TAP%d/Packets/Received", pDrvIns->iInstance);
     597    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecvBytes,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,             "Number of received bytes.",        "/Drivers/TAP%d/Bytes/Received", pDrvIns->iInstance);
     598    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit,      STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,    "Profiling packet transmit runs.",  "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);
     599    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive,       STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,    "Profiling packet receive runs.",   "/Drivers/TAP%d/Receive", pDrvIns->iInstance);
     600    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatRecvOverflows, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.", "/Drivers/TAP%d/RecvOverflows", pDrvIns->iInstance);
    443601#endif /* VBOX_WITH_STATISTICS */
    444602
     
    485643    NULL
    486644};
     645
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