third_party/virtualbox/src/VBox/Devices/Network/DevE1000.cpp
/* E1K_WITH_TXD_CACHE */
/**
 * TCP segmentation offloading fallback: Add descriptor's buffer to transmit
 * frame.
 *
 * We construct the frame in the fallback buffer first and the copy it to the SG
 * buffer before passing it down to the network driver code.
 *
 * @returns error code
 *
 * @param   pThis          The device state structure.
 * @param   pDesc           Pointer to the descriptor to transmit.
 * @param   cbFragment      Length of descriptor's buffer.
 * @param   fOnWorkerThread Whether we're on a worker thread or an EMT.
 * @thread  E1000_TX
 */
E1K_WITH_TXD_CACHE
TCP segmentation offloading fallback: Add descriptor's buffer to transmit
frame.

We construct the frame in the fallback buffer first and the copy it to the SG
buffer before passing it down to the network driver code.

@returns error code

@param   pThis          The device state structure.
@param   pDesc           Pointer to the descriptor to transmit.
@param   cbFragment      Length of descriptor's buffer.
@param   fOnWorkerThread Whether we're on a worker thread or an EMT.
E1K_WITH_TXD_CACHE TCP segmentation offloading fallback : Add descriptor ' s buffer to transmit frame . We construct the frame in the fallback buffer first and the copy it to the SG buffer before passing it down to the network driver code . @returns error code @param pThis The device state structure . @param pDesc Pointer to the descriptor to transmit . @param cbFragment Length of descriptor ' s buffer . @param fOnWorkerThread Whether we ' re on a worker thread or an EMT .
static int e1kFallbackAddToFrame(PE1KSTATE pThis, E1KTXDESC *pDesc, bool fOnWorkerThread)
{
#ifdef VBOX_STRICT
    PPDMSCATTERGATHER pTxSg = pThis->CTX_SUFF(pTxSg);
    Assert(e1kGetDescType(pDesc) == E1K_DTYP_DATA);
    Assert(pDesc->data.cmd.fTSE);
    Assert(!e1kXmitIsGsoBuf(pTxSg));
#endif
    uint16_t u16MaxPktLen = pThis->contextTSE.dw3.u8HDRLEN + pThis->contextTSE.dw3.u16MSS;
    if (u16MaxPktLen == 0)
        return VINF_SUCCESS;
    int rc = VINF_SUCCESS;
    do
    {
        uint32_t cb = u16MaxPktLen - pThis->u16TxPktLen;
        if (cb > pDesc->data.cmd.u20DTALEN)
        {
            cb = pDesc->data.cmd.u20DTALEN;
            rc = e1kFallbackAddSegment(pThis, pDesc->data.u64BufAddr, cb, pDesc->data.cmd.fEOP , fOnWorkerThread);
        }
        else
        {
            rc = e1kFallbackAddSegment(pThis, pDesc->data.u64BufAddr, cb, true , fOnWorkerThread);
            pThis->u16TxPktLen = pThis->contextTSE.dw3.u8HDRLEN;
        }
        pDesc->data.u64BufAddr    += cb;
        pDesc->data.cmd.u20DTALEN -= cb;
    } while (pDesc->data.cmd.u20DTALEN > 0 && RT_SUCCESS(rc));
    if (pDesc->data.cmd.fEOP)
    {
        if (pThis->u32PayRemain != 0)
            E1K_INC_CNT32(TSCTFC);
        pThis->u16TxPktLen = 0;
        e1kXmitFreeBuf(pThis);
    }
    return VINF_SUCCESS; 
}
static int e1kFallbackAddToFrame ( PE1KSTATE pThis , E1KTXDESC * pDesc , bool fOnWorkerThread ) { #ifdef VBOX_STRICT PPDMSCATTERGATHER pTxSg = pThis -> CTX_SUFF ( pTxSg ) ; Assert ( e1kGetDescType ( pDesc ) == E1K_DTYP_DATA ) ; Assert ( pDesc -> data . cmd . fTSE ) ; Assert ( ! e1kXmitIsGsoBuf ( pTxSg ) ) ; #endif uint16_t u16MaxPktLen = pThis -> contextTSE . dw3 . u8HDRLEN + pThis -> contextTSE . dw3 . u16MSS ; if ( u16MaxPktLen == 0 ) return VINF_SUCCESS ; int rc = VINF_SUCCESS ; do { uint32_t cb = u16MaxPktLen - pThis -> u16TxPktLen ; if ( cb > pDesc -> data . cmd . u20DTALEN ) { cb = pDesc -> data . cmd . u20DTALEN ; rc = e1kFallbackAddSegment ( pThis , pDesc -> data . u64BufAddr , cb , pDesc -> data . cmd . fEOP , fOnWorkerThread ) ; } else { rc = e1kFallbackAddSegment ( pThis , pDesc -> data . u64BufAddr , cb , true , fOnWorkerThread ) ; pThis -> u16TxPktLen = pThis -> contextTSE . dw3 . u8HDRLEN ; } pDesc -> data . u64BufAddr += cb ; pDesc -> data . cmd . u20DTALEN -= cb ; } while ( pDesc -> data . cmd . u20DTALEN > 0 && RT_SUCCESS ( rc ) ) ; if ( pDesc -> data . cmd . fEOP ) { if ( pThis -> u32PayRemain != 0 ) E1K_INC_CNT32 ( TSCTFC ) ; pThis -> u16TxPktLen = 0 ; e1kXmitFreeBuf ( pThis ) ; } return VINF_SUCCESS ; }
E1K_WITH_TXD_CACHE
 TCP segmentation offloading fallback: Add descriptor's buffer to transmit
 frame.
E1K_WITH_TXD_CACHE TCP segmentation offloading fallback : Add descriptor ' s buffer to transmit frame .
/* We cannot produce empty packets, ignore all TX descriptors (see @bugref{9571}) */ /*
     * Carve out segments.
     */ /* Calculate how many bytes we have left in this TCP segment */ /* This descriptor fits completely into current segment */ /*fSend*/ /*fSend*/ /*
             * Rewind the packet tail pointer to the beginning of payload,
             * so we continue writing right beyond the header.
             */ /* End of packet, next segment will contain header. */ /// @todo consider rc;