bool CNB::BindToDescriptor(CTXDescriptor &Descriptor) { if (m_SGL == nullptr) { return false; } Descriptor.SetNB(this); auto &HeadersArea = Descriptor.HeadersAreaAccessor(); auto EthHeaders = HeadersArea.EthHeadersAreaVA(); ULONG HeadersLength; ULONG L4HeaderOffset; if (!CopyHeaders(EthHeaders, HeadersArea.MaxEthHeadersSize(), HeadersLength, L4HeaderOffset)) { return false; } BuildPriorityHeader(HeadersArea.EthHeader(), HeadersArea.VlanHeader()); PrepareOffloads(HeadersArea.VirtioHeader(), HeadersArea.IPHeaders(), GetDataLength() - m_Context->Offload.ipHeaderOffset, L4HeaderOffset); return FillDescriptorSGList(Descriptor, HeadersLength); }
UINT CTXVirtQueue::ReleaseTransmitBuffers(CRawCNBList& listDone) { UINT len, i = 0; CTXDescriptor *TXDescriptor; DEBUG_ENTRY(4); while(NULL != (TXDescriptor = (CTXDescriptor *) GetBuf(&len))) { m_DescriptorsInUse.Remove(TXDescriptor); if (!TXDescriptor->GetUsedBuffersNum()) { DPrintf(0, ("[%s] ERROR: nofUsedBuffers not set!\n", __FUNCTION__)); } m_FreeHWBuffers += TXDescriptor->GetUsedBuffersNum(); listDone.PushBack(TXDescriptor->GetNB()); m_Descriptors.Push(TXDescriptor); DPrintf(3, ("[%s] Free Tx: desc %d, buff %d\n", __FUNCTION__, m_Descriptors.GetCount(), m_FreeHWBuffers)); ++i; } if (i) { NdisGetCurrentSystemTime(&m_Context->LastTxCompletionTimeStamp); m_DoKickOnNoBuffer = true; } DPrintf((i ? 3 : 5), ("[%s] returning i = %d\n", __FUNCTION__, i)); return i; }
void CTXVirtQueue::UpdateTXStats(const CNB &NB, CTXDescriptor &Descriptor) { auto &HeadersArea = Descriptor.HeadersAreaAccessor(); PVOID EthHeader = HeadersArea.EthHeader(); //TODO: Statistics must be atomic auto BytesSent = NB.GetDataLength(); auto NBL = NB.GetParentNBL(); m_Context->Statistics.ifHCOutOctets += BytesSent; if (ETH_IS_BROADCAST(EthHeader)) { m_Context->Statistics.ifHCOutBroadcastOctets += BytesSent; m_Context->Statistics.ifHCOutBroadcastPkts++; } else if (ETH_IS_MULTICAST(EthHeader)) { m_Context->Statistics.ifHCOutMulticastOctets += BytesSent; m_Context->Statistics.ifHCOutMulticastPkts++; } else { m_Context->Statistics.ifHCOutUcastOctets += BytesSent; m_Context->Statistics.ifHCOutUcastPkts++; } if (NBL->IsLSO()) { m_Context->extraStatistics.framesLSO++; auto EthHeaders = Descriptor.HeadersAreaAccessor().EthHeadersAreaVA(); auto TCPHdr = reinterpret_cast<TCPHeader *>(RtlOffsetToPointer(EthHeaders, NBL->TCPHeaderOffset())); NBL->UpdateLSOTxStats(NB.GetDataLength() - NBL->TCPHeaderOffset() - TCP_HEADER_LENGTH(TCPHdr)); } else if (NBL->IsTcpCSO() || NBL->IsUdpCSO()) { m_Context->extraStatistics.framesCSOffload++; } }
bool CNB::MapDataToVirtioSGL(CTXDescriptor &Descriptor, ULONG Offset) const { for (ULONG i = 0; i < m_SGL->NumberOfElements; i++) { if (Offset < m_SGL->Elements[i].Length) { PHYSICAL_ADDRESS PA; PA.QuadPart = m_SGL->Elements[i].Address.QuadPart + Offset; if (!Descriptor.AddDataChunk(PA, m_SGL->Elements[i].Length - Offset)) { return false; } Offset = 0; } else { Offset -= m_SGL->Elements[i].Length; } } return true; }
bool CNB::FillDescriptorSGList(CTXDescriptor &Descriptor, ULONG ParsedHeadersLength) const { return Descriptor.SetupHeaders(ParsedHeadersLength) && MapDataToVirtioSGL(Descriptor, ParsedHeadersLength + NET_BUFFER_DATA_OFFSET(m_NB)); }