VirtualBox

Changeset 49414 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Nov 8, 2013 7:12:07 AM (11 years ago)
Author:
vboxsync
Message:

Network/Adapters: Fix wrong link state transition upon host resume (#7057)

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

Legend:

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

    r47580 r49414  
    15271527    if (pTimer == pThis->CTX_SUFF(pTXDTimer))
    15281528        return "TXD";
     1529    if (pTimer == pThis->CTX_SUFF(pLUTimer))
     1530        return "LinkUp";
    15291531    return "unknown";
    15301532}
     
    25182520}
    25192521
     2522#ifdef IN_RING3
     2523/**
     2524 * Bring up the link immediately.
     2525 *
     2526 * @param   pThis       The device state structure.
     2527 */
     2528DECLINLINE(void) e1kR3LinkUp(PE1KSTATE pThis)
     2529{
     2530    E1kLog(("%s Link is up\n", pThis->szPrf));
     2531    STATUS |= STATUS_LU;
     2532    Phy::setLinkStatus(&pThis->phy, true);
     2533    e1kRaiseInterrupt(pThis, VERR_SEM_BUSY, ICR_LSC);
     2534    if (pThis->pDrvR3)
     2535        pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, PDMNETWORKLINKSTATE_UP);
     2536}
     2537
     2538/**
     2539 * Bring down the link immediately.
     2540 *
     2541 * @param   pThis       The device state structure.
     2542 */
     2543DECLINLINE(void) e1kR3LinkDown(PE1KSTATE pThis)
     2544{
     2545    E1kLog(("%s Link is down\n", pThis->szPrf));
     2546    STATUS &= ~STATUS_LU;
     2547    Phy::setLinkStatus(&pThis->phy, false);
     2548    e1kRaiseInterrupt(pThis, VERR_SEM_BUSY, ICR_LSC);
     2549    if (pThis->pDrvR3)
     2550        pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, PDMNETWORKLINKSTATE_DOWN);
     2551}
     2552
     2553/**
     2554 * Bring down the link temporarily.
     2555 *
     2556 * @param   pThis       The device state structure.
     2557 */
     2558DECLINLINE(void) e1kR3LinkDownTemp(PE1KSTATE pThis)
     2559{
     2560    E1kLog(("%s Link is down temporarily\n", pThis->szPrf));
     2561    STATUS &= ~STATUS_LU;
     2562    Phy::setLinkStatus(&pThis->phy, false);
     2563    e1kRaiseInterrupt(pThis, VERR_SEM_BUSY, ICR_LSC);
     2564    /*
     2565     * Notifying the associated driver that the link went down (even temporarily)
     2566     * seems to be the right thing, but it was not done before. This may cause
     2567     * a regression if the driver does not expect the link to go down as a result
     2568     * of sending PDMNETWORKLINKSTATE_DOWN_RESUME to this device. Earlier versions
     2569     * of code notified the driver that the link was up! See @bugref{7057}.
     2570     */
     2571    if (pThis->pDrvR3)
     2572        pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, PDMNETWORKLINKSTATE_DOWN);
     2573    e1kBringLinkUpDelayed(pThis);
     2574}
     2575#endif /* IN_RING3 */
     2576
    25202577#if 0 /* unused */
    25212578/**
     
    32783335        return;
    32793336
    3280     E1kLog(("%s e1kLinkUpTimer: Link is up\n", pThis->szPrf));
    3281     STATUS |= STATUS_LU;
    3282     Phy::setLinkStatus(&pThis->phy, true);
    3283     e1kRaiseInterrupt(pThis, VERR_SEM_BUSY, ICR_LSC);
     3337    e1kR3LinkUp(pThis);
    32843338}
    32853339
     
    64246478{
    64256479    PE1KSTATE pThis = RT_FROM_MEMBER(pInterface, E1KSTATE, INetworkConfig);
    6426     bool fOldUp = !!(STATUS & STATUS_LU);
    6427     bool fNewUp = enmState == PDMNETWORKLINKSTATE_UP || enmState == PDMNETWORKLINKSTATE_DOWN_RESUME;
    6428 
    6429     /* old state was connected but STATUS not yet written by guest */
    6430     if (   fNewUp != fOldUp
    6431         || (!fNewUp && pThis->fCableConnected)
    6432         || (pThis->fCableConnected && enmState == PDMNETWORKLINKSTATE_DOWN_RESUME))
    6433     {
    6434         if (fNewUp)
    6435         {
    6436             E1kLog(("%s Link will be up in approximately %d secs\n",
    6437                     pThis->szPrf, pThis->cMsLinkUpDelay / 1000));
     6480
     6481    E1kLog(("%s e1kR3SetLinkState: enmState=%d\n", pThis->szPrf, enmState));
     6482    switch (enmState)
     6483    {
     6484        case PDMNETWORKLINKSTATE_UP:
    64386485            pThis->fCableConnected = true;
    6439             STATUS &= ~STATUS_LU;
    6440             Phy::setLinkStatus(&pThis->phy, false);
    6441             e1kRaiseInterrupt(pThis, VERR_SEM_BUSY, ICR_LSC);
    6442             /* Restore the link back in 5 seconds (by default). */
    6443             e1kBringLinkUpDelayed(pThis);
    6444         }
    6445         else
    6446         {
    6447             E1kLog(("%s Link is down\n", pThis->szPrf));
     6486            /* If link was down, bring it up after a while. */
     6487            if (!(STATUS & STATUS_LU))
     6488                e1kBringLinkUpDelayed(pThis);
     6489            break;
     6490        case PDMNETWORKLINKSTATE_DOWN:
    64486491            pThis->fCableConnected = false;
    6449             STATUS &= ~STATUS_LU;
    6450             Phy::setLinkStatus(&pThis->phy, false);
    6451             e1kRaiseInterrupt(pThis, VERR_SEM_BUSY, ICR_LSC);
    6452         }
    6453 
    6454         if (pThis->pDrvR3)
    6455         {
     6492            /* If link was up, bring it down. */
     6493            if (STATUS & STATUS_LU)
     6494                e1kR3LinkDown(pThis);
     6495            break;
     6496        case PDMNETWORKLINKSTATE_DOWN_RESUME:
    64566497            /*
    6457              * Send a UP link state to the driver below if the network adapter is only
    6458              * temproarily disconnected due to resume event.
     6498             * There is not much sense in bringing down the link if it has not come up yet.
     6499             * If it is up though, we bring it down temporarely, then bring it up again.
    64596500             */
    6460             if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
    6461                 pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, PDMNETWORKLINKSTATE_UP);
    6462             else
    6463                 pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, enmState);
    6464         }
     6501            if (STATUS & STATUS_LU)
     6502                e1kR3LinkDownTemp(pThis);
     6503            break;
    64656504    }
    64666505    return VINF_SUCCESS;
     
    67536792        && pThis->cMsLinkUpDelay)
    67546793    {
    6755         E1kLog(("%s Link is down temporarily\n", pThis->szPrf));
    6756         STATUS &= ~STATUS_LU;
    6757         Phy::setLinkStatus(&pThis->phy, false);
    6758         e1kRaiseInterrupt(pThis, VERR_SEM_BUSY, ICR_LSC);
    6759         /* Restore the link back in five seconds (default). */
    6760         e1kBringLinkUpDelayed(pThis);
     6794        e1kR3LinkDownTemp(pThis);
    67616795    }
    67626796    return VINF_SUCCESS;
     
    71617195     */
    71627196    if ((STATUS & STATUS_LU) && RT_SUCCESS(rc))
    7163     {
    7164         STATUS &= ~STATUS_LU;
    7165         Phy::setLinkStatus(&pThis->phy, false);
    7166         e1kRaiseInterrupt(pThis, VERR_SEM_BUSY, ICR_LSC);
    7167         /* Restore the link back in 5 seconds (default). */
    7168         e1kBringLinkUpDelayed(pThis);
    7169     }
     7197        e1kR3LinkDownTemp(pThis);
    71707198
    71717199    PDMCritSectLeave(&pThis->cs);
  • trunk/src/VBox/Devices/Network/DevPCNet.cpp

    r47499 r49414  
    46704670                    ("Invalid link state: enmState=%d\n", enmState), VERR_INVALID_PARAMETER);
    46714671
     4672    if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
     4673    {
     4674        pcnetTempLinkDown(pThis);
     4675        /*
     4676         * Note that we do not notify the driver about the link state change because
     4677         * the change is only temporary and can be disregarded from the driver's
     4678         * point of view (see @bugref{7057}).
     4679         */
     4680        return VINF_SUCCESS;
     4681    }
    46724682    /* has the state changed? */
    4673     fLinkUp = enmState == PDMNETWORKLINKSTATE_UP || enmState == PDMNETWORKLINKSTATE_DOWN_RESUME;
    4674     if (   pThis->fLinkUp != fLinkUp
    4675         || enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
     4683    fLinkUp = enmState == PDMNETWORKLINKSTATE_UP;
     4684    if (pThis->fLinkUp != fLinkUp)
    46764685    {
    46774686        pThis->fLinkUp = fLinkUp;
     
    46954704        Assert(!PDMCritSectIsOwner(&pThis->CritSect));
    46964705        if (pThis->pDrvR3)
    4697         {
    4698             /*
    4699              * Send a UP link state to the driver below if the network adapter is only
    4700              * temproarily disconnected due to resume event.
    4701              */
    4702             if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
    4703                 pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, PDMNETWORKLINKSTATE_UP);
    4704             else
    4705                 pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, enmState);
    4706         }
     4706            pThis->pDrvR3->pfnNotifyLinkChanged(pThis->pDrvR3, enmState);
    47074707    }
    47084708    return VINF_SUCCESS;
  • trunk/src/VBox/Devices/Network/DevVirtioNet.cpp

    r47499 r49414  
    462462    else
    463463        STATUS = 0;
     464    Log(("%s vnetIoCb_Reset: Link is %s\n", INSTANCE(pThis), pThis->fCableConnected ? "up" : "down"));
    464465
    465466    /*
     
    501502
    502503/**
     504 * Takes down the link temporarily if it's current status is up.
     505 *
     506 * This is used during restore and when replumbing the network link.
     507 *
     508 * The temporary link outage is supposed to indicate to the OS that all network
     509 * connections have been lost and that it for instance is appropriate to
     510 * renegotiate any DHCP lease.
     511 *
     512 * @param  pThis        The Virtual I/O network device state.
     513 */
     514static void vnetTempLinkDown(PVNETSTATE pThis)
     515{
     516    if (STATUS & VNET_S_LINK_UP)
     517    {
     518        STATUS &= ~VNET_S_LINK_UP;
     519        vpciRaiseInterrupt(&pThis->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
     520        /* Restore the link back in 5 seconds. */
     521        int rc = TMTimerSetMillies(pThis->pLinkUpTimer, pThis->cMsLinkUpDelay);
     522        AssertRC(rc);
     523        Log(("%s vnetTempLinkDown: Link is down temporarily\n", INSTANCE(pThis)));
     524    }
     525}
     526
     527
     528/**
    503529 * @callback_method_impl{FNTMTIMERDEV, Link Up Timer handler.}
    504530 */
     
    514540    vnetWakeupReceive(pDevIns);
    515541    vnetCsLeave(pThis);
     542    Log(("%s vnetLinkUpTimer: Link is up\n", INSTANCE(pThis)));
     543    if (pThis->pDrv)
     544        pThis->pDrv->pfnNotifyLinkChanged(pThis->pDrv, PDMNETWORKLINKSTATE_UP);
    516545}
    517546
     
    9981027    PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig);
    9991028    bool fOldUp = !!(STATUS & VNET_S_LINK_UP);
    1000     bool fNewUp = enmState == PDMNETWORKLINKSTATE_UP || enmState == PDMNETWORKLINKSTATE_DOWN_RESUME;
    1001 
    1002     if (   fNewUp != fOldUp
    1003         || enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
     1029    bool fNewUp = enmState == PDMNETWORKLINKSTATE_UP;
     1030
     1031    Log(("%s vnetSetLinkState: enmState=%d\n", INSTANCE(pThis), enmState));
     1032    if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
     1033    {
     1034        if (fOldUp)
     1035        {
     1036            /*
     1037             * We bother to bring the link down only if it was up previously. The UP link state
     1038             * notification will be sent when the link actually goes up in vnetLinkUpTimer().
     1039             */
     1040            vnetTempLinkDown(pThis);
     1041            if (pThis->pDrv)
     1042                pThis->pDrv->pfnNotifyLinkChanged(pThis->pDrv, enmState);
     1043        }
     1044    }
     1045    else if (fNewUp != fOldUp)
    10041046    {
    10051047        if (fNewUp)
     
    10111053        else
    10121054        {
     1055            /* The link was brought down explicitly, make sure it won't come up by timer.  */
     1056            TMTimerStop(pThis->pLinkUpTimer);
    10131057            Log(("%s Link is down\n", INSTANCE(pThis)));
    10141058            STATUS &= ~VNET_S_LINK_UP;
     
    10161060        }
    10171061        if (pThis->pDrv)
    1018         {
    1019             /*
    1020              * Send a UP link state to the driver below if the network adapter is only
    1021              * temproarily disconnected due to resume event.
    1022              */
    1023             if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
    1024                 pThis->pDrv->pfnNotifyLinkChanged(pThis->pDrv, PDMNETWORKLINKSTATE_UP);
    1025             else
    1026                 pThis->pDrv->pfnNotifyLinkChanged(pThis->pDrv, enmState);
    1027         }
     1062            pThis->pDrv->pfnNotifyLinkChanged(pThis->pDrv, enmState);
    10281063    }
    10291064    return VINF_SUCCESS;
     
    16511686
    16521687/**
    1653  * Takes down the link temporarily if it's current status is up.
    1654  *
    1655  * This is used during restore and when replumbing the network link.
    1656  *
    1657  * The temporary link outage is supposed to indicate to the OS that all network
    1658  * connections have been lost and that it for instance is appropriate to
    1659  * renegotiate any DHCP lease.
    1660  *
    1661  * @param  pThis        The Virtual I/O network device state.
    1662  */
    1663 static void vnetTempLinkDown(PVNETSTATE pThis)
    1664 {
    1665     if (STATUS & VNET_S_LINK_UP)
    1666     {
    1667         STATUS &= ~VNET_S_LINK_UP;
    1668         vpciRaiseInterrupt(&pThis->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
    1669         /* Restore the link back in 5 seconds. */
    1670         int rc = TMTimerSetMillies(pThis->pLinkUpTimer, pThis->cMsLinkUpDelay);
    1671         AssertRC(rc);
    1672     }
    1673 }
    1674 
    1675 
    1676 /**
    16771688 * @callback_method_impl{FNSSMDEVLOADEXEC}
    16781689 */
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