wifi: Default ack manager returns that response is needed if TX window is stalled
Reported by Rami Abdallah
This commit is contained in:
@@ -88,6 +88,30 @@ OriginatorBlockAckAgreement::InitTxWindow()
|
||||
m_txWindow.Init(m_startingSeq, m_bufferSize);
|
||||
}
|
||||
|
||||
bool
|
||||
OriginatorBlockAckAgreement::AllAckedMpdusInTxWindow(const std::set<uint16_t>& seqNumbers) const
|
||||
{
|
||||
std::set<std::size_t> 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()
|
||||
{
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "block-ack-agreement.h"
|
||||
#include "block-ack-window.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
class OriginatorBlockAckWindowTest;
|
||||
|
||||
namespace ns3
|
||||
@@ -190,6 +192,16 @@ class OriginatorBlockAckAgreement : public BlockAckAgreement
|
||||
*/
|
||||
void NotifyDiscardedMpdu(Ptr<const WifiMpdu> 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<uint16_t>& seqNumbers) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Advance the transmit window so that the starting sequence number is the
|
||||
|
||||
@@ -133,27 +133,50 @@ WifiDefaultAckManager::IsResponseNeeded(Ptr<const WifiMpdu> mpdu,
|
||||
auto receiver = mpdu->GetHeader().GetAddr1();
|
||||
auto origReceiver = mpdu->GetOriginal()->GetHeader().GetAddr1();
|
||||
Ptr<QosTxop> 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
|
||||
|
||||
Reference in New Issue
Block a user