A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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/interference-helper.h"
24#include "ns3/multi-model-spectrum-channel.h"
25#include "ns3/qos-txop.h"
26#include "ns3/simulator.h"
27#include "ns3/spectrum-wifi-phy.h"
28#include "ns3/test.h"
29
30#include <list>
31#include <numeric>
32
33using namespace ns3;
34
35template <typename TxopType>
37
44template <typename TxopType>
45class TxopTest : public TxopType
46{
47 public:
55
61 void QueueTx(uint64_t txTime, uint64_t expectedGrantTime);
62
63 private:
66
68 void DoDispose() override;
70 void NotifyChannelAccessed(uint8_t linkId, Time txopDuration = Seconds(0)) override;
72 bool HasFramesToTransmit(uint8_t linkId) override;
74 void NotifySleep(uint8_t linkId) override;
76 void NotifyWakeUp(uint8_t linkId) override;
78 void GenerateBackoff(uint8_t linkId) override;
79
80 typedef std::pair<uint64_t, uint64_t> ExpectedGrant;
81 typedef std::list<ExpectedGrant> ExpectedGrants;
82
85 {
86 uint64_t at;
88 };
89
90 typedef std::list<ExpectedBackoff> ExpectedBackoffs;
91
95
103};
104
112{
113 public:
115 {
116 }
117
123 void SetSifs(Time sifs)
124 {
125 m_sifs = sifs;
126 }
127
133 void SetSlot(Time slot)
134 {
135 m_slot = slot;
136 }
137
143 void SetEifsNoDifs(Time eifsNoDifs)
144 {
145 m_eifsNoDifs = eifsNoDifs;
146 }
147
148 private:
149 Time GetSifs() const override
150 {
151 return m_sifs;
152 }
153
154 Time GetSlot() const override
155 {
156 return m_slot;
157 }
158
159 Time GetEifsNoDifs() const override
160 {
161 return m_eifsNoDifs;
162 }
163
167};
168
175template <typename TxopType>
177{
178 public:
185 : m_test(test)
186 {
187 }
188
197 bool StartTransmission(Ptr<Txop> dcf, uint16_t allowedWidth) override
198 {
199 dcf->NotifyChannelAccessed(0);
200 return true;
201 }
202
205 {
206 m_test->NotifyInternalCollision(DynamicCast<TxopTest<TxopType>>(txop));
207 }
208
210 void NotifySwitchingStartNow(Time duration) override
211 {
212 m_test->NotifyChannelSwitching();
213 }
214
215 private:
217};
218
225template <typename TxopType>
227{
228 public:
230 void DoRun() override;
231
251
252 private:
261 void StartTest(uint64_t slotTime,
262 uint64_t sifs,
263 uint64_t eifsNoDifsNoSifs,
264 uint32_t ackTimeoutValue = 20,
265 uint16_t chWidth = 20);
270 void AddTxop(uint32_t aifsn);
272 void EndTest();
279 void ExpectInternalCollision(uint64_t time, uint32_t nSlots, uint32_t from);
286 void ExpectBackoff(uint64_t time, uint32_t nSlots, uint32_t from);
292 void ExpectBusy(uint64_t time, bool busy);
297 void DoCheckBusy(bool busy);
303 void AddRxOkEvt(uint64_t at, uint64_t duration);
309 void AddRxErrorEvt(uint64_t at, uint64_t duration);
316 void AddRxErrorEvt(uint64_t at, uint64_t duration, uint64_t timeUntilError);
322 void AddRxInsideSifsEvt(uint64_t at, uint64_t duration);
328 void AddTxEvt(uint64_t at, uint64_t duration);
334 void AddNavReset(uint64_t at, uint64_t duration);
340 void AddNavStart(uint64_t at, uint64_t duration);
345 void AddAckTimeoutReset(uint64_t at);
353 void AddAccessRequest(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from);
361 void AddAccessRequestWithAckTimeout(uint64_t at,
362 uint64_t txTime,
363 uint64_t expectedGrantTime,
364 uint32_t from);
373 void AddAccessRequestWithSuccessfulAck(uint64_t at,
374 uint64_t txTime,
375 uint64_t expectedGrantTime,
376 uint32_t ackDelay,
377 uint32_t from);
384 void DoAccessRequest(uint64_t txTime,
385 uint64_t expectedGrantTime,
386 Ptr<TxopTest<TxopType>> state);
394 void AddCcaBusyEvt(uint64_t at,
395 uint64_t duration,
397 const std::vector<Time>& per20MhzDurations = {});
403 void AddSwitchingEvt(uint64_t at, uint64_t duration);
409 void AddRxStartEvt(uint64_t at, uint64_t duration);
410
411 typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests;
412
418};
419
420template <typename TxopType>
421void
422TxopTest<TxopType>::QueueTx(uint64_t txTime, uint64_t expectedGrantTime)
423{
424 m_expectedGrants.emplace_back(txTime, expectedGrantTime);
425}
426
427template <typename TxopType>
429 : m_test(test),
430 m_i(i)
431{
432}
433
434template <typename TxopType>
435void
437{
438 m_test = nullptr;
439 TxopType::DoDispose();
440}
441
442template <typename TxopType>
443void
445{
447 m_test->NotifyAccessGranted(m_i);
448}
449
450template <typename TxopType>
451void
453{
454 m_test->GenerateBackoff(m_i);
455}
456
457template <typename TxopType>
458bool
460{
461 return !m_expectedGrants.empty();
462}
463
464template <typename TxopType>
465void
467{
468}
469
470template <typename TxopType>
471void
473{
474}
475
476template <typename TxopType>
478 : TestCase("ChannelAccessManager")
479{
480}
481
482template <typename TxopType>
483void
485{
486 Ptr<TxopTest<TxopType>> state = m_txop[i];
487 NS_TEST_EXPECT_MSG_EQ(state->m_expectedGrants.empty(), false, "Have expected grants");
488 if (!state->m_expectedGrants.empty())
489 {
490 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front();
491 state->m_expectedGrants.pop_front();
493 MicroSeconds(expected.second),
494 "Expected access grant is now");
495 m_ChannelAccessManager->NotifyTxStartNow(MicroSeconds(expected.first));
496 m_ChannelAccessManager->NotifyAckTimeoutStartNow(
497 MicroSeconds(m_ackTimeoutValue + expected.first));
498 }
499}
500
501template <typename TxopType>
502void
503ChannelAccessManagerTest<TxopType>::AddTxEvt(uint64_t at, uint64_t duration)
504{
507 m_ChannelAccessManager,
508 MicroSeconds(duration));
509}
510
511template <typename TxopType>
512void
514{
515 NS_TEST_EXPECT_MSG_EQ(state->m_expectedInternalCollision.empty(),
516 false,
517 "Have expected internal collisions");
518 if (!state->m_expectedInternalCollision.empty())
519 {
520 struct TxopTest<TxopType>::ExpectedBackoff expected =
521 state->m_expectedInternalCollision.front();
522 state->m_expectedInternalCollision.pop_front();
523 NS_TEST_EXPECT_MSG_EQ(Simulator::Now(),
524 MicroSeconds(expected.at),
525 "Expected internal collision time is now");
526 state->StartBackoffNow(expected.nSlots, 0);
527 }
528}
529
530template <typename TxopType>
531void
533{
534 Ptr<TxopTest<TxopType>> state = m_txop[i];
535 NS_TEST_EXPECT_MSG_EQ(state->m_expectedBackoff.empty(), false, "Have expected backoffs");
536 if (!state->m_expectedBackoff.empty())
537 {
538 struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedBackoff.front();
539 state->m_expectedBackoff.pop_front();
540 NS_TEST_EXPECT_MSG_EQ(Simulator::Now(),
541 MicroSeconds(expected.at),
542 "Expected backoff is now");
543 state->StartBackoffNow(expected.nSlots, 0);
544 }
545}
546
547template <typename TxopType>
548void
549ChannelAccessManagerTest<TxopType>::NotifyChannelSwitching()
550{
551 for (auto& state : m_txop)
552 {
553 if (!state->m_expectedGrants.empty())
554 {
555 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front();
556 state->m_expectedGrants.pop_front();
558 MicroSeconds(expected.second),
559 "Expected grant is now");
560 }
561 state->Txop::GetLink(0).access = Txop::NOT_REQUESTED;
562 }
563}
564
565template <typename TxopType>
566void
568 uint32_t nSlots,
569 uint32_t from)
570{
571 Ptr<TxopTest<TxopType>> state = m_txop[from];
572 struct TxopTest<TxopType>::ExpectedBackoff col;
573 col.at = time;
574 col.nSlots = nSlots;
575 state->m_expectedInternalCollision.push_back(col);
576}
577
578template <typename TxopType>
579void
580ChannelAccessManagerTest<TxopType>::ExpectBackoff(uint64_t time, uint32_t nSlots, uint32_t from)
581{
582 Ptr<TxopTest<TxopType>> state = m_txop[from];
583 struct TxopTest<TxopType>::ExpectedBackoff backoff;
584 backoff.at = time;
585 backoff.nSlots = nSlots;
586 state->m_expectedBackoff.push_back(backoff);
587}
588
589template <typename TxopType>
590void
591ChannelAccessManagerTest<TxopType>::ExpectBusy(uint64_t time, bool busy)
592{
595 this,
596 busy);
597}
598
599template <typename TxopType>
600void
602{
603 NS_TEST_EXPECT_MSG_EQ(m_ChannelAccessManager->IsBusy(), busy, "Incorrect busy/idle state");
604}
605
606template <typename TxopType>
607void
609 uint64_t sifs,
610 uint64_t eifsNoDifsNoSifs,
611 uint32_t ackTimeoutValue,
612 uint16_t chWidth)
613{
614 m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub>();
615 m_feManager = CreateObject<FrameExchangeManagerStub<TxopType>>(this);
616 m_ChannelAccessManager->SetupFrameExchangeManager(m_feManager);
617 m_ChannelAccessManager->SetSlot(MicroSeconds(slotTime));
618 m_ChannelAccessManager->SetSifs(MicroSeconds(sifs));
619 m_ChannelAccessManager->SetEifsNoDifs(MicroSeconds(eifsNoDifsNoSifs + sifs));
620 m_ackTimeoutValue = ackTimeoutValue;
621 // the purpose of the following operations is to initialize the last busy struct
622 // of the ChannelAccessManager. Indeed, InitLastBusyStructs(), which is called by
623 // SetupPhyListener(), requires an attached PHY to determine the channel types
624 // to initialize
625 m_phy = CreateObject<SpectrumWifiPhy>();
626 m_phy->SetInterferenceHelper(CreateObject<InterferenceHelper>());
627 m_phy->AddChannel(CreateObject<MultiModelSpectrumChannel>());
628 m_phy->SetOperatingChannel(WifiPhy::ChannelTuple{0, chWidth, WIFI_PHY_BAND_UNSPECIFIED, 0});
629 m_phy->ConfigureStandard(WIFI_STANDARD_80211ac); // required to use 160 MHz channels
630 m_ChannelAccessManager->SetupPhyListener(m_phy);
631}
632
633template <typename TxopType>
634void
636{
637 Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>>(this, m_txop.size());
638 m_txop.push_back(txop);
639 m_ChannelAccessManager->Add(txop);
640 // the following causes the creation of a link for the txop object
641 auto mac = CreateObject<AdhocWifiMac>();
642 mac->SetWifiPhys({nullptr});
643 txop->SetWifiMac(mac);
644 txop->SetAifsn(aifsn);
645}
646
647template <typename TxopType>
648void
650{
652
653 for (typename TxopTests::const_iterator i = m_txop.begin(); i != m_txop.end(); i++)
654 {
655 Ptr<TxopTest<TxopType>> state = *i;
656 NS_TEST_EXPECT_MSG_EQ(state->m_expectedGrants.empty(), true, "Have no expected grants");
657 NS_TEST_EXPECT_MSG_EQ(state->m_expectedInternalCollision.empty(),
658 true,
659 "Have no internal collisions");
660 NS_TEST_EXPECT_MSG_EQ(state->m_expectedBackoff.empty(), true, "Have no expected backoffs");
661 state->Dispose();
662 state = nullptr;
663 }
664 m_txop.clear();
665
666 m_ChannelAccessManager->RemovePhyListener(m_phy);
667 m_phy->Dispose();
668 m_ChannelAccessManager->Dispose();
669 m_ChannelAccessManager = nullptr;
670 m_feManager = nullptr;
672}
673
674template <typename TxopType>
675void
677{
680 m_ChannelAccessManager,
681 MicroSeconds(duration));
682 Simulator::Schedule(MicroSeconds(at + duration) - Now(),
684 m_ChannelAccessManager);
685}
686
687template <typename TxopType>
688void
690{
693 m_ChannelAccessManager,
694 MicroSeconds(duration));
695}
696
697template <typename TxopType>
698void
700{
703 m_ChannelAccessManager,
704 MicroSeconds(duration));
705 Simulator::Schedule(MicroSeconds(at + duration) - Now(),
707 m_ChannelAccessManager);
708}
709
710template <typename TxopType>
711void
713 uint64_t duration,
714 uint64_t timeUntilError)
715{
718 m_ChannelAccessManager,
719 MicroSeconds(duration));
720 Simulator::Schedule(MicroSeconds(at + timeUntilError) - Now(),
722 m_ChannelAccessManager);
723 Simulator::Schedule(MicroSeconds(at + timeUntilError) - Now(),
725 m_ChannelAccessManager,
726 MicroSeconds(duration - timeUntilError),
728 std::vector<Time>{});
729}
730
731template <typename TxopType>
732void
734{
737 m_ChannelAccessManager,
738 MicroSeconds(duration));
739}
740
741template <typename TxopType>
742void
744{
747 m_ChannelAccessManager,
748 MicroSeconds(duration));
749}
750
751template <typename TxopType>
752void
754{
757 m_ChannelAccessManager);
758}
759
760template <typename TxopType>
761void
763 uint64_t txTime,
764 uint64_t expectedGrantTime,
765 uint32_t from)
766{
767 AddAccessRequestWithSuccessfulAck(at, txTime, expectedGrantTime, 0, from);
768}
769
770template <typename TxopType>
771void
773 uint64_t txTime,
774 uint64_t expectedGrantTime,
775 uint32_t from)
776{
779 this,
780 txTime,
781 expectedGrantTime,
782 m_txop[from]);
783}
784
785template <typename TxopType>
786void
788 uint64_t txTime,
789 uint64_t expectedGrantTime,
790 uint32_t ackDelay,
791 uint32_t from)
792{
793 NS_ASSERT(ackDelay < m_ackTimeoutValue);
796 this,
797 txTime,
798 expectedGrantTime,
799 m_txop[from]);
800 AddAckTimeoutReset(expectedGrantTime + txTime + ackDelay);
801}
802
803template <typename TxopType>
804void
806 uint64_t expectedGrantTime,
807 Ptr<TxopTest<TxopType>> state)
808{
809 if (m_ChannelAccessManager->NeedBackoffUponAccess(state))
810 {
811 state->GenerateBackoff(0);
812 }
813 state->QueueTx(txTime, expectedGrantTime);
814 m_ChannelAccessManager->RequestAccess(state);
815}
816
817template <typename TxopType>
818void
820 uint64_t duration,
821 WifiChannelListType channelType,
822 const std::vector<Time>& per20MhzDurations)
823{
826 m_ChannelAccessManager,
827 MicroSeconds(duration),
828 channelType,
829 per20MhzDurations);
830}
831
832template <typename TxopType>
833void
835{
838 m_ChannelAccessManager,
839 MicroSeconds(duration));
840}
841
842template <typename TxopType>
843void
845{
848 m_ChannelAccessManager,
849 MicroSeconds(duration));
850}
851
852/*
853 * Specialization of DoRun () method for DCF
854 */
855template <>
856void
858{
859 // DCF immediate access (no backoff)
860 // 1 4 5 6 8 11 12
861 // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
862 //
863 StartTest(1, 3, 10);
864 AddTxop(1);
865 AddAccessRequest(1, 1, 5, 0);
866 AddAccessRequest(8, 2, 12, 0);
867 EndTest();
868 // Check that receiving inside SIFS shall be cancelled properly:
869 // 1 4 5 6 9 10 14 17 18
870 // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
871 // |
872 // 7 start rx
873 //
874
875 StartTest(1, 3, 10);
876 AddTxop(1);
877 AddAccessRequest(1, 1, 5, 0);
878 AddRxInsideSifsEvt(7, 10);
879 AddTxEvt(9, 1);
880 AddAccessRequest(14, 2, 18, 0);
881 EndTest();
882 // The test below mainly intends to test the case where the medium
883 // becomes busy in the middle of a backoff slot: the backoff counter
884 // must not be decremented for this backoff slot. This is the case
885 // below for the backoff slot starting at time 78us.
886 //
887 // 20 60 66 70 74 78 80 100 106 110 114 118
888 // 120
889 // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 |
890 // bslot3 | tx |
891 // |
892 // 30 request access. backoff slots: 4
893
894 StartTest(4, 6, 10);
895 AddTxop(1);
896 AddRxOkEvt(20, 40);
897 AddRxOkEvt(80, 20);
898 AddAccessRequest(30, 2, 118, 0);
899 ExpectBackoff(30, 4, 0); // backoff: 4 slots
900 EndTest();
901 // Test the case where the backoff slots is zero.
902 //
903 // 20 60 66 70 72
904 // | rx | sifs | aifsn | tx |
905 // |
906 // 30 request access. backoff slots: 0
907
908 StartTest(4, 6, 10);
909 AddTxop(1);
910 AddRxOkEvt(20, 40);
911 AddAccessRequest(30, 2, 70, 0);
912 ExpectBackoff(30, 0, 0); // backoff: 0 slots
913 EndTest();
914 // Test shows when two frames are received without interval between
915 // them:
916 // 20 60 100 106 110 112
917 // | rx | rx |sifs | aifsn | tx |
918 // |
919 // 30 request access. backoff slots: 0
920
921 StartTest(4, 6, 10);
922 AddTxop(1);
923 AddRxOkEvt(20, 40);
924 AddRxOkEvt(60, 40);
925 AddAccessRequest(30, 2, 110, 0);
926 ExpectBackoff(30, 0, 0); // backoff: 0 slots
927 EndTest();
928
929 // Requesting access within SIFS interval (DCF immediate access)
930 //
931 // 20 60 62 68 72
932 // | rx | idle | sifs | aifsn | tx |
933 //
934 StartTest(4, 6, 10);
935 AddTxop(1);
936 AddRxOkEvt(20, 40);
937 AddAccessRequest(62, 2, 72, 0);
938 EndTest();
939
940 // Requesting access after DIFS (DCF immediate access)
941 //
942 // 20 60 70 76 80
943 // | rx | idle | sifs | aifsn | tx |
944 //
945 StartTest(4, 6, 10);
946 AddTxop(1);
947 AddRxOkEvt(20, 40);
948 AddAccessRequest(70, 2, 80, 0);
949 EndTest();
950
951 // Test an EIFS
952 //
953 // 20 60 66 76 86 90 94 98 102 106
954 // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
955 // | | <------eifs------>|
956 // 30 request access. backoff slots: 4
957 StartTest(4, 6, 10);
958 AddTxop(1);
959 AddRxErrorEvt(20, 40);
960 AddAccessRequest(30, 2, 102, 0);
961 ExpectBackoff(30, 4, 0); // backoff: 4 slots
962 EndTest();
963
964 // Test DCF immediate access after an EIFS (EIFS is greater)
965 //
966 // 20 60 66 76 86
967 // | <----+-eifs------>|
968 // | rx | sifs | acktxttime | sifs + aifsn | tx |
969 // | sifs + aifsn |
970 // request access 70 80
971 StartTest(4, 6, 10);
972 AddTxop(1);
973 AddRxErrorEvt(20, 40);
974 AddAccessRequest(70, 2, 86, 0);
975 EndTest();
976
977 // Test that channel stays busy for first frame's duration after Rx error
978 //
979 // 20 60
980 // | rx |
981 // |
982 // 40 force Rx error
983 StartTest(4, 6, 10);
984 AddTxop(1);
985 AddRxErrorEvt(20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
986 ExpectBusy(41, true); // channel should remain busy for remaining duration
987 ExpectBusy(59, true);
988 ExpectBusy(61, false);
989 EndTest();
990
991 // Test an EIFS which is interrupted by a successful transmission.
992 //
993 // 20 60 66 69 75 81 85 89 93 97 101 103
994 // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
995 // | | <--eifs-->|
996 // 30 request access. backoff slots: 4
997 StartTest(4, 6, 10);
998 AddTxop(1);
999 AddRxErrorEvt(20, 40);
1000 AddAccessRequest(30, 2, 101, 0);
1001 ExpectBackoff(30, 4, 0); // backoff: 4 slots
1002 AddRxOkEvt(69, 6);
1003 EndTest();
1004
1005 // Test two DCFs which suffer an internal collision. the first DCF has a higher
1006 // priority than the second DCF.
1007 //
1008 // 20 60 66 70 74 78 88
1009 // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
1010 // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn |
1011 // bslot | tx |
1012 // 94 98 102 106
1013 // 110 112
1014 StartTest(4, 6, 10);
1015 AddTxop(1); // high priority DCF
1016 AddTxop(3); // low priority DCF
1017 AddRxOkEvt(20, 40);
1018 AddAccessRequest(30, 10, 78, 0);
1019 ExpectBackoff(30, 2, 0); // backoff: 2 slot
1020 AddAccessRequest(40, 2, 110, 1);
1021 ExpectBackoff(40, 0, 1); // backoff: 0 slot
1022 ExpectInternalCollision(78, 1, 1); // backoff: 1 slot
1023 EndTest();
1024
1025 // Test of AckTimeout handling: First queue requests access and ack procedure fails,
1026 // inside the Ack timeout second queue with higher priority requests access.
1027 //
1028 // 20 26 34 54 74 80
1029 // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
1030 // DCF0 - high | | | sifs | tx |
1031 // ^ request access
1032 StartTest(4, 6, 10);
1033 AddTxop(0); // high priority DCF
1034 AddTxop(2); // low priority DCF
1035 AddAccessRequestWithAckTimeout(20, 20, 34, 1);
1036 AddAccessRequest(64, 10, 80, 0);
1037 EndTest();
1038
1039 // Test of AckTimeout handling:
1040 //
1041 // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
1042 // inside this interval second queue with higher priority requests access.
1043 //
1044 // 20 26 34 54 56 62
1045 // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
1046 // DCF0 - high | | | sifs | tx |
1047 // ^ request access
1048 StartTest(4, 6, 10);
1049 AddTxop(0); // high priority DCF
1050 AddTxop(2); // low priority DCF
1051 AddAccessRequestWithSuccessfulAck(20, 20, 34, 2, 1);
1052 AddAccessRequest(55, 10, 62, 0);
1053 EndTest();
1054
1055 // Repeat the same but with one queue:
1056 // 20 26 34 54 60 62 68 76 80
1057 // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
1058 // ^ request access
1059 StartTest(4, 6, 10);
1060 AddTxop(2);
1061 AddAccessRequest(20, 20, 34, 0);
1062 AddRxOkEvt(60, 2); // Ack
1063 AddAccessRequest(61, 10, 80, 0);
1064 ExpectBackoff(61, 1, 0); // 1 slot
1065 EndTest();
1066
1067 // test simple NAV count. This scenario models a simple Data+Ack handshake
1068 // where the data rate used for the Ack is higher than expected by the Data source
1069 // so, the data exchange completes before the end of NAV.
1070 StartTest(4, 6, 10);
1071 AddTxop(1);
1072 AddRxOkEvt(20, 40);
1073 AddNavStart(60, 15);
1074 AddRxOkEvt(66, 5);
1075 AddNavStart(71, 0);
1076 AddAccessRequest(30, 10, 93, 0);
1077 ExpectBackoff(30, 2, 0); // backoff: 2 slots
1078 EndTest();
1079
1080 // test more complex NAV handling by a CF-poll. This scenario models a
1081 // simple Data+Ack handshake interrupted by a CF-poll which resets the
1082 // NAV counter.
1083 StartTest(4, 6, 10);
1084 AddTxop(1);
1085 AddRxOkEvt(20, 40);
1086 AddNavStart(60, 15);
1087 AddRxOkEvt(66, 5);
1088 AddNavReset(71, 2);
1089 AddAccessRequest(30, 10, 91, 0);
1090 ExpectBackoff(30, 2, 0); // backoff: 2 slots
1091 EndTest();
1092
1093 // 20 60 80 86 94
1094 // | rx | idle | sifs | aifsn | tx |
1095 // ^ request access
1096 StartTest(4, 6, 10);
1097 AddTxop(2);
1098 AddRxOkEvt(20, 40);
1099 AddAccessRequest(80, 10, 94, 0);
1100 EndTest();
1101
1102 StartTest(4, 6, 10);
1103 AddTxop(2);
1104 AddRxOkEvt(20, 40);
1105 AddRxOkEvt(78, 8);
1106 AddAccessRequest(30, 50, 108, 0);
1107 ExpectBackoff(30, 3, 0); // backoff: 3 slots
1108 EndTest();
1109
1110 // Channel switching tests
1111
1112 // 0 20 21 24 25 26
1113 // | switching | idle | sifs | aifsn | tx |
1114 // ^ access request.
1115 StartTest(1, 3, 10);
1116 AddTxop(1);
1117 AddSwitchingEvt(0, 20);
1118 AddAccessRequest(21, 1, 25, 0);
1119 EndTest();
1120
1121 // 20 40 50 53 54 55 56 57
1122 // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
1123 // | |
1124 // 30 busy. 45 access request.
1125 //
1126 StartTest(1, 3, 10);
1127 AddTxop(1);
1128 AddSwitchingEvt(20, 20);
1129 AddCcaBusyEvt(30, 20);
1130 ExpectBackoff(45, 2, 0); // backoff: 2 slots
1131 AddAccessRequest(45, 1, 56, 0);
1132 EndTest();
1133
1134 // 20 30 50 51 54 55 56
1135 // | rx | switching | idle | sifs | aifsn | tx |
1136 // ^ access request.
1137 //
1138 StartTest(1, 3, 10);
1139 AddTxop(1);
1140 AddRxStartEvt(20, 40);
1141 AddSwitchingEvt(30, 20);
1142 AddAccessRequest(51, 1, 55, 0);
1143 EndTest();
1144
1145 // 20 30 50 51 54 55 56
1146 // | busy | switching | idle | sifs | aifsn | tx |
1147 // ^ access request.
1148 //
1149 StartTest(1, 3, 10);
1150 AddTxop(1);
1151 AddCcaBusyEvt(20, 40);
1152 AddSwitchingEvt(30, 20);
1153 AddAccessRequest(51, 1, 55, 0);
1154 EndTest();
1155
1156 // 20 30 50 51 54 55 56
1157 // | nav | switching | idle | sifs | aifsn | tx |
1158 // ^ access request.
1159 //
1160 StartTest(1, 3, 10);
1161 AddTxop(1);
1162 AddNavStart(20, 40);
1163 AddSwitchingEvt(30, 20);
1164 AddAccessRequest(51, 1, 55, 0);
1165 EndTest();
1166
1167 // 20 23 24 44 54 59 60 63 64 65
1168 // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1169 // | |
1170 // 49 access request. ^ access request.
1171 //
1172 StartTest(1, 3, 10);
1173 AddTxop(1);
1174 AddAccessRequestWithAckTimeout(20, 20, 24, 0);
1175 AddAccessRequest(49, 1, 54, 0);
1176 AddSwitchingEvt(54, 5);
1177 AddAccessRequest(60, 1, 64, 0);
1178 EndTest();
1179
1180 // 20 60 66 70 74 78 80 100 101 107 111 113
1181 // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1182 // | |
1183 // 30 access request. ^ access request.
1184 //
1185 StartTest(4, 6, 10);
1186 AddTxop(1);
1187 AddRxOkEvt(20, 40);
1188 AddAccessRequest(30, 2, 80, 0);
1189 ExpectBackoff(30, 4, 0); // backoff: 4 slots
1190 AddSwitchingEvt(80, 20);
1191 AddAccessRequest(101, 2, 111, 0);
1192 EndTest();
1193}
1194
1195/*
1196 * Specialization of DoRun () method for EDCA
1197 */
1198template <>
1199void
1201{
1202 // Check alignment at slot boundary after successful reception (backoff = 0).
1203 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1204 // 20 50 56 60 80
1205 // | cca_busy |
1206 // | rx | sifs | aifsn | tx |
1207 // |
1208 // 52 request access
1209 StartTest(4, 6, 10, 20, 40);
1210 AddTxop(1);
1211 AddRxOkEvt(20, 30);
1212 AddCcaBusyEvt(50, 10, WIFI_CHANLIST_SECONDARY);
1213 AddAccessRequest(52, 20, 60, 0);
1214 EndTest();
1215
1216 // Check alignment at slot boundary after successful reception (backoff = 0).
1217 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1218 // 20 50 56 60 80
1219 // | cca_busy |
1220 // | rx | sifs | aifsn | tx |
1221 // |
1222 // 58 request access
1223 StartTest(4, 6, 10, 20, 80);
1224 AddTxop(1);
1225 AddRxOkEvt(20, 30);
1226 AddCcaBusyEvt(50, 10, WIFI_CHANLIST_SECONDARY);
1227 AddAccessRequest(58, 20, 60, 0);
1228 EndTest();
1229
1230 // Check alignment at slot boundary after successful reception (backoff = 0).
1231 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1232 // 20 50 56 60 64 84
1233 // | cca_busy |
1234 // | rx | sifs | aifsn | idle | tx |
1235 // |
1236 // 62 request access
1237 StartTest(4, 6, 10, 20, 80);
1238 AddTxop(1);
1239 AddRxOkEvt(20, 30);
1240 AddCcaBusyEvt(50, 14, WIFI_CHANLIST_SECONDARY40);
1241 AddAccessRequest(62, 20, 64, 0);
1242 EndTest();
1243
1244 // Check alignment at slot boundary after failed reception (backoff = 0).
1245 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1246 // 20 50 56 66 76 96
1247 // | cca_busy |
1248 // | | <------eifs------>| | |
1249 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1250 // |
1251 // 55 request access
1252 StartTest(4, 6, 10, 20, 160);
1253 AddTxop(1);
1254 AddRxErrorEvt(20, 30);
1255 AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY);
1256 AddAccessRequest(55, 20, 76, 0);
1257 EndTest();
1258
1259 // Check alignment at slot boundary after failed reception (backoff = 0).
1260 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1261 // 20 50 56 66 76 96
1262 // | cca_busy |
1263 // | | <------eifs------>| | |
1264 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1265 // |
1266 // 70 request access
1267 StartTest(4, 6, 10, 20, 160);
1268 AddTxop(1);
1269 AddRxErrorEvt(20, 30);
1270 AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY40);
1271 AddAccessRequest(70, 20, 76, 0);
1272 EndTest();
1273
1274 // Check alignment at slot boundary after failed reception (backoff = 0).
1275 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1276 // 20 50 56 66 76 84
1277 // | cca_busy |
1278 // | | <------eifs------>| | |
1279 // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1280 // |
1281 // 82 request access
1282 StartTest(4, 6, 10, 20, 160);
1283 AddTxop(1);
1284 AddRxErrorEvt(20, 30);
1285 AddCcaBusyEvt(50, 34, WIFI_CHANLIST_SECONDARY80);
1286 AddAccessRequest(82, 20, 84, 0);
1287 EndTest();
1288
1289 // Check backoff decrement at slot boundaries. Medium idle during backoff
1290 // 20 50 56 60 64 68 72 76 96
1291 // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1292 // | | | | |
1293 // 30 request access. decrement decrement decrement decrement
1294 // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1295 StartTest(4, 6, 10);
1296 AddTxop(1);
1297 AddRxOkEvt(20, 30);
1298 AddAccessRequest(30, 20, 76, 0);
1299 ExpectBackoff(30, 4, 0);
1300 EndTest();
1301
1302 // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1303 // 20 50 56 60 61 71 77 81 85 87 97 103
1304 // 107 127
1305 // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs |
1306 // aifsn | tx |
1307 // | | | |
1308 // 30 request access. decrement decrement decrement
1309 // backoff slots: 3 slots: 2 slots: 1 slots: 0
1310 StartTest(4, 6, 10);
1311 AddTxop(1);
1312 AddRxOkEvt(20, 30);
1313 AddRxOkEvt(61, 10);
1314 AddRxOkEvt(87, 10);
1315 AddAccessRequest(30, 20, 107, 0);
1316 ExpectBackoff(30, 3, 0);
1317 EndTest();
1318}
1319
1333{
1334 public:
1337
1338 private:
1339 void DoRun() override;
1340
1347 void RunOne(uint16_t chWidth, WifiChannelListType busyChannel);
1348
1351};
1352
1354 : TestCase("Check calculation of the largest idle primary channel")
1355{
1356}
1357
1358void
1360{
1379 Time start = Simulator::Now();
1380
1381 // After 1ms, we are notified of CCA_BUSY for 1ms on the given channel
1382 Time ccaBusyStartDelay = MilliSeconds(1);
1383 Time ccaBusyDuration = MilliSeconds(1);
1384 Simulator::Schedule(ccaBusyStartDelay,
1386 m_cam,
1387 ccaBusyDuration,
1388 busyChannel,
1389 std::vector<Time>(chWidth == 20 ? 0 : chWidth / 20, Seconds(0)));
1390
1391 // During any interval ending within CCA_BUSY period, the idle channel is the
1392 // primary channel contiguous to the busy secondary channel, if the busy channel
1393 // is a secondary channel, or there is no idle channel, otherwise.
1394 uint16_t idleWidth = (busyChannel == WifiChannelListType::WIFI_CHANLIST_PRIMARY)
1395 ? 0
1396 : ((1 << (busyChannel - 1)) * 20);
1397
1398 Time checkTime1 = start + ccaBusyStartDelay + ccaBusyDuration / 2;
1399 Simulator::Schedule(checkTime1 - start, [=]() {
1400 Time interval1 = (ccaBusyStartDelay + ccaBusyDuration) / 2;
1402 idleWidth,
1403 "Incorrect width of the idle channel in an interval "
1404 << "ending within CCA_BUSY (channel width: " << chWidth
1405 << " MHz, busy channel: " << busyChannel << ")");
1406 });
1407
1408 // During any interval starting within CCA_BUSY period, the idle channel is the
1409 // same as the previous case
1410 Time ccaBusyRxInterval = MilliSeconds(1);
1411 Time checkTime2 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval / 2;
1412 Simulator::Schedule(checkTime2 - start, [=]() {
1413 Time interval2 = (ccaBusyDuration + ccaBusyRxInterval) / 2;
1415 idleWidth,
1416 "Incorrect width of the idle channel in an interval "
1417 << "starting within CCA_BUSY (channel width: " << chWidth
1418 << " MHz, busy channel: " << busyChannel << ")");
1419 });
1420
1421 // Notify RX start
1422 Time rxDuration = MilliSeconds(1);
1423 Simulator::Schedule(ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval,
1425 m_cam,
1426 rxDuration);
1427
1428 // At RX end, we check the status of the channel during an interval immediately
1429 // preceding RX start and overlapping the CCA_BUSY period.
1430 Time checkTime3 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval + rxDuration;
1431 Simulator::Schedule(checkTime3 - start, [=]() {
1432 Time interval3 = ccaBusyDuration / 2 + ccaBusyRxInterval;
1433 Time end3 = checkTime3 - rxDuration;
1435 idleWidth,
1436 "Incorrect width of the idle channel in an interval "
1437 << "preceding RX start and overlapping CCA_BUSY "
1438 << "(channel width: " << chWidth
1439 << " MHz, busy channel: " << busyChannel << ")");
1440 });
1441
1442 // At RX end, we check the status of the channel during the interval following
1443 // the CCA_BUSY period and preceding RX start. The entire operating channel is idle.
1444 const Time& checkTime4 = checkTime3;
1445 Simulator::Schedule(checkTime4 - start, [=]() {
1446 const Time& interval4 = ccaBusyRxInterval;
1447 Time end4 = checkTime4 - rxDuration;
1449 chWidth,
1450 "Incorrect width of the idle channel in the interval "
1451 << "following CCA_BUSY and preceding RX start (channel "
1452 << "width: " << chWidth << " MHz, busy channel: " << busyChannel
1453 << ")");
1454 });
1455
1456 // After RX end, the entire operating channel is idle if the interval does not
1457 // overlap the RX period
1458 Time interval5 = MilliSeconds(1);
1459 Time checkTime5 = checkTime4 + interval5;
1460 Simulator::Schedule(checkTime5 - start, [=]() {
1462 chWidth,
1463 "Incorrect width of the idle channel in an interval "
1464 << "following RX end (channel width: " << chWidth
1465 << " MHz, busy channel: " << busyChannel << ")");
1466 });
1467
1468 // After RX end, no channel is idle if the interval overlaps the RX period
1469 const Time& checkTime6 = checkTime5;
1470 Simulator::Schedule(checkTime6 - start, [=]() {
1471 Time interval6 = interval5 + rxDuration / 2;
1473 0,
1474 "Incorrect width of the idle channel in an interval "
1475 << "overlapping RX (channel width: " << chWidth
1476 << " MHz, busy channel: " << busyChannel << ")");
1477 });
1478}
1479
1480void
1482{
1483 m_cam = CreateObject<ChannelAccessManager>();
1484 uint16_t delay = 0;
1485 uint8_t channel = 0;
1486 std::list<WifiChannelListType> busyChannels;
1487
1488 for (uint16_t chWidth : {20, 40, 80, 160})
1489 {
1490 busyChannels.push_back(static_cast<WifiChannelListType>(channel));
1491
1492 for (const auto busyChannel : busyChannels)
1493 {
1494 Simulator::Schedule(Seconds(delay), [this, chWidth, busyChannel]() {
1495 // reset PHY
1496 if (m_phy)
1497 {
1499 m_phy->Dispose();
1500 }
1501 // create a new PHY operating on a channel of the current width
1502 m_phy = CreateObject<SpectrumWifiPhy>();
1503 m_phy->SetInterferenceHelper(CreateObject<InterferenceHelper>());
1504 m_phy->AddChannel(CreateObject<MultiModelSpectrumChannel>());
1508 // call SetupPhyListener to initialize the ChannelAccessManager
1509 // last busy structs
1511 // run the tests
1512 RunOne(chWidth, busyChannel);
1513 });
1514 delay++;
1515 }
1516 channel++;
1517 }
1518
1521 m_phy->Dispose();
1522 m_cam->Dispose();
1524}
1525
1533{
1534 public:
1535 TxopTestSuite();
1536};
1537
1539 : TestSuite("wifi-devices-dcf", UNIT)
1540{
1542}
1543
1545
1553{
1554 public:
1556};
1557
1559 : TestSuite("wifi-devices-edca", UNIT)
1560{
1562}
1563
1565
1573{
1574 public:
1576};
1577
1579 : TestSuite("wifi-channel-access-manager", UNIT)
1580{
1582}
1583
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 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.
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.
Ptr< SpectrumWifiPhy > m_phy
the PHY object
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.
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 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...
Ptr< SpectrumWifiPhy > m_phy
PHY object.
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
std::list< ExpectedBackoff > ExpectedBackoffs
expected backoffs typedef
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
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.
Definition: object.cc:219
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:568
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:140
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:199
static void Run()
Run the simulation.
Definition: simulator.cc:176
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
Attach a SpectrumChannel to use for a given frequency range.
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
@ NOT_REQUESTED
Definition: txop.h:100
LinkEntity & GetLink(uint8_t linkId) const
Get a reference to the link associated with the given ID.
Definition: txop.cc:170
virtual void SetInterferenceHelper(const Ptr< InterferenceHelper > helper)
Sets the interference helper.
Definition: wifi-phy.cc:633
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:950
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:1082
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:872
#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:1360
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
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
-ns3 Test suite for the ns3 wrapper script