bool CNB::ScheduleBuildSGListForTx() { NETKVM_ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); return NdisMAllocateNetBufferSGList(m_Context->DmaHandle, m_NB, this, NDIS_SG_LIST_WRITE_TO_DEVICE, nullptr, 0) == NDIS_STATUS_SUCCESS; }
bool CVirtQueue::Create(UINT Index, VirtIODevice *IODevice, NDIS_HANDLE DrvHandle) { m_DrvHandle = DrvHandle; m_Index = Index; m_IODevice = IODevice; if (!m_SharedMemory.Create(DrvHandle)) { DPrintf(0, "[%s] - shared memory creation failed\n", __FUNCTION__); return false; } NETKVM_ASSERT(m_VirtQueue == nullptr); if (AllocateQueueMemory()) { Renew(); } else { DPrintf(0, "[%s] - queue memory allocation failed, index = %d\n", __FUNCTION__, Index); } return m_VirtQueue != nullptr; }
CNB::~CNB() { NETKVM_ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); if(m_SGL != nullptr) { NdisMFreeNetBufferSGList(m_Context->DmaHandle, m_SGL, m_NB); } }
void __CRTDECL operator delete[](void *) throw() { NETKVM_ASSERT(FALSE); #ifdef DBG #pragma warning (push) #pragma warning (disable:28159) KeBugCheck(100); #pragma warning (pop) #endif }
ULONG CParaNdisAbstractPath::getCPUIndex() { #if NDIS_SUPPORT_NDIS620 PROCESSOR_NUMBER procNumber = { 0 }; procNumber.Group = DPCAffinity.Group; ULONG number = ParaNdis_GetIndexFromAffinity(DPCAffinity.Mask); if (number == INVALID_PROCESSOR_INDEX) { DPrintf(0, ("[%s] : bad in-group processor index: mask 0x%lx\n", __FUNCTION__, (ULONG)DPCAffinity.Mask)); NETKVM_ASSERT(FALSE); return INVALID_PROCESSOR_INDEX; } procNumber.Number = (UCHAR)number; procNumber.Reserved = 0; ULONG procIndex = KeGetProcessorIndexFromNumber(&procNumber); NETKVM_ASSERT(procIndex != INVALID_PROCESSOR_INDEX); return procIndex; #else return ParaNdis_GetIndexFromAffinity(DPCTargetProcessor); #endif }
void CParaNdisTX::NBLMappingDone(CNBL *NBLHolder) { NETKVM_ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); if (NBLHolder->MappingSuceeded()) { DoWithTXLock([NBLHolder, this](){ m_SendList.PushBack(NBLHolder); }); DoPendingTasks(false); } else { NBLHolder->SetStatus(NDIS_STATUS_FAILURE); NBLHolder->Release(); } }
static void ParaNdis_AdjustRxBufferHolderLength( pRxNetDescriptor p, ULONG ulDataOffset) { PMDL NextMdlLinkage = p->Holder; ULONG ulBytesLeft = p->PacketInfo.dataLength + ulDataOffset; while(NextMdlLinkage != NULL) { ULONG ulThisMdlBytes = min(PAGE_SIZE, ulBytesLeft); NdisAdjustMdlLength(NextMdlLinkage, ulThisMdlBytes); ulBytesLeft -= ulThisMdlBytes; NextMdlLinkage = NDIS_MDL_LINKAGE(NextMdlLinkage); } NETKVM_ASSERT(ulBytesLeft == 0); }
CNBL::~CNBL() { CDpcIrqlRaiser OnDpc; m_MappedBuffers.ForEachDetached([this](CNB *NB) { CNB::Destroy(NB, m_Context->MiniportHandle); }); m_Buffers.ForEachDetached([this](CNB *NB) { CNB::Destroy(NB, m_Context->MiniportHandle); }); if(m_NBL) { auto NBL = DetachInternalObject(); NETKVM_ASSERT(NET_BUFFER_LIST_NEXT_NBL(NBL) == nullptr); m_ParentTXPath->CompleteOutstandingNBLChain(NBL); } }
static void ParaNdis_AdjustRxBufferHolderLength( pRxNetDescriptor p, ULONG ulDataOffset) { PMDL NextMdlLinkage = p->Holder; ULONG ulBytesLeft = p->PacketInfo.dataLength + ulDataOffset; ULONG ulPageDescIndex = PARANDIS_FIRST_RX_DATA_PAGE; while(NextMdlLinkage != NULL) { ULONG ulThisMdlBytes = min(p->PhysicalPages[ulPageDescIndex].size, ulBytesLeft); NdisAdjustMdlLength(NextMdlLinkage, ulThisMdlBytes); ulBytesLeft -= ulThisMdlBytes; NextMdlLinkage = NDIS_MDL_LINKAGE(NextMdlLinkage); ulPageDescIndex++; } NETKVM_ASSERT(ulBytesLeft == 0); }
bool CNBL::ParseCSO(TClassPred IsClass, TOffloadPred IsOffload, TSupportedPred IsSupported, LPSTR OffloadName) { NETKVM_ASSERT(IsClass()); UNREFERENCED_PARAMETER(IsClass); if (IsOffload()) { if(!IsSupported()) { DPrintf(0, ("[%s] %s request when it is not supported\n", __FUNCTION__, OffloadName)); #if FAIL_UNEXPECTED // ignore unexpected CS requests while this passes WHQL return false; #endif } } return true; }
bool CNBL::ParseLSO() { NETKVM_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; }
bool CTXDescriptor::SetupHeaders(ULONG ParsedHeadersLength) { m_CurrVirtioSGLEntry = 0; if (m_Headers.VlanHeader()->TCI == 0) { if (m_AnyLayout) { return AddDataChunk(m_Headers.VirtioHeaderPA(), m_Headers.VirtioHeaderLength() + ParsedHeadersLength); } else { return AddDataChunk(m_Headers.VirtioHeaderPA(), m_Headers.VirtioHeaderLength()) && AddDataChunk(m_Headers.EthHeaderPA(), ParsedHeadersLength); } } else { NETKVM_ASSERT(ParsedHeadersLength >= ETH_HEADER_SIZE); if (!AddDataChunk(m_Headers.VirtioHeaderPA(), m_Headers.VirtioHeaderLength()) || !AddDataChunk(m_Headers.EthHeaderPA(), ETH_HEADER_SIZE) || !AddDataChunk(m_Headers.VlanHeaderPA(), ETH_PRIORITY_HEADER_SIZE)) { return false; } if (ParsedHeadersLength > ETH_HEADER_SIZE) { return AddDataChunk(m_Headers.IPHeadersPA(), ParsedHeadersLength - ETH_HEADER_SIZE); } return true; } }
bool CParaNdisTX::SendMapped(bool IsInterrupt) { if(ParaNdis_IsSendPossible(m_Context)) { bool SentOutSomeBuffers = false; auto HaveBuffers = true; while (HaveBuffers && HaveMappedNBLs()) { auto NBLHolder = PopMappedNBL(); if (NBLHolder->HaveMappedBuffers()) { auto NBHolder = NBLHolder->PopMappedNB(); auto result = m_VirtQueue.SubmitPacket(*NBHolder); switch (result) { case SUBMIT_NO_PLACE_IN_QUEUE: NBLHolder->PushMappedNB(NBHolder); PushMappedNBL(NBLHolder); HaveBuffers = false; // break the loop, allow to kick and free some buffers break; case SUBMIT_FAILURE: __fallthrough; case SUBMIT_SUCCESS: __fallthrough; case SUBMIT_PACKET_TOO_LARGE: // if this NBL finished? if (!NBLHolder->HaveMappedBuffers()) { m_WaitingList.Push(NBLHolder); } else { // no, insert it back to the queue PushMappedNBL(NBLHolder); } if (result == SUBMIT_SUCCESS) { SentOutSomeBuffers = true; } else { NBHolder->SendComplete(); CNB::Destroy(NBHolder, m_Context->MiniportHandle); } break; default: NETKVM_ASSERT(false); break; } } else { //TODO: Refactoring needed //This is a case when pause called, mapped list cleared but NBL is still in the send list m_WaitingList.Push(NBLHolder); } } if (SentOutSomeBuffers) { DPrintf(2, ("[%s] sent down\n", __FUNCTION__, SentOutSomeBuffers)); if (IsInterrupt) { return true; } else { m_VirtQueue.Kick(); } } } return false; }