VirtualBox

Ignore:
Timestamp:
Oct 27, 2021 5:55:32 AM (3 years ago)
Author:
vboxsync
Message:

Optimize how legacy/modern driver is determined to avoid polling, and eliminate code duplication for feature logging

File:
1 edited

Legend:

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

    r91703 r92091  
    8686/** @} */
    8787
     88static const VIRTIO_FEATURES_LIST s_aDevSpecificFeatures[] =
     89{
     90    { VIRTIONET_F_CSUM,                "   CSUM                 Host handles packets with partial checksum.\n" },
     91    { VIRTIONET_F_GUEST_CSUM,          "   GUEST_CSUM           Guest handles packets with partial checksum.\n" },
     92    { VIRTIONET_F_CTRL_GUEST_OFFLOADS, "   CTRL_GUEST_OFFLOADS  Control channel offloads reconfiguration support.\n" },
     93    { VIRTIONET_F_MAC,                 "   MAC                  Host has given MAC address.\n" },
     94    { VIRTIONET_F_GUEST_TSO4,          "   GUEST_TSO4           Guest can receive TSOv4.\n" },
     95    { VIRTIONET_F_GUEST_TSO6,          "   GUEST_TSO6           Guest can receive TSOv6.\n" },
     96    { VIRTIONET_F_GUEST_ECN,           "   GUEST_ECN            Guest can receive TSO with ECN.\n" },
     97    { VIRTIONET_F_GUEST_UFO,           "   GUEST_UFO            Guest can receive UFO.\n" },
     98    { VIRTIONET_F_HOST_TSO4,           "   HOST_TSO4            Host can receive TSOv4.\n" },
     99    { VIRTIONET_F_HOST_TSO6,           "   HOST_TSO6            Host can receive TSOv6.\n" },
     100    { VIRTIONET_F_HOST_ECN,            "   HOST_ECN             Host can receive TSO with ECN.\n" },
     101    { VIRTIONET_F_HOST_UFO,            "   HOST_UFO             Host can receive UFO.\n" },
     102    { VIRTIONET_F_MRG_RXBUF,           "   MRG_RXBUF            Guest can merge receive buffers.\n" },
     103    { VIRTIONET_F_STATUS,              "   STATUS               Configuration status field is available.\n" },
     104    { VIRTIONET_F_CTRL_VQ,             "   CTRL_VQ              Control channel is available.\n" },
     105    { VIRTIONET_F_CTRL_RX,             "   CTRL_RX              Control channel RX mode support.\n" },
     106    { VIRTIONET_F_CTRL_VLAN,           "   CTRL_VLAN            Control channel VLAN filtering.\n" },
     107    { VIRTIONET_F_GUEST_ANNOUNCE,      "   GUEST_ANNOUNCE       Guest can send gratuitous packets.\n" },
     108    { VIRTIONET_F_MQ,                  "   MQ                   Host supports multiqueue with automatic receive steering.\n" },
     109    { VIRTIONET_F_CTRL_MAC_ADDR,       "   CTRL_MAC_ADDR        Set MAC address through control channel.\n" },
     110};
     111
     112
    88113#ifdef VIRTIONET_WITH_GSO
    89114# define VIRTIONET_HOST_FEATURES_GSO    \
     
    293318/** @} */
    294319
     320typedef enum VIRTIONETPKTHDRTYPE
     321{
     322    kVirtioNetModernPktHdr_1_0          = 0,
     323    kVirtioNetLegacyPktHdr              = 1,
     324    kVirtioNetLegacyPktHdrWithoutMrgRx  = 2,
     325    kVirtioNetFor32BitHack              = 0x7fffffff
     326} VIRTIONETPKTHDRTYPE;
     327
    295328/**
    296329 * device-specific queue info
     
    436469    /** No broadcast mode - Supresses broadcast receive */
    437470    uint8_t                 fNoBroadcast;
     471
     472    /** Type of network pkt header based on guest driver version/features */
     473    VIRTIONETPKTHDRTYPE     ePktHdrType;
     474
     475    /** Size of network pkt header based on guest driver version/features */
     476    uint16_t                cbPktHdr;
    438477
    439478    /** True if physical cable is attached in configuration. */
     
    551590static int virtioNetR3CreateWorkerThreads(PPDMDEVINS, PVIRTIONET, PVIRTIONETCC);
    552591
    553 typedef enum VIRTIONETPKTHDRTYPE
    554 {
    555     kVirtioNetModernPktHdr_1_0          = 0,
    556     kVirtioNetLegacyPktHdr              = 1,
    557     kVirtioNetLegacyPktHdrWithoutMrgRx  = 2,
    558     kVirtioNetFor32BitHack              = 0x7fffffff
    559 } VIRTIONETPKTHDRTYPE;
    560 
    561 DECLINLINE(int) virtioNetPktHdrType(PVIRTIOCORE pVirtio, PVIRTIONET pThis)
    562 {
    563     if (!virtioCoreIsLegacyMode(pVirtio))
    564         return kVirtioNetModernPktHdr_1_0;
    565     else /* legacy mode */
    566         if (FEATURE_ENABLED(MRG_RXBUF))
    567             return kVirtioNetLegacyPktHdrWithoutMrgRx;
    568     return kVirtioNetLegacyPktHdr;
    569 }
    570 
    571 DECLINLINE(size_t) virtioNetCalcPktHdrSize(PVIRTIOCORE pVirtio, PVIRTIONET pThis)
    572 {
    573     size_t cbHdr = sizeof(VIRTIONETPKTHDR);
    574     if (virtioCoreIsLegacyMode(pVirtio) & !FEATURE_ENABLED(MRG_RXBUF))
    575         cbHdr -= RT_SIZEOFMEMB(VIRTIONETPKTHDR, uNumBuffers);
    576     return cbHdr;
    577 }
    578 
    579592DECLINLINE(const char *) virtioNetThreadStateName(PPDMTHREAD pThread)
    580593{
     
    720733}
    721734
    722 DECLINLINE(void) virtioNetPrintFeatures(VIRTIONET *pThis, PCDBGFINFOHLP pHlp)
    723 {
    724     static struct
    725     {
    726         uint64_t fFeatureBit;
    727         const char *pcszDesc;
    728     } const s_aFeatures[] =
    729     {
    730         { VIRTIONET_F_CSUM,                "   CSUM                 Host handles packets with partial checksum.\n" },
    731         { VIRTIONET_F_GUEST_CSUM,          "   GUEST_CSUM           Guest handles packets with partial checksum.\n" },
    732         { VIRTIONET_F_CTRL_GUEST_OFFLOADS, "   CTRL_GUEST_OFFLOADS  Control channel offloads reconfiguration support.\n" },
    733         { VIRTIONET_F_MAC,                 "   MAC                  Host has given MAC address.\n" },
    734         { VIRTIONET_F_GUEST_TSO4,          "   GUEST_TSO4           Guest can receive TSOv4.\n" },
    735         { VIRTIONET_F_GUEST_TSO6,          "   GUEST_TSO6           Guest can receive TSOv6.\n" },
    736         { VIRTIONET_F_GUEST_ECN,           "   GUEST_ECN            Guest can receive TSO with ECN.\n" },
    737         { VIRTIONET_F_GUEST_UFO,           "   GUEST_UFO            Guest can receive UFO.\n" },
    738         { VIRTIONET_F_HOST_TSO4,           "   HOST_TSO4            Host can receive TSOv4.\n" },
    739         { VIRTIONET_F_HOST_TSO6,           "   HOST_TSO6            Host can receive TSOv6.\n" },
    740         { VIRTIONET_F_HOST_ECN,            "   HOST_ECN             Host can receive TSO with ECN.\n" },
    741         { VIRTIONET_F_HOST_UFO,            "   HOST_UFO             Host can receive UFO.\n" },
    742         { VIRTIONET_F_MRG_RXBUF,           "   MRG_RXBUF            Guest can merge receive buffers.\n" },
    743         { VIRTIONET_F_STATUS,              "   STATUS               Configuration status field is available.\n" },
    744         { VIRTIONET_F_CTRL_VQ,             "   CTRL_VQ              Control channel is available.\n" },
    745         { VIRTIONET_F_CTRL_RX,             "   CTRL_RX              Control channel RX mode support.\n" },
    746         { VIRTIONET_F_CTRL_VLAN,           "   CTRL_VLAN            Control channel VLAN filtering.\n" },
    747         { VIRTIONET_F_GUEST_ANNOUNCE,      "   GUEST_ANNOUNCE       Guest can send gratuitous packets.\n" },
    748         { VIRTIONET_F_MQ,                  "   MQ                   Host supports multiqueue with automatic receive steering.\n" },
    749         { VIRTIONET_F_CTRL_MAC_ADDR,       "   CTRL_MAC_ADDR        Set MAC address through control channel.\n" }
    750     };
    751 
    752 #define MAXLINE 80
    753     /* Display as a single buf to prevent interceding log messages */
    754     uint64_t fFeaturesOfferedMask = VIRTIONET_HOST_FEATURES_OFFERED;
    755     uint16_t cbBuf = RT_ELEMENTS(s_aFeatures) * 132;
    756     char *pszBuf = (char *)RTMemAllocZ(cbBuf);
    757     Assert(pszBuf);
    758     char *cp = pszBuf;
    759     for (unsigned i = 0; i < RT_ELEMENTS(s_aFeatures); ++i)
    760     {
    761         uint64_t isOffered = fFeaturesOfferedMask & s_aFeatures[i].fFeatureBit;
    762         uint64_t isNegotiated = pThis->fNegotiatedFeatures & s_aFeatures[i].fFeatureBit;
    763         cp += RTStrPrintf(cp, cbBuf - (cp - pszBuf), "        %s       %s   %s",
    764                           isOffered ? "+" : "-", isNegotiated ? "x" : " ", s_aFeatures[i].pcszDesc);
    765     }
    766     if (pHlp)
    767         pHlp->pfnPrintf(pHlp, "VirtIO Net Features Configuration\n\n"
    768               "    Offered  Accepted  Feature              Description\n"
    769               "    -------  --------  -------              -----------\n"
    770               "%s\n", pszBuf);
    771 #ifdef LOG_ENABLED
    772     else
    773         Log3(("VirtIO Net Features Configuration\n\n"
    774               "    Offered  Accepted  Feature              Description\n"
    775               "    -------  --------  -------              -----------\n"
    776               "%s\n", pszBuf));
    777 #endif
    778     RTMemFree(pszBuf);
    779 }
    780735
    781736#ifdef LOG_ENABLED
     
    843798    if (fAll || fFeatures)
    844799    {
    845         virtioCorePrintFeatures(&pThis->Virtio, pHlp);
    846         virtioNetPrintFeatures(pThis, pHlp);
     800        virtioCorePrintDeviceFeatures(&pThis->Virtio, pHlp, s_aDevSpecificFeatures,
     801            RT_ELEMENTS(s_aDevSpecificFeatures));
    847802        pHlp->pfnPrintf(pHlp, "\n");
    848803    }
     
    15841539    uint64_t uOffset = 0;
    15851540
    1586     int uPktHdrType = virtioNetPktHdrType(&pThis->Virtio,  pThis);
    1587 
    15881541    while (uOffset < cb)
    15891542    {
     
    16041557         * Re-visit if needed */
    16051558
    1606         size_t cbPktHdr = virtioNetCalcPktHdrSize(&pThis->Virtio, pThis);
    1607 
    1608         AssertMsgReturn(pVirtqBuf->pSgPhysReturn->paSegs[0].cbSeg >= cbPktHdr,
     1559        AssertMsgReturn(pVirtqBuf->pSgPhysReturn->paSegs[0].cbSeg >= pThis->cbPktHdr,
    16091560                            ("Out of Memory"), VERR_NO_MEMORY);
    16101561
     
    16181569            {
    16191570                /* Lead with packet header */
    1620                 paVirtSegsToGuest[0].cbSeg = cbPktHdr;
    1621                 paVirtSegsToGuest[0].pvSeg = RTMemAlloc(cbPktHdr);
     1571                paVirtSegsToGuest[0].cbSeg = pThis->cbPktHdr;
     1572                paVirtSegsToGuest[0].pvSeg = RTMemAlloc(pThis->cbPktHdr);
    16221573                AssertReturn(paVirtSegsToGuest[0].pvSeg, VERR_NO_MEMORY);
    1623                 cbBufRemaining -= cbPktHdr;
    1624 
    1625                 memcpy(paVirtSegsToGuest[0].pvSeg, rxPktHdr, cbPktHdr);
    1626 
    1627                 if (uPktHdrType != kVirtioNetLegacyPktHdrWithoutMrgRx)
     1574                cbBufRemaining -= pThis->cbPktHdr;
     1575
     1576                memcpy(paVirtSegsToGuest[0].pvSeg, rxPktHdr, pThis->cbPktHdr);
     1577
     1578                if (pThis->ePktHdrType != kVirtioNetLegacyPktHdrWithoutMrgRx)
    16281579                {
    16291580                    /* Calculate & cache GCPhys addr of field to update after final value is known */
     
    16721623
    16731624
    1674     if (uPktHdrType != kVirtioNetLegacyPktHdrWithoutMrgRx)
     1625    if (pThis->ePktHdrType != kVirtioNetLegacyPktHdrWithoutMrgRx)
    16751626    {
    16761627        /* Fix-up pkthdr (in guest phys. memory) with number buffers (descriptors) processed */
     
    21962147static int virtioNetR3ReadHeader(PVIRTIOCORE pVirtio, PVIRTIONET pThis, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONETPKTHDR pPktHdr, size_t cbFrame)
    21972148{
    2198     size_t cbPktHdr = virtioNetCalcPktHdrSize(pVirtio, pThis);
    2199     int rc = virtioCoreGCPhysRead(pVirtio, pDevIns, GCPhys, pPktHdr, cbPktHdr);
     2149    int rc = virtioCoreGCPhysRead(pVirtio, pDevIns, GCPhys, pPktHdr, pThis->cbPktHdr);
    22002150    if (RT_FAILURE(rc))
    22012151        return rc;
     
    23652315        size_t uSize = 0;
    23662316
    2367         size_t cbPktHdr = virtioNetCalcPktHdrSize(pVirtio, pThis);
    2368 
    2369         AssertMsgReturn(paSegsFromGuest[0].cbSeg >= cbPktHdr,
     2317        AssertMsgReturn(paSegsFromGuest[0].cbSeg >= pThis->cbPktHdr,
    23702318                        ("Desc chain's first seg has insufficient space for pkt header!\n"),
    23712319                        VERR_INTERNAL_ERROR);
    23722320
    2373         PVIRTIONETPKTHDR pPktHdr = (PVIRTIONETPKTHDR)RTMemAllocZ(cbPktHdr);
     2321        PVIRTIONETPKTHDR pPktHdr = (PVIRTIONETPKTHDR)RTMemAllocZ(pThis->cbPktHdr);
    23742322        AssertMsgReturn(pPktHdr, ("Out of Memory\n"), VERR_NO_MEMORY);
    23752323
     
    23892337            uint64_t uOffset;
    23902338
    2391             uSize -= cbPktHdr;
     2339            uSize -= pThis->cbPktHdr;
    23922340            rc = virtioNetR3ReadHeader(pVirtio, pThis, pDevIns, paSegsFromGuest[0].GCPhys, pPktHdr, uSize);
    23932341            if (RT_FAILURE(rc))
    23942342                return rc;
    2395             virtioCoreGCPhysChainAdvance(pSgPhysSend, cbPktHdr);
     2343            virtioCoreGCPhysChainAdvance(pSgPhysSend, pThis->cbPktHdr);
    23962344
    23972345            PDMNETWORKGSO  Gso, *pGso = virtioNetR3SetupGsoCtx(&Gso, pPktHdr);
     
    27872735}
    27882736
     2737
    27892738/**
    27902739 * @callback_method_impl{VIRTIOCORER3,pfnStatusChanged}
     
    28042753
    28052754        pThis->fNegotiatedFeatures = virtioCoreGetNegotiatedFeatures(pVirtio);
    2806 
    28072755#ifdef LOG_ENABLED
    2808         virtioCorePrintFeatures(pVirtio, NULL);
    2809         virtioNetPrintFeatures(pThis, NULL);
     2756        virtioCorePrintDeviceFeatures(&pThis->Virtio, NULL, s_aDevSpecificFeatures,
     2757            RT_ELEMENTS(s_aDevSpecificFeatures));
    28102758#endif
    28112759
     
    28572805    }
    28582806}
     2807
     2808static DECLCALLBACK(void) virtioGuestVersionHandler(PVIRTIOCORE pVirtio, uint32_t fModern)
     2809{
     2810    LogFunc(("Guest Driver version is %s\n", fModern ? "modern" : "legacy"));
     2811
     2812    PVIRTIONET pThis = RT_FROM_MEMBER(pVirtio, VIRTIONET, Virtio);
     2813
     2814    /* Calculate network packet header type and size based on what we know now */
     2815    pThis->cbPktHdr = sizeof(VIRTIONETPKTHDR);
     2816
     2817    if (fModern)
     2818        pThis->ePktHdrType = kVirtioNetModernPktHdr_1_0;
     2819    else if (FEATURE_DISABLED(MRG_RXBUF))
     2820    {
     2821        pThis->ePktHdrType = kVirtioNetLegacyPktHdrWithoutMrgRx;
     2822        pThis->cbPktHdr -= RT_SIZEOFMEMB(VIRTIONETPKTHDR, uNumBuffers);
     2823    }
     2824    else /* Legacy guest with MRG_RX feature enabled */
     2825        pThis->ePktHdrType = kVirtioNetLegacyPktHdr;
     2826}
     2827
     2828
    28592829#endif /* IN_RING3 */
    28602830
     
    29272897
    29282898/**
    2929  * @interface_method_impl{PDMIBASE,pfnQueryInterface,
     2899 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    29302900 */
    29312901static DECLCALLBACK(void *) virtioNetR3QueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
     
    30453015
    30463016    pThis->virtioNetConfig.uMaxVirtqPairs   = VIRTIONET_MAX_QPAIRS;
    3047 
     3017    pThisCC->Virtio.pfnGuestVersionHandler  = virtioGuestVersionHandler;
    30483018    pThisCC->Virtio.pfnVirtqNotified        = virtioNetVirtqNotified;
    30493019    pThisCC->Virtio.pfnStatusChanged        = virtioNetR3StatusChg;
     
    31253095    else if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
    31263096             || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
     3097    {
    31273098                    Log(("[%s] No attached driver!\n", pThis->szInst));
     3099                    AssertRCReturn(rc, rc);
     3100    }
     3101
    31283102    /*
    31293103     * Status driver
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