From de2c14ae0828882c0fa8be34bc69246975526918 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Tue, 2 Sep 2025 13:20:55 +0200 Subject: [PATCH] wifi: Add test cases to check backoff after sleep/off period --- src/wifi/test/channel-access-manager-test.cc | 146 +++++++++++++++---- 1 file changed, 117 insertions(+), 29 deletions(-) diff --git a/src/wifi/test/channel-access-manager-test.cc b/src/wifi/test/channel-access-manager-test.cc index ff156b7a6..f87129e73 100644 --- a/src/wifi/test/channel-access-manager-test.cc +++ b/src/wifi/test/channel-access-manager-test.cc @@ -76,10 +76,6 @@ class TxopTest : public TxopType void NotifyChannelAccessed(uint8_t linkId, Time txopDuration = Seconds(0)) override; /// @copydoc ns3::Txop::HasFramesToTransmit bool HasFramesToTransmit(uint8_t linkId) override; - /// @copydoc ns3::Txop::NotifySleep - void NotifySleep(uint8_t linkId) override; - /// @copydoc ns3::Txop::NotifyWakeUp - void NotifyWakeUp(uint8_t linkId) override; /// @copydoc ns3::Txop::GenerateBackoff void GenerateBackoff(uint8_t linkId) override; @@ -117,8 +113,18 @@ class TxopTest : public TxopType class ChannelAccessManagerStub : public ChannelAccessManager { public: - ChannelAccessManagerStub() + /** + * @brief Get the type ID. + * @return the object TypeId + */ + static TypeId GetTypeId() { + static TypeId tid = TypeId("ns3::ChannelAccessManagerStub") + .SetParent() + .SetGroupName("Wifi") + .AddConstructor() + .HideFromDocumentation(); + return tid; } /** @@ -240,6 +246,7 @@ class ChannelAccessManagerTest : public TestCase uint64_t eifsNoDifsNoSifs{10}; ///< the EIFS no DIFS no SIFS in microseconds uint32_t ackTimeoutValue{20}; ///< the Ack timeout value in microseconds MHz_u chWidth{20}; ///< the channel width + uint64_t resetBackoffThr{}; ///< reset backoff threshold }; ChannelAccessManagerTest(); @@ -420,10 +427,9 @@ class ChannelAccessManagerTest : public TestCase * * @param at the event time * @param duration the duration of the interval during which no PHY is connected - * @param threshold the value for the ResetBackoffThreshold attribute * @param from the index of the Txop that has to request channel access when PHY is reconnected */ - void AddPhyDisconnectEvt(uint64_t at, uint64_t duration, uint64_t threshold, uint32_t from); + void AddPhyDisconnectEvt(uint64_t at, uint64_t duration, uint32_t from); /** * Add a PHY reconnect event consisting in another PHY operating on the link for the given time. @@ -433,6 +439,22 @@ class ChannelAccessManagerTest : public TestCase */ void AddPhyReconnectEvt(uint64_t at, uint64_t duration); + /** + * Add PHY sleep/resume events. + * + * @param at the event time + * @param duration the duration of the interval during which the PHY is in sleep state + */ + void AddPhySleepEvt(uint64_t at, uint64_t duration); + + /** + * Add PHY off/on events. + * + * @param at the event time + * @param duration the duration of the interval during which the PHY is in off state + */ + void AddPhyOffEvt(uint64_t at, uint64_t duration); + typedef std::vector>> TxopTests; //!< the TXOP tests typedef Ptr> m_feManager; //!< the Frame Exchange Manager stubbed @@ -486,18 +508,6 @@ TxopTest::HasFramesToTransmit(uint8_t linkId) return !m_expectedGrants.empty(); } -template -void -TxopTest::NotifySleep(uint8_t linkId) -{ -} - -template -void -TxopTest::NotifyWakeUp(uint8_t linkId) -{ -} - template ChannelAccessManagerTest::ChannelAccessManagerTest() : TestCase("ChannelAccessManager") @@ -632,7 +642,9 @@ template void ChannelAccessManagerTest::StartTest(const Params& params) { - m_ChannelAccessManager = CreateObject(); + m_ChannelAccessManager = CreateObjectWithAttributes( + "ResetBackoffThreshold", + TimeValue(MicroSeconds(params.resetBackoffThr))); m_feManager = CreateObject>(this); m_ChannelAccessManager->SetupFrameExchangeManager(m_feManager); m_ChannelAccessManager->SetSlot(MicroSeconds(params.slotTime)); @@ -662,7 +674,8 @@ ChannelAccessManagerTest::AddTxop(uint32_t aifsn) auto mac = CreateObjectWithAttributes( "Txop", PointerValue(CreateObjectWithAttributes("AcIndex", StringValue("AC_BE_NQOS")))); - mac->SetWifiPhys({nullptr}); + mac->SetWifiPhys({m_phy}); + mac->SetChannelAccessManagers({m_ChannelAccessManager}); txop->SetWifiMac(mac); txop->SetAifsn(aifsn); } @@ -908,11 +921,10 @@ template void ChannelAccessManagerTest::AddPhyDisconnectEvt(uint64_t at, uint64_t duration, - uint64_t threshold, uint32_t from) { - m_ChannelAccessManager->SetAttribute("ResetBackoffThreshold", - TimeValue(MicroSeconds(threshold))); + TimeValue threshold; + m_ChannelAccessManager->GetAttribute("ResetBackoffThreshold", threshold); Simulator::Schedule(MicroSeconds(at) - Now(), &ChannelAccessManager::RemovePhyListener, @@ -923,7 +935,7 @@ ChannelAccessManagerTest::AddPhyDisconnectEvt(uint64_t at, auto txop = m_txop[from]; auto hadFramesToTransmit = txop->HasFramesToTransmit(SINGLE_LINK_OP_ID); m_ChannelAccessManager->SetupPhyListener(m_phy); - if (duration > threshold) + if (MicroSeconds(duration) > threshold.Get()) { // request channel access again because all backoffs have been reset if (m_ChannelAccessManager->NeedBackoffUponAccess(txop, hadFramesToTransmit, true)) @@ -958,6 +970,22 @@ ChannelAccessManagerTest::AddPhyReconnectEvt(uint64_t at, uint64_t dur }); } +template +void +ChannelAccessManagerTest::AddPhySleepEvt(uint64_t at, uint64_t duration) +{ + Simulator::Schedule(MicroSeconds(at) - Now(), &WifiPhy::SetSleepMode, m_phy, false); + Simulator::Schedule(MicroSeconds(at + duration) - Now(), &WifiPhy::ResumeFromSleep, m_phy); +} + +template +void +ChannelAccessManagerTest::AddPhyOffEvt(uint64_t at, uint64_t duration) +{ + Simulator::Schedule(MicroSeconds(at) - Now(), &WifiPhy::SetOffMode, m_phy); + Simulator::Schedule(MicroSeconds(at + duration) - Now(), &WifiPhy::ResumeFromOff, m_phy); +} + /* * Specialization of DoRun () method for DCF */ @@ -1489,12 +1517,12 @@ ChannelAccessManagerTest::DoRun() // | | | // 30 request access. decrement reset // backoff slots: 3 slots: 2 backoff - StartTest({.slotTime = 4, .sifs = 6}); + StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 5}); AddTxop(1); AddRxOkEvt(20, 30); AddAccessRequest(30, 20, 81, 0); ExpectBackoff(30, 3, 0); - AddPhyDisconnectEvt(61, 10, 0, 0); + AddPhyDisconnectEvt(61, 10, 0); EndTest(); // Check backoff freeze while no PHY operates on a link for less than the threshold. @@ -1503,12 +1531,12 @@ ChannelAccessManagerTest::DoRun() // | | | | | // 30 request access. decrement resume decrement decrement // backoff slots: 3 slots: 2 backoff slots: 1 slots: 0 - StartTest({.slotTime = 4, .sifs = 6}); + StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 20}); AddTxop(1); AddRxOkEvt(20, 30); AddAccessRequest(30, 20, 89, 0); ExpectBackoff(30, 3, 0); - AddPhyDisconnectEvt(61, 10, 20, 0); + AddPhyDisconnectEvt(61, 10, 0); EndTest(); // Check backoff left unmodified when previous PHY is reconnected to the link @@ -1525,6 +1553,66 @@ ChannelAccessManagerTest::DoRun() ExpectBackoff(30, 4, 0); AddPhyReconnectEvt(61, 10); EndTest(); + + // Check reset of backoff and generation of new backoff value after that PHY is put to sleep for + // more than the threshold. + // 20 50 56 60 63 73 79 83 87 91 95 115 + // | rx | sifs | aifsn | idle | phy sleep | sifs | aifsn | idle | idle | idle | tx | + // | | | | | | + // 30 request access. decrement reset backoff decrement decrement decrement + // backoff slots: 3 slots: 2 backoff slots: 3 slots: 2 slots: 1 slots: 0 + StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 5}); + AddTxop(1); + AddRxOkEvt(20, 30); + AddAccessRequest(30, 20, 95, 0); + ExpectBackoff(30, 3, 0); + AddPhySleepEvt(63, 10); + ExpectBackoff(73, 3, 0); + EndTest(); + + // Check backoff freeze while PHY is put to sleep for less than the threshold. + // 20 50 56 60 61 71 77 81 85 89 109 + // | rx | sifs | aifsn | idle | phy sleep | sifs | aifsn | idle | idle | tx | + // | | | | | + // 30 request access. decrement resume decrement decrement + // backoff slots: 3 slots: 2 backoff slots: 1 slots: 0 + StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 20}); + AddTxop(1); + AddRxOkEvt(20, 30); + AddAccessRequest(30, 20, 89, 0); + ExpectBackoff(30, 3, 0); + AddPhySleepEvt(61, 10); + EndTest(); + + // Check reset of backoff and generation of new backoff value after that PHY is put to off for + // more than the threshold. + // 20 50 56 60 61 71 77 81 85 89 93 113 + // | rx | sifs | aifsn | idle | phy off | sifs | aifsn | idle | idle | idle | tx | + // | | | | | | + // 30 request access. decrement reset backoff decrement decrement decrement + // backoff slots: 3 slots: 2 backoff slots: 3 slots: 2 slots: 1 slots: 0 + StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 5}); + AddTxop(1); + AddRxOkEvt(20, 30); + AddAccessRequest(30, 20, 93, 0); + ExpectBackoff(30, 3, 0); + AddPhyOffEvt(61, 10); + ExpectBackoff(71, 3, 0); + EndTest(); + + // Check backoff freeze while PHY is put to off for less than the threshold. + // 20 50 56 60 63 73 79 83 87 91 111 + // | rx | sifs | aifsn | idle | phy off | sifs | aifsn | idle | idle | tx | + // | | | | | + // 30 request access. decrement resume decrement decrement + // backoff slots: 3 slots: 2 backoff slots: 1 slots: 0 + StartTest({.slotTime = 4, .sifs = 6, .resetBackoffThr = 20}); + AddTxop(1); + AddRxOkEvt(20, 30); + AddAccessRequest(30, 20, 91, 0); + ExpectBackoff(30, 3, 0); + AddPhyOffEvt(63, 10); + EndTest(); } /**