From 75df5d004dac5381ceedfd3f2aa067e1a76af884 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 1 Jul 2024 13:50:39 +0200 Subject: [PATCH] wifi: Default ack manager returns that response is needed if TX window is stalled Reported by Rami Abdallah --- .../model/originator-block-ack-agreement.cc | 24 ++++++++++ .../model/originator-block-ack-agreement.h | 12 +++++ src/wifi/model/wifi-default-ack-manager.cc | 47 ++++++++++++++----- 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/wifi/model/originator-block-ack-agreement.cc b/src/wifi/model/originator-block-ack-agreement.cc index 2d8fb3a4f..65d5cf34b 100644 --- a/src/wifi/model/originator-block-ack-agreement.cc +++ b/src/wifi/model/originator-block-ack-agreement.cc @@ -88,6 +88,30 @@ OriginatorBlockAckAgreement::InitTxWindow() m_txWindow.Init(m_startingSeq, m_bufferSize); } +bool +OriginatorBlockAckAgreement::AllAckedMpdusInTxWindow(const std::set& seqNumbers) const +{ + std::set distances; + for (const auto seqN : seqNumbers) + { + distances.insert(GetDistance(seqN)); + } + + for (std::size_t i = 0; i < m_txWindow.GetWinSize(); ++i) + { + if (distances.contains(i)) + { + continue; // this is one of the positions to ignore + } + if (!m_txWindow.At(i)) + { + return false; // this position is available or contains an unacknowledged MPDU + } + } + NS_LOG_INFO("TX window is blocked"); + return true; +} + void OriginatorBlockAckAgreement::AdvanceTxWindow() { diff --git a/src/wifi/model/originator-block-ack-agreement.h b/src/wifi/model/originator-block-ack-agreement.h index b7da72370..9d4fb5af6 100644 --- a/src/wifi/model/originator-block-ack-agreement.h +++ b/src/wifi/model/originator-block-ack-agreement.h @@ -12,6 +12,8 @@ #include "block-ack-agreement.h" #include "block-ack-window.h" +#include + class OriginatorBlockAckWindowTest; namespace ns3 @@ -190,6 +192,16 @@ class OriginatorBlockAckAgreement : public BlockAckAgreement */ void NotifyDiscardedMpdu(Ptr mpdu); + /** + * Check whether all the MPDUs in the TX window other than the given ones have been already + * acknowledged. + * + * \param seqNumbers the sequence numbers of the given MPDUs + * \return whether all the MPDUs in the TX window other than the given ones have been already + * acknowledged + */ + bool AllAckedMpdusInTxWindow(const std::set& seqNumbers) const; + private: /** * Advance the transmit window so that the starting sequence number is the diff --git a/src/wifi/model/wifi-default-ack-manager.cc b/src/wifi/model/wifi-default-ack-manager.cc index 48497c850..e4e51deff 100644 --- a/src/wifi/model/wifi-default-ack-manager.cc +++ b/src/wifi/model/wifi-default-ack-manager.cc @@ -133,27 +133,50 @@ WifiDefaultAckManager::IsResponseNeeded(Ptr mpdu, auto receiver = mpdu->GetHeader().GetAddr1(); auto origReceiver = mpdu->GetOriginal()->GetHeader().GetAddr1(); Ptr edca = m_mac->GetQosTxop(tid); + const auto& seqNumbers = txParams.GetPsduInfo(receiver)->seqNumbers.at(tid); // An immediate response (Ack or Block Ack) is needed if any of the following holds: + // * the BA threshold is set to zero + if (m_baThreshold == 0.0) + { + return true; + } // * the maximum distance between the sequence number of an MPDU to transmit // and the starting sequence number of the transmit window is greater than // or equal to the window size multiplied by the BaThreshold + if (GetMaxDistFromStartingSeq(mpdu, txParams) >= + m_baThreshold * edca->GetBaBufferSize(origReceiver, tid)) + { + return true; + } // * no other frame belonging to this BA agreement is queued (because, in such // a case, a Block Ack is not going to be requested anytime soon) + if (auto queueId = WifiContainerQueueId(WIFI_QOSDATA_QUEUE, WIFI_UNICAST, origReceiver, tid); + edca->GetWifiMacQueue()->GetNPackets(queueId) - + edca->GetBaManager()->GetNBufferedPackets(origReceiver, tid) - seqNumbers.size() < + 1) + { + return true; + } + // * the block ack TX window cannot advance because all the MPDUs in the TX window other than + // those being transmitted have been already acknowledged + if (m_mac->GetBaAgreementEstablishedAsOriginator(origReceiver, tid) + ->get() + .AllAckedMpdusInTxWindow(seqNumbers)) + { + return true; + } + // * this is the initial frame of a transmission opportunity and it is not // protected by RTS/CTS (see Annex G.3 of IEEE 802.11-2016) - return !( - m_baThreshold > 0 && - GetMaxDistFromStartingSeq(mpdu, txParams) < - m_baThreshold * edca->GetBaBufferSize(origReceiver, tid) && - (edca->GetWifiMacQueue()->GetNPackets( - {WIFI_QOSDATA_QUEUE, WIFI_UNICAST, origReceiver, tid}) - - edca->GetBaManager()->GetNBufferedPackets(origReceiver, tid) - - txParams.GetPsduInfo(receiver)->seqNumbers.at(tid).size() >= - 1) && - !(edca->GetTxopLimit(m_linkId).IsStrictlyPositive() && - edca->GetRemainingTxop(m_linkId) == edca->GetTxopLimit(m_linkId) && - !(txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS))); + if (edca->GetTxopLimit(m_linkId).IsStrictlyPositive() && + edca->GetRemainingTxop(m_linkId) == edca->GetTxopLimit(m_linkId) && + !(txParams.m_protection && txParams.m_protection->method == WifiProtection::RTS_CTS)) + { + return true; + } + + return false; } bool