Changeset 92091 in vbox for trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
- Timestamp:
- Oct 27, 2021 5:55:32 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet_1_0.cpp
r91703 r92091 86 86 /** @} */ 87 87 88 static 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 88 113 #ifdef VIRTIONET_WITH_GSO 89 114 # define VIRTIONET_HOST_FEATURES_GSO \ … … 293 318 /** @} */ 294 319 320 typedef enum VIRTIONETPKTHDRTYPE 321 { 322 kVirtioNetModernPktHdr_1_0 = 0, 323 kVirtioNetLegacyPktHdr = 1, 324 kVirtioNetLegacyPktHdrWithoutMrgRx = 2, 325 kVirtioNetFor32BitHack = 0x7fffffff 326 } VIRTIONETPKTHDRTYPE; 327 295 328 /** 296 329 * device-specific queue info … … 436 469 /** No broadcast mode - Supresses broadcast receive */ 437 470 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; 438 477 439 478 /** True if physical cable is attached in configuration. */ … … 551 590 static int virtioNetR3CreateWorkerThreads(PPDMDEVINS, PVIRTIONET, PVIRTIONETCC); 552 591 553 typedef enum VIRTIONETPKTHDRTYPE554 {555 kVirtioNetModernPktHdr_1_0 = 0,556 kVirtioNetLegacyPktHdr = 1,557 kVirtioNetLegacyPktHdrWithoutMrgRx = 2,558 kVirtioNetFor32BitHack = 0x7fffffff559 } 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 579 592 DECLINLINE(const char *) virtioNetThreadStateName(PPDMTHREAD pThread) 580 593 { … … 720 733 } 721 734 722 DECLINLINE(void) virtioNetPrintFeatures(VIRTIONET *pThis, PCDBGFINFOHLP pHlp)723 {724 static struct725 {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 80753 /* 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_ENABLED772 else773 Log3(("VirtIO Net Features Configuration\n\n"774 " Offered Accepted Feature Description\n"775 " ------- -------- ------- -----------\n"776 "%s\n", pszBuf));777 #endif778 RTMemFree(pszBuf);779 }780 735 781 736 #ifdef LOG_ENABLED … … 843 798 if (fAll || fFeatures) 844 799 { 845 virtioCorePrint Features(&pThis->Virtio, pHlp);846 virtioNetPrintFeatures(pThis, pHlp);800 virtioCorePrintDeviceFeatures(&pThis->Virtio, pHlp, s_aDevSpecificFeatures, 801 RT_ELEMENTS(s_aDevSpecificFeatures)); 847 802 pHlp->pfnPrintf(pHlp, "\n"); 848 803 } … … 1584 1539 uint64_t uOffset = 0; 1585 1540 1586 int uPktHdrType = virtioNetPktHdrType(&pThis->Virtio, pThis);1587 1588 1541 while (uOffset < cb) 1589 1542 { … … 1604 1557 * Re-visit if needed */ 1605 1558 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, 1609 1560 ("Out of Memory"), VERR_NO_MEMORY); 1610 1561 … … 1618 1569 { 1619 1570 /* 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); 1622 1573 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) 1628 1579 { 1629 1580 /* Calculate & cache GCPhys addr of field to update after final value is known */ … … 1672 1623 1673 1624 1674 if ( uPktHdrType != kVirtioNetLegacyPktHdrWithoutMrgRx)1625 if (pThis->ePktHdrType != kVirtioNetLegacyPktHdrWithoutMrgRx) 1675 1626 { 1676 1627 /* Fix-up pkthdr (in guest phys. memory) with number buffers (descriptors) processed */ … … 2196 2147 static int virtioNetR3ReadHeader(PVIRTIOCORE pVirtio, PVIRTIONET pThis, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONETPKTHDR pPktHdr, size_t cbFrame) 2197 2148 { 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); 2200 2150 if (RT_FAILURE(rc)) 2201 2151 return rc; … … 2365 2315 size_t uSize = 0; 2366 2316 2367 size_t cbPktHdr = virtioNetCalcPktHdrSize(pVirtio, pThis); 2368 2369 AssertMsgReturn(paSegsFromGuest[0].cbSeg >= cbPktHdr, 2317 AssertMsgReturn(paSegsFromGuest[0].cbSeg >= pThis->cbPktHdr, 2370 2318 ("Desc chain's first seg has insufficient space for pkt header!\n"), 2371 2319 VERR_INTERNAL_ERROR); 2372 2320 2373 PVIRTIONETPKTHDR pPktHdr = (PVIRTIONETPKTHDR)RTMemAllocZ( cbPktHdr);2321 PVIRTIONETPKTHDR pPktHdr = (PVIRTIONETPKTHDR)RTMemAllocZ(pThis->cbPktHdr); 2374 2322 AssertMsgReturn(pPktHdr, ("Out of Memory\n"), VERR_NO_MEMORY); 2375 2323 … … 2389 2337 uint64_t uOffset; 2390 2338 2391 uSize -= cbPktHdr;2339 uSize -= pThis->cbPktHdr; 2392 2340 rc = virtioNetR3ReadHeader(pVirtio, pThis, pDevIns, paSegsFromGuest[0].GCPhys, pPktHdr, uSize); 2393 2341 if (RT_FAILURE(rc)) 2394 2342 return rc; 2395 virtioCoreGCPhysChainAdvance(pSgPhysSend, cbPktHdr);2343 virtioCoreGCPhysChainAdvance(pSgPhysSend, pThis->cbPktHdr); 2396 2344 2397 2345 PDMNETWORKGSO Gso, *pGso = virtioNetR3SetupGsoCtx(&Gso, pPktHdr); … … 2787 2735 } 2788 2736 2737 2789 2738 /** 2790 2739 * @callback_method_impl{VIRTIOCORER3,pfnStatusChanged} … … 2804 2753 2805 2754 pThis->fNegotiatedFeatures = virtioCoreGetNegotiatedFeatures(pVirtio); 2806 2807 2755 #ifdef LOG_ENABLED 2808 virtioCorePrint Features(pVirtio, NULL);2809 virtioNetPrintFeatures(pThis, NULL);2756 virtioCorePrintDeviceFeatures(&pThis->Virtio, NULL, s_aDevSpecificFeatures, 2757 RT_ELEMENTS(s_aDevSpecificFeatures)); 2810 2758 #endif 2811 2759 … … 2857 2805 } 2858 2806 } 2807 2808 static 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 2859 2829 #endif /* IN_RING3 */ 2860 2830 … … 2927 2897 2928 2898 /** 2929 * @interface_method_impl{PDMIBASE,pfnQueryInterface ,2899 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 2930 2900 */ 2931 2901 static DECLCALLBACK(void *) virtioNetR3QueryInterface(struct PDMIBASE *pInterface, const char *pszIID) … … 3045 3015 3046 3016 pThis->virtioNetConfig.uMaxVirtqPairs = VIRTIONET_MAX_QPAIRS; 3047 3017 pThisCC->Virtio.pfnGuestVersionHandler = virtioGuestVersionHandler; 3048 3018 pThisCC->Virtio.pfnVirtqNotified = virtioNetVirtqNotified; 3049 3019 pThisCC->Virtio.pfnStatusChanged = virtioNetR3StatusChg; … … 3125 3095 else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER 3126 3096 || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME) 3097 { 3127 3098 Log(("[%s] No attached driver!\n", pThis->szInst)); 3099 AssertRCReturn(rc, rc); 3100 } 3101 3128 3102 /* 3129 3103 * Status driver
Note:
See TracChangeset
for help on using the changeset viewer.