VirtualBox

Changeset 83499 in vbox for trunk/src


Ignore:
Timestamp:
Apr 1, 2020 7:18:42 AM (5 years ago)
Author:
vboxsync
Message:

Network/DevVirtioNet_1_0.cpp: Round trip traffic happening continuously with network activity, but pings are not resolving yet. Need to dig into higher level packet traces, and validate thing like checksumming, etc...

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

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

    r83188 r83499  
    7575
    7676#define QUEUE_NAME(a_pVirtio, a_idxQueue) ((a_pVirtio)->virtqState[(a_idxQueue)].szVirtqName)
    77 #define VIRTQNAME(idxQueue)           (pThis->aszVirtqNames[idxQueue])
    78 #define CBVIRTQNAME(idxQueue)         RTStrNLen(VIRTQNAME(idxQueue), sizeof(VIRTQNAME(idxQueue)))
     77#define VIRTQNAME(idxQueue)       (pThis->aszVirtqNames[idxQueue])
     78#define CBVIRTQNAME(idxQueue)     RTStrNLen(VIRTQNAME(idxQueue), sizeof(VIRTQNAME(idxQueue)))
    7979#define FEATURE_ENABLED(feature)  (!!(pThis->fNegotiatedFeatures & VIRTIONET_F_##feature))
    8080#define FEATURE_DISABLED(feature) (!FEATURE_ENABLED(feature))
     
    8282
    8383#define SET_LINK_UP(pState) \
     84            LogFunc(("SET_LINK_UP\n")); \
    8485            pState->virtioNetConfig.uStatus |= VIRTIONET_F_LINK_UP; \
    8586            virtioCoreNotifyConfigChanged(&pThis->Virtio)
    8687
    8788#define SET_LINK_DOWN(pState) \
    88             pState->virtioNetConfig.uStatus &= !VIRTIONET_F_LINK_UP; \
     89            LogFunc(("SET_LINK_DOWN\n")); \
     90            pState->virtioNetConfig.uStatus &= ~VIRTIONET_F_LINK_UP; \
    8991            virtioCoreNotifyConfigChanged(&pThis->Virtio)
    9092
     
    194196#pragma pack()
    195197
    196 #define VIRTIONET_F_LINK_UP                  RT_BIT(1)          /**< config status: Link is up                      */
    197 #define VIRTIONET_F_ANNOUNCE                 RT_BIT(2)          /**< config status: Announce                        */
     198#define VIRTIONET_F_LINK_UP                          1          /**< config status: Link is up                      */
     199#define VIRTIONET_F_ANNOUNCE                         2          /**< config status: Announce                        */
    198200
    199201/** @name VirtIO 1.0 NET Host Device device specific control types
     
    14541456
    14551457        uint32_t cbDescChainLeft = pDescChain->cbPhysReturn;
    1456 
     1458        uint8_t  cbHdr = sizeof(VIRTIONET_PKT_HDR_T);
    14571459        /* Fill the Guest Rx buffer with data received from the interface */
    14581460        for (uint16_t cSegs = 0; uOffset < cb && cbDescChainLeft; )
     
    14611463            {
    14621464                /* Lead with packet header */
    1463                 paVirtSegsToGuest[0].cbSeg = sizeof(VIRTIONET_PKT_HDR_T);
    1464                 paVirtSegsToGuest[0].pvSeg = RTMemAlloc(sizeof(VIRTIONET_PKT_HDR_T));
     1465                paVirtSegsToGuest[0].cbSeg = cbHdr;
     1466                paVirtSegsToGuest[0].pvSeg = RTMemAlloc(cbHdr);
    14651467                AssertReturn(paVirtSegsToGuest[0].pvSeg, VERR_NO_MEMORY);
    1466                 cbDescChainLeft -= sizeof(VIRTIONET_PKT_HDR_T);
    1467 
    1468                 memcpy(paVirtSegsToGuest[0].pvSeg, &rxPktHdr, sizeof(VIRTIONET_PKT_HDR_T));
     1468                cbDescChainLeft -= cbHdr;
     1469
     1470                memcpy(paVirtSegsToGuest[0].pvSeg, &rxPktHdr, cbHdr);
    14691471
    14701472                /* Calculate & cache the field we will need to update later in gcPhys memory */
     
    14741476                cSegs++;
    14751477            }
     1478
    14761479            if (cSegs >= cSegsAllocated)
    14771480            {
     
    15071510
    15081511 /* Dump Rx Pkt after it's been written to guest physical memory via the virtio core API */
    1509     if (pThis->fLog)
    1510     {
     1512//    if (pThis->fLog)
     1513//    {
    15111514        virtioNetDumpGcPhysRxBuf(pDevIns, &rxPktHdr, cDescs, (uint8_t *)pvBuf, cb,
    15121515                                 gcPhysPktHdrNumBuffers - RT_UOFFSETOF(VIRTIONET_PKT_HDR_T, uNumBuffers),
    15131516                                 cb + sizeof(VIRTIONET_PKT_HDR_T));
    1514     }
     1517//    }
    15151518
    15161519    virtioCoreQueueSync(pDevIns, &pThis->Virtio, RXQIDX_QPAIR(idxQueue));
     
    15181521
    15191522if (pThis->fLog) {
    1520     RTThreadSleep(500);
    1521     RT_BREAKPOINT();
     1523//    RTThreadSleep(500);
     1524//   RT_BREAKPOINT();
    15221525    pThis->fBp = false;
    15231526}
     
    19111914}
    19121915
    1913 static bool virtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONET_PKT_HDR_T pPktHdr, uint32_t cbMax)
     1916static int virtioNetR3ReadHeader(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, PVIRTIONET_PKT_HDR_T pPktHdr, uint32_t cbMax)
    19141917{
    19151918    int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pPktHdr, sizeof(*pPktHdr));
    19161919    if (RT_FAILURE(rc))
    1917         return false;
    1918 
    1919     Log4(("virtio-net: header flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x cb=%x\n",
     1920        return rc;
     1921
     1922    Log(("virtio-net: header flags=%x gso-type=%x len=%x gso-size=%x Chksum-start=%x Chksum-offset=%x cb=%x\n",
    19201923          pPktHdr->uFlags, pPktHdr->uGsoType, pPktHdr->uHdrLen,
    19211924          pPktHdr->uGsoSize, pPktHdr->uChksumStart, pPktHdr->uChksumOffset, cbMax));
     
    19261929
    19271930        /* Segmentation offloading cannot be done without checksumming, and we do not support ECN */
    1928         if (  RT_UNLIKELY(!(pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM))
    1929             | RT_UNLIKELY(pPktHdr->uGsoType & VIRTIONET_HDR_GSO_ECN))
    1930                 return false;
     1931        AssertMsgReturn(   RT_LIKELY(pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM)
     1932                          && RT_UNLIKELY(pPktHdr->uGsoType & VIRTIONET_HDR_GSO_ECN),
     1933                          ("Unsupported ECN request in pkt header\n"), VERR_NOT_SUPPORTED);
    19311934
    19321935        switch (pPktHdr->uGsoType)
     
    19401943                break;
    19411944            default:
    1942                 return false;
     1945                LogFunc(("Bad GSO type in packet header\n"));
     1946                return VERR_INVALID_PARAMETER;
    19431947        }
    19441948        /* Header + MSS must not exceed the packet size. */
    1945         if (RT_UNLIKELY(uMinHdrSize + pPktHdr->uChksumStart + pPktHdr->uGsoSize > cbMax))
    1946             return false;
    1947     }
    1948     /* Checksum must fit into the frame (validating both checksum fields). */
    1949     if ((   pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM)
    1950          && sizeof(uint16_t) + pPktHdr->uChksumStart + pPktHdr->uChksumOffset > cbMax)
    1951                return false;
    1952     Log4Func(("returning true\n"));
    1953     return true;
     1949        AssertMsgReturn(RT_LIKELY(uMinHdrSize + pPktHdr->uChksumStart + pPktHdr->uGsoSize <= cbMax),
     1950                    ("Header plus message exceeds packet size"), VERR_BUFFER_OVERFLOW);
     1951    }
     1952
     1953    AssertMsgReturn(   !pPktHdr->uFlags & VIRTIONET_HDR_F_NEEDS_CSUM
     1954                      || sizeof(uint16_t) + pPktHdr->uChksumStart + pPktHdr->uChksumOffset <= cbMax,
     1955                ("Checksum doesn't fit into pkt header\n"), VERR_BUFFER_OVERFLOW);
     1956
     1957    return VINF_SUCCESS;
    19541958}
    19551959
     
    19571961                               PPDMNETWORKGSO pGso, PVIRTIONET_PKT_HDR_T pPktHdr)
    19581962{
    1959 LogFunc(("\n"));
    19601963    virtioNetR3PacketDump(pThis, (uint8_t *)pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, "--> Outgoing");
    19611964    if (pGso)
     
    20092012{
    20102013
    2011 LogFunc(("\n"));
    20122014    PVIRTIOCORE pVirtio = &pThis->Virtio;
    20132015
     
    20452047    }
    20462048
    2047     unsigned int cbPktHdr = sizeof(VIRTIONET_PKT_HDR_T);
    2048 
    20492049    int cPkts = virtioCoreR3QueuePendingCount(pVirtio->pDevIns, pVirtio, idxQueue);
    20502050    if (!cPkts)
     
    20642064    int rc;
    20652065    PVIRTIO_DESC_CHAIN_T pDescChain;
    2066     while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevIns, pVirtio, idxQueue, &pDescChain)))
     2066    while ((rc = virtioCoreR3QueuePeek(pVirtio->pDevIns, pVirtio, idxQueue, &pDescChain)) == VINF_SUCCESS)
    20672067    {
    20682068        if (RT_SUCCESS(rc))
     
    20742074        }
    20752075
    2076         uint32_t cSegsFromGuest = pDescChain->pSgPhysSend->cSegs;
    2077         PVIRTIOSGSEG paSegsFromGuest = pDescChain->pSgPhysSend->paSegs;
    2078 
    2079         if (cSegsFromGuest < 2 || paSegsFromGuest[0].cbSeg != cbPktHdr)
    2080         {
    2081             /* This check could be made more complex, because in theory (but not likely nor
    2082              * seen in practice) the first segment could contain header and data. */
    2083             LogFunc(("%s The first segment is not the header! (%u < 2 || %u != %u).\n",
    2084                  INSTANCE(pThis), cSegsFromGuest, paSegsFromGuest[0].cbSeg, cbPktHdr));
    2085             break;
    2086         }
     2076        PVIRTIOSGBUF pSgPhysSend = pDescChain->pSgPhysSend;
     2077        PVIRTIOSGSEG paSegsFromGuest = pSgPhysSend->paSegs;
     2078        uint32_t cSegsFromGuest = pSgPhysSend->cSegs;
    20872079
    20882080        VIRTIONET_PKT_HDR_T PktHdr;
    20892081        uint32_t uSize = 0;
    20902082
     2083        Assert(paSegsFromGuest[0].cbSeg >= sizeof(PktHdr));
     2084
    20912085        /* Compute total frame size. */
    2092         for (unsigned i = 1; i < cSegsFromGuest && uSize < VIRTIONET_MAX_FRAME_SIZE; i++)
     2086        for (unsigned i = 0; i < cSegsFromGuest && uSize < VIRTIONET_MAX_FRAME_SIZE; i++)
    20932087            uSize +=  paSegsFromGuest[i].cbSeg;
    20942088
     
    21002094            uSize = VIRTIONET_MAX_FRAME_SIZE;
    21012095
    2102         if (pThisCC->pDrv && virtioNetR3ReadHeader(pDevIns, paSegsFromGuest[0].gcPhys, &PktHdr, uSize))
     2096        if (pThisCC->pDrv)
    21032097        {
    21042098            PDMNETWORKGSO Gso, *pGso = virtioNetR3SetupGsoCtx(&Gso, &PktHdr);
     
    21092103            if (RT_SUCCESS(rc))
    21102104            {
    2111                 pSgBufToPdmLeafDevice->cbUsed = uSize;
    2112 
    2113                 /* Assemble a complete frame. */
    2114                 for (unsigned i = 1; i < cSegsFromGuest && uSize > 0; i++)
     2105                uSize -= sizeof(PktHdr);
     2106                rc = virtioNetR3ReadHeader(pDevIns, paSegsFromGuest[0].gcPhys, &PktHdr, sizeof(PktHdr));
     2107                virtioCoreSgBufAdvance(pSgPhysSend, sizeof(PktHdr));
     2108
     2109                uint64_t uOffset = 0;
     2110                size_t cbCopied = 0;
     2111                size_t cbTotal = 0;
     2112                size_t cbRemain = pSgBufToPdmLeafDevice->cbUsed = uSize;
     2113                while (cbRemain)
    21152114                {
    2116                     unsigned uOffset;
    2117                     unsigned cbSeg = RT_MIN(uSize, paSegsFromGuest[i].cbSeg);
    2118 
    2119                     PDMDevHlpPCIPhysRead(pDevIns, paSegsFromGuest[i].gcPhys,
    2120                                          ((uint8_t *)pSgBufToPdmLeafDevice->aSegs[0].pvSeg) + uOffset,
    2121                                          cbSeg);
    2122                     uOffset += cbSeg;
    2123                     uSize -= cbSeg;
     2115                    PVIRTIOSGSEG paSeg  = &pSgPhysSend->paSegs[pSgPhysSend->idxSeg];
     2116                    uint64_t srcSgStart = (uint64_t)paSeg->gcPhys;
     2117                    uint64_t srcSgLen   = (uint64_t)paSeg->cbSeg;
     2118                    uint64_t srcSgCur   = (uint64_t)pSgPhysSend->gcPhysCur;
     2119                    cbCopied = RT_MIN((uint64_t)cbRemain, srcSgLen - (srcSgCur - srcSgStart));
     2120                    PDMDevHlpPCIPhysRead(pDevIns,
     2121                                         (RTGCPHYS)pSgPhysSend->gcPhysCur,
     2122                                         ((uint8_t *)pSgBufToPdmLeafDevice->aSegs[0].pvSeg) + uOffset, cbCopied);
     2123                    virtioCoreSgBufAdvance(pSgPhysSend, cbCopied);
     2124                    cbRemain -= cbCopied;
     2125                    uOffset += cbCopied;
     2126                    cbTotal += cbCopied;
    21242127                }
     2128
     2129                LogFunc((".... Copied %lu bytes to %lu byte guest buffer, residual=%lu\n",
     2130                     cbTotal, pDescChain->cbPhysSend, pDescChain->cbPhysSend - cbTotal));
     2131
    21252132                rc = virtioNetR3TransmitFrame(pThis, pThisCC, pSgBufToPdmLeafDevice, pGso, &PktHdr);
    21262133                if (RT_FAILURE(rc))
     
    21362143                break;
    21372144            }
     2145
     2146            /* Remove this descriptor chain from the available ring */
     2147            virtioCoreR3QueueSkip(pVirtio, idxQueue);
     2148
     2149            /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */
     2150            virtioCoreR3QueuePut(pVirtio->pDevIns, pVirtio, idxQueue, NULL, pDescChain, false);
     2151
     2152            virtioCoreQueueSync(pVirtio->pDevIns, pVirtio, idxQueue);
    21382153        }
    2139         /* Remove this descriptor chain from the available ring */
    2140         virtioCoreR3QueueSkip(pVirtio, idxQueue);
    2141 
    2142         /* No data to return to guest, but call is needed put elem (e.g. desc chain) on used ring */
    2143         virtioCoreR3QueuePut(pVirtio->pDevIns, pVirtio, idxQueue, NULL, pDescChain, false);
    2144 
    2145         virtioCoreQueueSync(pVirtio->pDevIns, pVirtio, idxQueue);
    2146 
    21472154    }
    21482155    virtioNetR3SetWriteLed(pThisCC, false);
     
    22702277             else if (IS_TX_QUEUE(idxQueue))
    22712278             {
    2272 LogFunc(("Worker thread notified of pending Xmit packets!!!!!!\n"));
    22732279                 Log10Func(("%s Notified of data to transmit\n", INSTANCE(pThis)));
    22742280                 virtioNetR3TransmitPendingPackets(pDevIns, pThis, pThisCC,
     
    24812487        LogFunc(("%s VirtIO ready\n-----------------------------------------------------------------------------------------\n",
    24822488                 INSTANCE(pThis)));
     2489        pThis->virtioNetConfig.uStatus = pThis->fCableConnected ? VIRTIONET_F_LINK_UP : 0;
    24832490
    24842491        pThis->fResetting    = false;
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r83187 r83499  
    766766    uint16_t uAvailRingIdx = virtioReadAvailRingIdx(pDevIns, pVirtio, idxQueue);
    767767    uint16_t uNextAvailIdx = pVirtio->virtqState[idxQueue].uAvailIdx;
    768     int16_t  iDelta = uAvailRingIdx - uNextAvailIdx;
    769768    uint16_t uDelta = uAvailRingIdx - uNextAvailIdx;
    770     return iDelta >= 0 ? uDelta : VIRTQ_MAX_CNT + uDelta;
     769    if (uAvailRingIdx > uNextAvailIdx)
     770        return uDelta;
     771    return VIRTQ_MAX_CNT + uDelta;
    771772}
    772773/**
     
    906907              VIRTQNAME(pVirtio, idxQueue), virtioReadUsedRingIdx(pDevIns, pVirtio, idxQueue)));
    907908
    908     /*
    909      * Copy s/g buf (virtual memory) to guest phys mem (IN direction). This virtual memory
    910      * block will be small (fixed portion of response header + sense buffer area or
    911      * control commands or error return values)... The bulk of req data xfers to phys mem
    912      * is handled by client */
     909    /* Copy s/g buf (virtual memory) to guest phys mem (IN direction). */
    913910
    914911    size_t cbCopy = 0, cbTotal = 0, cbRemain = 0;
     
    937934    }
    938935
    939 
    940936    /* If this write-ahead crosses threshold where the driver wants to get an event flag it */
    941937    if (pVirtio->uDriverFeatures & VIRTIO_F_EVENT_IDX)
     
    946942     * Place used buffer's descriptor in used ring but don't update used ring's slot index.
    947943     * That will be done with a subsequent client call to virtioCoreQueueSync() */
    948     virtioWriteUsedElem(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdx++, pDescChain->uHeadIdx, (uint32_t)cbCopy);
    949 
    950     Log6Func((".... Copied %zu bytes in %d segs to %u byte buffer, residual=%zu\n",
    951               cbTotal - cbRemain, pSgVirtReturn->cSegs, pDescChain->cbPhysReturn, pDescChain->cbPhysReturn - cbCopy));
     944    virtioWriteUsedElem(pDevIns, pVirtio, idxQueue, pVirtq->uUsedIdx++, pDescChain->uHeadIdx, (uint32_t)cbTotal);
     945
     946    if (pSgVirtReturn)
     947        Log6Func((".... Copied %zu bytes in %d segs to %u byte buffer, residual=%zu\n",
     948              cbTotal - cbRemain, pSgVirtReturn->cSegs, pDescChain->cbPhysReturn, pDescChain->cbPhysReturn - cbTotal));
    952949
    953950    Log6Func(("Write ahead used_idx=%u, %s used_idx=%u\n",
     
    10691066            return;
    10701067        }
    1071 /* REMOVE THIS!!!!!!! DON'T INTEGRATE! EXPERIMENTAL/DEBUG */
    1072 //virtioKick(pDevIns, pVirtio, VIRTIO_ISR_VIRTQ_INTERRUPT, pVirtio->uQueueMsixVector[idxQueue], fForce);
    1073 //        Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n"));
     1068
     1069        Log6Func(("...skipping interrupt. Guest flagged VIRTQ_AVAIL_F_NO_INTERRUPT for queue\n"));
    10741070    }
    10751071}
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