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; }
/** * @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; }