From 95a6a263876387899e33b16a8aed23db41540d2b Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Sun, 29 Sep 2019 18:21:03 +0200 Subject: [PATCH] wifi: Schedule a BAR transmission subject to the availability of data frames --- examples/wireless/examples-to-run.py | 2 +- src/wifi/model/block-ack-manager.cc | 45 +++++++++++-------- src/wifi/model/block-ack-manager.h | 9 ++-- .../constant-wifi-ack-policy-selector.cc | 7 +++ src/wifi/model/qos-txop.cc | 26 +++++++++-- src/wifi/model/qos-txop.h | 3 +- 6 files changed, 66 insertions(+), 26 deletions(-) diff --git a/examples/wireless/examples-to-run.py b/examples/wireless/examples-to-run.py index b32adbd4a..154a10c61 100755 --- a/examples/wireless/examples-to-run.py +++ b/examples/wireless/examples-to-run.py @@ -48,7 +48,7 @@ cpp_examples = [ ("wifi-he-network --simulationTime=0.3 --frequency=5 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=745", "True", "True"), ("wifi-he-network --simulationTime=0.25 --frequency=2.4 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=238", "True", "True"), ("wifi-he-network --simulationTime=0.3 --frequency=2.4 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=223", "True", "True"), - ("wifi-simple-ht-hidden-stations --simulationTime=1.5 --enableRts=0 --nMpdus=32 --minExpectedThroughput=52 --maxExpectedThroughput=53", "True", "True"), + ("wifi-simple-ht-hidden-stations --simulationTime=1.5 --enableRts=0 --nMpdus=32 --minExpectedThroughput=50 --maxExpectedThroughput=51", "True", "True"), ("wifi-simple-ht-hidden-stations --simulationTime=1 --enableRts=1 --nMpdus=32 --minExpectedThroughput=57 --maxExpectedThroughput=58", "True", "True"), ("wifi-mixed-network --simulationTime=1", "True", "True"), ("wifi-aggregation --simulationTime=1 --verifyResults=1", "True", "True"), diff --git a/src/wifi/model/block-ack-manager.cc b/src/wifi/model/block-ack-manager.cc index b1ae1b31d..84aaa9776 100644 --- a/src/wifi/model/block-ack-manager.cc +++ b/src/wifi/model/block-ack-manager.cc @@ -37,11 +37,12 @@ Bar::Bar () NS_LOG_FUNCTION (this); } -Bar::Bar (Ptr bar, uint8_t tid) +Bar::Bar (Ptr bar, uint8_t tid, bool skipIfNoDataQueued) : bar (bar), - tid (tid) + tid (tid), + skipIfNoDataQueued (skipIfNoDataQueued) { - NS_LOG_FUNCTION (this << *bar << +tid); + NS_LOG_FUNCTION (this << *bar << +tid << skipIfNoDataQueued); } NS_OBJECT_ENSURE_REGISTERED (BlockAckManager); @@ -293,18 +294,26 @@ BlockAckManager::GetBar (bool remove) // (if needed) are scheduled m_retryPackets->Remove (WifiMacQueue::EMPTY, true); - while (!m_bars.empty ()) - { - auto nextBar = m_bars.front (); + auto nextBar = m_bars.begin (); - if (nextBar.bar->GetHeader ().IsBlockAckReq ()) + while (nextBar != m_bars.end ()) + { + if (nextBar->bar->GetHeader ().IsBlockAckReq ()) { - Mac48Address recipient = nextBar.bar->GetHeader ().GetAddr1 (); - AgreementsI it = m_agreements.find (std::make_pair (recipient, nextBar.tid)); + Mac48Address recipient = nextBar->bar->GetHeader ().GetAddr1 (); + AgreementsI it = m_agreements.find (std::make_pair (recipient, nextBar->tid)); if (it == m_agreements.end ()) { // BA agreement was torn down; remove this BAR and continue - m_bars.pop_front (); + nextBar = m_bars.erase (nextBar); + continue; + } + if (nextBar->skipIfNoDataQueued + && m_retryPackets->PeekByTidAndAddress (nextBar->tid, recipient) == m_retryPackets->end () + && m_queue->PeekByTidAndAddress (nextBar->tid, recipient) == m_queue->end ()) + { + // skip this BAR as there is no data queued + nextBar++; continue; } // remove expired outstanding MPDUs and update the starting sequence number @@ -323,20 +332,20 @@ BlockAckManager::GetBar (bool remove) } // update BAR if the starting sequence number changed CtrlBAckRequestHeader reqHdr; - nextBar.bar->GetPacket ()->PeekHeader (reqHdr); + nextBar->bar->GetPacket ()->PeekHeader (reqHdr); if (reqHdr.GetStartingSequence () != it->second.first.GetStartingSequence ()) { reqHdr.SetStartingSequence (it->second.first.GetStartingSequence ()); Ptr packet = Create (); packet->AddHeader (reqHdr); - nextBar.bar = Create (packet, nextBar.bar->GetHeader ()); + nextBar->bar = Create (packet, nextBar->bar->GetHeader ()); } } - bar = nextBar.bar; + bar = nextBar->bar; if (remove) { - m_bars.pop_front (); + m_bars.erase (nextBar); } break; } @@ -344,10 +353,10 @@ BlockAckManager::GetBar (bool remove) } bool -BlockAckManager::HasPackets (void) const +BlockAckManager::HasPackets (void) { NS_LOG_FUNCTION (this); - return (!m_retryPackets->IsEmpty () || m_bars.size () > 0); + return (!m_retryPackets->IsEmpty () || GetBar (false) != 0); } uint32_t @@ -661,7 +670,7 @@ BlockAckManager::GetBlockAckReqHeader (Mac48Address recipient, uint8_t tid) cons } void -BlockAckManager::ScheduleBar (Ptr bar) +BlockAckManager::ScheduleBar (Ptr bar, bool skipIfNoDataQueued) { NS_LOG_FUNCTION (this << *bar); NS_ASSERT (bar->GetHeader ().IsBlockAckReq ()); @@ -669,7 +678,7 @@ BlockAckManager::ScheduleBar (Ptr bar) CtrlBAckRequestHeader reqHdr; bar->GetPacket ()->PeekHeader (reqHdr); uint8_t tid = reqHdr.GetTidInfo (); - Bar request (bar, tid); + Bar request (bar, tid, skipIfNoDataQueued); // if a BAR for the given agreement is present, replace it with the new one for (std::list::const_iterator i = m_bars.begin (); i != m_bars.end (); i++) diff --git a/src/wifi/model/block-ack-manager.h b/src/wifi/model/block-ack-manager.h index 7b3a1ea42..4addc6628 100644 --- a/src/wifi/model/block-ack-manager.h +++ b/src/wifi/model/block-ack-manager.h @@ -54,10 +54,12 @@ struct Bar * * \param bar the BAR * \param tid the Traffic ID + * \param skipIfNoDataQueued true to hold this BAR if there is no data queued */ - Bar (Ptr bar, uint8_t tid); + Bar (Ptr bar, uint8_t tid, bool skipIfNoDataQueued = false); Ptr bar; ///< block ack request uint8_t tid; ///< TID + bool skipIfNoDataQueued; ///< do not send if there is no data queued }; @@ -161,7 +163,7 @@ public: * \return true if there are packets that need of retransmission or at least a BAR is scheduled, * false otherwise */ - bool HasPackets (void) const; + bool HasPackets (void); /** * Invoked upon receipt of an ack frame after the transmission of a QoS data frame * sent under an established Block Ack agreement. Remove the acknowledged frame @@ -400,13 +402,14 @@ public: /** * \param bar the Block Ack Request to enqueue + * \param skipIfNoDataQueued do not send if there is no data queued * * Enqueue the given Block Ack Request into the queue storing the next BAR * frames to transmit. If a BAR for the same recipient and TID is already present * in the queue, it is replaced by the new one. If the given BAR is retransmitted, * it is placed at the head of the queue, otherwise at the tail. */ - void ScheduleBar (Ptr bar); + void ScheduleBar (Ptr bar, bool skipIfNoDataQueued = false); private: /** diff --git a/src/wifi/model/constant-wifi-ack-policy-selector.cc b/src/wifi/model/constant-wifi-ack-policy-selector.cc index b431da763..c51e12c3e 100644 --- a/src/wifi/model/constant-wifi-ack-policy-selector.cc +++ b/src/wifi/model/constant-wifi-ack-policy-selector.cc @@ -92,6 +92,13 @@ ConstantWifiAckPolicySelector::UpdateTxParams (Ptr psdu, MacLowTransmi return; } + // If QosTxop forced the use of Block Ack QoS policy, do not make any change + if (params.MustSendBlockAckRequest ()) + { + NS_LOG_DEBUG ("Use Block Ack policy as requested"); + return; + } + // find the maximum distance from the sequence number of an MPDU included in the // PSDU to the starting sequence number of the transmit window. uint16_t maxDistToStartingSeq = psdu->GetMaxDistFromStartingSeq (m_qosTxop->GetBaStartingSequence (receiver, tid)); diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index 2a2934be8..2c320754b 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -164,9 +164,9 @@ QosTxop::PrepareBlockAckRequest (Mac48Address recipient, uint8_t tid) const } void -QosTxop::ScheduleBar (Ptr bar) +QosTxop::ScheduleBar (Ptr bar, bool skipIfNoDataQueued) { - m_baManager->ScheduleBar (bar); + m_baManager->ScheduleBar (bar, skipIfNoDataQueued); } void @@ -902,8 +902,28 @@ QosTxop::MissedBlockAck (uint8_t nMpdus) else { NS_LOG_DEBUG ("Block Ack Request Fail"); + // if a BA agreement exists, we can get here if there is no outstanding + // MPDU whose lifetime has not expired yet. + if (m_baManager->ExistsAgreementInState (m_currentHdr.GetAddr1 (), tid, + OriginatorBlockAckAgreement::ESTABLISHED)) + { + // If there is any (expired) outstanding MPDU, request the BA manager to discard + // it, which involves the scheduling of a BAR to advance the recipient's window + if (m_baManager->GetNBufferedPackets (m_currentHdr.GetAddr1 (), tid) > 0) + { + m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), tid); + } + // otherwise, it means that we have not received a Block Ack in response to a + // BlockAckRequest sent while no frame was outstanding, whose purpose was therefore + // to advance the recipient's window. Schedule a BlockAckRequest with + // skipIfNoDataQueued set to true, so that the BlockAckRequest is only sent + // if there are data frames queued for this recipient. + else + { + ScheduleBar (PrepareBlockAckRequest (m_currentHdr.GetAddr1 (), tid), true); + } + } //to reset the dcf. - m_baManager->DiscardOutstandingMpdus (m_currentHdr.GetAddr1 (), GetTid (m_currentPacket, m_currentHdr)); m_currentPacket = 0; ResetCw (); m_cwTrace = GetCw (); diff --git a/src/wifi/model/qos-txop.h b/src/wifi/model/qos-txop.h index 00cc987ba..84cbcc034 100644 --- a/src/wifi/model/qos-txop.h +++ b/src/wifi/model/qos-txop.h @@ -197,11 +197,12 @@ public: Ptr PrepareBlockAckRequest (Mac48Address recipient, uint8_t tid) const; /** * \param bar the Block Ack Request to schedule + * \param skipIfNoDataQueued do not send if there is no data queued * * Request the Block Ack manager to schedule the transmission of the given * Block Ack Request. */ - void ScheduleBar (Ptr bar); + void ScheduleBar (Ptr bar, bool skipIfNoDataQueued = false); /* dcf notifications forwarded here */ /**