VirtualBox

Changeset 10557 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 12, 2008 12:19:35 AM (16 years ago)
Author:
vboxsync
Message:

INTNET: Hopefully sorted out a bunch of unsafe locking (handle usage is still too trusting, but that can wait). Made the factory generic for all three trunk connections.

Location:
trunk/src/VBox/Devices/Network
Files:
2 edited

Legend:

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

    r10551 r10557  
    4343/**
    4444 * A network interface.
     45 *
     46 * Unless explicitly stated, all members are protect by the network semaphore.
    4547 */
    4648typedef struct INTNETIF
    4749{
    48     /** Pointer to the next interface. */
     50    /** Pointer to the next interface.
     51     * This is protected by the INTNET::FastMutex. */
    4952    struct INTNETIF        *pNext;
    5053    /** The current MAC address for the interface. */
     
    7679     * should return with the appropriate error condition. */
    7780    INTNETIFHANDLE          hIf;
    78     /** Pointer to the network this interface is connected to. */
     81    /** Pointer to the network this interface is connected to.
     82     * This is protected by the INTNET::FastMutex. */
    7983    struct INTNETNETWORK   *pNetwork;
    8084    /** The session this interface is associated with. */
     
    9397{
    9498    /** The Next network in the chain.
    95      * This is protected by the INTNET::Spinlock. */
     99     * This is protected by the INTNET::FastMutex. */
    96100    struct INTNETNETWORK   *pNext;
     101    /** List of interfaces connected to the network.
     102     * This is protected by the INTNET::FastMutex. */
     103    PINTNETIF               pIFs;
    97104    /** The network mutex.
    98105     * It protects everything dealing with this network. */
    99106    RTSEMFASTMUTEX          FastMutex;
    100     /** List of interfaces connected to the network. */
    101     PINTNETIF               pIFs;
    102107    /** Pointer to the instance data. */
    103108    struct INTNET          *pIntNet;
     
    140145typedef struct INTNETHT
    141146{
     147    /** Spinlock protecting all access. */
     148    RTSPINLOCK              Spinlock;
    142149    /** Pointer to the handle table. */
    143150    PINTNETHTE              paEntries;
     
    160167typedef struct INTNET
    161168{
    162     /** Mutex protecting the network creation. */
     169    /** Mutex protecting the network creation, opening and destruction.
     170     * (This means all operations affecting the pNetworks list.) */
    163171    RTSEMFASTMUTEX          FastMutex;
    164     /** Spinlock protecting the linked list of networks and the interface handle translation table. */
    165     RTSPINLOCK              Spinlock;
    166172    /** List of networks. Protected by INTNET::Spinlock. */
    167173    PINTNETNETWORK volatile pNetworks;
     
    172178
    173179
    174 
    175180/**
    176181 * Validates and translates an interface handle to a interface pointer.
     182 *
     183 * The caller already owns the spinlock, which means this is
     184 * for internal use only.
    177185 *
    178186 * @returns Pointer to interface.
    179187 * @returns NULL if the handle is invalid.
    180  * @param   pIntNet     Pointer to the instance data.
     188 * @param   pHT         Pointer to the handle table.
    181189 * @param   hIF         The interface handle to validate and translate.
    182  */
    183 DECLINLINE(PINTNETIF) intnetHandle2IFPtr(PINTNET pIntNet, INTNETIFHANDLE hIF)
    184 {
    185     Assert(pIntNet);
    186     if ((hIF & INTNET_HANDLE_MAGIC) != INTNET_HANDLE_MAGIC)
    187         return NULL;
    188 
    189     PINTNETHT       pHT = &pIntNet->IfHandles;
    190     const uint32_t  i   = hIF & INTNET_HANDLE_INDEX_MASK;
    191     PINTNETIF       pIF = NULL;
     190 *
     191 * @internal
     192 */
     193DECLINLINE(PINTNETIF) intnetHandle2IFPtrLocked(PINTNETHT pHT, INTNETIFHANDLE hIF)
     194{
     195    if (RT_LIKELY((hIF & INTNET_HANDLE_MAGIC) == INTNET_HANDLE_MAGIC))
     196    {
     197        const uint32_t i = hIF & INTNET_HANDLE_INDEX_MASK;
     198        if (RT_LIKELY(   i < pHT->cAllocated
     199                      && pHT->paEntries[i].iNext >= INTNET_HANDLE_MAX
     200                      && pHT->paEntries[i].iNext != UINT32_MAX))
     201            return pHT->paEntries[i].pIF;
     202    }
     203    return NULL;
     204}
     205
     206
     207/**
     208 * Validates and translates an interface handle to a interface pointer.
     209 *
     210 * @returns Pointer to interface.
     211 * @returns NULL if the handle is invalid.
     212 * @param   pHT         Pointer to the handle table.
     213 * @param   hIF         The interface handle to validate and translate.
     214 */
     215DECLINLINE(PINTNETIF) intnetHandle2IFPtr(PINTNETHT pHT, INTNETIFHANDLE hIF)
     216{
     217    AssertPtr(pHT);
    192218    RTSPINLOCKTMP   Tmp = RTSPINLOCKTMP_INITIALIZER;
    193     RTSpinlockAcquire(pIntNet->Spinlock, &Tmp);
    194 
    195     if (    i < pHT->cAllocated
    196         &&  pHT->paEntries[i].iNext >= INTNET_HANDLE_MAX
    197         &&  pHT->paEntries[i].iNext != UINT32_MAX)
    198         pIF = pHT->paEntries[i].pIF;
    199 
    200     RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
     219    RTSpinlockAcquire(pHT->Spinlock, &Tmp);
     220    PINTNETIF pIF = intnetHandle2IFPtrLocked(pHT, hIF);
     221    RTSpinlockRelease(pHT->Spinlock, &Tmp);
    201222
    202223    return pIF;
     
    221242
    222243    RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    223     RTSpinlockAcquire(pIntNet->Spinlock, &Tmp);
     244    RTSpinlockAcquire(pHT->Spinlock, &Tmp);
    224245    for (;;)
    225246    {
     
    235256
    236257            pHT->paEntries[i].pIF = pIF;
    237             RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
     258            RTSpinlockRelease(pHT->Spinlock, &Tmp);
    238259            if (paNew)
    239260                RTMemFree(paNew);
     
    245266         */
    246267        const unsigned cNew = pHT->cAllocated + 128;
    247         RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
     268        RTSpinlockRelease(pHT->Spinlock, &Tmp);
    248269        if (--cTries <= 0)
    249270        {
     
    258279         * Acquire the spinlock and check if someone raced us.
    259280         */
    260         RTSpinlockAcquire(pIntNet->Spinlock, &Tmp);
     281        RTSpinlockAcquire(pHT->Spinlock, &Tmp);
    261282        if (pHT->cAllocated < cNew)
    262283        {
     
    290311
    291312/**
    292  * Frees a handle.
    293  *
    294  * @returns Handle on success.
    295  * @returns Invalid handle on failure.
    296  * @param   pIntNet     Pointer to the instance data.
     313 * Validates and frees a handle.
     314 *
     315 * @returns Pointer to interface.
     316 * @returns NULL if the handle is invalid.
     317 * @param   pHT         Pointer to the handle table.
    297318 * @param   h           The handle we're freeing.
    298319 */
    299 static void intnetHandleFree(PINTNET pIntNet, INTNETIFHANDLE h)
    300 {
    301     Assert(intnetHandle2IFPtr(pIntNet, h));
    302     PINTNETHT       pHT = &pIntNet->IfHandles;
    303     const uint32_t  i   = h & INTNET_HANDLE_INDEX_MASK;
    304 
     320static PINTNETIF intnetHandleFree(PINTNETHT pHT, INTNETIFHANDLE h)
     321{
    305322    RTSPINLOCKTMP   Tmp = RTSPINLOCKTMP_INITIALIZER;
    306     RTSpinlockAcquire(pIntNet->Spinlock, &Tmp);
    307 
    308     if (i < pHT->cAllocated)
    309     {
    310         /*
    311          * Insert at the end of the free list.
    312          */
     323    RTSpinlockAcquire(pHT->Spinlock, &Tmp);
     324
     325    /*
     326     * Validate and get it, then insert the handle table entry
     327     * at the end of the free list.
     328     */
     329    PINTNETIF pIF = intnetHandle2IFPtrLocked(pHT, h);
     330    if (pIF)
     331    {
     332        const uint32_t i = h & INTNET_HANDLE_INDEX_MASK;
    313333        pHT->paEntries[i].iNext = UINT32_MAX;
    314334        const uint32_t iTail = pHT->iTail;
     
    319339        pHT->iTail = i;
    320340    }
    321     else
    322         AssertMsgFailed(("%d >= %d\n", i, pHT->cAllocated));
    323 
    324     RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
     341
     342    RTSpinlockRelease(pHT->Spinlock, &Tmp);
     343
     344    AssertMsg(pIF, ("%d >= %d\n", h & INTNET_HANDLE_INDEX_MASK, pHT->cAllocated));
     345    return pIF;
    325346}
    326347
     
    617638     */
    618639    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    619     PINTNETIF pIf = intnetHandle2IFPtr(pIntNet, hIf);
     640    PINTNETIF pIf = intnetHandle2IFPtr(&pIntNet->IfHandles, hIf);
    620641    if (!pIf)
    621642        return VERR_INVALID_HANDLE;
     
    694715     */
    695716    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    696     PINTNETIF pIf = intnetHandle2IFPtr(pIntNet, hIf);
     717    PINTNETIF pIf = intnetHandle2IFPtr(&pIntNet->IfHandles, hIf);
    697718    if (!pIf)
    698719        return VERR_INVALID_HANDLE;
     
    746767     * Validate input.
    747768     */
    748     AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    749     PINTNETIF pIf = intnetHandle2IFPtr(pIntNet, hIf);
     769    AssertPtrReturn(ppRing0Buf, VERR_INVALID_PARAMETER);
     770    *ppRing0Buf = NULL;
     771    AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
     772    PINTNETIF pIf = intnetHandle2IFPtr(&pIntNet->IfHandles, hIf);
    750773    if (!pIf)
    751774        return VERR_INVALID_HANDLE;
    752     AssertPtrReturn(ppRing0Buf, VERR_INVALID_PARAMETER);
    753 
    754     /*
    755      * Assuming that we're in Ring-0, this should be rather simple :-)
     775
     776    /*
     777     * Grab the lock and get the data.
     778     * ASSUMES that the handle isn't closed while we're here.
    756779     */
    757780    int rc = RTSemFastMutexRequest(pIf->pNetwork->FastMutex);
     
    783806     */
    784807    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    785     PINTNETIF pIf = intnetHandle2IFPtr(pIntNet, hIf);
     808    PINTNETIF pIf = intnetHandle2IFPtr(&pIntNet->IfHandles, hIf);
    786809    if (!pIf)
    787810        return VERR_INVALID_HANDLE;
     
    790813
    791814    /*
    792      * Assuming that we're in Ring-0, this should be rather simple :-)
     815     * Grab the lock and get the data.
     816     * ASSUMES that the handle isn't closed while we're here.
    793817     */
    794818    int rc = RTSemFastMutexRequest(pIf->pNetwork->FastMutex);
     
    796820        return rc;
    797821
    798     /** @todo make a SUPR0 api for obtaining the array. SUPR0 is keeping track of everything, there
     822    /** @todo make a SUPR0 api for obtaining the array. SUPR0/IPRT is keeping track of everything, there
    799823     * is no need for any extra bookkeeping here.. */
    800824    //*ppRing0Buf = pIf->pIntBuf;
     
    820844
    821845    /*
    822      * Get and validate essential handles.
     846     * Validate & translate input.
    823847     */
    824848    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    825     PINTNETIF pIf = intnetHandle2IFPtr(pIntNet, hIf);
     849    PINTNETIF pIf = intnetHandle2IFPtr(&pIntNet->IfHandles, hIf);
    826850    if (!pIf)
    827851    {
     
    829853        return VERR_INVALID_HANDLE;
    830854    }
     855
     856    /*
     857     * Grab the network semaphore and make the change.
     858     */
     859    int rc = RTSemFastMutexRequest(pIf->pNetwork->FastMutex);
     860    if (RT_FAILURE(rc))
     861        return rc;
     862
    831863    if (pIf->fPromiscuous != fPromiscuous)
    832864    {
    833865        Log(("INTNETR0IfSetPromiscuousMode: hIf=%RX32: Changed from %d -> %d\n",
    834866             hIf, !fPromiscuous, !!fPromiscuous));
    835         ASMAtomicXchgSize(&pIf->fPromiscuous, !!fPromiscuous);
    836     }
     867        ASMAtomicUoWriteBool(&pIf->fPromiscuous, fPromiscuous);
     868    }
     869
     870    RTSemFastMutexRelease(pIf->pNetwork->FastMutex);
    837871    return VINF_SUCCESS;
    838872}
     
    872906     */
    873907    AssertReturn(pIntNet, VERR_INVALID_PARAMETER);
    874     PINTNETIF pIf = intnetHandle2IFPtr(pIntNet, hIf);
     908    PINTNETIF pIf = intnetHandle2IFPtr(&pIntNet->IfHandles, hIf);
    875909    if (!pIf)
    876910    {
     
    891925     * but the problem with such an approach is that it will cause
    892926     * one unnecessary supervisor->user->supervisor trip. There is
    893      * already a risk for such, so we don't need to increase this.
     927     * already a slight risk for such, so no need to increase it.
    894928     */
    895929
     
    941975
    942976    /*
    943      * Get and validate essential handles.
     977     * Validate, get and free the handle.
    944978     */
    945979    AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
    946     PINTNETIF pIf = intnetHandle2IFPtr(pIntNet, hIf);
     980    PINTNETIF pIf = intnetHandleFree(&pIntNet->IfHandles, hIf);
    947981    if (!pIf)
    948982        return VERR_INVALID_HANDLE;
    949 
     983    ASMAtomicWriteU32(&pIf->hIf, INTNET_HANDLE_INVALID);
     984
     985    /*
     986     * Release our reference to the interface object.
     987     */
    950988    int rc = SUPR0ObjRelease(pIf->pvObj, pIf->pSession);
    951989    LogFlow(("INTNETR0IfClose: returns %Rrc\n", rc));
     
    9831021    PINTNET   pIntNet = (PINTNET)pvUser2;
    9841022
     1023    RTSemFastMutexRequest(pIntNet->FastMutex);
     1024
    9851025    /*
    9861026     * Delete the interface handle so the object no longer can be opened.
    9871027     */
    988     if (pIf->hIf != INTNET_HANDLE_INVALID)
    989     {
    990         intnetHandleFree(pIntNet, pIf->hIf);
    991         ASMAtomicXchgSize(&pIf->hIf, INTNET_HANDLE_INVALID);
    992     }
     1028    INTNETIFHANDLE hIf = ASMAtomicXchgU32(&pIf->hIf, INTNET_HANDLE_INVALID);
     1029    if (hIf != INTNET_HANDLE_INVALID)
     1030        intnetHandleFree(&pIntNet->IfHandles, hIf);
    9931031
    9941032    /*
     
    9991037    if (pNetwork)
    10001038    {
    1001         RTSemFastMutexRequest(pNetwork->FastMutex);
    10021039        if (pNetwork->pIFs == pIf)
    10031040            pNetwork->pIFs = pIf->pNext;
     
    10161053            Assert(pPrev);
    10171054        }
    1018         RTSemFastMutexRelease(pNetwork->FastMutex);
    10191055        pIf->pNext = NULL;
    10201056
    10211057        /*
    1022          * Release or reference to the network.
     1058         * Release our reference to the network.
    10231059         */
     1060        RTSemFastMutexRelease(pIntNet->FastMutex);
     1061
    10241062        SUPR0ObjRelease(pNetwork->pvObj, pIf->pSession);
    10251063        pIf->pNetwork = NULL;
    10261064    }
     1065    else
     1066        RTSemFastMutexRelease(pIntNet->FastMutex);
    10271067
    10281068    /*
     
    10821122    RTMemFree(pIf);
    10831123}
    1084 
    10851124
    10861125
     
    11991238
    12001239/**
     1240 * Creates the trunk connection (if any).
     1241 *
     1242 * @returns VBox status code.
     1243 *
     1244 * @param   pNetwork    The newly created network.
     1245 * @param   pSession    The session handle.
     1246 */
     1247static int intnetNetworkCreateTrunkConnection(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSession)
     1248{
     1249    const char *pszFactoryUUID;
     1250    switch (pNetwork->enmTrunkType)
     1251    {
     1252        /*
     1253         * The 'None' case, simple.
     1254         */
     1255        case kIntNetTrunkType_None:
     1256        case kIntNetTrunkType_WhateverNone:
     1257            return VINF_SUCCESS;
     1258        default:
     1259            return VERR_NOT_IMPLEMENTED;
     1260
     1261        case kIntNetTrunkType_NetFlt:
     1262            pszFactoryUUID = INTNETTRUNKFACTORY_NETFLT_UUID_STR;
     1263            break;
     1264        case kIntNetTrunkType_NetTap:
     1265            pszFactoryUUID = INTNETTRUNKFACTORY_NETTAP_UUID_STR;
     1266            break;
     1267        case kIntNetTrunkType_SrvNat:
     1268            pszFactoryUUID = INTNETTRUNKFACTORY_SRVNAT_UUID_STR;
     1269            break;
     1270    }
     1271
     1272    /*
     1273     * Query the factory.
     1274     */
     1275
     1276    return VERR_NOT_IMPLEMENTED;
     1277}
     1278
     1279
     1280/**
    12011281 * Close a network which was opened/created using intnetOpenNetwork()/intnetCreateNetwork().
    12021282 *
     
    12271307{
    12281308    LogFlow(("intnetNetworkDestruct: pvObj=%p pvUser1=%p pvUser2=%p\n", pvObj, pvUser1, pvUser2));
    1229     RTSPINLOCKTMP   Tmp = RTSPINLOCKTMP_INITIALIZER;
    12301309    PINTNETNETWORK  pNetwork = (PINTNETNETWORK)pvUser1;
    12311310    PINTNET         pIntNet = (PINTNET)pvUser2;
    12321311    Assert(pNetwork->pIntNet == pIntNet);
    12331312
    1234     /*
    1235      * Unlink the network.s
    1236      */
    1237     RTSpinlockAcquire(pIntNet->Spinlock, &Tmp);
     1313    RTSemFastMutexRequest(pIntNet->FastMutex);
     1314
     1315
     1316    /*
     1317     * Unlink the network.
     1318     * Note that it needn't be in the list if we failed during creation.
     1319     */
    12381320    PINTNETNETWORK pPrev = pIntNet->pNetworks;
    12391321    if (pPrev == pNetwork)
     
    12471329                break;
    12481330            }
    1249         Assert(pPrev);
    12501331    }
    12511332    pNetwork->pNext = NULL;
    12521333    pNetwork->pvObj = NULL;
    1253     RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
     1334
     1335    RTSemFastMutexRequest(pNetwork->FastMutex);
    12541336
    12551337    /*
     
    12581340     * deal with this by simply orphaning the interfaces.
    12591341     */
    1260     RTSemFastMutexRequest(pNetwork->FastMutex);
    12611342    PINTNETIF pCur = pNetwork->pIFs;
    12621343    while (pCur)
     
    12671348        pCur = pNext;
    12681349    }
     1350
    12691351    RTSemFastMutexRelease(pNetwork->FastMutex);
    12701352
     
    12751357    pNetwork->FastMutex = NIL_RTSEMFASTMUTEX;
    12761358    RTMemFree(pNetwork);
     1359
     1360    RTSemFastMutexRelease(pIntNet->FastMutex);
    12771361}
    12781362
     
    13131397    Assert(cchName && cchName < sizeof(pCur->szName)); /* caller ensures this */
    13141398
    1315     RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    1316     RTSpinlockAcquire(pIntNet->Spinlock, &Tmp);
    13171399    pCur = pIntNet->pNetworks;
    13181400    while (pCur)
     
    13321414                if (!((pCur->fFlags ^ fFlags) & (INTNET_OPEN_FLAGS_PUBLIC)))
    13331415                {
     1416
    13341417                    /*
    1335                      * Increment the reference and check that the
    1336                      * session can access this network.
     1418                     * Increment the reference and check that the session
     1419                     * can access this network.
    13371420                     */
    13381421                    rc = SUPR0ObjAddRef(pCur->pvObj, pSession);
    1339                     RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
    1340 
    13411422                    if (RT_SUCCESS(rc))
    13421423                    {
     
    13481429                            SUPR0ObjRelease(pCur->pvObj, pSession);
    13491430                    }
     1431                    else if (rc == VERR_WRONG_ORDER)
     1432                        rc = VERR_NOT_FOUND; /* destruction race, pretend the other isn't there. */
    13501433                }
    13511434                else
     
    13601443        pCur = pCur->pNext;
    13611444    }
    1362     RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
    13631445
    13641446    LogFlow(("intnetOpenNetwork: returns VERR_NOT_FOUND\n"));
     
    13701452 * Creates a new network.
    13711453 *
    1372  * The call must own the INTNET::FastMutex and has already
    1373  * attempted opening the network.
     1454 * The call must own the INTNET::FastMutex and has already attempted
     1455 * opening the network and found it to be non-existing.
    13741456 *
    13751457 * @returns VBox status code.
     
    13811463 * @param   pszTrunk        The trunk name. Its meaning is specfic to the type.
    13821464 * @param   fFlags          Flags, see INTNET_OPEN_FLAGS_*.
    1383  * @param   ppNetwork       Where to store the network.
     1465 * @param   ppNetwork       Where to store the network. In the case of failure whatever is returned
     1466 *                          here should be dereferenced outside the INTNET::FastMutex.
    13841467 */
    13851468static int intnetCreateNetwork(PINTNET pIntNet, PSUPDRVSESSION pSession, const char *pszNetwork, INTNETTRUNKTYPE enmTrunkType,
     
    14001483
    14011484    /*
    1402      * Verify that the network doesn't exist.
    1403      */
    1404     const uint8_t cchName = strlen(pszNetwork);
    1405     RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
    1406     RTSpinlockAcquire(pIntNet->Spinlock, &Tmp);
    1407     for (PINTNETNETWORK pCur = pIntNet->pNetworks; pCur; pCur = pCur->pNext)
    1408         if (    pCur->cchName == cchName
    1409             &&  !memcmp(pCur->szName, pszNetwork, cchName))
    1410         {
    1411             RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
    1412             LogFlow(("intnetCreateNetwork: returns VERR_ALREADY_EXISTS\n"));
    1413             return VERR_ALREADY_EXISTS;
    1414         }
    1415     RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
    1416 
    1417     /*
    14181485     * Allocate and initialize.
    14191486     */
     
    14271494        pNew->pIntNet = pIntNet;
    14281495        pNew->fFlags = fFlags;
     1496        size_t cchName = strlen(pszNetwork);
    14291497        pNew->cchName = cchName;
    14301498        Assert(cchName && cchName < sizeof(pNew->szName));  /* caller's responsibility. */
     
    14351503
    14361504        /*
    1437          * Register the object in the current session.
     1505         * Register the object in the current session and link it into the network list.
    14381506         */
    14391507        pNew->pvObj = SUPR0ObjRegister(pSession, SUPDRVOBJTYPE_INTERNAL_NETWORK, intnetNetworkDestruct, pNew, pIntNet);
    14401508        if (pNew->pvObj)
    14411509        {
    1442             /*
    1443              * Check again that the network doesn't exist and then link in the new one.
    1444              * This must be done before we attempt any SUPR0ObjRelease call.
    1445              */
    1446             RTSpinlockAcquire(pIntNet->Spinlock, &Tmp);
    1447             for (PINTNETNETWORK pCur = pIntNet->pNetworks; pCur; pCur = pCur->pNext)
    1448                 if (    pCur->cchName == cchName
    1449                     &&  !memcmp(pCur->szName, pszNetwork, cchName))
    1450                     rc = VERR_ALREADY_EXISTS;
    14511510            pNew->pNext = pIntNet->pNetworks;
    14521511            pIntNet->pNetworks = pNew;
    1453             RTSpinlockRelease(pIntNet->Spinlock, &Tmp);
    1454 
     1512
     1513            /*
     1514             * Check if the current session is actually allowed to create and open
     1515             * the network. It is possible to implement network name based policies
     1516             * and these must be checked now. SUPR0ObjRegister does no such checks.
     1517             */
     1518            rc = SUPR0ObjVerifyAccess(pNew->pvObj, pSession, pNew->szName);
    14551519            if (RT_SUCCESS(rc))
    14561520            {
    14571521                /*
    1458                  * Check if the current session is actually allowed to create and open
    1459                  * the network. It is possible to implement network name based policies
    1460                  * and these must be checked now. SUPR0ObjRegister does no such checks.
     1522                 * Connect the trunk.
    14611523                 */
    1462                 rc = SUPR0ObjVerifyAccess(pNew->pvObj, pSession, pNew->szName);
     1524                rc = intnetNetworkCreateTrunkConnection(pNew, pSession);
    14631525                if (RT_SUCCESS(rc))
    14641526                {
     
    14691531            }
    14701532
    1471             /* The release will destroy the object. */
    1472             SUPR0ObjRelease(pNew->pvObj, pSession);
     1533            /*
     1534             * We unlink it here so it cannot be opened when the caller leaves
     1535             * INTNET::FastMutex before dereferencing it.
     1536             */
     1537            Assert(pIntNet->pNetworks == pNew);
     1538            pIntNet->pNetworks = pNew->pNext;
     1539            pNew->pNext = NULL;
     1540
     1541            *ppNetwork = pNew;
    14731542            LogFlow(("intnetCreateNetwork: returns %Rrc\n", rc));
    14741543            return rc;
     
    15331602        case kIntNetTrunkType_None:
    15341603        case kIntNetTrunkType_WhateverNone:
    1535             AssertReturn(!pszTrunk, VERR_INVALID_PARAMETER);
     1604            AssertReturn(!*pszTrunk, VERR_INVALID_PARAMETER);
    15361605            break;
    15371606
     
    15551624
    15561625    /*
    1557      * Try open/create the network.
    1558      */
    1559     PINTNETNETWORK pNetwork;
     1626     * Try open / create the network and create an interface on it for the caller to use.
     1627     *
     1628     * Note that because of the destructors grabbing INTNET::FastMutex and us being required
     1629     * to own this semaphore for the entire network opening / creation and interface creation
     1630     * sequence, intnetCreateNetwork will have to defer the network cleanup to us on failure.
     1631     */
     1632    PINTNETNETWORK pNetwork = NULL;
    15601633    rc = intnetOpenNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork);
    1561     if (rc == VERR_NOT_FOUND)
    1562         rc = intnetCreateNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork);
    1563     if (RT_SUCCESS(rc))
    1564     {
    1565         /*
    1566          * Create a new interface to this network.
    1567          * On failure we close the network. On success it remains open until the
    1568          * interface is destroyed or the last session is doing cleanup (order problems).
    1569          */
    1570         rc = intnetNetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, phIf);
    1571         if (RT_FAILURE(rc))
     1634    if (RT_SUCCESS(rc) || rc == VERR_NOT_FOUND)
     1635    {
     1636        if (rc == VERR_NOT_FOUND)
     1637            rc = intnetCreateNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork);
     1638        if (RT_SUCCESS(rc))
     1639            rc = intnetNetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, phIf);
     1640
     1641        RTSemFastMutexRelease(pIntNet->FastMutex);
     1642
     1643        if (RT_FAILURE(rc) && pNetwork)
    15721644            intnetNetworkClose(pNetwork, pSession);
    15731645    }
    1574 
    1575     RTSemFastMutexRelease(pIntNet->FastMutex);
     1646    else
     1647        RTSemFastMutexRelease(pIntNet->FastMutex);
    15761648
    15771649    LogFlow(("INTNETR0Open: return %Rrc *phIf=%RX32\n", rc, *phIf));
     
    16111683    if (!pIntNet)
    16121684        return;
     1685    AssertPtrReturnVoid(pIntNet);
    16131686
    16141687    /*
     
    16211694        pIntNet->FastMutex = NIL_RTSEMFASTMUTEX;
    16221695    }
    1623     if (pIntNet->Spinlock != NIL_RTSPINLOCK)
    1624     {
    1625         RTSpinlockDestroy(pIntNet->Spinlock);
    1626         pIntNet->Spinlock = NIL_RTSPINLOCK;
     1696    if (pIntNet->IfHandles.Spinlock != NIL_RTSPINLOCK)
     1697    {
     1698        RTSpinlockDestroy(pIntNet->IfHandles.Spinlock);
     1699        pIntNet->IfHandles.Spinlock = NIL_RTSPINLOCK;
    16271700    }
    16281701
     
    16531726        if (RT_SUCCESS(rc))
    16541727        {
    1655             rc = RTSpinlockCreate(&pIntNet->Spinlock);
     1728            rc = RTSpinlockCreate(&pIntNet->IfHandles.Spinlock);
    16561729            if (RT_SUCCESS(rc))
    16571730            {
  • trunk/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp

    r10524 r10557  
    487487                            /*
    488488                             * Start threaded testcase.
     489                             * Give it 5 mins to finish.
    489490                             */
    490491                            if (!g_cErrors)
     
    520521                                {
    521522                                    int rc2 = VINF_SUCCESS;
    522                                     rc = RTThreadWait(ThreadSend0, 30000, &rc2);
    523                                     if (    VBOX_SUCCESS(rc)
    524                                         &&  VBOX_SUCCESS(rc2))
    525                                         rc = RTThreadWait(ThreadSend1, 30000, &rc2);
     523                                    rc = RTThreadWait(ThreadSend0, 5*60*1000, &rc2);
     524#if 1 /** @todo it looks like I'm subject to some false wakeup calls here. (2.6.23-gentoo-r3 amd64) */
     525                                    for (int cTries = 100; rc == VERR_TIMEOUT && cTries > 0; cTries--)
     526                                    {
     527                                        RTThreadSleep(1);
     528                                        rc = RTThreadWait(ThreadSend0, 1, &rc2);
     529                                    }
     530#endif
     531                                    AssertRC(rc);
     532                                    if (VBOX_SUCCESS(rc))
     533                                    {
     534                                        ThreadSend0 = NIL_RTTHREAD;
     535                                        rc = RTThreadWait(ThreadSend1, 5*60*1000, RT_SUCCESS(rc2) ? &rc2 : NULL);
     536#if 1 /** @todo it looks like I'm subject to some false wakeup calls here. (2.6.23-gentoo-r3 amd64) */
     537                                        for (int cTries = 100; rc == VERR_TIMEOUT && cTries > 0; cTries--)
     538                                        {
     539                                            RTThreadSleep(1);
     540                                            rc = RTThreadWait(ThreadSend1, 1, &rc2);
     541                                        }
     542#endif
     543                                        AssertRC(rc);
     544                                        if (RT_SUCCESS(rc))
     545                                            ThreadSend1 = NIL_RTTHREAD;
     546                                    }
    526547                                    if (    VBOX_SUCCESS(rc)
    527548                                        &&  VBOX_SUCCESS(rc2))
     
    544565                                         * Closing time...
    545566                                         */
     567                                        rc = RTThreadWait(ThreadRecv0, 5000, &rc2);
     568                                        if (RT_SUCCESS(rc))
     569                                            ThreadRecv0 = NIL_RTTHREAD;
     570                                        if (VBOX_FAILURE(rc) || VBOX_FAILURE(rc2))
     571                                        {
     572                                            RTPrintf("tstIntNetR0: Failed waiting on receiver thread 0, rc=%Vrc, rc2=%Vrc\n", rc, rc2);
     573                                            g_cErrors++;
     574                                        }
     575
     576                                        rc = RTThreadWait(ThreadRecv1, 5000, &rc2);
     577                                        if (RT_SUCCESS(rc))
     578                                            ThreadRecv1 = NIL_RTTHREAD;
     579                                        if (VBOX_FAILURE(rc) || VBOX_FAILURE(rc2))
     580                                        {
     581                                            RTPrintf("tstIntNetR0: Failed waiting on receiver thread 1, rc=%Vrc, rc2=%Vrc\n", rc, rc2);
     582                                            g_cErrors++;
     583                                        }
     584
    546585                                        rc = INTNETR0IfClose(pIntNet, hIf0);
    547586                                        if (VBOX_SUCCESS(rc))
     
    555594                                            g_cErrors++;
    556595                                        }
     596
    557597                                        rc = INTNETR0IfClose(pIntNet, hIf1);
    558598                                        if (VBOX_SUCCESS(rc))
     
    567607                                        }
    568608
    569                                         rc = RTThreadWait(ThreadRecv0, 5000, &rc2);
    570                                         if (VBOX_FAILURE(rc) || VBOX_FAILURE(rc2))
    571                                         {
    572                                             RTPrintf("tstIntNetR0: Failed waiting on receiver thread 0, rc=%Vrc, rc2=%Vrc\n", rc, rc2);
    573                                             g_cErrors++;
    574                                         }
    575 
    576                                         rc = RTThreadWait(ThreadRecv1, 5000, &rc2);
    577                                         if (VBOX_FAILURE(rc) || VBOX_FAILURE(rc2))
    578                                         {
    579                                             RTPrintf("tstIntNetR0: Failed waiting on receiver thread 1, rc=%Vrc, rc2=%Vrc\n", rc, rc2);
    580                                             g_cErrors++;
    581                                         }
    582609
    583610                                        /* check if the network still exist... */
     
    593620                                        g_cErrors++;
    594621                                    }
     622
     623                                    /*
     624                                     * Give them a chance to complete...
     625                                     */
     626                                    RTThreadWait(ThreadRecv0, 5000, NULL);
     627                                    RTThreadWait(ThreadRecv1, 5000, NULL);
     628                                    RTThreadWait(ThreadSend0, 5000, NULL);
     629                                    RTThreadWait(ThreadSend1, 5000, NULL);
     630
    595631                                }
    596632                                else
     
    618654                    g_cErrors++;
    619655                }
     656
     657                if (hIf1 != INTNET_HANDLE_INVALID)
     658                    rc = INTNETR0IfClose(pIntNet, hIf1);
    620659            }
    621660            else
     
    624663                g_cErrors++;
    625664            }
     665
     666            if (hIf0 != INTNET_HANDLE_INVALID)
     667                rc = INTNETR0IfClose(pIntNet, hIf0);
    626668        }
    627669        else
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