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 (auto 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 nullptr,
840 MicroSeconds(duration));
841}
842
843template <typename TxopType>
844void
846{
849 m_ChannelAccessManager,
850 MicroSeconds(duration));
851}
852
853/*
854 * Specialization of DoRun () method for DCF
855 */
856template <>
857void
859{
860 // DCF immediate access (no backoff)
861 // 1 4 5 6 8 11 12
862 // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
863 //
864 StartTest(1, 3, 10);
865 AddTxop(1);
866 AddAccessRequest(1, 1, 5, 0);
867 AddAccessRequest(8, 2, 12, 0);
868 EndTest();
869 // Check that receiving inside SIFS shall be cancelled properly:
870 // 1 4 5 6 9 10 14 17 18
871 // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
872 // |
873 // 7 start rx
874 //
875
876 StartTest(1, 3, 10);
877 AddTxop(1);
878 AddAccessRequest(1, 1, 5, 0);
879 AddRxInsideSifsEvt(7, 10);
880 AddTxEvt(9, 1);
881 AddAccessRequest(14, 2, 18, 0);
882 EndTest();
883 // The test below mainly intends to test the case where the medium
884 // becomes busy in the middle of a backoff slot: the backoff counter
885 // must not be decremented for this backoff slot. This is the case
886 // below for the backoff slot starting at time 78us.
887 //
888 // 20 60 66 70 74 78 80 100 106 110 114 118
889 // 120
890 // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 |
891 // bslot3 | tx |
892 // |
893 // 30 request access. backoff slots: 4
894
895 StartTest(4, 6, 10);
896 AddTxop(1);
897 AddRxOkEvt(20, 40);
898 AddRxOkEvt(80, 20);
899 AddAccessRequest(30, 2, 118, 0);
900 ExpectBackoff(30, 4, 0); // backoff: 4 slots
901 EndTest();
902 // Test the case where the backoff slots is zero.
903 //
904 // 20 60 66 70 72
905 // | rx | sifs | aifsn | tx |
906 // |
907 // 30 request access. backoff slots: 0
908
909 StartTest(4, 6, 10);
910 AddTxop(1);
911 AddRxOkEvt(20, 40);
912 AddAccessRequest(30, 2, 70, 0);
913 ExpectBackoff(30, 0, 0); // backoff: 0 slots
914 EndTest();
915 // Test shows when two frames are received without interval between
916 // them:
917 // 20 60 100 106 110 112
918 // | rx | rx |sifs | aifsn | tx |
919 // |
920 // 30 request access. backoff slots: 0
921
922 StartTest(4, 6, 10);
923 AddTxop(1);
924 AddRxOkEvt(20, 40);
925 AddRxOkEvt(60, 40);
926 AddAccessRequest(30, 2, 110, 0);
927 ExpectBackoff(30, 0, 0); // backoff: 0 slots
928 EndTest();
929
930 // Requesting access within SIFS interval (DCF immediate access)
931 //
932 // 20 60 62 68 72
933 // | rx | idle | sifs | aifsn | tx |
934 //
935 StartTest(4, 6, 10);
936 AddTxop(1);
937 AddRxOkEvt(20, 40);
938 AddAccessRequest(62, 2, 72, 0);
939 EndTest();
940
941 // Requesting access after DIFS (DCF immediate access)
942 //
943 // 20 60 70 76 80
944 // | rx | idle | sifs | aifsn | tx |
945 //
946 StartTest(4, 6, 10);
947 AddTxop(1);
948 AddRxOkEvt(20, 40);
949 AddAccessRequest(70, 2, 80, 0);
950 EndTest();
951
952 // Test an EIFS
953 //
954 // 20 60 66 76 86 90 94 98 102 106
955 // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
956 // | | <------eifs------>|
957 // 30 request access. backoff slots: 4
958 StartTest(4, 6, 10);
959 AddTxop(1);
960 AddRxErrorEvt(20, 40);
961 AddAccessRequest(30, 2, 102, 0);
962 ExpectBackoff(30, 4, 0); // backoff: 4 slots
963 EndTest();
964
965 // Test DCF immediate access after an EIFS (EIFS is greater)
966 //
967 // 20 60 66 76 86
968 // | <----+-eifs------>|
969 // | rx | sifs | acktxttime | sifs + aifsn | tx |
970 // | sifs + aifsn |
971 // request access 70 80
972 StartTest(4, 6, 10);
973 AddTxop(1);
974 AddRxErrorEvt(20, 40);
975 AddAccessRequest(70, 2, 86, 0);
976 EndTest();
977
978 // Test that channel stays busy for first frame's duration after Rx error
979 //
980 // 20 60
981 // | rx |
982 // |
983 // 40 force Rx error
984 StartTest(4, 6, 10);
985 AddTxop(1);
986 AddRxErrorEvt(20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
987 ExpectBusy(41, true); // channel should remain busy for remaining duration
988 ExpectBusy(59, true);
989 ExpectBusy(61, false);
990 EndTest();
991
992 // Test an EIFS which is interrupted by a successful transmission.
993 //
994 // 20 60 66 69 75 81 85 89 93 97 101 103
995 // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
996 // | | <--eifs-->|
997 // 30 request access. backoff slots: 4
998 StartTest(4, 6, 10);
999 AddTxop(1);
1000 AddRxErrorEvt(20, 40);
1001 AddAccessRequest(30, 2, 101, 0);
1002 ExpectBackoff(30, 4, 0); // backoff: 4 slots
1003 AddRxOkEvt(69, 6);
1004 EndTest();
1005
1006 // Test two DCFs which suffer an internal collision. the first DCF has a higher
1007 // priority than the second DCF.
1008 //
1009 // 20 60 66 70 74 78 88
1010 // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
1011 // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn |
1012 // bslot | tx |
1013 // 94 98 102 106
1014 // 110 112
1015 StartTest(4, 6, 10);
1016 AddTxop(1); // high priority DCF
1017 AddTxop(3); // low priority DCF
1018 AddRxOkEvt(20, 40);
1019 AddAccessRequest(30, 10, 78, 0);
1020 ExpectBackoff(30, 2, 0); // backoff: 2 slot
1021 AddAccessRequest(40, 2, 110, 1);
1022 ExpectBackoff(40, 0, 1); // backoff: 0 slot
1023 ExpectInternalCollision(78, 1, 1); // backoff: 1 slot
1024 EndTest();
1025
1026 // Test of AckTimeout handling: First queue requests access and ack procedure fails,
1027 // inside the Ack timeout second queue with higher priority requests access.
1028 //
1029 // 20 26 34 54 74 80
1030 // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
1031 // DCF0 - high | | | sifs | tx |
1032 // ^ request access
1033 StartTest(4, 6, 10);
1034 AddTxop(0); // high priority DCF
1035 AddTxop(2); // low priority DCF
1036 AddAccessRequestWithAckTimeout(20, 20, 34, 1);
1037 AddAccessRequest(64, 10, 80, 0);
1038 EndTest();
1039
1040 // Test of AckTimeout handling:
1041 //
1042 // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
1043 // inside this interval second queue with higher priority requests access.
1044 //
1045 // 20 26 34 54 56 62
1046 // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
1047 // DCF0 - high | | | sifs | tx |
1048 // ^ request access
1049 StartTest(4, 6, 10);
1050 AddTxop(0); // high priority DCF
1051 AddTxop(2); // low priority DCF
1052 AddAccessRequestWithSuccessfulAck(20, 20, 34, 2, 1);
1053 AddAccessRequest(55, 10, 62, 0);
1054 EndTest();
1055
1056 // Repeat the same but with one queue:
1057 // 20 26 34 54 60 62 68 76 80
1058 // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
1059 // ^ request access
1060 StartTest(4, 6, 10);
1061 AddTxop(2);
1062 AddAccessRequest(20, 20, 34, 0);
1063 AddRxOkEvt(60, 2); // Ack
1064 AddAccessRequest(61, 10, 80, 0);
1065 ExpectBackoff(61, 1, 0); // 1 slot
1066 EndTest();
1067
1068 // test simple NAV count. This scenario models a simple Data+Ack handshake
1069 // where the data rate used for the Ack is higher than expected by the Data source
1070 // so, the data exchange completes before the end of NAV.
1071 StartTest(4, 6, 10);
1072 AddTxop(1);
1073 AddRxOkEvt(20, 40);
1074 AddNavStart(60, 15);
1075 AddRxOkEvt(66, 5);
1076 AddNavStart(71, 0);
1077 AddAccessRequest(30, 10, 93, 0);
1078 ExpectBackoff(30, 2, 0); // backoff: 2 slots
1079 EndTest();
1080
1081 // test more complex NAV handling by a CF-poll. This scenario models a
1082 // simple Data+Ack handshake interrupted by a CF-poll which resets the
1083 // NAV counter.
1084 StartTest(4, 6, 10);
1085 AddTxop(1);
1086 AddRxOkEvt(20, 40);
1087 AddNavStart(60, 15);
1088 AddRxOkEvt(66, 5);
1089 AddNavReset(71, 2);
1090 AddAccessRequest(30, 10, 91, 0);
1091 ExpectBackoff(30, 2, 0); // backoff: 2 slots
1092 EndTest();
1093
1094 // 20 60 80 86 94
1095 // | rx | idle | sifs | aifsn | tx |
1096 // ^ request access
1097 StartTest(4, 6, 10);
1098 AddTxop(2);
1099 AddRxOkEvt(20, 40);
1100 AddAccessRequest(80, 10, 94, 0);
1101 EndTest();
1102
1103 StartTest(4, 6, 10);
1104 AddTxop(2);
1105 AddRxOkEvt(20, 40);
1106 AddRxOkEvt(78, 8);
1107 AddAccessRequest(30, 50, 108, 0);
1108 ExpectBackoff(30, 3, 0); // backoff: 3 slots
1109 EndTest();
1110
1111 // Channel switching tests
1112
1113 // 0 20 21 24 25 26
1114 // | switching | idle | sifs | aifsn | tx |
1115 // ^ access request.
1116 StartTest(1, 3, 10);
1117 AddTxop(1);
1118 AddSwitchingEvt(0, 20);
1119 AddAccessRequest(21, 1, 25, 0);
1120 EndTest();
1121
1122 // 20 40 50 53 54 55 56 57
1123 // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
1124 // | |
1125 // 30 busy. 45 access request.
1126 //
1127 StartTest(1, 3, 10);
1128 AddTxop(1);
1129 AddSwitchingEvt(20, 20);
1130 AddCcaBusyEvt(30, 20);
1131 ExpectBackoff(45, 2, 0); // backoff: 2 slots
1132 AddAccessRequest(45, 1, 56, 0);
1133 EndTest();
1134
1135 // 20 30 50 51 54 55 56
1136 // | rx | switching | idle | sifs | aifsn | tx |
1137 // ^ access request.
1138 //
1139 StartTest(1, 3, 10);
1140 AddTxop(1);
1141 AddRxStartEvt(20, 40);
1142 AddSwitchingEvt(30, 20);
1143 AddAccessRequest(51, 1, 55, 0);
1144 EndTest();
1145
1146 // 20 30 50 51 54 55 56
1147 // | busy | switching | idle | sifs | aifsn | tx |
1148 // ^ access request.
1149 //
1150 StartTest(1, 3, 10);
1151 AddTxop(1);
1152 AddCcaBusyEvt(20, 40);
1153 AddSwitchingEvt(30, 20);
1154 AddAccessRequest(51, 1, 55, 0);
1155 EndTest();
1156
1157 // 20 30 50 51 54 55 56
1158 // | nav | switching | idle | sifs | aifsn | tx |
1159 // ^ access request.
1160 //
1161 StartTest(1, 3, 10);
1162 AddTxop(1);
1163 AddNavStart(20, 40);
1164 AddSwitchingEvt(30, 20);
1165 AddAccessRequest(51, 1, 55, 0);
1166 EndTest();
1167
1168 // 20 23 24 44 54 59 60 63 64 65
1169 // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1170 // | |
1171 // 49 access request. ^ access request.
1172 //
1173 StartTest(1, 3, 10);
1174 AddTxop(1);
1175 AddAccessRequestWithAckTimeout(20, 20, 24, 0);
1176 AddAccessRequest(49, 1, 54, 0);
1177 AddSwitchingEvt(54, 5);
1178 AddAccessRequest(60, 1, 64, 0);
1179 EndTest();
1180
1181 // 20 60 66 70 74 78 80 100 101 107 111 113
1182 // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1183 // | |
1184 // 30 access request. ^ access request.
1185 //
1186 StartTest(4, 6, 10);
1187 AddTxop(1);
1188 AddRxOkEvt(20, 40);
1189 AddAccessRequest(30, 2, 80, 0);
1190 ExpectBackoff(30, 4, 0); // backoff: 4 slots
1191 AddSwitchingEvt(80, 20);
1192 AddAccessRequest(101, 2, 111, 0);
1193 EndTest();
1194}
1195
1196/*
1197 * Specialization of DoRun () method for EDCA
1198 */
1199template <>
1200void
1202{
1203 // Check alignment at slot boundary after successful reception (backoff = 0).
1204 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1205 // 20 50 56 60 80
1206 // | cca_busy |
1207 // | rx | sifs | aifsn | tx |
1208 // |
1209 // 52 request access
1210 StartTest(4, 6, 10, 20, 40);
1211 AddTxop(1);
1212 AddRxOkEvt(20, 30);
1213 AddCcaBusyEvt(50, 10, WIFI_CHANLIST_SECONDARY);
1214 AddAccessRequest(52, 20, 60, 0);
1215 EndTest();
1216
1217 // Check alignment at slot boundary after successful reception (backoff = 0).
1218 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1219 // 20 50 56 60 80
1220 // | cca_busy |
1221 // | rx | sifs | aifsn | tx |
1222 // |
1223 // 58 request access
1224 StartTest(4, 6, 10, 20, 80);
1225 AddTxop(1);
1226 AddRxOkEvt(20, 30);
1227 AddCcaBusyEvt(50, 10, WIFI_CHANLIST_SECONDARY);
1228 AddAccessRequest(58, 20, 60, 0);
1229 EndTest();
1230
1231 // Check alignment at slot boundary after successful reception (backoff = 0).
1232 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1233 // 20 50 56 60 64 84
1234 // | cca_busy |
1235 // | rx | sifs | aifsn | idle | tx |
1236 // |
1237 // 62 request access
1238 StartTest(4, 6, 10, 20, 80);
1239 AddTxop(1);
1240 AddRxOkEvt(20, 30);
1241 AddCcaBusyEvt(50, 14, WIFI_CHANLIST_SECONDARY40);
1242 AddAccessRequest(62, 20, 64, 0);
1243 EndTest();
1244
1245 // Check alignment at slot boundary after failed reception (backoff = 0).
1246 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1247 // 20 50 56 66 76 96
1248 // | cca_busy |
1249 // | | <------eifs------>| | |
1250 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1251 // |
1252 // 55 request access
1253 StartTest(4, 6, 10, 20, 160);
1254 AddTxop(1);
1255 AddRxErrorEvt(20, 30);
1256 AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY);
1257 AddAccessRequest(55, 20, 76, 0);
1258 EndTest();
1259
1260 // Check alignment at slot boundary after failed reception (backoff = 0).
1261 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1262 // 20 50 56 66 76 96
1263 // | cca_busy |
1264 // | | <------eifs------>| | |
1265 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1266 // |
1267 // 70 request access
1268 StartTest(4, 6, 10, 20, 160);
1269 AddTxop(1);
1270 AddRxErrorEvt(20, 30);
1271 AddCcaBusyEvt(50, 26, WIFI_CHANLIST_SECONDARY40);
1272 AddAccessRequest(70, 20, 76, 0);
1273 EndTest();
1274
1275 // Check alignment at slot boundary after failed reception (backoff = 0).
1276 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1277 // 20 50 56 66 76 84
1278 // | cca_busy |
1279 // | | <------eifs------>| | |
1280 // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1281 // |
1282 // 82 request access
1283 StartTest(4, 6, 10, 20, 160);
1284 AddTxop(1);
1285 AddRxErrorEvt(20, 30);
1286 AddCcaBusyEvt(50, 34, WIFI_CHANLIST_SECONDARY80);
1287 AddAccessRequest(82, 20, 84, 0);
1288 EndTest();
1289
1290 // Check backoff decrement at slot boundaries. Medium idle during backoff
1291 // 20 50 56 60 64 68 72 76 96
1292 // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1293 // | | | | |
1294 // 30 request access. decrement decrement decrement decrement
1295 // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1296 StartTest(4, 6, 10);
1297 AddTxop(1);
1298 AddRxOkEvt(20, 30);
1299 AddAccessRequest(30, 20, 76, 0);
1300 ExpectBackoff(30, 4, 0);
1301 EndTest();
1302
1303 // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1304 // 20 50 56 60 61 71 77 81 85 87 97 103
1305 // 107 127
1306 // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs |
1307 // aifsn | tx |
1308 // | | | |
1309 // 30 request access. decrement decrement decrement
1310 // backoff slots: 3 slots: 2 slots: 1 slots: 0
1311 StartTest(4, 6, 10);
1312 AddTxop(1);
1313 AddRxOkEvt(20, 30);
1314 AddRxOkEvt(61, 10);
1315 AddRxOkEvt(87, 10);
1316 AddAccessRequest(30, 20, 107, 0);
1317 ExpectBackoff(30, 3, 0);
1318 EndTest();
1319}
1320
1334{
1335 public:
1338
1339 private:
1340 void DoRun() override;
1341
1348 void RunOne(uint16_t chWidth, WifiChannelListType busyChannel);
1349
1352};
1353
1355 : TestCase("Check calculation of the largest idle primary channel")
1356{
1357}
1358
1359void
1361{
1380 Time start = Simulator::Now();
1381
1382 // After 1ms, we are notified of CCA_BUSY for 1ms on the given channel
1383 Time ccaBusyStartDelay = MilliSeconds(1);
1384 Time ccaBusyDuration = MilliSeconds(1);
1385 Simulator::Schedule(ccaBusyStartDelay,
1387 m_cam,
1388 ccaBusyDuration,
1389 busyChannel,
1390 std::vector<Time>(chWidth == 20 ? 0 : chWidth / 20, Seconds(0)));
1391
1392 // During any interval ending within CCA_BUSY period, the idle channel is the
1393 // primary channel contiguous to the busy secondary channel, if the busy channel
1394 // is a secondary channel, or there is no idle channel, otherwise.
1395 uint16_t idleWidth = (busyChannel == WifiChannelListType::WIFI_CHANLIST_PRIMARY)
1396 ? 0
1397 : ((1 << (busyChannel - 1)) * 20);
1398
1399 Time checkTime1 = start + ccaBusyStartDelay + ccaBusyDuration / 2;
1400 Simulator::Schedule(checkTime1 - start, [=]() {
1401 Time interval1 = (ccaBusyStartDelay + ccaBusyDuration) / 2;
1403 idleWidth,
1404 "Incorrect width of the idle channel in an interval "
1405 << "ending within CCA_BUSY (channel width: " << chWidth
1406 << " MHz, busy channel: " << busyChannel << ")");
1407 });
1408
1409 // During any interval starting within CCA_BUSY period, the idle channel is the
1410 // same as the previous case
1411 Time ccaBusyRxInterval = MilliSeconds(1);
1412 Time checkTime2 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval / 2;
1413 Simulator::Schedule(checkTime2 - start, [=]() {
1414 Time interval2 = (ccaBusyDuration + ccaBusyRxInterval) / 2;
1416 idleWidth,
1417 "Incorrect width of the idle channel in an interval "
1418 << "starting within CCA_BUSY (channel width: " << chWidth
1419 << " MHz, busy channel: " << busyChannel << ")");
1420 });
1421
1422 // Notify RX start
1423 Time rxDuration = MilliSeconds(1);
1424 Simulator::Schedule(ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval,
1426 m_cam,
1427 rxDuration);
1428
1429 // At RX end, we check the status of the channel during an interval immediately
1430 // preceding RX start and overlapping the CCA_BUSY period.
1431 Time checkTime3 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval + rxDuration;
1432 Simulator::Schedule(checkTime3 - start, [=]() {
1433 Time interval3 = ccaBusyDuration / 2 + ccaBusyRxInterval;
1434 Time end3 = checkTime3 - rxDuration;
1436 idleWidth,
1437 "Incorrect width of the idle channel in an interval "
1438 << "preceding RX start and overlapping CCA_BUSY "
1439 << "(channel width: " << chWidth
1440 << " MHz, busy channel: " << busyChannel << ")");
1441 });
1442
1443 // At RX end, we check the status of the channel during the interval following
1444 // the CCA_BUSY period and preceding RX start. The entire operating channel is idle.
1445 const Time& checkTime4 = checkTime3;
1446 Simulator::Schedule(checkTime4 - start, [=]() {
1447 const Time& interval4 = ccaBusyRxInterval;
1448 Time end4 = checkTime4 - rxDuration;
1450 chWidth,
1451 "Incorrect width of the idle channel in the interval "
1452 << "following CCA_BUSY and preceding RX start (channel "
1453 << "width: " << chWidth << " MHz, busy channel: " << busyChannel
1454 << ")");
1455 });
1456
1457 // After RX end, the entire operating channel is idle if the interval does not
1458 // overlap the RX period
1459 Time interval5 = MilliSeconds(1);
1460 Time checkTime5 = checkTime4 + interval5;
1461 Simulator::Schedule(checkTime5 - start, [=]() {
1463 chWidth,
1464 "Incorrect width of the idle channel in an interval "
1465 << "following RX end (channel width: " << chWidth
1466 << " MHz, busy channel: " << busyChannel << ")");
1467 });
1468
1469 // After RX end, no channel is idle if the interval overlaps the RX period
1470 const Time& checkTime6 = checkTime5;
1471 Simulator::Schedule(checkTime6 - start, [=]() {
1472 Time interval6 = interval5 + rxDuration / 2;
1474 0,
1475 "Incorrect width of the idle channel in an interval "
1476 << "overlapping RX (channel width: " << chWidth
1477 << " MHz, busy channel: " << busyChannel << ")");
1478 });
1479}
1480
1481void
1483{
1484 m_cam = CreateObject<ChannelAccessManager>();
1485 uint16_t delay = 0;
1486 uint8_t channel = 0;
1487 std::list<WifiChannelListType> busyChannels;
1488
1489 for (uint16_t chWidth : {20, 40, 80, 160})
1490 {
1491 busyChannels.push_back(static_cast<WifiChannelListType>(channel));
1492
1493 for (const auto busyChannel : busyChannels)
1494 {
1495 Simulator::Schedule(Seconds(delay), [this, chWidth, busyChannel]() {
1496 // reset PHY
1497 if (m_phy)
1498 {
1500 m_phy->Dispose();
1501 }
1502 // create a new PHY operating on a channel of the current width
1503 m_phy = CreateObject<SpectrumWifiPhy>();
1504 m_phy->SetInterferenceHelper(CreateObject<InterferenceHelper>());
1505 m_phy->AddChannel(CreateObject<MultiModelSpectrumChannel>());
1509 // call SetupPhyListener to initialize the ChannelAccessManager
1510 // last busy structs
1512 // run the tests
1513 RunOne(chWidth, busyChannel);
1514 });
1515 delay++;
1516 }
1517 channel++;
1518 }
1519
1522 m_phy->Dispose();
1523 m_cam->Dispose();
1525}
1526
1534{
1535 public:
1536 TxopTestSuite();
1537};
1538
1540 : TestSuite("wifi-devices-dcf", UNIT)
1541{
1543}
1544
1546
1554{
1555 public:
1557};
1558
1560 : TestSuite("wifi-devices-edca", UNIT)
1561{
1563}
1564
1566
1574{
1575 public:
1577};
1578
1580 : TestSuite("wifi-channel-access-manager", UNIT)
1581{
1583}
1584
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 NotifySwitchingStartNow(PhyListener *phyListener, 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 on the given PHY.
void SetupPhyListener(Ptr< WifiPhy > phy)
Set up (or reactivate) listener for PHY events on the given PHY.
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:558
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:101
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:1349
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1325
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1337
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:621
-ns3 Test suite for the ns3 wrapper script