/**
 * Writes a frame packet to the buffer.
 *
 * @returns VBox status code.
 * @param   pBuf        The buffer.
 * @param   pRingBuf    The ring buffer to read from.
 * @param   cSegs       The number of segments.
 * @param   paSegs      The segments.
 */
int VBoxNetIntIfRingWriteFrame(PINTNETBUF pBuf, PINTNETRINGBUF pRingBuf, size_t cSegs, PCINTNETSEG paSegs)
{
    RT_NOREF(pBuf);

    /*
     * Validate input.
     */
    AssertPtr(pBuf);
    AssertPtr(pRingBuf);
    AssertPtr(paSegs);
    Assert(cSegs > 0);

    /*
     * Calc frame size.
     */
    uint32_t cbFrame = 0;
    for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
        cbFrame += paSegs[iSeg].cb;
    Assert(cbFrame >= sizeof(RTMAC) * 2);

    /*
     * Allocate a frame, copy the data and commit it.
     */
    PINTNETHDR pHdr = NULL;
    void *pvFrame = NULL;
    int rc = IntNetRingAllocateFrame(pRingBuf, cbFrame, &pHdr, &pvFrame);
    if (RT_SUCCESS(rc))
    {
        vboxnetIntIfCopySG(pvFrame, cSegs, paSegs);
        IntNetRingCommitFrame(pRingBuf, pHdr);
        return VINF_SUCCESS;
    }

    return rc;
}
Beispiel #2
0
/* S/G API */
int VBoxNetBaseService::sendBufferOnWire(PCINTNETSEG pcSg, int cSg, size_t cbFrame)
{
    int rc = VINF_SUCCESS;
    PINTNETHDR pHdr = NULL;
    uint8_t *pu8Frame = NULL;
    int offFrame = 0;
    int idxSg = 0;
    /* Allocate frame */
    rc = IntNetRingAllocateFrame(&m_pIfBuf->Send, cbFrame, &pHdr, (void **)&pu8Frame);
    AssertRCReturn(rc, rc);
    /* Now we fill pvFrame with S/G above */
    for (idxSg = 0; idxSg < cSg; ++idxSg)
    {
        memcpy(&pu8Frame[offFrame], pcSg[idxSg].pv, pcSg[idxSg].cb);
        offFrame+=pcSg[idxSg].cb;
    }
    /* Commit */
    IntNetRingCommitFrame(&m_pIfBuf->Send, pHdr);

    LogFlowFuncLeaveRC(rc);
    return rc;
}