bool CNBL::ParseOffloads() { if (IsLSO()) { if(!ParseLSO()) { return false; } } else if (IsIP4CSO()) { if(!ParseCSO([this] () -> bool { return IsIP4CSO(); }, [this] () -> bool { return m_CsoInfo.Transmit.TcpChecksum; }, [this] () -> bool { return m_Context->Offload.flags.fTxTCPChecksum && m_Context->bOffloadv4Enabled; }, "TCP4 CSO")) { return false; } else if(!ParseCSO([this] () -> bool { return IsIP4CSO(); }, [this] () -> bool { return m_CsoInfo.Transmit.UdpChecksum; }, [this] () -> bool { return m_Context->Offload.flags.fTxUDPChecksum && m_Context->bOffloadv4Enabled; }, "UDP4 CSO")) { return false; } if(!ParseCSO([this] () -> bool { return IsIP4CSO(); }, [this] () -> bool { return m_CsoInfo.Transmit.IpHeaderChecksum; }, [this] () -> bool { return m_Context->Offload.flags.fTxIPChecksum && m_Context->bOffloadv4Enabled; }, "IP4 CSO")) { return false; } } else if (IsIP6CSO()) { if(!ParseCSO([this] () -> bool { return IsIP6CSO(); }, [this] () -> bool { return m_CsoInfo.Transmit.TcpChecksum; }, [this] () -> bool { return m_Context->Offload.flags.fTxTCPv6Checksum && m_Context->bOffloadv6Enabled; }, "TCP6 CSO")) { return false; } else if(!ParseCSO([this] () -> bool { return IsIP6CSO(); }, [this] () -> bool { return m_CsoInfo.Transmit.UdpChecksum; }, [this] () -> bool { return m_Context->Offload.flags.fTxUDPv6Checksum && m_Context->bOffloadv6Enabled; }, "UDP6 CSO")) { return false; } } return true; }
PNET_BUFFER_LIST CNBL::DetachInternalObject() { // do it for both LsoV1 and LsoV2 if (IsLSO()) { m_LsoInfo.LsoV1TransmitComplete.TcpPayload = m_TransferSize; } //Flush changes made in LSO structures NET_BUFFER_LIST_INFO(m_NBL, TcpLargeSendNetBufferListInfo) = m_LsoInfo.Value; auto Res = m_NBL; m_NBL = nullptr; return Res; }
bool CNBL::ParseLSO() { ASSERT(IsLSO()); if (m_LsoInfo.LsoV1Transmit.Type != NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE && m_LsoInfo.LsoV2Transmit.Type != NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE) { return false; } if (NeedsLSO() && (!m_LsoInfo.LsoV2Transmit.MSS || !m_LsoInfo.LsoV2Transmit.TcpHeaderOffset)) { return false; } if (!FitsLSO()) { return false; } if (!LsoTcpHeaderOffset() != !MSS()) { return false; } if ((!m_Context->Offload.flags.fTxLso || !m_Context->bOffloadv4Enabled) && m_LsoInfo.LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv4) { return false; } if (m_LsoInfo.LsoV2Transmit.Type == NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE && m_LsoInfo.LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6 && (!m_Context->Offload.flags.fTxLsov6 || !m_Context->bOffloadv6Enabled)) { return false; } return true; }
PNET_BUFFER_LIST CNBL::DetachInternalObject() { m_MappedBuffers.ForEach([this](CNB *NB) { NB->ReleaseResources(); }); // do it for both LsoV1 and LsoV2 if (IsLSO()) { m_LsoInfo.LsoV1TransmitComplete.TcpPayload = m_TransferSize; } //Flush changes made in LSO structures NET_BUFFER_LIST_INFO(m_NBL, TcpLargeSendNetBufferListInfo) = m_LsoInfo.Value; auto Res = m_NBL; m_NBL = nullptr; return Res; }
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++; } }