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 CNBL::ParseBuffers() { m_MaxDataLength = 0; for (auto NB = NET_BUFFER_LIST_FIRST_NB(m_NBL); NB != nullptr; NB = NET_BUFFER_NEXT_NB(NB)) { CNB *NBHolder = new (m_Context->MiniportHandle) CNB(NB, this, m_Context); if(!NBHolder || !NBHolder->IsValid()) { return false; } RegisterNB(NBHolder); m_MaxDataLength = max(m_MaxDataLength, NBHolder->GetDataLength()); } if(m_MaxDataLength == 0) { DPrintf(0, ("Empty NBL (%p) dropped\n", __FUNCTION__, m_NBL)); return false; } return true; }
SubmitTxPacketResult CTXVirtQueue::SubmitPacket(CNB &NB) { if (!m_Descriptors.GetCount()) { KickQueueOnOverflow(); return SUBMIT_NO_PLACE_IN_QUEUE; } auto TXDescriptor = m_Descriptors.Pop(); if (!NB.BindToDescriptor(*TXDescriptor)) { m_Descriptors.Push(TXDescriptor); return SUBMIT_FAILURE; } auto res = TXDescriptor->Enqueue(this, m_TotalHWBuffers, m_FreeHWBuffers); switch (res) { case SUBMIT_NO_PLACE_IN_QUEUE: { KickQueueOnOverflow(); //Fall-through __fallthrough; } case SUBMIT_PACKET_TOO_LARGE: __fallthrough; case SUBMIT_FAILURE: { m_Descriptors.Push(TXDescriptor); break; } case SUBMIT_SUCCESS: { m_FreeHWBuffers -= TXDescriptor->GetUsedBuffersNum(); m_DescriptorsInUse.PushBack(TXDescriptor); UpdateTXStats(NB, *TXDescriptor); break; } } return res; }