VirtualBox

Ignore:
Timestamp:
Oct 22, 2015 3:11:33 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
103610
Message:

VBoxNetAdp: G/c VBOXANETADP_DO_NOT_USE_NETFLT code that has never been
used. Same object code is generated. On an off chance we need it
again, it's always there in the version history.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdp.c

    r58340 r58380  
    3636#include <VBox/err.h>
    3737#include <iprt/string.h>
    38 
    39 #ifdef VBOXANETADP_DO_NOT_USE_NETFLT
    40 #error "this code is broken"
    41 
    42 #include <VBox/sup.h>
    43 #include <iprt/assert.h>
    44 #include <iprt/spinlock.h>
    45 #include <iprt/uuid.h>
    46 #include <VBox/version.h>
    47 
    48 /** r=bird: why is this here in the agnostic code? */
    49 #ifdef RT_OS_DARWIN
    50 # include <net/ethernet.h>
    51 # include <net/if_ether.h>
    52 # include <net/if_types.h>
    53 # include <sys/socket.h>
    54 # include <net/if.h>
    55 # include <net/if_dl.h>
    56 # include <sys/errno.h>
    57 # include <sys/param.h>
    58 #endif
    59 
    60 
    61 /*********************************************************************************************************************************
    62 *   Defined Constants And Macros                                                                                                 *
    63 *********************************************************************************************************************************/
    64 #define IFPORT_2_VBOXNETADP(pIfPort) \
    65     ( (PVBOXNETADP)((uint8_t *)pIfPort - RT_OFFSETOF(VBOXNETADP, MyPort)) )
    66 
    67 
    68 AssertCompileMemberSize(VBOXNETADP, enmState, sizeof(uint32_t));
    69 
    70 /**
    71  * Gets the enmState member atomically.
    72  *
    73  * Used for all reads.
    74  *
    75  * @returns The enmState value.
    76  * @param   pThis           The instance.
    77  */
    78 DECLINLINE(VBOXNETADPSTATE) vboxNetAdpGetState(PVBOXNETADP pThis)
    79 {
    80     return (VBOXNETADPSTATE)ASMAtomicUoReadU32((uint32_t volatile *)&pThis->enmState);
    81 }
    82 
    83 
    84 /**
    85  * Sets the enmState member atomically.
    86  *
    87  * Used for all updates.
    88  *
    89  * @param   pThis           The instance.
    90  * @param   enmNewState     The new value.
    91  */
    92 DECLINLINE(void) vboxNetAdpSetState(PVBOXNETADP pThis, VBOXNETADPSTATE enmNewState)
    93 {
    94     Log(("vboxNetAdpSetState: pThis=%p, state change: %d -> %d.\n", pThis, vboxNetAdpGetState(pThis), enmNewState));
    95     ASMAtomicWriteU32((uint32_t volatile *)&pThis->enmState, enmNewState);
    96 }
    97 
    98 
    99 /**
    100  * Sets the enmState member atomically after first acquiring the spinlock.
    101  *
    102  * Used for all updates.
    103  *
    104  * @param   pThis           The instance.
    105  * @param   enmNewState     The new value.
    106  */
    107 DECLINLINE(void) vboxNetAdpSetStateWithLock(PVBOXNETADP pThis, VBOXNETADPSTATE enmNewState)
    108 {
    109     Log(("vboxNetAdpSetStateWithLock: pThis=%p, state=%d.\n", pThis, enmNewState));
    110     RTSpinlockAcquire(pThis->hSpinlock);
    111     vboxNetAdpSetState(pThis, enmNewState);
    112     RTSpinlockRelease(pThis->hSpinlock);
    113 }
    114 
    115 
    116 /**
    117  * Gets the enmState member with locking.
    118  *
    119  * Used for all reads.
    120  *
    121  * @returns The enmState value.
    122  * @param   pThis           The instance.
    123  */
    124 DECLINLINE(VBOXNETADPSTATE) vboxNetAdpGetStateWithLock(PVBOXNETADP pThis)
    125 {
    126     VBOXNETADPSTATE enmState;
    127     RTSpinlockAcquire(pThis->hSpinlock);
    128     enmState = vboxNetAdpGetState(pThis);
    129     RTSpinlockRelease(pThis->hSpinlock);
    130     Log(("vboxNetAdpGetStateWithLock: pThis=%p, state=%d.\n", pThis, enmState));
    131     return enmState;
    132 }
    133 
    134 
    135 /**
    136  * Checks and sets the enmState member atomically.
    137  *
    138  * Used for all updates.
    139  *
    140  * @returns true if the state has been changed.
    141  * @param   pThis           The instance.
    142  * @param   enmNewState     The new value.
    143  */
    144 DECLINLINE(bool) vboxNetAdpCheckAndSetState(PVBOXNETADP pThis, VBOXNETADPSTATE enmOldState, VBOXNETADPSTATE enmNewState)
    145 {
    146     VBOXNETADPSTATE enmActualState;
    147     bool fRc = true; /* be optimistic */
    148 
    149     RTSpinlockAcquire(pThis->hSpinlock);
    150     enmActualState = vboxNetAdpGetState(pThis); /** @todo r=bird: ASMAtomicCmpXchgU32()*/
    151     if (enmActualState == enmOldState)
    152         vboxNetAdpSetState(pThis, enmNewState);
    153     else
    154         fRc = false;
    155     RTSpinlockRelease(pThis->hSpinlock);
    156 
    157     if (fRc)
    158         Log(("vboxNetAdpCheckAndSetState: pThis=%p, state changed: %d -> %d.\n", pThis, enmOldState, enmNewState));
    159     else
    160         Log(("vboxNetAdpCheckAndSetState: pThis=%p, no state change: %d != %d (expected).\n", pThis, enmActualState, enmOldState));
    161     return fRc;
    162 }
    163 
    164 
    165 /**
    166  * Finds a instance by its name, the caller does the locking.
    167  *
    168  * @returns Pointer to the instance by the given name. NULL if not found.
    169  * @param   pGlobals        The globals.
    170  * @param   pszName         The name of the instance.
    171  */
    172 static PVBOXNETADP vboxNetAdpFind(PVBOXNETADPGLOBALS pGlobals, const char *pszName)
    173 {
    174     unsigned i;
    175 
    176     for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++)
    177     {
    178         PVBOXNETADP pThis = &pGlobals->aAdapters[i];
    179         RTSpinlockAcquire(pThis->hSpinlock);
    180         if (    vboxNetAdpGetState(pThis)
    181             &&  !strcmp(pThis->szName, pszName))
    182         {
    183             RTSpinlockRelease(pThis->hSpinlock);
    184             return pThis;
    185         }
    186         RTSpinlockRelease(pThis->hSpinlock);
    187     }
    188     return NULL;
    189 }
    190 
    191 
    192 /**
    193  * Releases a reference to the specified instance.
    194  *
    195  * @param   pThis           The instance.
    196  * @param   fBusy           Whether the busy counter should be decremented too.
    197  */
    198 DECLHIDDEN(void) vboxNetAdpRelease(PVBOXNETADP pThis)
    199 {
    200     uint32_t cRefs;
    201 
    202     /*
    203      * Paranoid Android.
    204      */
    205     AssertPtr(pThis);
    206     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    207     Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
    208     Assert(vboxNetAdpGetState(pThis) > kVBoxNetAdpState_Invalid);
    209     AssertPtr(pThis->pGlobals);
    210     Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
    211     Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
    212     Assert(pThis->szName[0]);
    213 
    214     /*
    215      * The object reference counting.
    216      */
    217     cRefs = ASMAtomicDecU32(&pThis->cRefs);
    218     Assert(cRefs < UINT32_MAX / 2);
    219 }
    220 
    221 
    222 /**
    223  * Decrements the busy counter and does idle wakeup.
    224  *
    225  * @param   pThis           The instance.
    226  */
    227 DECLHIDDEN(void) vboxNetAdpIdle(PVBOXNETADP pThis)
    228 {
    229     uint32_t cBusy;
    230 
    231     /*
    232      * Paranoid Android.
    233      */
    234     AssertPtr(pThis);
    235     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    236     Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
    237     Assert(vboxNetAdpGetState(pThis) >= kVBoxNetAdpState_Connected);
    238     AssertPtr(pThis->pGlobals);
    239     Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
    240 
    241     cBusy = ASMAtomicDecU32(&pThis->cBusy);
    242     if (!cBusy)
    243     {
    244         int rc = RTSemEventSignal(pThis->hEventIdle);
    245         AssertRC(rc);
    246     }
    247     else
    248         Assert(cBusy < UINT32_MAX / 2);
    249 }
    250 
    251 
    252 /**
    253  * Retains a reference to the specified instance.
    254  *
    255  * @param   pThis           The instance.
    256  */
    257 DECLHIDDEN(void) vboxNetAdpRetain(PVBOXNETADP pThis)
    258 {
    259     uint32_t cRefs;
    260 
    261     /*
    262      * Paranoid Android.
    263      */
    264     AssertPtr(pThis);
    265     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    266     Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
    267     Assert(vboxNetAdpGetState(pThis) > kVBoxNetAdpState_Invalid);
    268     AssertPtr(pThis->pGlobals);
    269     Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
    270     Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
    271     Assert(pThis->szName[0]);
    272 
    273     /*
    274      * Retain the object.
    275      */
    276     cRefs = ASMAtomicIncU32(&pThis->cRefs);
    277     Assert(cRefs > 1 && cRefs < UINT32_MAX / 2);
    278 
    279     NOREF(cRefs);
    280 }
    281 
    282 
    283 /**
    284  * Increments busy counter.
    285  *
    286  * @param   pThis           The instance.
    287  */
    288 DECLHIDDEN(void) vboxNetAdpBusy(PVBOXNETADP pThis)
    289 {
    290     uint32_t cBusy;
    291 
    292     /*
    293      * Are we vigilant enough?
    294      */
    295     AssertPtr(pThis);
    296     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    297     Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
    298     Assert(vboxNetAdpGetState(pThis) >= kVBoxNetAdpState_Connected);
    299     AssertPtr(pThis->pGlobals);
    300     Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
    301     cBusy = ASMAtomicIncU32(&pThis->cBusy);
    302     Assert(cBusy > 0 && cBusy < UINT32_MAX / 2);
    303 
    304     NOREF(cBusy);
    305 }
    306 
    307 
    308 /**
    309  * Generate a suitable MAC address.
    310  *
    311  * @param   pThis       The instance.
    312  * @param   pMac        Where to return the MAC address.
    313  */
    314 DECLHIDDEN(void) vboxNetAdpComposeMACAddress(PVBOXNETADP pThis, PRTMAC pMac)
    315 {
    316 #if 0 /* Use a locally administered version of the OUI we use for the guest NICs. */
    317     pMac->au8[0] = 0x08 | 2;
    318     pMac->au8[1] = 0x00;
    319     pMac->au8[2] = 0x27;
    320 #else /* this is what \0vb comes down to. It seems to be unassigned atm. */
    321     pMac->au8[0] = 0;
    322     pMac->au8[1] = 0x76;
    323     pMac->au8[2] = 0x62;
    324 #endif
    325 
    326     pMac->au8[3] = 0; /* pThis->uUnit >> 16; */
    327     pMac->au8[4] = 0; /* pThis->uUnit >> 8; */
    328     pMac->au8[5] = pThis->uUnit;
    329 }
    330 
    331 
    332 /**
    333  * Checks if receive is possible and increases busy and ref counters if so.
    334  *
    335  * @param   pThis           The instance.
    336  */
    337 DECLHIDDEN(bool) vboxNetAdpPrepareToReceive(PVBOXNETADP pThis)
    338 {
    339     bool fCanReceive  = false;
    340     /*
    341      * Input validation.
    342      */
    343     AssertPtr(pThis);
    344     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    345     RTSpinlockAcquire(pThis->hSpinlock);
    346     if (vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Active)
    347     {
    348         fCanReceive = true;
    349         vboxNetAdpRetain(pThis);
    350         vboxNetAdpBusy(pThis);
    351     }
    352     RTSpinlockRelease(pThis->hSpinlock);
    353     Log(("vboxNetAdpPrepareToReceive: fCanReceive=%d.\n", fCanReceive));
    354 
    355     return fCanReceive;
    356 }
    357 
    358 
    359 /**
    360  * Forwards scatter/gather list to internal network and decreases busy and ref counters.
    361  *
    362  * @param   pThis           The instance.
    363  */
    364 DECLHIDDEN(void) vboxNetAdpReceive(PVBOXNETADP pThis, PINTNETSG pSG)
    365 {
    366     /*
    367      * Input validation.
    368      */
    369     AssertPtr(pThis);
    370     AssertPtr(pSG);
    371     AssertPtr(pThis->pSwitchPort);
    372     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    373     Log(("vboxNetAdpReceive: forwarding packet to internal net...\n"));
    374     pThis->pSwitchPort->pfnRecv(pThis->pSwitchPort, pSG, INTNETTRUNKDIR_HOST);
    375     vboxNetAdpIdle(pThis);
    376     vboxNetAdpRelease(pThis);
    377 }
    378 
    379 
    380 /**
    381  * Decreases busy and ref counters.
    382  *
    383  * @param   pThis           The instance.
    384  */
    385 DECLHIDDEN(void) vboxNetAdpCancelReceive(PVBOXNETADP pThis)
    386 {
    387     Log(("vboxNetAdpCancelReceive: cancelled.\n"));
    388     vboxNetAdpIdle(pThis);
    389     vboxNetAdpRelease(pThis);
    390 }
    391 
    392 
    393 /**
    394  * @copydoc INTNETTRUNKIFPORT::pfnXmit
    395  */
    396 static DECLCALLBACK(int) vboxNetAdpPortXmit(PINTNETTRUNKIFPORT pIfPort, PINTNETSG pSG, uint32_t fDst)
    397 {
    398     PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
    399     int rc = VINF_SUCCESS;
    400 
    401     /*
    402      * Input validation.
    403      */
    404     AssertPtr(pThis);
    405     AssertPtr(pSG);
    406     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    407 
    408     Log(("vboxNetAdpPortXmit: outgoing packet (len=%d)\n", pSG->cbTotal));
    409 
    410     /*
    411      * Do a retain/busy, invoke the OS specific code.
    412      */
    413     RTSpinlockAcquire(pThis->hSpinlock);
    414     if (vboxNetAdpGetState(pThis) != kVBoxNetAdpState_Active)
    415     {
    416         RTSpinlockRelease(pThis->hSpinlock);
    417         Log(("vboxNetAdpReceive: Dropping incoming packet for inactive interface %s.\n",
    418              pThis->szName));
    419         return VERR_INVALID_STATE;
    420     }
    421     vboxNetAdpRetain(pThis);
    422     vboxNetAdpBusy(pThis);
    423     RTSpinlockRelease(pThis->hSpinlock);
    424 
    425     rc = vboxNetAdpPortOsXmit(pThis, pSG, fDst);
    426     vboxNetAdpIdle(pThis);
    427     vboxNetAdpRelease(pThis);
    428 
    429     return rc;
    430 }
    431 
    432 
    433 /**
    434  * @copydoc INTNETTRUNKIFPORT::pfnGetMacAddress
    435  */
    436 static DECLCALLBACK(void) vboxNetAdpPortGetMacAddress(PINTNETTRUNKIFPORT pIfPort, PRTMAC pMac)
    437 {
    438     PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
    439 
    440     /*
    441      * Input validation.
    442      */
    443     AssertPtr(pThis);
    444     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    445     Assert(vboxNetAdpGetStateWithLock(pThis) == kVBoxNetAdpState_Active);
    446 
    447     /*
    448      * Forward the question to the OS specific code.
    449      */
    450     vboxNetAdpPortOsGetMacAddress(pThis, pMac);
    451 }
    452 
    453 
    454 /**
    455  * @copydoc INTNETTRUNKIFPORT::pfnWaitForIdle
    456  */
    457 static DECLCALLBACK(int) vboxNetAdpPortWaitForIdle(PINTNETTRUNKIFPORT pIfPort, uint32_t cMillies)
    458 {
    459     int rc;
    460     PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
    461 
    462     /*
    463      * Input validation.
    464      */
    465     AssertPtr(pThis);
    466     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    467     AssertReturn(vboxNetAdpGetStateWithLock(pThis) >= kVBoxNetAdpState_Connected, VERR_INVALID_STATE);
    468 
    469     /*
    470      * Go to sleep on the semaphore after checking the busy count.
    471      */
    472     vboxNetAdpRetain(pThis);
    473 
    474     rc = VINF_SUCCESS;
    475     while (pThis->cBusy && RT_SUCCESS(rc))
    476         rc = RTSemEventWait(pThis->hEventIdle, cMillies); /** @todo make interruptible? */
    477 
    478     vboxNetAdpRelease(pThis);
    479 
    480     return rc;
    481 }
    482 
    483 
    484 /**
    485  * @copydoc INTNETTRUNKIFPORT::pfnSetActive
    486  */
    487 static DECLCALLBACK(bool) vboxNetAdpPortSetActive(PINTNETTRUNKIFPORT pIfPort, bool fActive)
    488 {
    489     bool fPreviouslyActive;
    490     PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
    491 
    492     /*
    493      * Input validation.
    494      */
    495     AssertPtr(pThis);
    496     AssertPtr(pThis->pGlobals);
    497     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    498 
    499     Log(("vboxNetAdpPortSetActive: pThis=%p, fActive=%d, state before: %d.\n", pThis, fActive, vboxNetAdpGetState(pThis)));
    500     RTSpinlockAcquire(pThis->hSpinlock);
    501 
    502     fPreviouslyActive = vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Active;
    503     if (fPreviouslyActive != fActive)
    504     {
    505         switch (vboxNetAdpGetState(pThis))
    506         {
    507             case kVBoxNetAdpState_Connected:
    508                 vboxNetAdpSetState(pThis, kVBoxNetAdpState_Active);
    509                 break;
    510             case kVBoxNetAdpState_Active:
    511                 vboxNetAdpSetState(pThis, kVBoxNetAdpState_Connected);
    512                 break;
    513             default:
    514                 break;
    515         }
    516     }
    517 
    518     RTSpinlockRelease(pThis->hSpinlock);
    519     Log(("vboxNetAdpPortSetActive: state after: %RTbool.\n", vboxNetAdpGetState(pThis)));
    520     return fPreviouslyActive;
    521 }
    522 
    523 
    524 /**
    525  * @copydoc INTNETTRUNKIFPORT::pfnDisconnectAndRelease
    526  */
    527 static DECLCALLBACK(void) vboxNetAdpPortDisconnectAndRelease(PINTNETTRUNKIFPORT pIfPort)
    528 {
    529     PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
    530 
    531     /*
    532      * Serious paranoia.
    533      */
    534     AssertPtr(pThis);
    535     Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION);
    536     Assert(pThis->MyPort.u32VersionEnd == INTNETTRUNKIFPORT_VERSION);
    537     AssertPtr(pThis->pGlobals);
    538     Assert(pThis->hEventIdle != NIL_RTSEMEVENT);
    539     Assert(pThis->hSpinlock != NIL_RTSPINLOCK);
    540 
    541 
    542     /*
    543      * Disconnect and release it.
    544      */
    545     RTSpinlockAcquire(pThis->hSpinlock);
    546     //Assert(vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Connected);
    547     Assert(!pThis->cBusy);
    548     vboxNetAdpSetState(pThis, kVBoxNetAdpState_Transitional);
    549     RTSpinlockRelease(pThis->hSpinlock);
    550 
    551     vboxNetAdpOsDisconnectIt(pThis);
    552     pThis->pSwitchPort = NULL;
    553 
    554     RTSpinlockAcquire(pThis->hSpinlock);
    555     vboxNetAdpSetState(pThis, kVBoxNetAdpState_Available);
    556     RTSpinlockRelease(pThis->hSpinlock);
    557 
    558     vboxNetAdpRelease(pThis);
    559 }
    560 
    561 
    562 /**
    563  * @copydoc INTNETTRUNKIFPORT::pfnRelease
    564  */
    565 static DECLCALLBACK(void) vboxNetAdpPortRelease(PINTNETTRUNKIFPORT pIfPort)
    566 {
    567     PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
    568     vboxNetAdpRelease(pThis);
    569 }
    570 
    571 
    572 /**
    573  * @copydoc INTNETTRUNKIFPORT::pfnRetain
    574  */
    575 static DECLCALLBACK(void) vboxNetAdpPortRetain(PINTNETTRUNKIFPORT pIfPort)
    576 {
    577     PVBOXNETADP pThis = IFPORT_2_VBOXNETADP(pIfPort);
    578     vboxNetAdpRetain(pThis);
    579 }
    580 
    581 
    582 int vboxNetAdpCreate(PINTNETTRUNKFACTORY pIfFactory, PVBOXNETADP *ppNew)
    583 {
    584     PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
    585     unsigned i;
    586     int rc;
    587 
    588     for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++)
    589     {
    590         PVBOXNETADP pThis = &pGlobals->aAdapters[i];
    591 
    592         if (vboxNetAdpCheckAndSetState(pThis, kVBoxNetAdpState_Invalid, kVBoxNetAdpState_Transitional))
    593         {
    594             /* Found an empty slot -- use it. */
    595             uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
    596             Assert(cRefs == 1);
    597             RTMAC Mac;
    598             vboxNetAdpComposeMACAddress(pThis, &Mac);
    599             rc = vboxNetAdpOsCreate(pThis, &Mac);
    600             *ppNew = pThis;
    601 
    602             RTSpinlockAcquire(pThis->hSpinlock);
    603             vboxNetAdpSetState(pThis, kVBoxNetAdpState_Available);
    604             RTSpinlockRelease(pThis->hSpinlock);
    605             return rc;
    606         }
    607     }
    608 
    609     /* All slots in adapter array are busy. */
    610     return VERR_OUT_OF_RESOURCES;
    611 }
    612 
    613 int vboxNetAdpDestroy(PVBOXNETADP pThis)
    614 {
    615     int rc = VINF_SUCCESS;
    616 
    617     RTSpinlockAcquire(pThis->hSpinlock);
    618     if (vboxNetAdpGetState(pThis) != kVBoxNetAdpState_Available || pThis->cBusy)
    619     {
    620         RTSpinlockRelease(pThis->hSpinlock);
    621         return VERR_INTNET_FLT_IF_BUSY;
    622     }
    623     vboxNetAdpSetState(pThis, kVBoxNetAdpState_Transitional);
    624     RTSpinlockRelease(pThis->hSpinlock);
    625     vboxNetAdpRelease(pThis);
    626 
    627     vboxNetAdpOsDestroy(pThis);
    628 
    629     RTSpinlockAcquire(pThis->hSpinlock);
    630     vboxNetAdpSetState(pThis, kVBoxNetAdpState_Invalid);
    631     RTSpinlockRelease(pThis->hSpinlock);
    632 
    633     return rc;
    634 }
    635 
    636 /**
    637  * Connects the instance to the specified switch port.
    638  *
    639  * Called while owning the lock. We're ASSUMING that the internal
    640  * networking code is already owning an recursive mutex, so, there
    641  * will be no deadlocks when vboxNetAdpOsConnectIt calls back into
    642  * it for setting preferences.
    643  *
    644  * @returns VBox status code.
    645  * @param   pThis               The instance.
    646  * @param   pSwitchPort         The port on the internal network 'switch'.
    647  * @param   ppIfPort            Where to return our port interface.
    648  */
    649 static int vboxNetAdpConnectIt(PVBOXNETADP pThis, PINTNETTRUNKSWPORT pSwitchPort, PINTNETTRUNKIFPORT *ppIfPort)
    650 {
    651     int rc;
    652 
    653     /*
    654      * Validate state.
    655      */
    656     Assert(!pThis->cBusy);
    657     Assert(vboxNetAdpGetStateWithLock(pThis) == kVBoxNetAdpState_Transitional);
    658 
    659     /*
    660      * Do the job.
    661      * Note that we're calling the os stuff while owning the semaphore here.
    662      */
    663     pThis->pSwitchPort = pSwitchPort;
    664     rc = vboxNetAdpOsConnectIt(pThis);
    665     if (RT_SUCCESS(rc))
    666     {
    667         *ppIfPort = &pThis->MyPort;
    668     }
    669     else
    670         pThis->pSwitchPort = NULL;
    671 
    672     return rc;
    673 }
    674 
    675 
    676 /**
    677  * @copydoc INTNETTRUNKFACTORY::pfnCreateAndConnect
    678  */
    679 static DECLCALLBACK(int) vboxNetAdpFactoryCreateAndConnect(PINTNETTRUNKFACTORY pIfFactory, const char *pszName,
    680                                                            PINTNETTRUNKSWPORT pSwitchPort, uint32_t fFlags,
    681                                                            PINTNETTRUNKIFPORT *ppIfPort)
    682 {
    683     PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
    684     PVBOXNETADP pThis;
    685     int rc;
    686 
    687     LogFlow(("vboxNetAdpFactoryCreateAndConnect: pszName=%p:{%s} fFlags=%#x\n", pszName, pszName, fFlags));
    688     Assert(pGlobals->cFactoryRefs > 0);
    689     AssertMsgReturn(!fFlags,
    690                     ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
    691 
    692     /*
    693      * Find instance, check if busy, connect if not.
    694      */
    695     pThis = vboxNetAdpFind(pGlobals, pszName);
    696     if (pThis)
    697     {
    698         if (vboxNetAdpCheckAndSetState(pThis, kVBoxNetAdpState_Available, kVBoxNetAdpState_Transitional))
    699         {
    700             vboxNetAdpRetain(pThis);
    701             rc = vboxNetAdpConnectIt(pThis, pSwitchPort, ppIfPort);
    702             vboxNetAdpSetStateWithLock(pThis, RT_SUCCESS(rc) ? kVBoxNetAdpState_Connected : kVBoxNetAdpState_Available);
    703         }
    704         else
    705             rc = VERR_INTNET_FLT_IF_BUSY;
    706     }
    707     else
    708         rc = VERR_INTNET_FLT_IF_NOT_FOUND;
    709 
    710     return rc;
    711 }
    712 
    713 
    714 /**
    715  * @copydoc INTNETTRUNKFACTORY::pfnRelease
    716  */
    717 static DECLCALLBACK(void) vboxNetAdpFactoryRelease(PINTNETTRUNKFACTORY pIfFactory)
    718 {
    719     PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pIfFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, TrunkFactory));
    720 
    721     int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
    722     Assert(cRefs >= 0); NOREF(cRefs);
    723     LogFlow(("vboxNetAdpFactoryRelease: cRefs=%d (new)\n", cRefs));
    724 }
    725 
    726 
    727 /**
    728  * Implements the SUPDRV component factor interface query method.
    729  *
    730  * @returns Pointer to an interface. NULL if not supported.
    731  *
    732  * @param   pSupDrvFactory      Pointer to the component factory registration structure.
    733  * @param   pSession            The session - unused.
    734  * @param   pszInterfaceUuid    The factory interface id.
    735  */
    736 static DECLCALLBACK(void *) vboxNetAdpQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
    737 {
    738     PVBOXNETADPGLOBALS pGlobals = (PVBOXNETADPGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXNETADPGLOBALS, SupDrvFactory));
    739 
    740     /*
    741      * Convert the UUID strings and compare them.
    742      */
    743     RTUUID UuidReq;
    744     int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
    745     if (RT_SUCCESS(rc))
    746     {
    747         if (!RTUuidCompareStr(&UuidReq, INTNETTRUNKFACTORY_UUID_STR))
    748         {
    749             ASMAtomicIncS32(&pGlobals->cFactoryRefs);
    750             return &pGlobals->TrunkFactory;
    751         }
    752 #ifdef LOG_ENABLED
    753         else
    754             Log(("VBoxNetAdp: unknown factory interface query (%s)\n", pszInterfaceUuid));
    755 #endif
    756     }
    757     else
    758         Log(("VBoxNetAdp: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
    759 
    760     return NULL;
    761 }
    762 
    763 
    764 /**
    765  * Checks whether the VBoxNetAdp wossname can be unloaded.
    766  *
    767  * This will return false if someone is currently using the module.
    768  *
    769  * @returns true if it's relatively safe to unload it, otherwise false.
    770  * @param   pGlobals        Pointer to the globals.
    771  */
    772 DECLHIDDEN(bool) vboxNetAdpCanUnload(PVBOXNETADPGLOBALS pGlobals)
    773 {
    774     bool fRc = true; /* Assume it can be unloaded. */
    775     unsigned i;
    776 
    777     for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++)
    778     {
    779         PVBOXNETADP pThis = &pGlobals->aAdapters[i];
    780         if (vboxNetAdpGetStateWithLock(&pGlobals->aAdapters[i]) >= kVBoxNetAdpState_Connected)
    781         {
    782             fRc = false;
    783             break; /* We already know the answer. */
    784         }
    785     }
    786     return fRc && ASMAtomicUoReadS32((int32_t volatile *)&pGlobals->cFactoryRefs) <= 0;
    787 }
    788 
    789 /**
    790  * tries to deinitialize Idc
    791  * we separate the globals settings "base" which is actually
    792  * "general" globals settings except for Idc, and idc.
    793  * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
    794  * thus it's not possible to make idc initialization from the driver startup routine for it,
    795  * though the "base is still needed for the driver to functions".
    796  * @param pGlobals
    797  * @return VINF_SUCCESS on success, VERR_WRONG_ORDER if we're busy.
    798  */
    799 DECLHIDDEN(int) vboxNetAdpTryDeleteIdc(PVBOXNETADPGLOBALS pGlobals)
    800 {
    801     int rc;
    802 
    803     Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
    804 
    805     /*
    806      * Check before trying to deregister the factory.
    807      */
    808     if (!vboxNetAdpCanUnload(pGlobals))
    809         return VERR_WRONG_ORDER;
    810 
    811     /*
    812      * Disconnect from SUPDRV and check that nobody raced us,
    813      * reconnect if that should happen.
    814      */
    815     rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
    816     AssertRC(rc);
    817     if (!vboxNetAdpCanUnload(pGlobals))
    818     {
    819         rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
    820         AssertRC(rc);
    821         return VERR_WRONG_ORDER;
    822     }
    823 
    824     SUPR0IdcClose(&pGlobals->SupDrvIDC);
    825 
    826     return rc;
    827 }
    828 
    829 static int vboxNetAdpSlotCreate(PVBOXNETADPGLOBALS pGlobals, unsigned uUnit, PVBOXNETADP pNew)
    830 {
    831     int rc;
    832 
    833     pNew->MyPort.u32Version             = INTNETTRUNKIFPORT_VERSION;
    834     pNew->MyPort.pfnRetain              = vboxNetAdpPortRetain;
    835     pNew->MyPort.pfnRelease             = vboxNetAdpPortRelease;
    836     pNew->MyPort.pfnDisconnectAndRelease= vboxNetAdpPortDisconnectAndRelease;
    837     pNew->MyPort.pfnSetState            = vboxNetAdpPortSetState;
    838     pNew->MyPort.pfnWaitForIdle         = vboxNetAdpPortWaitForIdle;
    839     pNew->MyPort.pfnXmit                = vboxNetAdpPortXmit;
    840     pNew->MyPort.u32VersionEnd          = INTNETTRUNKIFPORT_VERSION;
    841     pNew->pSwitchPort                   = NULL;
    842     pNew->pGlobals                      = pGlobals;
    843     pNew->hSpinlock                     = NIL_RTSPINLOCK;
    844     pNew->enmState                      = kVBoxNetAdpState_Invalid;
    845     pNew->cRefs                         = 0;
    846     pNew->cBusy                         = 0;
    847     pNew->hEventIdle                    = NIL_RTSEMEVENT;
    848 
    849     rc = RTSpinlockCreate(&pNew->hSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxNetAdptSlotCreate");
    850     if (RT_SUCCESS(rc))
    851     {
    852         rc = RTSemEventCreate(&pNew->hEventIdle);
    853         if (RT_SUCCESS(rc))
    854         {
    855             rc = vboxNetAdpOsInit(pNew);
    856             if (RT_SUCCESS(rc))
    857             {
    858                 return rc;
    859             }
    860             RTSemEventDestroy(pNew->hEventIdle);
    861             pNew->hEventIdle = NIL_RTSEMEVENT;
    862         }
    863         RTSpinlockDestroy(pNew->hSpinlock);
    864         pNew->hSpinlock = NIL_RTSPINLOCK;
    865     }
    866     return rc;
    867 }
    868 
    869 static void vboxNetAdpSlotDestroy(PVBOXNETADP pThis)
    870 {
    871     Assert(pThis->cRefs == 0);
    872     Assert(pThis->cBusy == 0);
    873     Assert(vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Invalid);
    874     if (pThis->hEventIdle != NIL_RTSEMEVENT)
    875     {
    876         RTSemEventDestroy(pThis->hEventIdle);
    877         pThis->hEventIdle = NIL_RTSEMEVENT;
    878     }
    879     if (pThis->hSpinlock != NIL_RTSPINLOCK)
    880     {
    881         RTSpinlockDestroy(pThis->hSpinlock);
    882         pThis->hSpinlock = NIL_RTSPINLOCK;
    883     }
    884 }
    885 
    886 /**
    887  * performs "base" globals deinitialization
    888  * we separate the globals settings "base" which is actually
    889  * "general" globals settings except for Idc, and idc.
    890  * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
    891  * thus it's not possible to make idc initialization from the driver startup routine for it,
    892  * though the "base is still needed for the driver to functions".
    893  * @param pGlobals
    894  * @return none
    895  */
    896 DECLHIDDEN(void) vboxNetAdpDeleteGlobalsBase(PVBOXNETADPGLOBALS pGlobals)
    897 {
    898     int i;
    899     /*
    900      * Release resources.
    901      */
    902     for (i = 0; i < (int)RT_ELEMENTS(pGlobals->aAdapters); i++)
    903         if (RT_SUCCESS(vboxNetAdpDestroy(&pGlobals->aAdapters[i])))
    904             vboxNetAdpSlotDestroy(&pGlobals->aAdapters[i]);
    905 
    906     RTSemFastMutexDestroy(pGlobals->hFastMtx);
    907     pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
    908 
    909 #ifdef VBOXNETADP_STATIC_CONFIG
    910     RTSemEventDestroy(pGlobals->hTimerEvent);
    911     pGlobals->hTimerEvent = NIL_RTSEMEVENT;
    912 #endif
    913 
    914 }
    915 
    916 
    917 /**
    918  * Called by the native part when the OS wants the driver to unload.
    919  *
    920  * @returns VINF_SUCCESS on success, VERR_WRONG_ORDER if we're busy.
    921  *
    922  * @param   pGlobals        Pointer to the globals.
    923  */
    924 DECLHIDDEN(int) vboxNetAdpTryDeleteGlobals(PVBOXNETADPGLOBALS pGlobals)
    925 {
    926     int rc = vboxNetAdpTryDeleteIdc(pGlobals);
    927     if (RT_SUCCESS(rc))
    928     {
    929         vboxNetAdpDeleteGlobalsBase(pGlobals);
    930     }
    931     return rc;
    932 }
    933 
    934 
    935 /**
    936  * performs the "base" globals initialization
    937  * we separate the globals initialization to globals "base" initialization which is actually
    938  * "general" globals initialization except for Idc not being initialized, and idc initialization.
    939  * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
    940  * thus it's not possible to make idc initialization from the driver startup routine for it.
    941  *
    942  * @returns VBox status code.
    943  * @param   pGlobals    Pointer to the globals. */
    944 DECLHIDDEN(int) vboxNetAdpInitGlobalsBase(PVBOXNETADPGLOBALS pGlobals)
    945 {
    946     /*
    947      * Initialize the common portions of the structure.
    948      */
    949     int i;
    950     int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
    951     if (RT_SUCCESS(rc))
    952     {
    953         memset(pGlobals->aAdapters, 0, sizeof(pGlobals->aAdapters));
    954         for (i = 0; i < (int)RT_ELEMENTS(pGlobals->aAdapters); i++)
    955         {
    956             rc = vboxNetAdpSlotCreate(pGlobals, i, &pGlobals->aAdapters[i]);
    957             if (RT_FAILURE(rc))
    958             {
    959                 /* Clean up. */
    960                 while (--i >= 0)
    961                     vboxNetAdpSlotDestroy(&pGlobals->aAdapters[i]);
    962                 Log(("vboxNetAdpInitGlobalsBase: Failed to create fast mutex (rc=%Rrc).\n", rc));
    963                 RTSemFastMutexDestroy(pGlobals->hFastMtx);
    964                 return rc;
    965             }
    966         }
    967         pGlobals->TrunkFactory.pfnRelease = vboxNetAdpFactoryRelease;
    968         pGlobals->TrunkFactory.pfnCreateAndConnect = vboxNetAdpFactoryCreateAndConnect;
    969 
    970         strcpy(pGlobals->SupDrvFactory.szName, "VBoxNetAdp");
    971         pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxNetAdpQueryFactoryInterface;
    972     }
    973 
    974     return rc;
    975 }
    976 
    977 /**
    978  * performs the Idc initialization
    979  * we separate the globals initialization to globals "base" initialization which is actually
    980  * "general" globals initialization except for Idc not being initialized, and idc initialization.
    981  * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
    982  * thus it's not possible to make idc initialization from the driver startup routine for it.
    983  *
    984  * @returns VBox status code.
    985  * @param   pGlobals    Pointer to the globals. */
    986 DECLHIDDEN(int) vboxNetAdpInitIdc(PVBOXNETADPGLOBALS pGlobals)
    987 {
    988     int rc;
    989     /*
    990      * Establish a connection to SUPDRV and register our component factory.
    991      */
    992     rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
    993     if (RT_SUCCESS(rc))
    994     {
    995         rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
    996         if (RT_SUCCESS(rc))
    997         {
    998 #if 1 /** @todo REMOVE ME! */
    999             PVBOXNETADP pTmp;
    1000             rc = vboxNetAdpCreate(&pGlobals->TrunkFactory, &pTmp);
    1001             if (RT_FAILURE(rc))
    1002                 Log(("Failed to create vboxnet0, rc=%Rrc.\n", rc));
    1003 #endif
    1004             Log(("VBoxNetAdp: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
    1005             return rc;
    1006         }
    1007 
    1008         /* bail out. */
    1009         LogRel(("VBoxNetAdp: Failed to register component factory, rc=%Rrc\n", rc));
    1010         SUPR0IdcClose(&pGlobals->SupDrvIDC);
    1011     }
    1012 
    1013     return rc;
    1014 }
    1015 
    1016 /**
    1017  * Called by the native driver/kext module initialization routine.
    1018  *
    1019  * It will initialize the common parts of the globals, assuming the caller
    1020  * has already taken care of the OS specific bits.
    1021  *
    1022  * @returns VBox status code.
    1023  * @param   pGlobals    Pointer to the globals.
    1024  */
    1025 DECLHIDDEN(int) vboxNetAdpInitGlobals(PVBOXNETADPGLOBALS pGlobals)
    1026 {
    1027     /*
    1028      * Initialize the common portions of the structure.
    1029      */
    1030     int rc = vboxNetAdpInitGlobalsBase(pGlobals);
    1031     if (RT_SUCCESS(rc))
    1032     {
    1033         rc = vboxNetAdpInitIdc(pGlobals);
    1034         if (RT_SUCCESS(rc))
    1035         {
    1036             return rc;
    1037         }
    1038 
    1039         /* bail out. */
    1040         vboxNetAdpDeleteGlobalsBase(pGlobals);
    1041     }
    1042 
    1043     return rc;
    1044 }
    1045 
    1046 #else /* !VBOXANETADP_DO_NOT_USE_NETFLT */
    104738
    104839
     
    1227218        vboxNetAdpDestroy(&g_aAdapters[i]);
    1228219}
    1229 #endif /* !VBOXANETADP_DO_NOT_USE_NETFLT */
Note: See TracChangeset for help on using the changeset viewer.

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