third_party/virtualbox/src/VBox/Devices/Network/DevE1000.cpp
/**
 * 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 true if the frame should be transmitted, false if not.
 *
 * @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
 */
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 true if the frame should be transmitted, false if not.

@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.
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 true if the frame should be transmitted false if not . @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 bool e1kFallbackAddToFrame(PE1KSTATE pThis, E1KTXDESC *pDesc, uint32_t cbFragment, bool fOnWorkerThread)
{
    PPDMSCATTERGATHER pTxSg = pThis->CTX_SUFF(pTxSg);
    Assert(e1kGetDescType(pDesc) == E1K_DTYP_DATA);
    Assert(pDesc->data.cmd.fTSE);
    Assert(!e1kXmitIsGsoBuf(pTxSg));
    uint16_t u16MaxPktLen = pThis->contextTSE.dw3.u8HDRLEN + pThis->contextTSE.dw3.u16MSS;
    Assert(u16MaxPktLen != 0);
    Assert(u16MaxPktLen < E1K_MAX_TX_PKT_SIZE);
    do
    {
        uint32_t cb = u16MaxPktLen - pThis->u16TxPktLen;
        if (cb > cbFragment)
        {
            cb = cbFragment;
            e1kFallbackAddSegment(pThis, pDesc->data.u64BufAddr, cb, pDesc->data.cmd.fEOP , fOnWorkerThread);
        }
        else
        {
            e1kFallbackAddSegment(pThis, pDesc->data.u64BufAddr, cb, true , fOnWorkerThread);
            pThis->u16TxPktLen = pThis->contextTSE.dw3.u8HDRLEN;
        }
        pDesc->data.u64BufAddr += cb;
        cbFragment             -= cb;
    } while (cbFragment > 0);
    if (pDesc->data.cmd.fEOP)
    {
        if (pThis->u32PayRemain != 0)
            E1K_INC_CNT32(TSCTFC);
        pThis->u16TxPktLen = 0;
        e1kXmitFreeBuf(pThis);
    }
    return false;
}
static bool e1kFallbackAddToFrame ( PE1KSTATE pThis , E1KTXDESC * pDesc , uint32_t cbFragment , bool fOnWorkerThread ) { PPDMSCATTERGATHER pTxSg = pThis -> CTX_SUFF ( pTxSg ) ; Assert ( e1kGetDescType ( pDesc ) == E1K_DTYP_DATA ) ; Assert ( pDesc -> data . cmd . fTSE ) ; Assert ( ! e1kXmitIsGsoBuf ( pTxSg ) ) ; uint16_t u16MaxPktLen = pThis -> contextTSE . dw3 . u8HDRLEN + pThis -> contextTSE . dw3 . u16MSS ; Assert ( u16MaxPktLen != 0 ) ; Assert ( u16MaxPktLen < E1K_MAX_TX_PKT_SIZE ) ; do { uint32_t cb = u16MaxPktLen - pThis -> u16TxPktLen ; if ( cb > cbFragment ) { cb = cbFragment ; e1kFallbackAddSegment ( pThis , pDesc -> data . u64BufAddr , cb , pDesc -> data . cmd . fEOP , fOnWorkerThread ) ; } else { e1kFallbackAddSegment ( pThis , pDesc -> data . u64BufAddr , cb , true , fOnWorkerThread ) ; pThis -> u16TxPktLen = pThis -> contextTSE . dw3 . u8HDRLEN ; } pDesc -> data . u64BufAddr += cb ; cbFragment -= cb ; } while ( cbFragment > 0 ) ; if ( pDesc -> data . cmd . fEOP ) { if ( pThis -> u32PayRemain != 0 ) E1K_INC_CNT32 ( TSCTFC ) ; pThis -> u16TxPktLen = 0 ; e1kXmitFreeBuf ( pThis ) ; } return false ; }
TCP segmentation offloading fallback: Add descriptor's buffer to transmit
 frame.
TCP segmentation offloading fallback : Add descriptor ' s buffer to transmit frame .
/*
     * 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. */