int VBoxNetLwipNAT::processGSO(PCPDMNETWORKGSO pGso, size_t cbFrame)
{
    if (!PDMNetGsoIsValid(pGso, cbFrame,
                          cbFrame - sizeof(PDMNETWORKGSO)))
        return VERR_INVALID_PARAMETER;

    cbFrame -= sizeof(PDMNETWORKGSO);
    uint8_t         abHdrScratch[256];
    uint32_t const  cSegs = PDMNetGsoCalcSegmentCount(pGso,
                                                      cbFrame);
    for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
    {
        uint32_t cbSegFrame;
        void    *pvSegFrame =
          PDMNetGsoCarveSegmentQD(pGso,
                                  (uint8_t *)(pGso + 1),
                                  cbFrame,
                                  abHdrScratch,
                                  iSeg,
                                  cSegs,
                                  &cbSegFrame);

        int rc = processFrame(pvSegFrame, cbSegFrame);
        if (RT_FAILURE(rc))
        {
            return rc;
        }
    }

    return VINF_SUCCESS;
}
示例#2
0
文件: network.cpp 项目: 0xxx/genode
/**
 * @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
 */
static DECLCALLBACK(int) drvNicNetworkUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
{
	PDRVNIC pThis = PDMINETWORKUP_2_DRVNIC(pInterface);
	Nic_client *nic_client = pThis->nic_client;

	AssertPtr(pSgBuf);
	Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) == PDMSCATTERGATHER_FLAGS_MAGIC);

	/* Set an FTM checkpoint as this operation changes the state permanently. */
	PDMDrvHlpFTSetCheckpoint(pThis->pDrvIns, FTMCHECKPOINTTYPE_NETWORK);

	int rc;
	if (!pSgBuf->pvUser)
	{
		Log2(("drvNicSend: pSgBuf->aSegs[0].pvSeg=%p pSgBuf->cbUsed=%#x\n"
		      "%.*Rhxd\n", pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, pSgBuf->cbUsed,
		      pSgBuf->aSegs[0].pvSeg));

		rc = nic_client->send_packet(pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed);
	}
	else
	{
		uint8_t         abHdrScratch[256];
		uint8_t const  *pbFrame = (uint8_t const *)pSgBuf->aSegs[0].pvSeg;
		PCPDMNETWORKGSO pGso    = (PCPDMNETWORKGSO)pSgBuf->pvUser;
		uint32_t const  cSegs   = PDMNetGsoCalcSegmentCount(pGso, pSgBuf->cbUsed);
		Assert(cSegs > 1);
		rc = VINF_SUCCESS;
		for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
		{
			uint32_t cbSegFrame;
			void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t *)pbFrame, pSgBuf->cbUsed,
			                                           abHdrScratch, iSeg, cSegs, &cbSegFrame);
			rc = nic_client->send_packet(pvSegFrame, cbSegFrame);
			if (RT_FAILURE(rc))
				break;
		}
	}

	pSgBuf->fFlags = 0;
	RTMemFree(pSgBuf);

	AssertRC(rc);
	if (RT_FAILURE(rc))
		rc = rc == VERR_NO_MEMORY ? VERR_NET_NO_BUFFER_SPACE : VERR_NET_DOWN;
	return rc;
}