VirtualBox

Ignore:
Timestamp:
Jul 15, 2008 8:00:27 PM (16 years ago)
Author:
vboxsync
Message:

intnet: More TrunkIf code.

File:
1 edited

Legend:

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

    r10677 r10681  
    3636#include <iprt/assert.h>
    3737#include <iprt/string.h>
     38#include <iprt/time.h>
    3839
    3940
     
    9798{
    9899    /** The port interface we present to the component. */
    99     INTNETTRUNKSWPORT   SwitchPort;
     100    INTNETTRUNKSWPORT       SwitchPort;
    100101    /** The port interface we get from the component. */
    101     PINTNETTRUNKIFPORT  pIfPort;
     102    PINTNETTRUNKIFPORT      pIfPort;
    102103    /** The trunk mutex that serializes all calls <b>to</b> the component. */
    103     RTSEMFASTMUTEX      FastMutex;
     104    RTSEMFASTMUTEX          FastMutex;
     105    /** Pointer to the network we're connect to.
     106     * This may be NULL if we're orphaned? */
     107    struct INTNETNETWORK   *pNetwork;
     108    /** Whether to supply physical addresses with the outbound SGs. */
     109    bool volatile           fPhysSG;
    104110} INTNETTRUNKIF;
    105111/** Pointer to a trunk interface. */
    106112typedef INTNETTRUNKIF *PINTNETTRUNKIF;
     113
     114/** Converts a pointer to INTNETTRUNKIF::SwitchPort to a PINTNETTRUNKIF. */
     115#define INTNET_SWITCHPORT_2_TRUNKIF(pSwitchPort) ((PINTNETTRUNKIF)(pSwitchPort))
    107116
    108117
     
    118127     * This is protected by the INTNET::FastMutex. */
    119128    PINTNETIF               pIFs;
     129    /** Pointer to the trunk interface.
     130     * Can be NULL if there is no trunk connection. */
     131    PINTNETTRUNKIF          pTrunkIF;
    120132    /** The network mutex.
    121133     * It protects everything dealing with this network. */
     
    191203    INTNETHT                IfHandles;
    192204} INTNET;
     205
     206
     207/*******************************************************************************
     208*   Internal Functions                                                         *
     209*******************************************************************************/
     210static PINTNETTRUNKIF intnetTrunkIfRetain(PINTNETTRUNKIF pThis);
     211static void intnetTrunkIfRelease(PINTNETTRUNKIF pThis);
     212static bool intnetTrunkIfOutLock(PINTNETTRUNKIF pThis);
     213static void intnetTrunkIfOutUnlock(PINTNETTRUNKIF pThis);
    193214
    194215
     
    12531274
    12541275
    1255 #ifdef IN_RING0
     1276
     1277
    12561278
    12571279/** @copydoc INTNETTRUNKSWPORT::pfnSetSGPhys */
    1258 static DECLCALLBACK(bool) intnetTrunkIfPortSetSGPhys(PINTNETTRUNKSWPORT pIfPort, bool fEnable)
    1259 {
     1280static DECLCALLBACK(bool) intnetTrunkIfPortSetSGPhys(PINTNETTRUNKSWPORT pSwitchPort, bool fEnable)
     1281{
     1282    PINTNETTRUNKIF pThis = INTNET_SWITCHPORT_2_TRUNKIF(pSwitchPort);
    12601283    AssertMsgFailed(("Not implemented because it wasn't required on Darwin\n"));
     1284    return ASMAtomicXchgBool(&pThis->fPhysSG, fEnable);
     1285}
     1286
     1287
     1288/** @copydoc INTNETTRUNKSWPORT::pfnRecv */
     1289static DECLCALLBACK(bool) intnetTrunkIfPortRecv(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG, uint32_t fSrc)
     1290{
     1291    PINTNETTRUNKIF pThis = INTNET_SWITCHPORT_2_TRUNKIF(pSwitchPort);
     1292    PINTNETNETWORK pNetwork = pThis->pNetwork;
     1293
     1294    /* assert some sanity */
     1295    AssertPtrReturn(pNetwork, false);
     1296    AssertReturn(pNetwork->FastMutex != NIL_RTSEMFASTMUTEX, false);
     1297    AssertPtr(pSG);
     1298    Assert(fSrc);
     1299
     1300    /*
     1301     *
     1302     */
     1303
     1304
    12611305    return false;
    12621306}
    12631307
    12641308
    1265 /** @copydoc INTNETTRUNKSWPORT::pfnRecv */
    1266 static DECLCALLBACK(bool) intnetTrunkIfPortRecv(PINTNETTRUNKSWPORT pIfPort, PINTNETSG pSG, uint32_t fSrc)
    1267 {
     1309/** @copydoc INTNETTRUNKSWPORT::pfnSGRetain */
     1310static DECLCALLBACK(void) intnetTrunkIfPortSGRetain(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG)
     1311{
     1312    PINTNETTRUNKIF pThis = INTNET_SWITCHPORT_2_TRUNKIF(pSwitchPort);
     1313    PINTNETNETWORK pNetwork = pThis->pNetwork;
     1314
     1315    /* assert some sanity */
     1316    AssertPtrReturnVoid(pNetwork);
     1317    AssertReturnVoid(pNetwork->FastMutex != NIL_RTSEMFASTMUTEX);
     1318    AssertPtr(pSG);
     1319    Assert(pSG->cUsers > 0);
     1320
     1321    /* do it. */
     1322    ++pSG->cUsers;
     1323}
     1324
     1325
     1326/** @copydoc INTNETTRUNKSWPORT::pfnSGRelease */
     1327static DECLCALLBACK(void) intnetTrunkIfPortSGRelease(PINTNETTRUNKSWPORT pSwitchPort, PINTNETSG pSG)
     1328{
     1329    PINTNETTRUNKIF pThis = INTNET_SWITCHPORT_2_TRUNKIF(pSwitchPort);
     1330    PINTNETNETWORK pNetwork = pThis->pNetwork;
     1331
     1332    /* assert some sanity */
     1333    AssertPtrReturnVoid(pNetwork);
     1334    AssertReturnVoid(pNetwork->FastMutex != NIL_RTSEMFASTMUTEX);
     1335    AssertPtr(pSG);
     1336    Assert(pSG->cUsers > 0);
     1337
     1338    /*
     1339     * Free it?
     1340     */
     1341    if (!--pSG->cUsers)
     1342    {
     1343        /** @todo later */
     1344    }
     1345}
     1346
     1347
     1348/**
     1349 * Retain the trunk interface.
     1350 *
     1351 * @returns pThis.
     1352 *
     1353 * @param   pThis       The trunk.
     1354 *
     1355 * @remarks Any locks.
     1356 */
     1357static PINTNETTRUNKIF intnetTrunkIfRetain(PINTNETTRUNKIF pThis)
     1358{
     1359    if (pThis && pThis->pIfPort)
     1360        pThis->pIfPort->pfnRetain(pThis->pIfPort);
     1361    return pThis;
     1362}
     1363
     1364
     1365/**
     1366 * Release the trunk interface.
     1367 *
     1368 * @param   pThis       The trunk.
     1369 */
     1370static void intnetTrunkIfRelease(PINTNETTRUNKIF pThis)
     1371{
     1372    if (pThis && pThis->pIfPort)
     1373        pThis->pIfPort->pfnRelease(pThis->pIfPort);
     1374}
     1375
     1376
     1377/**
     1378 * Takes the out-bound trunk lock.
     1379 *
     1380 * This will ensure that pIfPort is valid.
     1381 *
     1382 * @returns success indicator.
     1383 * @param   pThis       The trunk.
     1384 *
     1385 * @remarks No locks other than the create/destroy one.
     1386 */
     1387static bool intnetTrunkIfOutLock(PINTNETTRUNKIF pThis)
     1388{
     1389    AssertPtrReturn(pThis, false);
     1390    int rc = RTSemFastMutexRequest(pThis->FastMutex);
     1391    if (RT_SUCCESS(rc))
     1392    {
     1393        if (RT_LIKELY(pThis->pIfPort))
     1394            return true;
     1395        RTSemFastMutexRelease(pThis->FastMutex);
     1396    }
     1397    else
     1398        AssertMsg(rc == VERR_SEM_DESTROYED, ("%Rrc\n", rc));
    12681399    return false;
    12691400}
    12701401
    12711402
    1272 /** @copydoc INTNETTRUNKSWPORT::pfnSGRetain */
    1273 static DECLCALLBACK(void) intnetTrunkIfPortSGRetain(PINTNETTRUNKSWPORT pIfPort, PINTNETSG pSG)
    1274 {
    1275 
    1276 }
    1277 
    1278 
    1279 /** @copydoc INTNETTRUNKSWPORT::pfnSGRelease */
    1280 static DECLCALLBACK(void) intnetTrunkIfPortSGRelease(PINTNETTRUNKSWPORT pIfPort, PINTNETSG pSG)
    1281 {
    1282 
     1403/**
     1404 * Releases the out-bound trunk lock.
     1405 *
     1406 * @param   pThis       The trunk.
     1407 */
     1408static void intnetTrunkIfOutUnlock(PINTNETTRUNKIF pThis)
     1409{
     1410    if (pThis)
     1411    {
     1412        int rc = RTSemFastMutexRelease(pThis->FastMutex);
     1413        AssertRC(rc);
     1414    }
     1415}
     1416
     1417
     1418/**
     1419 * Activates the trunk interface.
     1420 *
     1421 * @param   pThis       The trunk.
     1422 * @param   fActive     What to do with it.
     1423 *
     1424 * @remarks Caller may only own the create/destroy lock.
     1425 */
     1426static void intnetTrunkIfActivate(PINTNETTRUNKIF pThis, bool fActive)
     1427{
     1428    if (intnetTrunkIfOutLock(pThis))
     1429    {
     1430        pThis->pIfPort->pfnSetActive(pThis->pIfPort, fActive);
     1431        intnetTrunkIfOutUnlock(pThis);
     1432    }
     1433}
     1434
     1435
     1436/**
     1437 * Shutdown the trunk interface.
     1438 *
     1439 * @param   pThis       The trunk.
     1440 * @param   pNetworks   The network.
     1441 *
     1442 * @remarks The caller must *NOT* hold the network lock. The global
     1443 *          create/destroy lock is fine though.
     1444 */
     1445static void intnetTrunkIfDestroy(PINTNETTRUNKIF pThis, PINTNETNETWORK pNetwork)
     1446{
     1447    /* assert sanity */
     1448    if (!pThis)
     1449        return;
     1450    AssertPtr(pThis);
     1451    Assert(pThis->pNetwork == pNetwork);
     1452    AssertPtrNull(pThis->pIfPort);
     1453
     1454    /*
     1455     * The interface has already been deactivated, we just to wait for
     1456     * it to become idle before we can disconnect and release it.
     1457     */
     1458    PINTNETTRUNKIFPORT pIfPort = pThis->pIfPort;
     1459    if (pIfPort)
     1460    {
     1461        intnetTrunkIfOutLock(pThis);
     1462
     1463        /* unset it */
     1464        pThis->pIfPort = NULL;
     1465
     1466        /* wait in portions so we can complain ever now an then. */
     1467        uint64_t StartTS = RTTimeSystemNanoTS();
     1468        int rc = pIfPort->pfnWaitForIdle(pIfPort, 10*1000);
     1469        if (RT_FAILURE(rc))
     1470        {
     1471            LogRel(("intnet: '%s' did't become idle in %RU64 ns (%Rrc).\n",
     1472                    pNetwork->szName, RTTimeSystemNanoTS() - StartTS, rc));
     1473            Assert(rc == VERR_TIMEOUT);
     1474            while (     RT_FAILURE(rc)
     1475                   &&   RTTimeSystemNanoTS() - StartTS < UINT64_C(30000000000)) /* 30 sec */
     1476                rc = pIfPort->pfnWaitForIdle(pIfPort, 10*1000);
     1477            if (rc == VERR_TIMEOUT)
     1478            {
     1479                LogRel(("intnet: '%s' did't become idle in %RU64 ns (%Rrc).\n",
     1480                        pNetwork->szName, RTTimeSystemNanoTS() - StartTS, rc));
     1481                while (     rc == VERR_TIMEOUT
     1482                       &&   RTTimeSystemNanoTS() - StartTS < UINT64_C(360000000000)) /* 360 sec */
     1483                    rc = pIfPort->pfnWaitForIdle(pIfPort, 30*1000);
     1484                if (RT_FAILURE(rc))
     1485                {
     1486                    LogRel(("intnet: '%s' did't become idle in %RU64 ns (%Rrc), giving up.\n",
     1487                            pNetwork->szName, RTTimeSystemNanoTS() - StartTS, rc));
     1488                    AssertRC(rc);
     1489                }
     1490            }
     1491        }
     1492
     1493        /* disconnect & release it. */
     1494        pIfPort->pfnDisconnectAndRelease(pIfPort);
     1495    }
     1496
     1497    /*
     1498     * Free up the resources.
     1499     */
     1500    RTSEMFASTMUTEX FastMutex = pThis->FastMutex;
     1501    pThis->FastMutex = NIL_RTSEMFASTMUTEX;
     1502    pThis->pNetwork = NULL;
     1503    RTSemFastMutexRelease(FastMutex);
     1504    RTSemFastMutexDestroy(FastMutex);
     1505    RTMemFree(pThis);
    12831506}
    12841507
     
    13351558    pTrunkIF->SwitchPort.u32VersionEnd  = INTNETTRUNKSWPORT_VERSION;
    13361559    //pTrunkIF->pIfPort = NULL;
     1560    pTrunkIF->pNetwork = pNetwork;
     1561    //pTrunkIF->fPhysSG = false;
    13371562    int rc = RTSemFastMutexCreate(&pTrunkIF->FastMutex);
    13381563    if (RT_SUCCESS(rc))
    13391564    {
     1565#ifdef IN_RING0 /* (testcase is ring-3) */
    13401566        /*
    13411567         * Query the factory we want, then use it create and connect the trunk.
     
    13501576            {
    13511577                Assert(pTrunkIF->pIfPort);
     1578                pNetwork->pTrunkIF = pTrunkIF;
    13521579                LogFlow(("intnetNetworkCreateTrunkConnection: VINF_SUCCESS - pszName=%s szTrunk=%s Network=%s\n",
    13531580                         rc, pszName, pNetwork->szTrunk, pNetwork->szName));
     
    13551582            }
    13561583        }
    1357 
    1358         RTMemFree(pTrunkIF);
    1359     }
     1584#endif /* IN_RING0 */
     1585        RTSemFastMutexDestroy(pTrunkIF->FastMutex);
     1586    }
     1587    RTMemFree(pTrunkIF);
    13601588    LogFlow(("intnetNetworkCreateTrunkConnection: %Rrc - pszName=%s szTrunk=%s Network=%s\n",
    13611589             rc, pszName, pNetwork->szTrunk, pNetwork->szName));
     
    13631591}
    13641592
    1365 #endif /* IN_RING0 */
    13661593
    13671594
     
    13991626    Assert(pNetwork->pIntNet == pIntNet);
    14001627
     1628    /* take the create/destroy sem. */
    14011629    RTSemFastMutexRequest(pIntNet->FastMutex);
    14021630
     1631    /*
     1632     * Deactivate the trunk connection first (if any).
     1633     */
     1634    if (pNetwork->pTrunkIF)
     1635        intnetTrunkIfActivate(pNetwork->pTrunkIF, false /* fActive */);
    14031636
    14041637    /*
     
    14211654    pNetwork->pvObj = NULL;
    14221655
    1423     RTSemFastMutexRequest(pNetwork->FastMutex);
    1424 
    14251656    /*
    14261657     * Because of the undefined order of the per session object dereferencing when closing a session,
     
    14281659     * deal with this by simply orphaning the interfaces.
    14291660     */
     1661    RTSemFastMutexRequest(pNetwork->FastMutex);
     1662
    14301663    PINTNETIF pCur = pNetwork->pIFs;
    14311664    while (pCur)
     
    14371670    }
    14381671
     1672    /* Grab and zap the trunk pointer before leaving the mutex. */
     1673    PINTNETTRUNKIF pTrunkIF = pNetwork->pTrunkIF;
     1674    pNetwork->pTrunkIF = NULL;
     1675
    14391676    RTSemFastMutexRelease(pNetwork->FastMutex);
     1677
     1678    /*
     1679     * If there is a trunk, delete it.
     1680     * Note that this may tak a while if we're unlucky...
     1681     */
     1682    if (pTrunkIF)
     1683        intnetTrunkIfDestroy(pTrunkIF, pNetwork);
    14401684
    14411685    /*
     
    14461690    RTMemFree(pNetwork);
    14471691
     1692    /* release the create/destroy sem. (can be done before trunk destruction.) */
    14481693    RTSemFastMutexRelease(pIntNet->FastMutex);
    14491694}
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