A Discrete-Event Network Simulator
API
channel-access-manager-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006 INRIA
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19
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"
26#include "ns3/test.h"
27
28#include <list>
29#include <numeric>
30
31using namespace ns3;
32
33template <typename TxopType>
35
42template <typename TxopType>
43class TxopTest : public TxopType
44{
45 public:
53
59 void QueueTx(uint64_t txTime, uint64_t expectedGrantTime);
60
61 private:
64
66 void DoDispose() override;
68 void NotifyChannelAccessed(uint8_t linkId, Time txopDuration = Seconds(0)) override;
70 bool HasFramesToTransmit(uint8_t linkId) override;
72 void NotifySleep(uint8_t linkId) override;
74 void NotifyWakeUp(uint8_t linkId) override;
76 void GenerateBackoff(uint8_t linkId) override;
77
78 typedef std::pair<uint64_t, uint64_t> ExpectedGrant;
79 typedef std::list<ExpectedGrant> ExpectedGrants;
80
83 {
84 uint64_t at;
86 };
87 typedef std::list<struct ExpectedBackoff> ExpectedBackoffs;
88
92
100};
101
109{
110 public:
112 {
113 }
114
120 void SetSifs(Time sifs)
121 {
122 m_sifs = sifs;
123 }
124
130 void SetSlot(Time slot)
131 {
132 m_slot = slot;
133 }
134
140 void SetEifsNoDifs(Time eifsNoDifs)
141 {
142 m_eifsNoDifs = eifsNoDifs;
143 }
144
145 private:
146 Time GetSifs() const override
147 {
148 return m_sifs;
149 }
150
151 Time GetSlot() const override
152 {
153 return m_slot;
154 }
155
156 Time GetEifsNoDifs() const override
157 {
158 return m_eifsNoDifs;
159 }
160
164};
165
172template <typename TxopType>
174{
175 public:
182 : m_test(test)
183 {
184 }
185
194 bool StartTransmission(Ptr<Txop> dcf, uint16_t allowedWidth) override
195 {
196 dcf->NotifyChannelAccessed(0);
197 return true;
198 }
199
202 {
203 m_test->NotifyInternalCollision(DynamicCast<TxopTest<TxopType>>(txop));
204 }
205
207 void NotifySwitchingStartNow(Time duration) override
208 {
209 m_test->NotifyChannelSwitching();
210 }
211
212 private:
214};
215
222template <typename TxopType>
224{
225 public:
227 void DoRun() override;
228
248
249 private:
258 void StartTest(uint64_t slotTime,
259 uint64_t sifs,
260 uint64_t eifsNoDifsNoSifs,
261 uint32_t ackTimeoutValue = 20,
262 uint16_t chWidth = 20);
267 void AddTxop(uint32_t aifsn);
269 void EndTest();
276 void ExpectInternalCollision(uint64_t time, uint32_t nSlots, uint32_t from);
283 void ExpectBackoff(uint64_t time, uint32_t nSlots, uint32_t from);
289 void ExpectBusy(uint64_t time, bool busy);
294 void DoCheckBusy(bool busy);
300 void AddRxOkEvt(uint64_t at, uint64_t duration);
306 void AddRxErrorEvt(uint64_t at, uint64_t duration);
313 void AddRxErrorEvt(uint64_t at, uint64_t duration, uint64_t timeUntilError);
319 void AddRxInsideSifsEvt(uint64_t at, uint64_t duration);
325 void AddTxEvt(uint64_t at, uint64_t duration);
331 void AddNavReset(uint64_t at, uint64_t duration);
337 void AddNavStart(uint64_t at, uint64_t duration);
342 void AddAckTimeoutReset(uint64_t at);
350 void AddAccessRequest(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from);
358 void AddAccessRequestWithAckTimeout(uint64_t at,
359 uint64_t txTime,
360 uint64_t expectedGrantTime,
361 uint32_t from);
370 void AddAccessRequestWithSuccessfullAck(uint64_t at,
371 uint64_t txTime,
372 uint64_t expectedGrantTime,
373 uint32_t ackDelay,
374 uint32_t from);
381 void DoAccessRequest(uint64_t txTime,
382 uint64_t expectedGrantTime,
383 Ptr<TxopTest<TxopType>> state);
391 void AddCcaBusyEvt(uint64_t at,
392 uint64_t duration,
394 const std::vector<Time>& per20MhzDurations = {});
400 void AddSwitchingEvt(uint64_t at, uint64_t duration);
406 void AddRxStartEvt(uint64_t at, uint64_t duration);
407
408 typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests;
409
415};
416
417template <typename TxopType>
418void
419TxopTest<TxopType>::QueueTx(uint64_t txTime, uint64_t expectedGrantTime)
420{
421 m_expectedGrants.emplace_back(txTime, expectedGrantTime);
422}
423
424template <typename TxopType>
426 : m_test(test),
427 m_i(i)
428{
429}
430
431template <typename TxopType>
432void
434{
435 m_test = nullptr;
436 TxopType::DoDispose();
437}
438
439template <typename TxopType>
440void
442{
443 Txop::GetLink(0).access = Txop::NOT_REQUESTED;
444 m_test->NotifyAccessGranted(m_i);
445}
446
447template <typename TxopType>
448void
450{
451 m_test->GenerateBackoff(m_i);
452}
453
454template <typename TxopType>
455bool
457{
458 return !m_expectedGrants.empty();
459}
460
461template <typename TxopType>
462void
464{
465}
466
467template <typename TxopType>
468void
470{
471}
472
473template <typename TxopType>
475 : TestCase("ChannelAccessManager")
476{
477}
478
479template <typename TxopType>
480void
482{
483 Ptr<TxopTest<TxopType>> state = m_txop[i];
484 NS_TEST_EXPECT_MSG_EQ(state->m_expectedGrants.empty(), false, "Have expected grants");
485 if (!state->m_expectedGrants.empty())
486 {
487 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front();
488 state->m_expectedGrants.pop_front();
490 MicroSeconds(expected.second),
491 "Expected access grant is now");
492 m_ChannelAccessManager->NotifyTxStartNow(MicroSeconds(expected.first));
493 m_ChannelAccessManager->NotifyAckTimeoutStartNow(
494 MicroSeconds(m_ackTimeoutValue + expected.first));
495 }
496}
497
498template <typename TxopType>
499void
500ChannelAccessManagerTest<TxopType>::AddTxEvt(uint64_t at, uint64_t duration)
501{
502 Simulator::Schedule(MicroSeconds(at) - Now(),
503 &ChannelAccessManager::NotifyTxStartNow,
504 m_ChannelAccessManager,
505 MicroSeconds(duration));
506}
507
508template <typename TxopType>
509void
511{
512 NS_TEST_EXPECT_MSG_EQ(state->m_expectedInternalCollision.empty(),
513 false,
514 "Have expected internal collisions");
515 if (!state->m_expectedInternalCollision.empty())
516 {
517 struct TxopTest<TxopType>::ExpectedBackoff expected =
518 state->m_expectedInternalCollision.front();
519 state->m_expectedInternalCollision.pop_front();
520 NS_TEST_EXPECT_MSG_EQ(Simulator::Now(),
521 MicroSeconds(expected.at),
522 "Expected internal collision time is now");
523 state->StartBackoffNow(expected.nSlots, 0);
524 }
525}
526
527template <typename TxopType>
528void
530{
531 Ptr<TxopTest<TxopType>> state = m_txop[i];
532 NS_TEST_EXPECT_MSG_EQ(state->m_expectedBackoff.empty(), false, "Have expected backoffs");
533 if (!state->m_expectedBackoff.empty())
534 {
535 struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedBackoff.front();
536 state->m_expectedBackoff.pop_front();
537 NS_TEST_EXPECT_MSG_EQ(Simulator::Now(),
538 MicroSeconds(expected.at),
539 "Expected backoff is now");
540 state->StartBackoffNow(expected.nSlots, 0);
541 }
542}
543
544template <typename TxopType>
545void
546ChannelAccessManagerTest<TxopType>::NotifyChannelSwitching()
547{
548 for (auto& state : m_txop)
549 {
550 if (!state->m_expectedGrants.empty())
551 {
552 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front();
553 state->m_expectedGrants.pop_front();
555 MicroSeconds(expected.second),
556 "Expected grant is now");
557 }
558 state->Txop::GetLink(0).access = Txop::NOT_REQUESTED;
559 }
560}
561
562template <typename TxopType>
563void
565 uint32_t nSlots,
566 uint32_t from)
567{
568 Ptr<TxopTest<TxopType>> state = m_txop[from];
569 struct TxopTest<TxopType>::ExpectedBackoff col;
570 col.at = time;
571 col.nSlots = nSlots;
572 state->m_expectedInternalCollision.push_back(col);
573}
574
575template <typename TxopType>
576void
577ChannelAccessManagerTest<TxopType>::ExpectBackoff(uint64_t time, uint32_t nSlots, uint32_t from)
578{
579 Ptr<TxopTest<TxopType>> state = m_txop[from];
580 struct TxopTest<TxopType>::ExpectedBackoff backoff;
581 backoff.at = time;
582 backoff.nSlots = nSlots;
583 state->m_expectedBackoff.push_back(backoff);
584}
585
586template <typename TxopType>
587void
588ChannelAccessManagerTest<TxopType>::ExpectBusy(uint64_t time, bool busy)
589{
590 Simulator::Schedule(MicroSeconds(time) - Now(),
592 this,
593 busy);
594}
595
596template <typename TxopType>
597void
599{
600 NS_TEST_EXPECT_MSG_EQ(m_ChannelAccessManager->IsBusy(), busy, "Incorrect busy/idle state");
601}
602
603template <typename TxopType>
604void
606 uint64_t sifs,
607 uint64_t eifsNoDifsNoSifs,
608 uint32_t ackTimeoutValue,
609 uint16_t chWidth)
610{
611 m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub>();
612 m_feManager = CreateObject<FrameExchangeManagerStub<TxopType>>(this);
613 m_ChannelAccessManager->SetupFrameExchangeManager(m_feManager);
614 m_ChannelAccessManager->SetSlot(MicroSeconds(slotTime));
615 m_ChannelAccessManager->SetSifs(MicroSeconds(sifs));
616 m_ChannelAccessManager->SetEifsNoDifs(MicroSeconds(eifsNoDifsNoSifs + sifs));
617 m_ackTimeoutValue = ackTimeoutValue;
618 // the purpose of the following operations is to initialize the last busy struct
619 // of the ChannelAccessManager. Indeed, InitLastBusyStructs(), which is called by
620 // SetupPhyListener(), requires an attached PHY to determine the channel types
621 // to initialize
622 m_phy = CreateObject<SpectrumWifiPhy>();
623 m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{0, chWidth, WIFI_PHY_BAND_UNSPECIFIED, 0});
624 m_phy->ConfigureStandard(WIFI_STANDARD_80211ac); // required to use 160 MHz channels
625 m_ChannelAccessManager->SetupPhyListener(m_phy);
626}
627
628template <typename TxopType>
629void
631{
632 Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>>(this, m_txop.size());
633 m_txop.push_back(txop);
634 m_ChannelAccessManager->Add(txop);
635 // the following causes the creation of a link for the txop object
636 auto mac = CreateObject<AdhocWifiMac>();
637 mac->SetWifiPhys({nullptr});
638 txop->SetWifiMac(mac);
639 txop->SetAifsn(aifsn);
640}
641
642template <typename TxopType>
643void
645{
646 Simulator::Run();
647
648 for (typename TxopTests::const_iterator i = m_txop.begin(); i != m_txop.end(); i++)
649 {
650 Ptr<TxopTest<TxopType>> state = *i;
651 NS_TEST_EXPECT_MSG_EQ(state->m_expectedGrants.empty(), true, "Have no expected grants");
652 NS_TEST_EXPECT_MSG_EQ(state->m_expectedInternalCollision.empty(),
653 true,
654 "Have no internal collisions");
655 NS_TEST_EXPECT_MSG_EQ(state->m_expectedBackoff.empty(), true, "Have no expected backoffs");
656 state->Dispose();
657 state = nullptr;
658 }
659 m_txop.clear();
660
661 m_ChannelAccessManager->RemovePhyListener(m_phy);
662 m_phy->Dispose();
663 m_ChannelAccessManager->Dispose();
664 m_ChannelAccessManager = nullptr;
665 m_feManager = nullptr;
666 Simulator::Destroy();
667}
668
669template <typename TxopType>
670void
672{
673 Simulator::Schedule(MicroSeconds(at) - Now(),
674 &ChannelAccessManager::NotifyRxStartNow,
675 m_ChannelAccessManager,
676 MicroSeconds(duration));
677 Simulator::Schedule(MicroSeconds(at + duration) - Now(),
678 &ChannelAccessManager::NotifyRxEndOkNow,
679 m_ChannelAccessManager);
680}
681
682template <typename TxopType>
683void
685{
686 Simulator::Schedule(MicroSeconds(at) - Now(),
687 &ChannelAccessManager::NotifyRxStartNow,
688 m_ChannelAccessManager,
689 MicroSeconds(duration));
690}
691
692template <typename TxopType>
693void
695{
696 Simulator::Schedule(MicroSeconds(at) - Now(),
697 &ChannelAccessManager::NotifyRxStartNow,
698 m_ChannelAccessManager,
699 MicroSeconds(duration));
700 Simulator::Schedule(MicroSeconds(at + duration) - Now(),
701 &ChannelAccessManager::NotifyRxEndErrorNow,
702 m_ChannelAccessManager);
703}
704
705template <typename TxopType>
706void
708 uint64_t duration,
709 uint64_t timeUntilError)
710{
711 Simulator::Schedule(MicroSeconds(at) - Now(),
712 &ChannelAccessManager::NotifyRxStartNow,
713 m_ChannelAccessManager,
714 MicroSeconds(duration));
715 Simulator::Schedule(MicroSeconds(at + timeUntilError) - Now(),
716 &ChannelAccessManager::NotifyRxEndErrorNow,
717 m_ChannelAccessManager);
718 Simulator::Schedule(MicroSeconds(at + timeUntilError) - Now(),
719 &ChannelAccessManager::NotifyCcaBusyStartNow,
720 m_ChannelAccessManager,
721 MicroSeconds(duration - timeUntilError),
723 std::vector<Time>{});
724}
725
726template <typename TxopType>
727void
729{
730 Simulator::Schedule(MicroSeconds(at) - Now(),
731 &ChannelAccessManager::NotifyNavResetNow,
732 m_ChannelAccessManager,
733 MicroSeconds(duration));
734}
735
736template <typename TxopType>
737void
739{
740 Simulator::Schedule(MicroSeconds(at) - Now(),
741 &ChannelAccessManager::NotifyNavStartNow,
742 m_ChannelAccessManager,
743 MicroSeconds(duration));
744}
745
746template <typename TxopType>
747void
749{
750 Simulator::Schedule(MicroSeconds(at) - Now(),
751 &ChannelAccessManager::NotifyAckTimeoutResetNow,
752 m_ChannelAccessManager);
753}
754
755template <typename TxopType>
756void
758 uint64_t txTime,
759 uint64_t expectedGrantTime,
760 uint32_t from)
761{
762 AddAccessRequestWithSuccessfullAck(at, txTime, expectedGrantTime, 0, from);
763}
764
765template <typename TxopType>
766void
768 uint64_t txTime,
769 uint64_t expectedGrantTime,
770 uint32_t from)
771{
772 Simulator::Schedule(MicroSeconds(at) - Now(),
774 this,
775 txTime,
776 expectedGrantTime,
777 m_txop[from]);
778}
779
780template <typename TxopType>
781void
783 uint64_t txTime,
784 uint64_t expectedGrantTime,
785 uint32_t ackDelay,
786 uint32_t from)
787{
788 NS_ASSERT(ackDelay < m_ackTimeoutValue);
789 Simulator::Schedule(MicroSeconds(at) - Now(),
791 this,
792 txTime,
793 expectedGrantTime,
794 m_txop[from]);
795 AddAckTimeoutReset(expectedGrantTime + txTime + ackDelay);
796}
797
798template <typename TxopType>
799void
801 uint64_t expectedGrantTime,
802 Ptr<TxopTest<TxopType>> state)
803{
804 if (m_ChannelAccessManager->NeedBackoffUponAccess(state))
805 {
806 state->GenerateBackoff(0);
807 }
808 state->QueueTx(txTime, expectedGrantTime);
809 m_ChannelAccessManager->RequestAccess(state);
810}
811
812template <typename TxopType>
813void
815 uint64_t duration,
816 WifiChannelListType channelType,
817 const std::vector<Time>& per20MhzDurations)
818{
819 Simulator::Schedule(MicroSeconds(at) - Now(),
820 &ChannelAccessManager::NotifyCcaBusyStartNow,
821 m_ChannelAccessManager,
822 MicroSeconds(duration),
823 channelType,
824 per20MhzDurations);
825}
826
827template <typename TxopType>
828void
830{
831 Simulator::Schedule(MicroSeconds(at) - Now(),
832 &ChannelAccessManager::NotifySwitchingStartNow,
833 m_ChannelAccessManager,
834 MicroSeconds(duration));
835}
836
837template <typename TxopType>
838void
840{
841 Simulator::Schedule(MicroSeconds(at) - Now(),
842 &ChannelAccessManager::NotifyRxStartNow,
843 m_ChannelAccessManager,
844 MicroSeconds(duration));
845}
846
847/*
848 * Specialization of DoRun () method for DCF
849 */
850template <>
851void
853{
854 // DCF immediate access (no backoff)
855 // 1 4 5 6 8 11 12
856 // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
857 //
858 StartTest(1, 3, 10);
859 AddTxop(1);
860 AddAccessRequest(1, 1, 5, 0);
861 AddAccessRequest(8, 2, 12, 0);
862 EndTest();
863 // Check that receiving inside SIFS shall be cancelled properly:
864 // 1 4 5 6 9 10 14 17 18
865 // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
866 // |
867 // 7 start rx
868 //
869
870 StartTest(1, 3, 10);
871 AddTxop(1);
872 AddAccessRequest(1, 1, 5, 0);
873 AddRxInsideSifsEvt(7, 10);
874 AddTxEvt(9, 1);
875 AddAccessRequest(14, 2, 18, 0);
876 EndTest();
877 // The test below mainly intends to test the case where the medium
878 // becomes busy in the middle of a backoff slot: the backoff counter
879 // must not be decremented for this backoff slot. This is the case
880 // below for the backoff slot starting at time 78us.
881 //
882 // 20 60 66 70 74 78 80 100 106 110 114 118
883 // 120
884 // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 |
885 // bslot3 | tx |
886 // |
887 // 30 request access. backoff slots: 4
888
889 StartTest(4, 6, 10);
890 AddTxop(1);
891 AddRxOkEvt(20, 40);
892 AddRxOkEvt(80, 20);
893 AddAccessRequest(30, 2, 118, 0);
894 ExpectBackoff(30, 4, 0); // backoff: 4 slots
895 EndTest();
896 // Test the case where the backoff slots is zero.
897 //
898 // 20 60 66 70 72
899 // | rx | sifs | aifsn | tx |
900 // |
901 // 30 request access. backoff slots: 0
902
903 StartTest(4, 6, 10);
904 AddTxop(1);
905 AddRxOkEvt(20, 40);
906 AddAccessRequest(30, 2, 70, 0);
907 ExpectBackoff(30, 0, 0); // backoff: 0 slots
908 EndTest();
909 // Test shows when two frames are received without interval between
910 // them:
911 // 20 60 100 106 110 112
912 // | rx | rx |sifs | aifsn | tx |
913 // |
914 // 30 request access. backoff slots: 0
915
916 StartTest(4, 6, 10);
917 AddTxop(1);
918 AddRxOkEvt(20, 40);
919 AddRxOkEvt(60, 40);
920 AddAccessRequest(30, 2, 110, 0);
921 ExpectBackoff(30, 0, 0); // backoff: 0 slots
922 EndTest();
923
924 // Requesting access within SIFS interval (DCF immediate access)
925 //
926 // 20 60 62 68 72
927 // | rx | idle | sifs | aifsn | tx |
928 //
929 StartTest(4, 6, 10);
930 AddTxop(1);
931 AddRxOkEvt(20, 40);
932 AddAccessRequest(62, 2, 72, 0);
933 EndTest();
934
935 // Requesting access after DIFS (DCF immediate access)
936 //
937 // 20 60 70 76 80
938 // | rx | idle | sifs | aifsn | tx |
939 //
940 StartTest(4, 6, 10);
941 AddTxop(1);
942 AddRxOkEvt(20, 40);
943 AddAccessRequest(70, 2, 80, 0);
944 EndTest();
945
946 // Test an EIFS
947 //
948 // 20 60 66 76 86 90 94 98 102 106
949 // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
950 // | | <------eifs------>|
951 // 30 request access. backoff slots: 4
952 StartTest(4, 6, 10);
953 AddTxop(1);
954 AddRxErrorEvt(20, 40);
955 AddAccessRequest(30, 2, 102, 0);
956 ExpectBackoff(30, 4, 0); // backoff: 4 slots
957 EndTest();
958
959 // Test DCF immediate access after an EIFS (EIFS is greater)
960 //
961 // 20 60 66 76 86
962 // | <----+-eifs------>|
963 // | rx | sifs | acktxttime | sifs + aifsn | tx |
964 // | sifs + aifsn |
965 // request access 70 80
966 StartTest(4, 6, 10);
967 AddTxop(1);
968 AddRxErrorEvt(20, 40);
969 AddAccessRequest(70, 2, 86, 0);
970 EndTest();
971
972 // Test that channel stays busy for first frame's duration after Rx error
973 //
974 // 20 60
975 // | rx |
976 // |
977 // 40 force Rx error
978 StartTest(4, 6, 10);
979 AddTxop(1);
980 AddRxErrorEvt(20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
981 ExpectBusy(41, true); // channel should remain busy for remaining duration
982 ExpectBusy(59, true);
983 ExpectBusy(61, false);
984 EndTest();
985
986 // Test an EIFS which is interrupted by a successful transmission.
987 //
988 // 20 60 66 69 75 81 85 89 93 97 101 103
989 // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
990 // | | <--eifs-->|
991 // 30 request access. backoff slots: 4
992 StartTest(4, 6, 10);
993 AddTxop(1);
994 AddRxErrorEvt(20, 40);
995 AddAccessRequest(30, 2, 101, 0);
996 ExpectBackoff(30, 4, 0); // backoff: 4 slots
997 AddRxOkEvt(69, 6);
998 EndTest();
999
1000 // Test two DCFs which suffer an internal collision. the first DCF has a higher
1001 // priority than the second DCF.
1002 //
1003 // 20 60 66 70 74 78 88
1004 // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
1005 // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn |
1006 // bslot | tx |
1007 // 94 98 102 106
1008 // 110 112
1009 StartTest(4, 6, 10);
1010 AddTxop(1); // high priority DCF
1011 AddTxop(3); // low priority DCF
1012 AddRxOkEvt(20, 40);
1013 AddAccessRequest(30, 10, 78, 0);
1014 ExpectBackoff(30, 2, 0); // backoff: 2 slot
1015 AddAccessRequest(40, 2, 110, 1);
1016 ExpectBackoff(40, 0, 1); // backoff: 0 slot
1017 ExpectInternalCollision(78, 1, 1); // backoff: 1 slot
1018 EndTest();
1019
1020 // Test of AckTimeout handling: First queue requests access and ack procedure fails,
1021 // inside the Ack timeout second queue with higher priority requests access.
1022 //
1023 // 20 26 34 54 74 80
1024 // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
1025 // DCF0 - high | | | sifs | tx |
1026 // ^ request access
1027 StartTest(4, 6, 10);
1028 AddTxop(0); // high priority DCF
1029 AddTxop(2); // low priority DCF
1030 AddAccessRequestWithAckTimeout(20, 20, 34, 1);
1031 AddAccessRequest(64, 10, 80, 0);
1032 EndTest();
1033
1034 // Test of AckTimeout handling:
1035 //
1036 // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
1037 // inside this interval second queue with higher priority requests access.
1038 //
1039 // 20 26 34 54 56 62
1040 // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
1041 // DCF0 - high | | | sifs | tx |
1042 // ^ request access
1043 StartTest(4, 6, 10);
1044 AddTxop(0); // high priority DCF
1045 AddTxop(2); // low priority DCF
1046 AddAccessRequestWithSuccessfullAck(20, 20, 34, 2, 1);
1047 AddAccessRequest(55, 10, 62, 0);
1048 EndTest();
1049
1050 // Repeat the same but with one queue:
1051 // 20 26 34 54 60 62 68 76 80
1052 // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
1053 // ^ request access
1054 StartTest(4, 6, 10);
1055 AddTxop(2);
1056 AddAccessRequest(20, 20, 34, 0);
1057 AddRxOkEvt(60, 2); // Ack
1058 AddAccessRequest(61, 10, 80, 0);
1059 ExpectBackoff(61, 1, 0); // 1 slot
1060 EndTest();
1061
1062 // test simple NAV count. This scenario models a simple Data+Ack handshake
1063 // where the data rate used for the Ack is higher than expected by the Data source
1064 // so, the data exchange completes before the end of NAV.
1065 StartTest(4, 6, 10);
1066 AddTxop(1);
1067 AddRxOkEvt(20, 40);
1068 AddNavStart(60, 15);
1069 AddRxOkEvt(66, 5);
1070 AddNavStart(71, 0);
1071 AddAccessRequest(30, 10, 93, 0);
1072 ExpectBackoff(30, 2, 0); // backoff: 2 slots
1073 EndTest();
1074
1075 // test more complex NAV handling by a CF-poll. This scenario models a
1076 // simple Data+Ack handshake interrupted by a CF-poll which resets the
1077 // NAV counter.
1078 StartTest(4, 6, 10);
1079 AddTxop(1);
1080 AddRxOkEvt(20, 40);
1081 AddNavStart(60, 15);
1082 AddRxOkEvt(66, 5);
1083 AddNavReset(71, 2);
1084 AddAccessRequest(30, 10, 91, 0);
1085 ExpectBackoff(30, 2, 0); // backoff: 2 slots
1086 EndTest();
1087
1088 // 20 60 80 86 94
1089 // | rx | idle | sifs | aifsn | tx |
1090 // ^ request access
1091 StartTest(4, 6, 10);
1092 AddTxop(2);
1093 AddRxOkEvt(20, 40);
1094 AddAccessRequest(80, 10, 94, 0);
1095 EndTest();
1096
1097 StartTest(4, 6, 10);
1098 AddTxop(2);
1099 AddRxOkEvt(20, 40);
1100 AddRxOkEvt(78, 8);
1101 AddAccessRequest(30, 50, 108, 0);
1102 ExpectBackoff(30, 3, 0); // backoff: 3 slots
1103 EndTest();
1104
1105 // Channel switching tests
1106
1107 // 0 20 21 24 25 26
1108 // | switching | idle | sifs | aifsn | tx |
1109 // ^ access request.
1110 StartTest(1, 3, 10);
1111 AddTxop(1);
1112 AddSwitchingEvt(0, 20);
1113 AddAccessRequest(21, 1, 25, 0);
1114 EndTest();
1115
1116 // 20 40 50 53 54 55 56 57
1117 // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
1118 // | |
1119 // 30 busy. 45 access request.
1120 //
1121 StartTest(1, 3, 10);
1122 AddTxop(1);
1123 AddSwitchingEvt(20, 20);
1124 AddCcaBusyEvt(30, 20);
1125 ExpectBackoff(45, 2, 0); // backoff: 2 slots
1126 AddAccessRequest(45, 1, 56, 0);
1127 EndTest();
1128
1129 // 20 30 50 51 54 55 56
1130 // | rx | switching | idle | sifs | aifsn | tx |
1131 // ^ access request.
1132 //
1133 StartTest(1, 3, 10);
1134 AddTxop(1);
1135 AddRxStartEvt(20, 40);
1136 AddSwitchingEvt(30, 20);
1137 AddAccessRequest(51, 1, 55, 0);
1138 EndTest();
1139
1140 // 20 30 50 51 54 55 56
1141 // | busy | switching | idle | sifs | aifsn | tx |
1142 // ^ access request.
1143 //
1144 StartTest(1, 3, 10);
1145 AddTxop(1);
1146 AddCcaBusyEvt(20, 40);
1147 AddSwitchingEvt(30, 20);
1148 AddAccessRequest(51, 1, 55, 0);
1149 EndTest();
1150
1151 // 20 30 50 51 54 55 56
1152 // | nav | switching | idle | sifs | aifsn | tx |
1153 // ^ access request.
1154 //
1155 StartTest(1, 3, 10);
1156 AddTxop(1);
1157 AddNavStart(20, 40);
1158 AddSwitchingEvt(30, 20);
1159 AddAccessRequest(51, 1, 55, 0);
1160 EndTest();
1161
1162 // 20 23 24 44 54 59 60 63 64 65
1163 // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1164 // | |
1165 // 49 access request. ^ access request.
1166 //
1167 StartTest(1, 3, 10);
1168 AddTxop(1);
1169 AddAccessRequestWithAckTimeout(20, 20, 24, 0);
1170 AddAccessRequest(49, 1, 54, 0);
1171 AddSwitchingEvt(54, 5);
1172 AddAccessRequest(60, 1, 64, 0);
1173 EndTest();
1174
1175 // 20 60 66 70 74 78 80 100 101 107 111 113
1176 // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1177 // | |
1178 // 30 access request. ^ access request.
1179 //
1180 StartTest(4, 6, 10);
1181 AddTxop(1);
1182 AddRxOkEvt(20, 40);
1183 AddAccessRequest(30, 2, 80, 0);
1184 ExpectBackoff(30, 4, 0); // backoff: 4 slots
1185 AddSwitchingEvt(80, 20);
1186 AddAccessRequest(101, 2, 111, 0);
1187 EndTest();
1188}
1189
1190/*
1191 * Specialization of DoRun () method for EDCA
1192 */
1193template <>
1194void
1196{
1197 // Check alignment at slot boundary after successful reception (backoff = 0).
1198 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1199 // 20 50 56 60 80
1200 // | cca_busy |
1201 // | rx | sifs | aifsn | tx |
1202 // |
1203 // 52 request access
1204 StartTest(4, 6, 10, 20, 40);
1205 AddTxop(1);
1206 AddRxOkEvt(20, 30);
1207 AddCcaBusyEvt(50, 10, WIFI_CHANLIST_SECONDARY);
1208 AddAccessRequest(52, 20, 60, 0);
1209 EndTest();
1210
1211 // Check alignment at slot boundary after successful reception (backoff = 0).
1212 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1213 // 20 50 56 60 80
1214 // | cca_busy |
1215 // | rx | sifs | aifsn | tx |
1216 // |
1217 // 58 request access
1218 StartTest(4, 6, 10, 20, 80);
1219 AddTxop(1);
1220 AddRxOkEvt(20, 30);
1221 AddCcaBusyEvt(50, 10, WIFI_CHANLIST_SECONDARY);
1222 AddAccessRequest(58, 20, 60, 0);
1223 EndTest();
1224
1225 // Check alignment at slot boundary after successful reception (backoff = 0).
1226 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1227 // 20 50 56 60 64 84
1228 // | cca_busy |
1229 // | rx | sifs | aifsn | idle | tx |
1230 // |
1231 // 62 request access
1232 StartTest(4, 6, 10, 20, 80);
1233 AddTxop(1);
1234 AddRxOkEvt(20, 30);
1235 AddCcaBusyEvt(50, 14, WIFI_CHANLIST_SECONDARY40);
1236 AddAccessRequest(62, 20, 64, 0);
1237 EndTest();
1238
1239 // Check alignment at slot boundary after failed reception (backoff = 0).
1240 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1241 // 20 50 56 66 76 96
1242 // | cca_busy |
1243 // | | <------eifs------>| | |
1244 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1245 // |
1246 // 55 request access
1247 StartTest(4, 6, 10, 20, 160);
1248 AddTxop(1);
1249 AddRxErrorEvt(20, 30);
1250 AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY);
1251 AddAccessRequest(55, 20, 76, 0);
1252 EndTest();
1253
1254 // Check alignment at slot boundary after failed reception (backoff = 0).
1255 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1256 // 20 50 56 66 76 96
1257 // | cca_busy |
1258 // | | <------eifs------>| | |
1259 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1260 // |
1261 // 70 request access
1262 StartTest(4, 6, 10, 20, 160);
1263 AddTxop(1);
1264 AddRxErrorEvt(20, 30);
1265 AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY40);
1266 AddAccessRequest(70, 20, 76, 0);
1267 EndTest();
1268
1269 // Check alignment at slot boundary after failed reception (backoff = 0).
1270 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1271 // 20 50 56 66 76 84
1272 // | cca_busy |
1273 // | | <------eifs------>| | |
1274 // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1275 // |
1276 // 82 request access
1277 StartTest(4, 6, 10, 20, 160);
1278 AddTxop(1);
1279 AddRxErrorEvt(20, 30);
1280 AddCcaBusyEvt(50, 34, WIFI_CHANLIST_SECONDARY80);
1281 AddAccessRequest(82, 20, 84, 0);
1282 EndTest();
1283
1284 // Check backoff decrement at slot boundaries. Medium idle during backoff
1285 // 20 50 56 60 64 68 72 76 96
1286 // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1287 // | | | | |
1288 // 30 request access. decrement decrement decrement decrement
1289 // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1290 StartTest(4, 6, 10);
1291 AddTxop(1);
1292 AddRxOkEvt(20, 30);
1293 AddAccessRequest(30, 20, 76, 0);
1294 ExpectBackoff(30, 4, 0);
1295 EndTest();
1296
1297 // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1298 // 20 50 56 60 61 71 77 81 85 87 97 103
1299 // 107 127
1300 // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs |
1301 // aifsn | tx |
1302 // | | | |
1303 // 30 request access. decrement decrement decrement
1304 // backoff slots: 3 slots: 2 slots: 1 slots: 0
1305 StartTest(4, 6, 10);
1306 AddTxop(1);
1307 AddRxOkEvt(20, 30);
1308 AddRxOkEvt(61, 10);
1309 AddRxOkEvt(87, 10);
1310 AddAccessRequest(30, 20, 107, 0);
1311 ExpectBackoff(30, 3, 0);
1312 EndTest();
1313}
1314
1328{
1329 public:
1332
1333 private:
1334 void DoRun() override;
1335
1342 void RunOne(uint16_t chWidth, WifiChannelListType busyChannel);
1343
1346};
1347
1349 : TestCase("Check calculation of the largest idle primary channel")
1350{
1351}
1352
1353void
1355{
1375
1376 // After 1ms, we are notified of CCA_BUSY for 1ms on the given channel
1377 Time ccaBusyStartDelay = MilliSeconds(1);
1378 Time ccaBusyDuration = MilliSeconds(1);
1379 Simulator::Schedule(ccaBusyStartDelay,
1380 &ChannelAccessManager::NotifyCcaBusyStartNow,
1381 m_cam,
1382 ccaBusyDuration,
1383 busyChannel,
1384 std::vector<Time>(chWidth / 20, Seconds(0)));
1385
1386 // During any interval ending within CCA_BUSY period, the idle channel is the
1387 // primary channel contiguous to the busy secondary channel, if the busy channel
1388 // is a secondary channel, or there is no idle channel, otherwise.
1389 uint16_t idleWidth = (busyChannel == WifiChannelListType::WIFI_CHANLIST_PRIMARY)
1390 ? 0
1391 : ((1 << (busyChannel - 1)) * 20);
1392
1393 Time checkTime1 = start + ccaBusyStartDelay + ccaBusyDuration / 2;
1394 Simulator::Schedule(checkTime1 - start, [=]() {
1395 Time interval1 = (ccaBusyStartDelay + ccaBusyDuration) / 2;
1397 idleWidth,
1398 "Incorrect width of the idle channel in an interval "
1399 << "ending within CCA_BUSY (channel width: " << chWidth
1400 << " MHz, busy channel: " << busyChannel << ")");
1401 });
1402
1403 // During any interval starting within CCA_BUSY period, the idle channel is the
1404 // same as the previous case
1405 Time ccaBusyRxInterval = MilliSeconds(1);
1406 Time checkTime2 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval / 2;
1407 Simulator::Schedule(checkTime2 - start, [=]() {
1408 Time interval2 = (ccaBusyDuration + ccaBusyRxInterval) / 2;
1410 idleWidth,
1411 "Incorrect width of the idle channel in an interval "
1412 << "starting within CCA_BUSY (channel width: " << chWidth
1413 << " MHz, busy channel: " << busyChannel << ")");
1414 });
1415
1416 // Notify RX start
1417 Time rxDuration = MilliSeconds(1);
1418 Simulator::Schedule(ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval,
1419 &ChannelAccessManager::NotifyRxStartNow,
1420 m_cam,
1421 rxDuration);
1422
1423 // At RX end, we check the status of the channel during an interval immediately
1424 // preceding RX start and overlapping the CCA_BUSY period.
1425 Time checkTime3 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval + rxDuration;
1426 Simulator::Schedule(checkTime3 - start, [=]() {
1427 Time interval3 = ccaBusyDuration / 2 + ccaBusyRxInterval;
1428 Time end3 = checkTime3 - rxDuration;
1430 idleWidth,
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 << ")");
1435 });
1436
1437 // At RX end, we check the status of the channel during the interval following
1438 // the CCA_BUSY period and preceding RX start. The entire operating channel is idle.
1439 Time checkTime4 = checkTime3;
1440 Simulator::Schedule(checkTime4 - start, [=]() {
1441 Time interval4 = ccaBusyRxInterval;
1442 Time end4 = checkTime4 - rxDuration;
1444 chWidth,
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
1448 << ")");
1449 });
1450
1451 // After RX end, the entire operating channel is idle if the interval does not
1452 // overlap the RX period
1453 Time interval5 = MilliSeconds(1);
1454 Time checkTime5 = checkTime4 + interval5;
1455 Simulator::Schedule(checkTime5 - start, [=]() {
1457 chWidth,
1458 "Incorrect width of the idle channel in an interval "
1459 << "following RX end (channel width: " << chWidth
1460 << " MHz, busy channel: " << busyChannel << ")");
1461 });
1462
1463 // After RX end, no channel is idle if the interval overlaps the RX period
1464 Time checkTime6 = checkTime5;
1465 Simulator::Schedule(checkTime6 - start, [=]() {
1466 Time interval6 = interval5 + rxDuration / 2;
1468 0,
1469 "Incorrect width of the idle channel in an interval "
1470 << "overlapping RX (channel width: " << chWidth
1471 << " MHz, busy channel: " << busyChannel << ")");
1472 });
1473}
1474
1475void
1477{
1478 m_cam = CreateObject<ChannelAccessManager>();
1479 uint16_t delay = 0;
1480 uint8_t channel = 0;
1481 std::list<WifiChannelListType> busyChannels;
1482
1483 for (uint16_t chWidth : {20, 40, 80, 160})
1484 {
1485 busyChannels.push_back(static_cast<WifiChannelListType>(channel));
1486
1487 for (const auto busyChannel : busyChannels)
1488 {
1489 Simulator::Schedule(Seconds(delay), [this, chWidth, busyChannel]() {
1490 // reset PHY
1491 if (m_phy)
1492 {
1494 m_phy->Dispose();
1495 }
1496 // create a new PHY operating on a channel of the current width
1497 m_phy = CreateObject<SpectrumWifiPhy>();
1501 // call SetupPhyListener to initialize the ChannelAccessManager
1502 // last busy structs
1504 // run the tests
1505 RunOne(chWidth, busyChannel);
1506 });
1507 delay++;
1508 }
1509 channel++;
1510 }
1511
1512 Simulator::Run();
1514 m_phy->Dispose();
1515 m_cam->Dispose();
1516 Simulator::Destroy();
1517}
1518
1526{
1527 public:
1528 TxopTestSuite();
1529};
1530
1532 : TestSuite("wifi-devices-dcf", UNIT)
1533{
1534 AddTestCase(new ChannelAccessManagerTest<Txop>, TestCase::QUICK);
1535}
1536
1538
1546{
1547 public:
1549};
1550
1552 : TestSuite("wifi-devices-edca", UNIT)
1553{
1554 AddTestCase(new ChannelAccessManagerTest<QosTxop>, TestCase::QUICK);
1555}
1556
1558
1566{
1567 public:
1569};
1570
1572 : TestSuite("wifi-channel-access-manager", UNIT)
1573{
1574 AddTestCase(new LargestIdlePrimaryChannelTest, TestCase::QUICK);
1575}
1576
static ChannelAccessManagerTestSuite g_camTestSuite
static TxopTestSuite g_dcfTestSuite
static QosTxopTestSuite g_edcaTestSuite
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 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 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.
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 AddAccessRequestWithSuccessfullAck(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
Add access request with successful ack.
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.
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...
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
TxopTest Txop Test.
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 RemovePhyListener(Ptr< WifiPhy > phy)
Remove current registered listener for PHY events.
void SetupPhyListener(Ptr< WifiPhy > phy)
Set up listener for PHY events.
FrameExchangeManager is a base class handling the basic frame exchange sequences for non-QoS stations...
void Dispose()
Dispose of this Object.
Definition: object.cc:219
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
virtual void NotifyChannelAccessed(uint8_t linkId, Time txopDuration=Seconds(0))
Called by the FrameExchangeManager to notify that channel access has been granted on the given link f...
Definition: txop.cc:578
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:895
void SetOperatingChannel(const ChannelTuple &channelTuple)
If the standard for this object has not been set yet, store the given channel settings.
Definition: wifi-phy.cc:1004
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:869
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:251
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ WIFI_PHY_BAND_UNSPECIFIED
Unspecified.
Definition: wifi-phy-band.h:43
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ WIFI_CHANLIST_PRIMARY
@ 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.
Definition: ptr.h:625
channel
Definition: third.py:81
mac
Definition: third.py:85
def start()
Definition: core.py:1861