void CParaNdisTX::Send(PNET_BUFFER_LIST NBL) { PNET_BUFFER_LIST nextNBL = nullptr; for(auto currNBL = NBL; currNBL != nullptr; currNBL = nextNBL) { nextNBL = NET_BUFFER_LIST_NEXT_NBL(currNBL); NET_BUFFER_LIST_NEXT_NBL(currNBL) = nullptr; auto NBLHolder = new (m_Context->MiniportHandle) CNBL(currNBL, m_Context, *this); if (NBLHolder == nullptr) { CNBL OnStack(currNBL, m_Context, *this); OnStack.SetStatus(NDIS_STATUS_RESOURCES); DPrintf(0, ("ERROR: Failed to allocate CNBL instance\n")); continue; } if(NBLHolder->Prepare() && ParaNdis_IsSendPossible(m_Context)) { NBLHolder->StartMapping(); } else { NBLHolder->SetStatus(ParaNdis_ExactSendFailureStatus(m_Context)); NBLHolder->Release(); } } }
void CParaNdisTX::Send(PNET_BUFFER_LIST NBL) { PNET_BUFFER_LIST nextNBL = nullptr; NDIS_STATUS RejectionStatus = NDIS_STATUS_FAILURE; if (!m_StateMachine.RegisterOutstandingItems(ParaNdis_CountNBLs(NBL), &RejectionStatus)) { ParaNdis_CompleteNBLChainWithStatus(m_Context->MiniportHandle, NBL, RejectionStatus); return; } for(auto currNBL = NBL; currNBL != nullptr; currNBL = nextNBL) { nextNBL = NET_BUFFER_LIST_NEXT_NBL(currNBL); NET_BUFFER_LIST_NEXT_NBL(currNBL) = nullptr; auto NBLHolder = new (m_Context->MiniportHandle) CNBL(currNBL, m_Context, *this); if (NBLHolder == nullptr) { currNBL->Status = NDIS_STATUS_RESOURCES; CompleteOutstandingNBLChain(currNBL); DPrintf(0, ("ERROR: Failed to allocate CNBL instance\n")); continue; } if(NBLHolder->Prepare() && ParaNdis_IsSendPossible(m_Context)) { NBLHolder->StartMapping(); } else { NBLHolder->SetStatus(ParaNdis_ExactSendFailureStatus(m_Context)); NBLHolder->Release(); } } }
bool CParaNdisTX::SendMapped(bool IsInterrupt, PNET_BUFFER_LIST &NBLFailNow) { if(!ParaNdis_IsSendPossible(m_Context)) { NBLFailNow = RemoveAllNonWaitingNBLs(); if (NBLFailNow) { DPrintf(0, (__FUNCTION__ " Failing send")); } } else { 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: case SUBMIT_SUCCESS: 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: 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; }