VirtualBox

Changeset 28054 in vbox


Ignore:
Timestamp:
Apr 7, 2010 5:22:17 PM (15 years ago)
Author:
vboxsync
Message:

DrvNAT: Handle GSO SGs.

File:
1 edited

Legend:

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

    r27973 r28054  
    3131#include <VBox/pdmdrv.h>
    3232#include <VBox/pdmnetifs.h>
     33#include <VBox/pdmnetinline.h>
    3334#include <iprt/assert.h>
    3435#include <iprt/file.h>
     
    387388    if (pSgBuf->pvAllocator)
    388389    {
     390        Assert(!pSgBuf->pvUser);
    389391        slirp_ext_m_free(pThis->pNATState, (struct mbuf *)pSgBuf->pvAllocator);
    390392        pSgBuf->pvAllocator = NULL;
     393    }
     394    else if (pSgBuf->pvUser)
     395    {
     396        RTMemFree(pSgBuf->aSegs[0].pvSeg);
     397        pSgBuf->aSegs[0].pvSeg = NULL;
     398        RTMemFree(pSgBuf->pvUser);
     399        pSgBuf->pvUser = NULL;
    391400    }
    392401    RTMemFree(pSgBuf);
     
    406415    {
    407416        struct mbuf *m = (struct mbuf *)pSgBuf->pvAllocator;
    408         pSgBuf->pvAllocator = NULL;
    409         slirp_input(pThis->pNATState, m, pSgBuf->cbUsed);
     417        if (m)
     418        {
     419            /*
     420             * A normal frame.
     421             */
     422            pSgBuf->pvAllocator = NULL;
     423            slirp_input(pThis->pNATState, m, pSgBuf->cbUsed);
     424        }
     425        else
     426        {
     427            /*
     428             * GSO frame, need to segment it.
     429             */
     430            /** @todo Make the NAT engine grok large frames?  Could be more efficient... */
     431            uint8_t const  *pbFrame = (uint8_t const *)pSgBuf->aSegs[0].pvSeg;
     432            PCPDMNETWORKGSO pGso    = (PCPDMNETWORKGSO)pSgBuf->pvUser;
     433            uint32_t const  cSegs   = PDMNetGsoCalcSegmentCount(pGso, pSgBuf->cbUsed);  Assert(cSegs > 1);
     434            for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
     435            {
     436                size_t cbSeg;
     437                void  *pvSeg;
     438                m = slirp_ext_m_get(pThis->pNATState, pGso->cbHdrs + pGso->cbMaxSeg, &pvSeg, &cbSeg);
     439                if (!m)
     440                    break;
     441
     442                uint32_t cbPayload;
     443                uint32_t offPayload = PDMNetGsoCarveSegment(pGso, pbFrame, pSgBuf->cbUsed,
     444                                                            iSeg, cSegs, (uint8_t *)pvSeg, &cbPayload);
     445                memcpy((uint8_t *)pvSeg + pGso->cbHdrs, pbFrame + offPayload, cbPayload);
     446
     447                slirp_input(pThis->pNATState, m, cbPayload + pGso->cbHdrs);
     448            }
     449        }
    410450    }
    411451    drvNATFreeSgBuf(pThis, pSgBuf);
     
    421461{
    422462    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
    423 AssertReturn(!pGso, VERR_NOT_IMPLEMENTED); /** @todo GSO buffer allocation. */
    424463
    425464    /*
     
    438477    if (!pSgBuf)
    439478        return VERR_NO_MEMORY;
    440     pSgBuf->pvAllocator = slirp_ext_m_get(pThis->pNATState, cbMin,
    441                                           &pSgBuf->aSegs[0].pvSeg, &pSgBuf->aSegs[0].cbSeg);
    442     if (!pSgBuf->pvAllocator)
    443     {
    444         RTMemFree(pSgBuf);
    445         /** @todo Implement the VERR_TRY_AGAIN sematics. */
    446         return VERR_NO_MEMORY;
     479    if (!pGso)
     480    {
     481        pSgBuf->pvUser      = NULL;
     482        pSgBuf->pvAllocator = slirp_ext_m_get(pThis->pNATState, cbMin,
     483                                              &pSgBuf->aSegs[0].pvSeg, &pSgBuf->aSegs[0].cbSeg);
     484        if (!pSgBuf->pvAllocator)
     485        {
     486            RTMemFree(pSgBuf);
     487            /** @todo Implement the VERR_TRY_AGAIN semantics. */
     488            return VERR_NO_MEMORY;
     489        }
     490    }
     491    else
     492    {
     493        pSgBuf->pvUser      = RTMemDup(pGso, sizeof(*pGso));
     494        pSgBuf->pvAllocator = NULL;
     495        pSgBuf->aSegs[0].cbSeg = RT_ALIGN_Z(cbMin, 16);
     496        pSgBuf->aSegs[0].pvSeg = RTMemAlloc(pSgBuf->aSegs[0].cbSeg);
     497        if (!pSgBuf->pvUser || !pSgBuf->aSegs[0].pvSeg)
     498        {
     499            RTMemFree(pSgBuf->aSegs[0].pvSeg);
     500            RTMemFree(pSgBuf->pvUser);
     501            RTMemFree(pSgBuf);
     502            /** @todo Implement the VERR_TRY_AGAIN semantics. */
     503            return VERR_NO_MEMORY;
     504        }
    447505    }
    448506
     
    453511    pSgBuf->cbUsed      = 0;
    454512    pSgBuf->cbAvailable = pSgBuf->aSegs[0].cbSeg;
    455     pSgBuf->pvUser      = NULL;
    456513    pSgBuf->cSegs       = 1;
    457514
     515#if 1 /* poison */
     516    memset(pSgBuf->aSegs[0].pvSeg, 'F', pSgBuf->aSegs[0].cbSeg);
     517#endif
    458518    *ppSgBuf = pSgBuf;
    459519    return VINF_SUCCESS;
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