From 8cbcd0cb9622c6b4f5cd595db0cf822c16f70935 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Fri, 22 Sep 2023 13:31:33 +0200 Subject: [PATCH] wifi: Possibly invoke backoff when no transmission is made in a TXOP --- CHANGES.md | 1 + .../hwmp-simplest-regression-test-0-1.pcap | Bin 77751 -> 77751 bytes .../hwmp-simplest-regression-test-1-1.pcap | Bin 81147 -> 81147 bytes .../test/flame/flame-regression-test-0-1.pcap | Bin 5320 -> 5320 bytes .../test/flame/flame-regression-test-1-1.pcap | Bin 7122 -> 7122 bytes .../test/flame/flame-regression-test-2-1.pcap | Bin 5350 -> 5350 bytes src/wifi/doc/source/wifi-design.rst | 2 + src/wifi/model/channel-access-manager.cc | 40 +++++++++++++++++- src/wifi/model/channel-access-manager.h | 26 ++++++++++++ src/wifi/model/qos-txop.cc | 21 ++++++++- 10 files changed, 88 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 126440e66..0759b60f1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ Changes from ns-3.40 to ns-3-dev ### New API * (spectrum) `SpectrumSignalParameters` is extended to include two new members called: `spectrumChannelMatrix` and `precodingMatrix` which are the key information needed to support MIMO simulations. +* (wifi) Added new attribute `ChannelAccessManager:GenerateBackoffIfTxopWithoutTx` to invoke the backoff procedure when an AC gains the right to start a TXOP but it does not transmit any frame, provided that the queue is not actually empty. No transmission may occur,e.g., due to constraints associated with EMLSR operations. This possibility is specified by the current draft revision of the IEEE 802.11 standard. ### Changes to existing API diff --git a/src/mesh/test/dot11s/hwmp-simplest-regression-test-0-1.pcap b/src/mesh/test/dot11s/hwmp-simplest-regression-test-0-1.pcap index 664ad59546c73594212957f48d758e3fd1cd45d9..a4f6f2d05161e238eac6666765cdfbc0f3cc5671 100644 GIT binary patch delta 20 ccmdmfpJn@fmJR(Jj3=8XaBQEz!Kkhd0AsZW{{R30 delta 20 ccmdmfpJn@fmJR(JjF*}xaBQEz!Kkhd0Avpc2mk;8 diff --git a/src/mesh/test/dot11s/hwmp-simplest-regression-test-1-1.pcap b/src/mesh/test/dot11s/hwmp-simplest-regression-test-1-1.pcap index c04cb9bd5d8d0b27c8d822097199f9f66f94ae6d..b6603fdd915f931b4ac0ff543d46a5187edd6628 100644 GIT binary patch delta 20 ccmezUljZkMmJR(JjGoOCIJQsVV9YiF0Bo!Xi~s-t delta 20 ccmezUljZkMmJR(Jj6uy4IJQsVV9YiF0Br^cl>h($ diff --git a/src/mesh/test/flame/flame-regression-test-0-1.pcap b/src/mesh/test/flame/flame-regression-test-0-1.pcap index b93b5b31a36a4d77e27396c8bb7c1bb53bf09320..465b711b6312297b3e854fec0b16d584f479db62 100644 GIT binary patch delta 20 ccmX@1c|vo;B|c`W73`A(S>-o>;k&{L09UOC^#A|> delta 20 ccmX@1c|vo;B|c{773`A(S>-o>;k&{L09Y9Z{r~^~ diff --git a/src/mesh/test/flame/flame-regression-test-1-1.pcap b/src/mesh/test/flame/flame-regression-test-1-1.pcap index 5413f34c3fa88d57c97a43cde5a19015d0b42535..3109fe71ec5aa8a715d6d3dd13b3a86b002653dc 100644 GIT binary patch delta 38 ucmca)e#v~p9AU=Z$#aEknaftNPxfaLXJ=zzVBlTJKG~5)esh#a1v>x%lM6%u delta 38 ucmca)e#v~p9AU<3ljjQ8GS{zQpX|>h&d$cbz@V{`eX=8q{N^Z;3U&Yly$f*w diff --git a/src/mesh/test/flame/flame-regression-test-2-1.pcap b/src/mesh/test/flame/flame-regression-test-2-1.pcap index cc5acb9ed3649a7e246796ad991d1d4a15a9aa98..c8c18bd710fe7b141f4cd1d953768dc659fe6421 100644 GIT binary patch delta 41 wcmaE+`Al() + .SetGroupName("Wifi") + .AddConstructor() + .AddAttribute("GenerateBackoffIfTxopWithoutTx", + "Specify whether the backoff should be invoked when the AC gains the " + "right to start a TXOP but it does not transmit any frame " + "(e.g., due to constraints associated with EMLSR operations), " + "provided that the queue is not actually empty.", + BooleanValue(false), + MakeBooleanAccessor(&ChannelAccessManager::SetGenerateBackoffOnNoTx, + &ChannelAccessManager::GetGenerateBackoffOnNoTx), + MakeBooleanChecker()); + return tid; +} + ChannelAccessManager::ChannelAccessManager() : m_lastAckTimeoutEnd(0), m_lastCtsTimeoutEnd(0), @@ -453,7 +475,7 @@ void ChannelAccessManager::RequestAccess(Ptr txop) { NS_LOG_FUNCTION(this << txop); - if (m_phy) + if (m_phy && txop->HasFramesToTransmit(m_linkId)) { m_phy->NotifyChannelAccessRequested(); } @@ -558,6 +580,9 @@ ChannelAccessManager::DoGrantDcfAccess() } else { + // this TXOP did not transmit anything, make sure that backoff counter starts + // decreasing in a slot again + txop->UpdateBackoffSlotsNow(0, now, m_linkId); // reset the current state to the EDCAF that won the contention // but did not transmit anything i--; @@ -801,6 +826,19 @@ ChannelAccessManager::DisableEdcaFor(Ptr qosTxop, Time duration) DoRestartAccessTimeoutIfNeeded(); } +void +ChannelAccessManager::SetGenerateBackoffOnNoTx(bool enable) +{ + NS_LOG_FUNCTION(this << enable); + m_generateBackoffOnNoTx = enable; +} + +bool +ChannelAccessManager::GetGenerateBackoffOnNoTx() const +{ + return m_generateBackoffOnNoTx; +} + void ChannelAccessManager::NotifyRxStartNow(Time duration) { diff --git a/src/wifi/model/channel-access-manager.h b/src/wifi/model/channel-access-manager.h index 477846b9b..e3ff7c552 100644 --- a/src/wifi/model/channel-access-manager.h +++ b/src/wifi/model/channel-access-manager.h @@ -62,6 +62,12 @@ class ChannelAccessManager : public Object ChannelAccessManager(); ~ChannelAccessManager() override; + /** + * \brief Get the type ID. + * \return the object TypeId + */ + static TypeId GetTypeId(); + /** * Set up (or reactivate) listener for PHY events on the given PHY. The new (or reactivated) * listener becomes the active listener and the previous active listener attached to another @@ -157,6 +163,22 @@ class ChannelAccessManager : public Object */ void DisableEdcaFor(Ptr qosTxop, Time duration); + /** + * Set the member variable indicating whether the backoff should be invoked when an AC gains + * the right to start a TXOP but it does not transmit any frame (e.g., due to constraints + * associated with EMLSR operations), provided that the queue is not actually empty. + * + * \param enable whether to enable backoff generation when no TX is performed in a TXOP + */ + void SetGenerateBackoffOnNoTx(bool enable); + + /** + * \return whether the backoff should be invoked when an AC gains the right to start a TXOP + * but it does not transmit any frame (e.g., due to constraints associated with EMLSR + * operations), provided that the queue is not actually empty + */ + bool GetGenerateBackoffOnNoTx() const; + /** * Return the width of the largest primary channel that has been idle for the * given time interval before the given time, if any primary channel has been @@ -431,6 +453,10 @@ class ChannelAccessManager : public Object bool m_off; //!< flag whether it is in off state Time m_eifsNoDifs; //!< EIFS no DIFS time EventId m_accessTimeout; //!< the access timeout ID + bool m_generateBackoffOnNoTx; //!< whether the backoff should be invoked when the AC gains the + //!< right to start a TXOP but it does not transmit any frame + //!< (e.g., due to constraints associated with EMLSR operations), + //!< provided that the queue is not actually empty /// Information associated with each PHY that is going to operate on another EMLSR link struct EmlsrLinkSwitchInfo diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index df48f11b1..8d306e5ee 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -593,8 +593,27 @@ QosTxop::NotifyChannelReleased(uint8_t linkId) NS_LOG_DEBUG("Terminating TXOP. Duration = " << Simulator::Now() - *link.startTxop); m_txopTrace(*link.startTxop, Simulator::Now() - *link.startTxop, linkId); } + + // generate a new backoff value if either the TXOP duration is not null (i.e., some frames + // were transmitted) or no frame was transmitted but the queue actually contains frame to + // transmit and the user indicated that a backoff value should be generated in this situation. + // This behavior reflects the following specs text (Sec. 35.3.16.4 of 802.11be D4.0): + // An AP or non-AP STA affiliated with an MLD that has gained the right to initiate the + // transmission of a frame as described in 10.23.2.4 (Obtaining an EDCA TXOP) for an AC but + // does not transmit any frame corresponding to that AC for the reasons stated above may: + // - invoke a backoff for the EDCAF associated with that AC as allowed per h) of 10.23.2.2 + // (EDCA backoff procedure). + auto hasTransmitted = link.startTxop.has_value() && Simulator::Now() > *link.startTxop; + + m_queue->WipeAllExpiredMpdus(); + if ((hasTransmitted) || + (!m_queue->IsEmpty() && m_mac->GetChannelAccessManager(linkId)->GetGenerateBackoffOnNoTx())) + { + GenerateBackoff(linkId); + Simulator::ScheduleNow(&QosTxop::RequestAccess, this, linkId); + } link.startTxop.reset(); - Txop::NotifyChannelReleased(linkId); + GetLink(linkId).access = NOT_REQUESTED; } Time