From 11641a57d883c82777f6c6dbca6e94cd1236b3f9 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Wed, 8 Jan 2020 17:37:04 +0100 Subject: [PATCH] wifi: Extend channel access manager test to check EDCA operations --- src/wifi/test/channel-access-manager-test.cc | 297 +++++++++++++++---- 1 file changed, 234 insertions(+), 63 deletions(-) diff --git a/src/wifi/test/channel-access-manager-test.cc b/src/wifi/test/channel-access-manager-test.cc index ff28eeba5..ce3befe15 100644 --- a/src/wifi/test/channel-access-manager-test.cc +++ b/src/wifi/test/channel-access-manager-test.cc @@ -21,11 +21,12 @@ #include "ns3/test.h" #include "ns3/simulator.h" #include "ns3/channel-access-manager.h" -#include "ns3/txop.h" +#include "ns3/qos-txop.h" #include "ns3/mac-low.h" using namespace ns3; +template class ChannelAccessManagerTest; /** @@ -34,7 +35,8 @@ class ChannelAccessManagerTest; * * \brief TxopTest Txop Test */ -class TxopTest : public Txop +template +class TxopTest : public TxopType { public: /** @@ -43,7 +45,7 @@ public: * \param test the test DCF manager * \param i the DCF state */ - TxopTest (ChannelAccessManagerTest *test, uint32_t i); + TxopTest (ChannelAccessManagerTest *test, uint32_t i); /** * Queue transmit function @@ -54,7 +56,7 @@ public: private: /// allow ChannelAccessManagerTest class access - friend class ChannelAccessManagerTest; + friend class ChannelAccessManagerTest; typedef std::pair ExpectedGrant; //!< the expected grant typedef typedef std::list ExpectedGrants; //!< the collection of expected grants typedef @@ -81,7 +83,7 @@ private: void NotifyWakeUp (void); void DoDispose (void); - ChannelAccessManagerTest *m_test; //!< the test DCF manager + ChannelAccessManagerTest *m_test; //!< the test DCF/EDCA manager uint32_t m_i; //!< the DCF state bool m_accessRequested; //!< true if access requested }; @@ -113,6 +115,7 @@ public: * * \brief Dcf Manager Test */ +template class ChannelAccessManagerTest : public TestCase { public: @@ -264,7 +267,7 @@ private: * \param expectedGrantTime DoAccessRequest expectedGrantTime * \param state TxopTest */ - void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr state); + void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr> state); /** * Add CCA busy event function * \param at the event time @@ -284,7 +287,7 @@ private: */ void AddRxStartEvt (uint64_t at, uint64_t duration); - typedef std::vector > TxopTests; //!< the TXOP tests typedef + typedef std::vector>> TxopTests; //!< the TXOP tests typedef Ptr m_low; //!< the MAC low stubbed Ptr m_ChannelAccessManager; //!< the DCF manager @@ -292,88 +295,102 @@ private: uint32_t m_ackTimeoutValue; //!< the ack timeout value }; +template void -TxopTest::QueueTx (uint64_t txTime, uint64_t expectedGrantTime) +TxopTest::QueueTx (uint64_t txTime, uint64_t expectedGrantTime) { m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime)); } -TxopTest::TxopTest (ChannelAccessManagerTest *test, uint32_t i) +template +TxopTest::TxopTest (ChannelAccessManagerTest *test, uint32_t i) : m_test (test), m_i (i), m_accessRequested (false) { } +template void -TxopTest::DoDispose (void) +TxopTest::DoDispose (void) { m_test = 0; Txop::DoDispose (); } +template bool -TxopTest::IsAccessRequested (void) const +TxopTest::IsAccessRequested (void) const { return m_accessRequested; } +template void -TxopTest::NotifyAccessRequested (void) +TxopTest::NotifyAccessRequested (void) { m_accessRequested = true; } +template void -TxopTest::NotifyAccessGranted (void) +TxopTest::NotifyAccessGranted (void) { m_accessRequested = false; m_test->NotifyAccessGranted (m_i); } +template void -TxopTest::NotifyInternalCollision (void) +TxopTest::NotifyInternalCollision (void) { m_test->NotifyInternalCollision (m_i); } +template void -TxopTest::GenerateBackoff (void) +TxopTest::GenerateBackoff (void) { m_test->GenerateBackoff (m_i); } +template bool -TxopTest::HasFramesToTransmit (void) +TxopTest::HasFramesToTransmit (void) { return !m_expectedGrants.empty (); } +template void -TxopTest::NotifyChannelSwitching (void) +TxopTest::NotifyChannelSwitching (void) { m_test->NotifyChannelSwitching (m_i); } +template void -TxopTest::NotifySleep (void) +TxopTest::NotifySleep (void) { } +template void -TxopTest::NotifyWakeUp (void) +TxopTest::NotifyWakeUp (void) { } -ChannelAccessManagerTest::ChannelAccessManagerTest () +template +ChannelAccessManagerTest::ChannelAccessManagerTest () : TestCase ("ChannelAccessManager") { } +template void -ChannelAccessManagerTest::NotifyAccessGranted (uint32_t i) +ChannelAccessManagerTest::NotifyAccessGranted (uint32_t i) { - Ptr state = m_txop[i]; + Ptr> state = m_txop[i]; NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants"); if (!state->m_expectedGrants.empty ()) { @@ -385,46 +402,50 @@ ChannelAccessManagerTest::NotifyAccessGranted (uint32_t i) } } +template void -ChannelAccessManagerTest::AddTxEvt (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddTxEvt (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyTxStartNow, m_ChannelAccessManager, MicroSeconds (duration)); } +template void -ChannelAccessManagerTest::NotifyInternalCollision (uint32_t i) +ChannelAccessManagerTest::NotifyInternalCollision (uint32_t i) { - Ptr state = m_txop[i]; + Ptr> state = m_txop[i]; NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions"); if (!state->m_expectedInternalCollision.empty ()) { - struct TxopTest::ExpectedBackoff expected = state->m_expectedInternalCollision.front (); + struct TxopTest::ExpectedBackoff expected = state->m_expectedInternalCollision.front (); state->m_expectedInternalCollision.pop_front (); NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now"); state->StartBackoffNow (expected.nSlots); } } +template void -ChannelAccessManagerTest::GenerateBackoff (uint32_t i) +ChannelAccessManagerTest::GenerateBackoff (uint32_t i) { - Ptr state = m_txop[i]; + Ptr> state = m_txop[i]; NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), false, "Have expected backoffs"); if (!state->m_expectedBackoff.empty ()) { - struct TxopTest::ExpectedBackoff expected = state->m_expectedBackoff.front (); + struct TxopTest::ExpectedBackoff expected = state->m_expectedBackoff.front (); state->m_expectedBackoff.pop_front (); NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected backoff is now"); state->StartBackoffNow (expected.nSlots); } } +template void -ChannelAccessManagerTest::NotifyChannelSwitching (uint32_t i) +ChannelAccessManagerTest::NotifyChannelSwitching (uint32_t i) { - Ptr state = m_txop[i]; + Ptr> state = m_txop[i]; if (!state->m_expectedGrants.empty ()) { std::pair expected = state->m_expectedGrants.front (); @@ -434,41 +455,46 @@ ChannelAccessManagerTest::NotifyChannelSwitching (uint32_t i) state->m_accessRequested = false; } +template void -ChannelAccessManagerTest::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from) +ChannelAccessManagerTest::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from) { - Ptr state = m_txop[from]; - struct TxopTest::ExpectedBackoff col; + Ptr> state = m_txop[from]; + struct TxopTest::ExpectedBackoff col; col.at = time; col.nSlots = nSlots; state->m_expectedInternalCollision.push_back (col); } +template void -ChannelAccessManagerTest::ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from) +ChannelAccessManagerTest::ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from) { - Ptr state = m_txop[from]; - struct TxopTest::ExpectedBackoff backoff; + Ptr> state = m_txop[from]; + struct TxopTest::ExpectedBackoff backoff; backoff.at = time; backoff.nSlots = nSlots; state->m_expectedBackoff.push_back (backoff); } +template void -ChannelAccessManagerTest::ExpectBusy (uint64_t time, bool busy) +ChannelAccessManagerTest::ExpectBusy (uint64_t time, bool busy) { Simulator::Schedule (MicroSeconds (time) - Now (), &ChannelAccessManagerTest::DoCheckBusy, this, busy); } +template void -ChannelAccessManagerTest::DoCheckBusy (bool busy) +ChannelAccessManagerTest::DoCheckBusy (bool busy) { NS_TEST_EXPECT_MSG_EQ (m_ChannelAccessManager->IsBusy (), busy, "Incorrect busy/idle state"); } +template void -ChannelAccessManagerTest::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue) +ChannelAccessManagerTest::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue) { m_ChannelAccessManager = CreateObject (); m_low = CreateObject (); @@ -481,25 +507,27 @@ ChannelAccessManagerTest::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t m_ackTimeoutValue = ackTimeoutValue; } +template void -ChannelAccessManagerTest::AddDcfState (uint32_t aifsn) +ChannelAccessManagerTest::AddDcfState (uint32_t aifsn) { - Ptr txop = CreateObject (this, m_txop.size ()); + Ptr> txop = CreateObject> (this, m_txop.size ()); txop->SetAifsn (aifsn); m_txop.push_back (txop); txop->SetChannelAccessManager (m_ChannelAccessManager); txop->SetMacLow (m_low); } +template void -ChannelAccessManagerTest::EndTest (void) +ChannelAccessManagerTest::EndTest (void) { Simulator::Run (); Simulator::Destroy (); - for (TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++) + for (typename TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++) { - Ptr state = *i; + Ptr> state = *i; NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants"); NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions"); NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), true, "Have no expected backoffs"); @@ -507,9 +535,9 @@ ChannelAccessManagerTest::EndTest (void) } m_txop.clear (); - for (TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++) + for (typename TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++) { - Ptr txop = *i; + Ptr> txop = *i; txop->Dispose (); txop = 0; } @@ -519,8 +547,9 @@ ChannelAccessManagerTest::EndTest (void) m_low = 0; } +template void -ChannelAccessManagerTest::AddRxOkEvt (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddRxOkEvt (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager, @@ -529,16 +558,18 @@ ChannelAccessManagerTest::AddRxOkEvt (uint64_t at, uint64_t duration) &ChannelAccessManager::NotifyRxEndOkNow, m_ChannelAccessManager); } +template void -ChannelAccessManagerTest::AddRxInsideSifsEvt (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddRxInsideSifsEvt (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager, MicroSeconds (duration)); } +template void -ChannelAccessManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager, @@ -547,8 +578,9 @@ ChannelAccessManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration) &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager); } +template void -ChannelAccessManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError) +ChannelAccessManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager, @@ -558,38 +590,43 @@ ChannelAccessManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_ } +template void -ChannelAccessManagerTest::AddNavReset (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddNavReset (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyNavResetNow, m_ChannelAccessManager, MicroSeconds (duration)); } +template void -ChannelAccessManagerTest::AddNavStart (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddNavStart (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyNavStartNow, m_ChannelAccessManager, MicroSeconds (duration)); } +template void -ChannelAccessManagerTest::AddAckTimeoutReset (uint64_t at) +ChannelAccessManagerTest::AddAckTimeoutReset (uint64_t at) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyAckTimeoutResetNow, m_ChannelAccessManager); } +template void -ChannelAccessManagerTest::AddAccessRequest (uint64_t at, uint64_t txTime, +ChannelAccessManagerTest::AddAccessRequest (uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from) { AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from); } +template void -ChannelAccessManagerTest::AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime, +ChannelAccessManagerTest::AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from) { Simulator::Schedule (MicroSeconds (at) - Now (), @@ -597,8 +634,9 @@ ChannelAccessManagerTest::AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime, expectedGrantTime, m_txop[from]); } +template void -ChannelAccessManagerTest::AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime, +ChannelAccessManagerTest::AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from) { NS_ASSERT (ackDelay < m_ackTimeoutValue); @@ -608,40 +646,49 @@ ChannelAccessManagerTest::AddAccessRequestWithSuccessfullAck (uint64_t at, uint6 AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay); } +template void -ChannelAccessManagerTest::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr state) +ChannelAccessManagerTest::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, + Ptr> state) { state->GenerateBackoffUponAccessIfNeeded (); state->QueueTx (txTime, expectedGrantTime); m_ChannelAccessManager->RequestAccess (state); } +template void -ChannelAccessManagerTest::AddCcaBusyEvt (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddCcaBusyEvt (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyMaybeCcaBusyStartNow, m_ChannelAccessManager, MicroSeconds (duration)); } +template void -ChannelAccessManagerTest::AddSwitchingEvt (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddSwitchingEvt (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifySwitchingStartNow, m_ChannelAccessManager, MicroSeconds (duration)); } +template void -ChannelAccessManagerTest::AddRxStartEvt (uint64_t at, uint64_t duration) +ChannelAccessManagerTest::AddRxStartEvt (uint64_t at, uint64_t duration) { Simulator::Schedule (MicroSeconds (at) - Now (), &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager, MicroSeconds (duration)); } +/* + * Specialization of DoRun () method for DCF + */ +template <> void -ChannelAccessManagerTest::DoRun (void) +ChannelAccessManagerTest::DoRun (void) { // DCF immediate access (no backoff) // 1 4 5 6 8 11 12 @@ -978,6 +1025,110 @@ ChannelAccessManagerTest::DoRun (void) EndTest (); } +/* + * Specialization of DoRun () method for EDCA + */ +template <> +void +ChannelAccessManagerTest::DoRun (void) +{ + // Check alignment at slot boundary after successful reception (backoff = 0): + // 20 50 56 60 80 + // | rx | sifs | aifsn | tx | + // | + // 52 request access + StartTest (4, 6, 10); + AddDcfState (1); + AddRxOkEvt (20, 30); + AddAccessRequest (52, 20, 60, 0); + EndTest (); + + // Check alignment at slot boundary after successful reception (backoff = 0): + // 20 50 56 60 80 + // | rx | sifs | aifsn | tx | + // | + // 58 request access + StartTest (4, 6, 10); + AddDcfState (1); + AddRxOkEvt (20, 30); + AddAccessRequest (52, 20, 60, 0); + EndTest (); + + // Check alignment at slot boundary after successful reception (backoff = 0): + // 20 50 56 60 64 84 + // | rx | sifs | aifsn | idle | tx | + // | + // 62 request access + StartTest (4, 6, 10); + AddDcfState (1); + AddRxOkEvt (20, 30); + AddAccessRequest (62, 20, 64, 0); + EndTest (); + + // Check alignment at slot boundary after failed reception (backoff = 0): + // 20 50 56 66 76 96 + // | | <------eifs------>| | | + // | rx | sifs | acktxttime | sifs + aifsn | tx | + // | + // 55 request access + StartTest (4, 6, 10); + AddDcfState (1); + AddRxErrorEvt (20, 30); + AddAccessRequest (55, 20, 76, 0); + EndTest (); + + // Check alignment at slot boundary after failed reception (backoff = 0): + // 20 50 56 66 76 96 + // | | <------eifs------>| | | + // | rx | sifs | acktxttime | sifs + aifsn | tx | + // | + // 70 request access + StartTest (4, 6, 10); + AddDcfState (1); + AddRxErrorEvt (20, 30); + AddAccessRequest (70, 20, 76, 0); + EndTest (); + + // Check alignment at slot boundary after failed reception (backoff = 0): + // 20 50 56 66 76 84 + // | | <------eifs------>| | | + // | rx | sifs | acktxttime | sifs + aifsn | idle | tx | + // | + // 82 request access + StartTest (4, 6, 10); + AddDcfState (1); + AddRxErrorEvt (20, 30); + AddAccessRequest (82, 20, 84, 0); + EndTest (); + + // Check backoff decrement at slot boundaries. Medium idle during backoff + // 20 50 56 60 64 68 72 76 96 + // | rx | sifs | aifsn | idle | idle | idle | idle | tx | + // | | | | | + // 30 request access. decrement decrement decrement decrement + // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0 + StartTest (4, 6, 10); + AddDcfState (1); + AddRxOkEvt (20, 30); + AddAccessRequest (30, 20, 76, 0); + ExpectBackoff (30, 4, 0); + EndTest (); + + // Check backoff decrement at slot boundaries. Medium becomes busy during backoff + // 20 50 56 60 61 71 77 81 85 87 97 103 107 127 + // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs | aifsn | tx | + // | | | | + // 30 request access. decrement decrement decrement + // backoff slots: 3 slots: 2 slots: 1 slots: 0 + StartTest (4, 6, 10); + AddDcfState (1); + AddRxOkEvt (20, 30); + AddRxOkEvt (61, 10); + AddRxOkEvt (87, 10); + AddAccessRequest (30, 20, 107, 0); + ExpectBackoff (30, 3, 0); + EndTest (); +} /** * \ingroup wifi-test @@ -994,7 +1145,27 @@ public: DcfTestSuite::DcfTestSuite () : TestSuite ("wifi-devices-dcf", UNIT) { - AddTestCase (new ChannelAccessManagerTest, TestCase::QUICK); + AddTestCase (new ChannelAccessManagerTest, TestCase::QUICK); } static DcfTestSuite g_dcfTestSuite; + +/** + * \ingroup wifi-test + * \ingroup tests + * + * \brief Edca Test Suite + */ +class EdcaTestSuite : public TestSuite +{ +public: + EdcaTestSuite (); +}; + +EdcaTestSuite::EdcaTestSuite () + : TestSuite ("wifi-devices-edca", UNIT) +{ + AddTestCase (new ChannelAccessManagerTest, TestCase::QUICK); +} + +static EdcaTestSuite g_edcaTestSuite;