20#include "ns3/adhoc-wifi-mac.h"
21#include "ns3/channel-access-manager.h"
22#include "ns3/frame-exchange-manager.h"
23#include "ns3/qos-txop.h"
24#include "ns3/simulator.h"
25#include "ns3/spectrum-wifi-phy.h"
33template <
typename TxopType>
42template <
typename TxopType>
59 void QueueTx(uint64_t txTime, uint64_t expectedGrantTime);
172template <
typename TxopType>
196 dcf->NotifyChannelAccessed(0);
209 m_test->NotifyChannelSwitching();
222template <
typename TxopType>
260 uint64_t eifsNoDifsNoSifs,
262 uint16_t chWidth = 20);
300 void AddRxOkEvt(uint64_t at, uint64_t duration);
313 void AddRxErrorEvt(uint64_t at, uint64_t duration, uint64_t timeUntilError);
325 void AddTxEvt(uint64_t at, uint64_t duration);
360 uint64_t expectedGrantTime,
372 uint64_t expectedGrantTime,
382 uint64_t expectedGrantTime,
394 const std::vector<Time>& per20MhzDurations = {});
417template <
typename TxopType>
421 m_expectedGrants.emplace_back(txTime, expectedGrantTime);
424template <
typename TxopType>
431template <
typename TxopType>
436 TxopType::DoDispose();
439template <
typename TxopType>
444 m_test->NotifyAccessGranted(m_i);
447template <
typename TxopType>
451 m_test->GenerateBackoff(m_i);
454template <
typename TxopType>
458 return !m_expectedGrants.empty();
461template <
typename TxopType>
467template <
typename TxopType>
473template <
typename TxopType>
479template <
typename TxopType>
485 if (!state->m_expectedGrants.empty())
487 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front();
488 state->m_expectedGrants.pop_front();
491 "Expected access grant is now");
492 m_ChannelAccessManager->NotifyTxStartNow(
MicroSeconds(expected.first));
493 m_ChannelAccessManager->NotifyAckTimeoutStartNow(
498template <
typename TxopType>
504 m_ChannelAccessManager,
508template <
typename TxopType>
514 "Have expected internal collisions");
515 if (!state->m_expectedInternalCollision.empty())
521 MicroSeconds(expected.at),
522 "Expected internal collision time is now");
523 state->StartBackoffNow(expected.nSlots, 0);
527template <typename TxopType>
533 if (!state->m_expectedBackoff.empty())
538 MicroSeconds(expected.at),
539 "Expected backoff is now");
540 state->StartBackoffNow(expected.nSlots, 0);
544template <typename TxopType>
548 for (
auto& state : m_txop)
550 if (!state->m_expectedGrants.empty())
552 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front();
553 state->m_expectedGrants.pop_front();
556 "Expected grant is now");
562template <
typename TxopType>
575template <typename TxopType>
582 backoff.nSlots = nSlots;
586template <typename TxopType>
596template <
typename TxopType>
603template <
typename TxopType>
607 uint64_t eifsNoDifsNoSifs,
611 m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub>();
612 m_feManager = CreateObject<FrameExchangeManagerStub<TxopType>>(
this);
613 m_ChannelAccessManager->SetupFrameExchangeManager(m_feManager);
614 m_ChannelAccessManager->SetSlot(
MicroSeconds(slotTime));
616 m_ChannelAccessManager->SetEifsNoDifs(
MicroSeconds(eifsNoDifsNoSifs + sifs));
617 m_ackTimeoutValue = ackTimeoutValue;
622 m_phy = CreateObject<SpectrumWifiPhy>();
625 m_ChannelAccessManager->SetupPhyListener(m_phy);
628template <
typename TxopType>
633 m_txop.push_back(txop);
634 m_ChannelAccessManager->Add(txop);
636 auto mac = CreateObject<AdhocWifiMac>();
637 mac->SetWifiPhys({
nullptr});
638 txop->SetWifiMac(mac);
639 txop->SetAifsn(aifsn);
642template <
typename TxopType>
648 for (
typename TxopTests::const_iterator i = m_txop.begin(); i != m_txop.end(); i++)
654 "Have no internal collisions");
661 m_ChannelAccessManager->RemovePhyListener(m_phy);
663 m_ChannelAccessManager->Dispose();
664 m_ChannelAccessManager =
nullptr;
665 m_feManager =
nullptr;
669template <
typename TxopType>
675 m_ChannelAccessManager,
679 m_ChannelAccessManager);
682template <
typename TxopType>
688 m_ChannelAccessManager,
692template <
typename TxopType>
698 m_ChannelAccessManager,
702 m_ChannelAccessManager);
705template <
typename TxopType>
709 uint64_t timeUntilError)
713 m_ChannelAccessManager,
717 m_ChannelAccessManager);
720 m_ChannelAccessManager,
723 std::vector<Time>{});
726template <
typename TxopType>
732 m_ChannelAccessManager,
736template <
typename TxopType>
742 m_ChannelAccessManager,
746template <
typename TxopType>
752 m_ChannelAccessManager);
755template <
typename TxopType>
759 uint64_t expectedGrantTime,
762 AddAccessRequestWithSuccessfulAck(at, txTime, expectedGrantTime, 0, from);
765template <
typename TxopType>
769 uint64_t expectedGrantTime,
780template <
typename TxopType>
784 uint64_t expectedGrantTime,
795 AddAckTimeoutReset(expectedGrantTime + txTime + ackDelay);
798template <
typename TxopType>
801 uint64_t expectedGrantTime,
804 if (m_ChannelAccessManager->NeedBackoffUponAccess(state))
806 state->GenerateBackoff(0);
808 state->QueueTx(txTime, expectedGrantTime);
809 m_ChannelAccessManager->RequestAccess(state);
812template <
typename TxopType>
817 const std::vector<Time>& per20MhzDurations)
821 m_ChannelAccessManager,
827template <
typename TxopType>
833 m_ChannelAccessManager,
837template <
typename TxopType>
843 m_ChannelAccessManager,
860 AddAccessRequest(1, 1, 5, 0);
861 AddAccessRequest(8, 2, 12, 0);
872 AddAccessRequest(1, 1, 5, 0);
873 AddRxInsideSifsEvt(7, 10);
875 AddAccessRequest(14, 2, 18, 0);
893 AddAccessRequest(30, 2, 118, 0);
894 ExpectBackoff(30, 4, 0);
906 AddAccessRequest(30, 2, 70, 0);
907 ExpectBackoff(30, 0, 0);
920 AddAccessRequest(30, 2, 110, 0);
921 ExpectBackoff(30, 0, 0);
932 AddAccessRequest(62, 2, 72, 0);
943 AddAccessRequest(70, 2, 80, 0);
954 AddRxErrorEvt(20, 40);
955 AddAccessRequest(30, 2, 102, 0);
956 ExpectBackoff(30, 4, 0);
968 AddRxErrorEvt(20, 40);
969 AddAccessRequest(70, 2, 86, 0);
980 AddRxErrorEvt(20, 40, 20);
981 ExpectBusy(41,
true);
982 ExpectBusy(59,
true);
983 ExpectBusy(61,
false);
994 AddRxErrorEvt(20, 40);
995 AddAccessRequest(30, 2, 101, 0);
996 ExpectBackoff(30, 4, 0);
1009 StartTest(4, 6, 10);
1013 AddAccessRequest(30, 10, 78, 0);
1014 ExpectBackoff(30, 2, 0);
1015 AddAccessRequest(40, 2, 110, 1);
1016 ExpectBackoff(40, 0, 1);
1017 ExpectInternalCollision(78, 1, 1);
1027 StartTest(4, 6, 10);
1030 AddAccessRequestWithAckTimeout(20, 20, 34, 1);
1031 AddAccessRequest(64, 10, 80, 0);
1043 StartTest(4, 6, 10);
1046 AddAccessRequestWithSuccessfulAck(20, 20, 34, 2, 1);
1047 AddAccessRequest(55, 10, 62, 0);
1054 StartTest(4, 6, 10);
1056 AddAccessRequest(20, 20, 34, 0);
1058 AddAccessRequest(61, 10, 80, 0);
1059 ExpectBackoff(61, 1, 0);
1065 StartTest(4, 6, 10);
1068 AddNavStart(60, 15);
1071 AddAccessRequest(30, 10, 93, 0);
1072 ExpectBackoff(30, 2, 0);
1078 StartTest(4, 6, 10);
1081 AddNavStart(60, 15);
1084 AddAccessRequest(30, 10, 91, 0);
1085 ExpectBackoff(30, 2, 0);
1091 StartTest(4, 6, 10);
1094 AddAccessRequest(80, 10, 94, 0);
1097 StartTest(4, 6, 10);
1101 AddAccessRequest(30, 50, 108, 0);
1102 ExpectBackoff(30, 3, 0);
1110 StartTest(1, 3, 10);
1112 AddSwitchingEvt(0, 20);
1113 AddAccessRequest(21, 1, 25, 0);
1121 StartTest(1, 3, 10);
1123 AddSwitchingEvt(20, 20);
1124 AddCcaBusyEvt(30, 20);
1125 ExpectBackoff(45, 2, 0);
1126 AddAccessRequest(45, 1, 56, 0);
1133 StartTest(1, 3, 10);
1135 AddRxStartEvt(20, 40);
1136 AddSwitchingEvt(30, 20);
1137 AddAccessRequest(51, 1, 55, 0);
1144 StartTest(1, 3, 10);
1146 AddCcaBusyEvt(20, 40);
1147 AddSwitchingEvt(30, 20);
1148 AddAccessRequest(51, 1, 55, 0);
1155 StartTest(1, 3, 10);
1157 AddNavStart(20, 40);
1158 AddSwitchingEvt(30, 20);
1159 AddAccessRequest(51, 1, 55, 0);
1167 StartTest(1, 3, 10);
1169 AddAccessRequestWithAckTimeout(20, 20, 24, 0);
1170 AddAccessRequest(49, 1, 54, 0);
1171 AddSwitchingEvt(54, 5);
1172 AddAccessRequest(60, 1, 64, 0);
1180 StartTest(4, 6, 10);
1183 AddAccessRequest(30, 2, 80, 0);
1184 ExpectBackoff(30, 4, 0);
1185 AddSwitchingEvt(80, 20);
1186 AddAccessRequest(101, 2, 111, 0);
1204 StartTest(4, 6, 10, 20, 40);
1208 AddAccessRequest(52, 20, 60, 0);
1218 StartTest(4, 6, 10, 20, 80);
1222 AddAccessRequest(58, 20, 60, 0);
1232 StartTest(4, 6, 10, 20, 80);
1236 AddAccessRequest(62, 20, 64, 0);
1247 StartTest(4, 6, 10, 20, 160);
1249 AddRxErrorEvt(20, 30);
1251 AddAccessRequest(55, 20, 76, 0);
1262 StartTest(4, 6, 10, 20, 160);
1264 AddRxErrorEvt(20, 30);
1266 AddAccessRequest(70, 20, 76, 0);
1277 StartTest(4, 6, 10, 20, 160);
1279 AddRxErrorEvt(20, 30);
1281 AddAccessRequest(82, 20, 84, 0);
1290 StartTest(4, 6, 10);
1293 AddAccessRequest(30, 20, 76, 0);
1294 ExpectBackoff(30, 4, 0);
1305 StartTest(4, 6, 10);
1310 AddAccessRequest(30, 20, 107, 0);
1311 ExpectBackoff(30, 3, 0);
1334 void DoRun()
override;
1349 :
TestCase(
"Check calculation of the largest idle primary channel")
1384 std::vector<Time>(chWidth == 20 ? 0 : chWidth / 20,
Seconds(0)));
1389 uint16_t idleWidth = (busyChannel == WifiChannelListType::WIFI_CHANLIST_PRIMARY)
1391 : ((1 << (busyChannel - 1)) * 20);
1393 Time checkTime1 = start + ccaBusyStartDelay + ccaBusyDuration / 2;
1395 Time interval1 = (ccaBusyStartDelay + ccaBusyDuration) / 2;
1398 "Incorrect width of the idle channel in an interval "
1399 <<
"ending within CCA_BUSY (channel width: " << chWidth
1400 <<
" MHz, busy channel: " << busyChannel <<
")");
1406 Time checkTime2 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval / 2;
1408 Time interval2 = (ccaBusyDuration + ccaBusyRxInterval) / 2;
1411 "Incorrect width of the idle channel in an interval "
1412 <<
"starting within CCA_BUSY (channel width: " << chWidth
1413 <<
" MHz, busy channel: " << busyChannel <<
")");
1425 Time checkTime3 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval + rxDuration;
1427 Time interval3 = ccaBusyDuration / 2 + ccaBusyRxInterval;
1428 Time end3 = checkTime3 - rxDuration;
1431 "Incorrect width of the idle channel in an interval "
1432 <<
"preceding RX start and overlapping CCA_BUSY "
1433 <<
"(channel width: " << chWidth
1434 <<
" MHz, busy channel: " << busyChannel <<
")");
1439 Time checkTime4 = checkTime3;
1441 Time interval4 = ccaBusyRxInterval;
1442 Time end4 = checkTime4 - rxDuration;
1445 "Incorrect width of the idle channel in the interval "
1446 <<
"following CCA_BUSY and preceding RX start (channel "
1447 <<
"width: " << chWidth <<
" MHz, busy channel: " << busyChannel
1454 Time checkTime5 = checkTime4 + interval5;
1458 "Incorrect width of the idle channel in an interval "
1459 <<
"following RX end (channel width: " << chWidth
1460 <<
" MHz, busy channel: " << busyChannel <<
")");
1464 Time checkTime6 = checkTime5;
1466 Time interval6 = interval5 + rxDuration / 2;
1469 "Incorrect width of the idle channel in an interval "
1470 <<
"overlapping RX (channel width: " << chWidth
1471 <<
" MHz, busy channel: " << busyChannel <<
")");
1478 m_cam = CreateObject<ChannelAccessManager>();
1480 uint8_t channel = 0;
1481 std::list<WifiChannelListType> busyChannels;
1483 for (uint16_t chWidth : {20, 40, 80, 160})
1487 for (
const auto busyChannel : busyChannels)
1497 m_phy = CreateObject<SpectrumWifiPhy>();
1505 RunOne(chWidth, busyChannel);
1572 :
TestSuite(
"wifi-channel-access-manager", UNIT)
static ChannelAccessManagerTestSuite g_camTestSuite
static TxopTestSuite g_dcfTestSuite
static QosTxopTestSuite g_edcaTestSuite
ChannelAccessManager Stub.
ChannelAccessManagerStub()
Time GetEifsNoDifs() const override
Return the EIFS duration minus a DIFS.
void SetEifsNoDifs(Time eifsNoDifs)
Set the duration of EIFS - DIFS.
void SetSlot(Time slot)
Set the slot duration.
Time GetSlot() const override
Return the slot duration for this PHY.
Time m_sifs
SIFS duration.
Time GetSifs() const override
Return the Short Interframe Space (SIFS) for this PHY.
void SetSifs(Time sifs)
Set the Short Interframe Space (SIFS).
Time m_eifsNoDifs
EIFS duration minus a DIFS.
Channel Access Manager Test.
void AddAccessRequestWithSuccessfulAck(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
Add access request with successful ack.
void AddAckTimeoutReset(uint64_t at)
Add Ack timeout reset function.
void NotifyInternalCollision(Ptr< TxopTest< TxopType > > state)
Notify internal collision function.
void AddRxOkEvt(uint64_t at, uint64_t duration)
Add receive OK event function.
void AddRxStartEvt(uint64_t at, uint64_t duration)
Add receive start event function.
uint32_t m_ackTimeoutValue
the Ack timeout value
void AddAccessRequestWithAckTimeout(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Add access request with Ack timeout.
ChannelAccessManagerTest()
void GenerateBackoff(uint32_t i)
Generate backoff function.
void NotifyAccessGranted(uint32_t i)
Notify access granted function.
std::vector< Ptr< TxopTest< TxopType > > > TxopTests
the TXOP tests typedef
void StartTest(uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue=20, uint16_t chWidth=20)
Start test function.
void ExpectBackoff(uint64_t time, uint32_t nSlots, uint32_t from)
Expect generate backoff function.
void DoRun() override
Implementation to actually run this TestCase.
void AddTxop(uint32_t aifsn)
Add Txop function.
void DoAccessRequest(uint64_t txTime, uint64_t expectedGrantTime, Ptr< TxopTest< TxopType > > state)
Add access request with successful Ack.
void AddAccessRequest(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Add access function.
Ptr< WifiPhy > m_phy
the PHY object
void AddSwitchingEvt(uint64_t at, uint64_t duration)
Add switching event function.
Ptr< ChannelAccessManagerStub > m_ChannelAccessManager
the channel access manager
void AddRxErrorEvt(uint64_t at, uint64_t duration)
Add receive error event function for error at end of frame.
void ExpectBusy(uint64_t time, bool busy)
Schedule a check that the channel access manager is busy or idle.
void EndTest()
End test function.
void AddCcaBusyEvt(uint64_t at, uint64_t duration, WifiChannelListType channelType=WIFI_CHANLIST_PRIMARY, const std::vector< Time > &per20MhzDurations={})
Add CCA busy event function.
TxopTests m_txop
the vector of Txop test instances
void ExpectInternalCollision(uint64_t time, uint32_t nSlots, uint32_t from)
Expect internal collision function.
void AddNavStart(uint64_t at, uint64_t duration)
Add NAV start function.
void AddRxInsideSifsEvt(uint64_t at, uint64_t duration)
Add receive inside SIFS event function.
Ptr< FrameExchangeManagerStub< TxopType > > m_feManager
the Frame Exchange Manager stubbed
void DoCheckBusy(bool busy)
Perform check that channel access manager is busy or idle.
void AddNavReset(uint64_t at, uint64_t duration)
Add NAV reset function.
void AddTxEvt(uint64_t at, uint64_t duration)
Add transmit event function.
void NotifyChannelSwitching()
Notify channel switching function.
ChannelAccessManager Test Suite.
ChannelAccessManagerTestSuite()
Frame Exchange Manager Stub.
void NotifySwitchingStartNow(Time duration) override
void NotifyInternalCollision(Ptr< Txop > txop) override
Notify that an internal collision has occurred for the given Txop.
ChannelAccessManagerTest< TxopType > * m_test
the test DCF/EDCA manager
FrameExchangeManagerStub(ChannelAccessManagerTest< TxopType > *test)
Constructor.
bool StartTransmission(Ptr< Txop > dcf, uint16_t allowedWidth) override
Request the FrameExchangeManager to start a frame exchange sequence.
Test the calculation of the largest idle primary channel performed by ChannelAccessManager::GetLarges...
Ptr< WifiPhy > m_phy
PHY object.
LargestIdlePrimaryChannelTest()
void RunOne(uint16_t chWidth, WifiChannelListType busyChannel)
Test a specific combination of operating channel width and busy channel type.
~LargestIdlePrimaryChannelTest() override=default
void DoRun() override
Implementation to actually run this TestCase.
Ptr< ChannelAccessManager > m_cam
channel access manager
ExpectedBackoffs m_expectedInternalCollision
expected backoff due to an internal collision
void DoDispose() override
Destructor implementation.
void GenerateBackoff(uint8_t linkId) override
Generate a new backoff for the given link now.
uint32_t m_i
the index of the Txop
void NotifyChannelAccessed(uint8_t linkId, Time txopDuration=Seconds(0)) override
Called by the FrameExchangeManager to notify that channel access has been granted on the given link f...
void QueueTx(uint64_t txTime, uint64_t expectedGrantTime)
Queue transmit function.
ExpectedBackoffs m_expectedBackoff
expected backoff (not due to an internal collision)
std::list< ExpectedGrant > ExpectedGrants
the collection of expected grants typedef
void NotifySleep(uint8_t linkId) override
Notify that the given link switched to sleep mode.
ChannelAccessManagerTest< TxopType > * m_test
Check if the Txop has frames to transmit.
ExpectedGrants m_expectedGrants
expected grants
void NotifyWakeUp(uint8_t linkId) override
When wake up operation occurs on a link, channel access on that link will be restarted.
bool HasFramesToTransmit(uint8_t linkId) override
Check if the Txop has frames to transmit over the given link.
TxopTest(ChannelAccessManagerTest< TxopType > *test, uint32_t i)
Constructor.
std::pair< uint64_t, uint64_t > ExpectedGrant
the expected grant typedef
std::list< struct ExpectedBackoff > ExpectedBackoffs
expected backoffs typedef
Manage a set of ns3::Txop.
uint16_t GetLargestIdlePrimaryChannel(Time interval, Time end)
Return the width of the largest primary channel that has been idle for the given time interval before...
void NotifyRxEndErrorNow()
Notify the Txop that a packet reception was just completed unsuccessfuly.
void NotifyRxStartNow(Time duration)
void NotifyAckTimeoutResetNow()
Notify that ack timer has reset.
void NotifyTxStartNow(Time duration)
void NotifyRxEndOkNow()
Notify the Txop that a packet reception was just completed successfully.
void NotifyCcaBusyStartNow(Time duration, WifiChannelListType channelType, const std::vector< Time > &per20MhzDurations)
void RemovePhyListener(Ptr< WifiPhy > phy)
Remove current registered listener for PHY events.
void SetupPhyListener(Ptr< WifiPhy > phy)
Set up listener for PHY events.
void NotifySwitchingStartNow(Time duration)
void NotifyNavResetNow(Time duration)
void NotifyNavStartNow(Time duration)
FrameExchangeManager is a base class handling the basic frame exchange sequences for non-QoS stations...
void Dispose()
Dispose of this Object.
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
static Time Now()
Return the current simulation virtual time.
static void Run()
Run the simulation.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Simulation virtual time values and global simulation resolution.
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Time Now()
create an ns3::Time instance which contains the current simulation time.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_CHANLIST_SECONDARY40
@ WIFI_CHANLIST_SECONDARY
@ WIFI_CHANLIST_SECONDARY80
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
-ns3 Test suite for the ns3 wrapper script
ExpectedBackoff structure.
uint32_t nSlots
number of slots
ChannelAccessStatus access
channel access status