VirtualBox

Changeset 107309 in vbox for trunk


Ignore:
Timestamp:
Dec 13, 2024 8:13:55 AM (3 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
166340
Message:

UsbNet: bugref:10779 Implemented link state handling

File:
1 edited

Legend:

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

    r107243 r107309  
    377377    /** If set the link is temporarily down because of a saved state load. */
    378378    bool                                fLinkTempDown;
     379    /** Link Up(/Restore) Timer. */
     380    TMTIMERHANDLE                       hTimerLinkUp;
    379381
    380382    bool                                fInitialLinkStatusSent;
     
    13681370
    13691371
     1372DECLHIDDEN(void) usbNetLinkStateNotify(PUSBNET pThis, PDMNETWORKLINKSTATE enmLinkState);
     1373
     1374/**
     1375 * @callback_method_impl{FNTMTIMERUSB}
     1376 *
     1377 * By the time the host resumes after sleep the network environment may have changed considerably.
     1378 * We handle this by temporarily lowering the link state. This callback brings the link back up.
     1379 */
     1380static DECLCALLBACK(void) usbNetTimerLinkUp(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, void *pvUser)
     1381{
     1382    PUSBNET pThis = (PUSBNET)pvUser;
     1383    RT_NOREF(pUsbIns, hTimer);
     1384
     1385    LogFlowFunc(("#%d\n", pUsbIns->iInstance));
     1386
     1387    /* @todo: Do we really care for potential races with link state? */
     1388    pThis->fLinkTempDown = false;
     1389    if (!pThis->fLinkUp)
     1390        usbNetLinkStateNotify(pThis, PDMNETWORKLINKSTATE_UP);
     1391}
     1392
     1393
    13701394/**
    13711395 * @interface_method_impl{PDMINETWORKCONFIG,pfnSetLinkState}
     
    13751399    PUSBNET pThis = RT_FROM_MEMBER(pInterface, USBNET, Lun0.INetworkConfig);
    13761400
    1377     //bool            fLinkUp;
    1378 
    1379     LogFlowFunc(("#%d\n", pThis->pUsbIns->iInstance));
     1401    bool fLinkUp = enmState == PDMNETWORKLINKSTATE_UP;
     1402
     1403    LogFlowFunc(("#%d enmState=%d\n", pThis->pUsbIns->iInstance, enmState));
    13801404    AssertMsgReturn(enmState > PDMNETWORKLINKSTATE_INVALID && enmState <= PDMNETWORKLINKSTATE_DOWN_RESUME,
    13811405                    ("Invalid link state: enmState=%d\n", enmState), VERR_INVALID_PARAMETER);
    1382     RT_NOREF(pThis);
    1383 
    1384 #if 0
     1406
    13851407    if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
    13861408    {
    1387         dp8390TempLinkDown(pDevIns, pThis);
    1388         /*
    1389          * Note that we do not notify the driver about the link state change because
    1390          * the change is only temporary and can be disregarded from the driver's
    1391          * point of view (see @bugref{7057}).
    1392          */
    1393         return VINF_SUCCESS;
     1409        pThis->fLinkTempDown = true;
     1410        /* Do not bother to notify anyone if the link has been down */
     1411        PDMUsbHlpTimerSetMillies(pThis->pUsbIns, pThis->hTimerLinkUp, 500);    /* 0.5 sec */
    13941412    }
    13951413    /* has the state changed? */
    1396     fLinkUp = enmState == PDMNETWORKLINKSTATE_UP;
    13971414    if (pThis->fLinkUp != fLinkUp)
    13981415    {
    13991416        pThis->fLinkUp = fLinkUp;
    1400         if (fLinkUp)
    1401         {
    1402             /* Connect with a configured delay. */
    1403             pThis->fLinkTempDown = true;
    1404             pThis->cLinkDownReported = 0;
    1405             pThis->cLinkRestorePostponed = 0;
    1406             pThis->Led.Asserted.s.fError = pThis->Led.Actual.s.fError = 1;
    1407             int rc = PDMDevHlpTimerSetMillies(pDevIns, pThis->hTimerRestore, pThis->cMsLinkUpDelay);
    1408             AssertRC(rc);
    1409         }
    1410         else
    1411         {
    1412             /* Disconnect. */
    1413             pThis->cLinkDownReported = 0;
    1414             pThis->cLinkRestorePostponed = 0;
    1415             pThis->Led.Asserted.s.fError = pThis->Led.Actual.s.fError = 1;
    1416         }
    1417         Assert(!PDMDevHlpCritSectIsOwner(pDevIns, &pThis->CritSect));
    1418         if (pThisCC->pDrv)
    1419             pThisCC->pDrv->pfnNotifyLinkChanged(pThisCC->pDrv, enmState);
    1420     }
    1421 #endif
     1417        usbNetLinkStateNotify(pThis, enmState);
     1418    }
    14221419    return VINF_SUCCESS;
    14231420}
     
    16651662        return usbNetCompleteStall(pThis, NULL, pUrb, pEp->fHalted ? "Halted pipe" : "No request");
    16661663
    1667     if (!pThis->fInitialLinkStatusSent)
    1668     {
    1669         USBCDCNOTIFICICATION LinkNotification;
    1670         LinkNotification.bmRequestType     = 0xa1;
    1671         LinkNotification.bNotificationCode = USB_CDC_NOTIFICATION_CODE_NETWORK_CONNECTION;
    1672         LinkNotification.wValue            = pThis->fLinkUp ? 1 : 0;
    1673         LinkNotification.wIndex            = 0;
    1674         LinkNotification.wLength           = 0;
    1675         usbNetCompleteNotificationOk(pThis, pUrb, &LinkNotification, sizeof(LinkNotification));
    1676         pThis->fInitialLinkStatusSent = true;
    1677     }
    1678     else if (!pThis->fInitialSpeedChangeSent)
     1664    /* CONNECTION_SPEED_CHANGE is sent first, followed by NETWORK_CONNECTION. See [NCM10] (section 7.1) */
     1665    if (!pThis->fInitialSpeedChangeSent)
    16791666    {
    16801667        USBCDCNOTIFICICATIONSPEEDCHG SpeedChange;
     
    16891676        pThis->fInitialSpeedChangeSent = true;
    16901677    }
     1678    else if (!pThis->fInitialLinkStatusSent)
     1679    {
     1680        USBCDCNOTIFICICATION LinkNotification;
     1681        LinkNotification.bmRequestType     = 0xa1;
     1682        LinkNotification.bNotificationCode = USB_CDC_NOTIFICATION_CODE_NETWORK_CONNECTION;
     1683        LinkNotification.wValue            = pThis->fLinkUp ? 1 : 0;
     1684        LinkNotification.wIndex            = 0;
     1685        LinkNotification.wLength           = 0;
     1686        usbNetCompleteNotificationOk(pThis, pUrb, &LinkNotification, sizeof(LinkNotification));
     1687        pThis->fInitialLinkStatusSent = true;
     1688    }
    16911689    else
    16921690        usbNetQueueAddTail(&pThis->ToHostIntrQueue, pUrb);
     
    16941692    LogFlow(("usbNetHandleIntrDevToHost: Added %p:%s to the to-host interrupt queue\n", pUrb, pUrb->pszDesc));
    16951693    return VINF_SUCCESS;
     1694}
     1695
     1696
     1697/**
     1698 * Notifies both the guest and the network/driver of link state changes.
     1699 *
     1700 * @param   pThis               The UsbNet instance.
     1701 * @param   enmLinkState        The new link state.
     1702 */
     1703DECLHIDDEN(void) usbNetLinkStateNotify(PUSBNET pThis, PDMNETWORKLINKSTATE enmLinkState)
     1704{
     1705    LogFlowFunc(("#%d enmLinkState=%d\n", pThis->pUsbIns->iInstance, enmLinkState));
     1706    RTCritSectEnter(&pThis->CritSect);
     1707    /* Trigger notifications */
     1708    pThis->fInitialLinkStatusSent  = false;
     1709    pThis->fInitialSpeedChangeSent = false;
     1710    PVUSBURB pUrb = usbNetQueueRemoveHead(&pThis->ToHostIntrQueue);
     1711    /* If there is a request pending, use it. Otherwise the host should poll us soon. */
     1712    if (pUrb)
     1713        usbNetHandleIntrDevToHost(pThis, &pThis->aEps[3], pUrb);
     1714    RTCritSectLeave(&pThis->CritSect);
     1715    /* Always notify our network when notifying the guest. */
     1716    if (pThis->Lun0.pINetwork)
     1717        pThis->Lun0.pINetwork->pfnNotifyLinkChanged(pThis->Lun0.pINetwork, enmLinkState);
    16961718}
    16971719
     
    20972119    LogFlow(("usbNetDestruct/#%u:\n", pUsbIns->iInstance));
    20982120
     2121    PDMUsbHlpTimerDestroy(pUsbIns, pThis->hTimerLinkUp);
     2122
    20992123    if (RTCritSectIsInitialized(&pThis->CritSect))
    21002124    {
     
    22042228        return PDMUsbHlpVMSetError(pUsbIns, VERR_PDM_MISSING_INTERFACE_BELOW, RT_SRC_POS,
    22052229                                   N_("USBNET failed to query the PDMINETWORKUP from the driver below it"));
     2230
     2231    /*
     2232     * Create the timer for delaying of bringing the link up.
     2233     */
     2234    rc = PDMUsbHlpTimerCreate(pUsbIns, TMCLOCK_VIRTUAL, usbNetTimerLinkUp, pThis,
     2235                              TMTIMER_FLAGS_DEFAULT_CRIT_SECT,
     2236                              "Link Up", &pThis->hTimerLinkUp);
    22062237
    22072238    /*
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