A Discrete-Event Network Simulator
API
channel-access-manager-test.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2005,2006 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20
21#include <list>
22#include <numeric>
23#include "ns3/test.h"
24#include "ns3/simulator.h"
25#include "ns3/channel-access-manager.h"
26#include "ns3/frame-exchange-manager.h"
27#include "ns3/qos-txop.h"
28#include "ns3/spectrum-wifi-phy.h"
29#include "ns3/adhoc-wifi-mac.h"
30
31using namespace ns3;
32
33template <typename TxopType>
35
42template <typename TxopType>
43class TxopTest : public TxopType
44{
45public:
53
59 void QueueTx (uint64_t txTime, uint64_t expectedGrantTime);
60
61private:
64
66 void DoDispose (void) override;
68 void NotifyChannelAccessed (uint8_t linkId, Time txopDuration = Seconds (0)) override;
70 bool HasFramesToTransmit (void) 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;
82 {
83 uint64_t at;
85 };
86 typedef std::list<struct ExpectedBackoff> ExpectedBackoffs;
87
91
99};
100
108{
109public:
111 {
112 }
118 void SetSifs (Time sifs)
119 {
120 m_sifs = sifs;
121 }
127 void SetSlot (Time slot)
128 {
129 m_slot = slot;
130 }
136 void SetEifsNoDifs (Time eifsNoDifs)
137 {
138 m_eifsNoDifs = eifsNoDifs;
139 }
140
141private:
142 Time GetSifs (void) const override
143 {
144 return m_sifs;
145 }
146
147 Time GetSlot (void) const override
148 {
149 return m_slot;
150 }
151
152 Time GetEifsNoDifs (void) const override
153 {
154 return m_eifsNoDifs;
155 }
156
160};
161
168template <typename TxopType>
170{
171public:
178 : m_test (test)
179 {
180 }
188 bool StartTransmission (Ptr<Txop> dcf) override
189 {
190 dcf->NotifyChannelAccessed (0);
191 return true;
192 }
195 {
196 m_test->NotifyInternalCollision (DynamicCast<TxopTest<TxopType>> (txop));
197 }
199 void NotifySwitchingStartNow (Time duration) override
200 {
201 m_test->NotifyChannelSwitching ();
202 }
203
204private:
206};
207
214template <typename TxopType>
216{
217public:
219 void DoRun (void) override;
220
235 void GenerateBackoff (uint32_t i);
239 void NotifyChannelSwitching (void);
240
241
242private:
251 void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue = 20, uint16_t chWidth = 20);
256 void AddTxop (uint32_t aifsn);
258 void EndTest (void);
265 void ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from);
272 void ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from);
278 void ExpectBusy (uint64_t time, bool busy);
283 void DoCheckBusy (bool busy);
289 void AddRxOkEvt (uint64_t at, uint64_t duration);
295 void AddRxErrorEvt (uint64_t at, uint64_t duration);
302 void AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError);
308 void AddRxInsideSifsEvt (uint64_t at, uint64_t duration);
314 void AddTxEvt (uint64_t at, uint64_t duration);
320 void AddNavReset (uint64_t at, uint64_t duration);
326 void AddNavStart (uint64_t at, uint64_t duration);
331 void AddAckTimeoutReset (uint64_t at);
339 void AddAccessRequest (uint64_t at, uint64_t txTime,
340 uint64_t expectedGrantTime, uint32_t from);
348 void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
349 uint64_t expectedGrantTime, uint32_t from);
358 void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
359 uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
366 void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr<TxopTest<TxopType>> state);
374 void AddCcaBusyEvt (uint64_t at, uint64_t duration,
376 const std::vector<Time>& per20MhzDurations = {});
382 void AddSwitchingEvt (uint64_t at, uint64_t duration);
388 void AddRxStartEvt (uint64_t at, uint64_t duration);
389
390 typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests;
391
397};
398
399template <typename TxopType>
400void
401TxopTest<TxopType>::QueueTx (uint64_t txTime, uint64_t expectedGrantTime)
402{
403 m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime));
404}
405
406template <typename TxopType>
408 : m_test (test),
409 m_i (i)
410{
411}
412
413template <typename TxopType>
414void
416{
417 m_test = 0;
418 TxopType::DoDispose ();
419}
420
421template <typename TxopType>
422void
424{
425 Txop::GetLink (0).access = Txop::NOT_REQUESTED;
426 m_test->NotifyAccessGranted (m_i);
427}
428
429template <typename TxopType>
430void
432{
433 m_test->GenerateBackoff (m_i);
434}
435
436template <typename TxopType>
437bool
439{
440 return !m_expectedGrants.empty ();
441}
442
443template <typename TxopType>
444void
446{
447}
448
449template <typename TxopType>
450void
452{
453}
454
455template <typename TxopType>
457 : TestCase ("ChannelAccessManager")
458{
459}
460
461template <typename TxopType>
462void
464{
465 Ptr<TxopTest<TxopType>> state = m_txop[i];
466 NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants");
467 if (!state->m_expectedGrants.empty ())
468 {
469 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
470 state->m_expectedGrants.pop_front ();
471 NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected access grant is now");
472 m_ChannelAccessManager->NotifyTxStartNow (MicroSeconds (expected.first));
473 m_ChannelAccessManager->NotifyAckTimeoutStartNow (MicroSeconds (m_ackTimeoutValue + expected.first));
474 }
475}
476
477template <typename TxopType>
478void
479ChannelAccessManagerTest<TxopType>::AddTxEvt (uint64_t at, uint64_t duration)
480{
481 Simulator::Schedule (MicroSeconds (at) - Now (),
482 &ChannelAccessManager::NotifyTxStartNow, m_ChannelAccessManager,
483 MicroSeconds (duration));
484}
485
486template <typename TxopType>
487void
489{
490 NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions");
491 if (!state->m_expectedInternalCollision.empty ())
492 {
493 struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedInternalCollision.front ();
494 state->m_expectedInternalCollision.pop_front ();
495 NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now");
496 state->StartBackoffNow (expected.nSlots, 0);
497 }
498}
499
500template <typename TxopType>
501void
503{
504 Ptr<TxopTest<TxopType>> state = m_txop[i];
505 NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), false, "Have expected backoffs");
506 if (!state->m_expectedBackoff.empty ())
507 {
508 struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedBackoff.front ();
509 state->m_expectedBackoff.pop_front ();
510 NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected backoff is now");
511 state->StartBackoffNow (expected.nSlots, 0);
512 }
513}
514
515template <typename TxopType>
516void
517ChannelAccessManagerTest<TxopType>::NotifyChannelSwitching (void)
518{
519 for (auto& state : m_txop)
520 {
521 if (!state->m_expectedGrants.empty ())
522 {
523 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
524 state->m_expectedGrants.pop_front ();
525 NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected grant is now");
526 }
527 state->Txop::GetLink (0).access = Txop::NOT_REQUESTED;
528 }
529}
530
531template <typename TxopType>
532void
534{
535 Ptr<TxopTest<TxopType>> state = m_txop[from];
536 struct TxopTest<TxopType>::ExpectedBackoff col;
537 col.at = time;
538 col.nSlots = nSlots;
539 state->m_expectedInternalCollision.push_back (col);
540}
541
542template <typename TxopType>
543void
544ChannelAccessManagerTest<TxopType>::ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from)
545{
546 Ptr<TxopTest<TxopType>> state = m_txop[from];
547 struct TxopTest<TxopType>::ExpectedBackoff backoff;
548 backoff.at = time;
549 backoff.nSlots = nSlots;
550 state->m_expectedBackoff.push_back (backoff);
551}
552
553template <typename TxopType>
554void
555ChannelAccessManagerTest<TxopType>::ExpectBusy (uint64_t time, bool busy)
556{
557 Simulator::Schedule (MicroSeconds (time) - Now (),
559}
560
561template <typename TxopType>
562void
564{
565 NS_TEST_EXPECT_MSG_EQ (m_ChannelAccessManager->IsBusy (), busy, "Incorrect busy/idle state");
566}
567
568template <typename TxopType>
569void
570ChannelAccessManagerTest<TxopType>::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue, uint16_t chWidth)
571{
572 m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub> ();
573 m_feManager = CreateObject<FrameExchangeManagerStub<TxopType>> (this);
574 m_ChannelAccessManager->SetupFrameExchangeManager (m_feManager);
575 m_ChannelAccessManager->SetSlot (MicroSeconds (slotTime));
576 m_ChannelAccessManager->SetSifs (MicroSeconds (sifs));
577 m_ChannelAccessManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs + sifs));
578 m_ackTimeoutValue = ackTimeoutValue;
579 // the purpose of the following operations is to initialize the last busy struct
580 // of the ChannelAccessManager. Indeed, InitLastBusyStructs(), which is called by
581 // SetupPhyListener(), requires an attached PHY to determine the channel types
582 // to initialize
583 m_phy = CreateObject<SpectrumWifiPhy> ();
584 m_phy->SetOperatingChannel (WifiPhy::ChannelTuple {0, chWidth,
586 m_phy->ConfigureStandard (WIFI_STANDARD_80211ac); // required to use 160 MHz channels
587 m_ChannelAccessManager->SetupPhyListener (m_phy);
588}
589
590template <typename TxopType>
591void
593{
594 Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>> (this, m_txop.size ());
595 m_txop.push_back (txop);
596 m_ChannelAccessManager->Add (txop);
597 // the following causes the creation of a link for the txop object
598 auto mac = CreateObject<AdhocWifiMac> ();
599 mac->SetWifiPhys ({nullptr});
600 txop->SetWifiMac (mac);
601 txop->SetAifsn (aifsn);
602}
603
604template <typename TxopType>
605void
607{
609
610 for (typename TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++)
611 {
612 Ptr<TxopTest<TxopType>> state = *i;
613 NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants");
614 NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions");
615 NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), true, "Have no expected backoffs");
616 state->Dispose ();
617 state = 0;
618 }
619 m_txop.clear ();
620
621 m_ChannelAccessManager->RemovePhyListener (m_phy);
622 m_phy->Dispose ();
623 m_ChannelAccessManager->Dispose ();
624 m_ChannelAccessManager = 0;
625 m_feManager = 0;
626 Simulator::Destroy ();
627}
628
629template <typename TxopType>
630void
632{
633 Simulator::Schedule (MicroSeconds (at) - Now (),
634 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
635 MicroSeconds (duration));
636 Simulator::Schedule (MicroSeconds (at + duration) - Now (),
637 &ChannelAccessManager::NotifyRxEndOkNow, m_ChannelAccessManager);
638}
639
640template <typename TxopType>
641void
643{
644 Simulator::Schedule (MicroSeconds (at) - Now (),
645 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
646 MicroSeconds (duration));
647}
648
649template <typename TxopType>
650void
652{
653 Simulator::Schedule (MicroSeconds (at) - Now (),
654 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
655 MicroSeconds (duration));
656 Simulator::Schedule (MicroSeconds (at + duration) - Now (),
657 &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
658}
659
660template <typename TxopType>
661void
662ChannelAccessManagerTest<TxopType>::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError)
663{
664 Simulator::Schedule (MicroSeconds (at) - Now (),
665 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
666 MicroSeconds (duration));
667 Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
668 &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
669 Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
670 &ChannelAccessManager::NotifyCcaBusyStartNow, m_ChannelAccessManager,
671 MicroSeconds (duration - timeUntilError), WIFI_CHANLIST_PRIMARY, std::vector<Time> {});
672}
673
674
675template <typename TxopType>
676void
678{
679 Simulator::Schedule (MicroSeconds (at) - Now (),
680 &ChannelAccessManager::NotifyNavResetNow, m_ChannelAccessManager,
681 MicroSeconds (duration));
682}
683
684template <typename TxopType>
685void
687{
688 Simulator::Schedule (MicroSeconds (at) - Now (),
689 &ChannelAccessManager::NotifyNavStartNow, m_ChannelAccessManager,
690 MicroSeconds (duration));
691}
692
693template <typename TxopType>
694void
696{
697 Simulator::Schedule (MicroSeconds (at) - Now (),
698 &ChannelAccessManager::NotifyAckTimeoutResetNow, m_ChannelAccessManager);
699}
700
701template <typename TxopType>
702void
704 uint64_t expectedGrantTime, uint32_t from)
705{
706 AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from);
707}
708
709template <typename TxopType>
710void
712 uint64_t expectedGrantTime, uint32_t from)
713{
714 Simulator::Schedule (MicroSeconds (at) - Now (),
716 txTime, expectedGrantTime, m_txop[from]);
717}
718
719template <typename TxopType>
720void
722 uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
723{
724 NS_ASSERT (ackDelay < m_ackTimeoutValue);
725 Simulator::Schedule (MicroSeconds (at) - Now (),
727 txTime, expectedGrantTime, m_txop[from]);
728 AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay);
729}
730
731template <typename TxopType>
732void
733ChannelAccessManagerTest<TxopType>::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime,
734 Ptr<TxopTest<TxopType>> state)
735{
736 if (m_ChannelAccessManager->NeedBackoffUponAccess (state))
737 {
738 state->GenerateBackoff (0);
739 }
740 state->QueueTx (txTime, expectedGrantTime);
741 m_ChannelAccessManager->RequestAccess (state);
742}
743
744template <typename TxopType>
745void
747 WifiChannelListType channelType,
748 const std::vector<Time>& per20MhzDurations)
749{
750 Simulator::Schedule (MicroSeconds (at) - Now (),
751 &ChannelAccessManager::NotifyCcaBusyStartNow, m_ChannelAccessManager,
752 MicroSeconds (duration), channelType, per20MhzDurations);
753}
754
755template <typename TxopType>
756void
758{
759 Simulator::Schedule (MicroSeconds (at) - Now (),
760 &ChannelAccessManager::NotifySwitchingStartNow, m_ChannelAccessManager,
761 MicroSeconds (duration));
762}
763
764template <typename TxopType>
765void
767{
768 Simulator::Schedule (MicroSeconds (at) - Now (),
769 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
770 MicroSeconds (duration));
771}
772
773/*
774 * Specialization of DoRun () method for DCF
775 */
776template <>
777void
779{
780 // DCF immediate access (no backoff)
781 // 1 4 5 6 8 11 12
782 // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
783 //
784 StartTest (1, 3, 10);
785 AddTxop (1);
786 AddAccessRequest (1, 1, 5, 0);
787 AddAccessRequest (8, 2, 12, 0);
788 EndTest ();
789 // Check that receiving inside SIFS shall be cancelled properly:
790 // 1 4 5 6 9 10 14 17 18
791 // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
792 // |
793 // 7 start rx
794 //
795
796 StartTest (1, 3, 10);
797 AddTxop (1);
798 AddAccessRequest (1, 1, 5, 0);
799 AddRxInsideSifsEvt (7, 10);
800 AddTxEvt (9, 1);
801 AddAccessRequest (14, 2, 18, 0);
802 EndTest ();
803 // The test below mainly intends to test the case where the medium
804 // becomes busy in the middle of a backoff slot: the backoff counter
805 // must not be decremented for this backoff slot. This is the case
806 // below for the backoff slot starting at time 78us.
807 //
808 // 20 60 66 70 74 78 80 100 106 110 114 118 120
809 // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 | bslot3 | tx |
810 // |
811 // 30 request access. backoff slots: 4
812
813 StartTest (4, 6, 10);
814 AddTxop (1);
815 AddRxOkEvt (20, 40);
816 AddRxOkEvt (80, 20);
817 AddAccessRequest (30, 2, 118, 0);
818 ExpectBackoff (30, 4, 0); //backoff: 4 slots
819 EndTest ();
820 // Test the case where the backoff slots is zero.
821 //
822 // 20 60 66 70 72
823 // | rx | sifs | aifsn | tx |
824 // |
825 // 30 request access. backoff slots: 0
826
827 StartTest (4, 6, 10);
828 AddTxop (1);
829 AddRxOkEvt (20, 40);
830 AddAccessRequest (30, 2, 70, 0);
831 ExpectBackoff (30, 0, 0); // backoff: 0 slots
832 EndTest ();
833 // Test shows when two frames are received without interval between
834 // them:
835 // 20 60 100 106 110 112
836 // | rx | rx |sifs | aifsn | tx |
837 // |
838 // 30 request access. backoff slots: 0
839
840 StartTest (4, 6, 10);
841 AddTxop (1);
842 AddRxOkEvt (20, 40);
843 AddRxOkEvt (60, 40);
844 AddAccessRequest (30, 2, 110, 0);
845 ExpectBackoff (30, 0, 0); //backoff: 0 slots
846 EndTest ();
847
848 // Requesting access within SIFS interval (DCF immediate access)
849 //
850 // 20 60 62 68 72
851 // | rx | idle | sifs | aifsn | tx |
852 //
853 StartTest (4, 6, 10);
854 AddTxop (1);
855 AddRxOkEvt (20, 40);
856 AddAccessRequest (62, 2, 72, 0);
857 EndTest ();
858
859 // Requesting access after DIFS (DCF immediate access)
860 //
861 // 20 60 70 76 80
862 // | rx | idle | sifs | aifsn | tx |
863 //
864 StartTest (4, 6, 10);
865 AddTxop (1);
866 AddRxOkEvt (20, 40);
867 AddAccessRequest (70, 2, 80, 0);
868 EndTest ();
869
870 // Test an EIFS
871 //
872 // 20 60 66 76 86 90 94 98 102 106
873 // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
874 // | | <------eifs------>|
875 // 30 request access. backoff slots: 4
876 StartTest (4, 6, 10);
877 AddTxop (1);
878 AddRxErrorEvt (20, 40);
879 AddAccessRequest (30, 2, 102, 0);
880 ExpectBackoff (30, 4, 0); //backoff: 4 slots
881 EndTest ();
882
883 // Test DCF immediate access after an EIFS (EIFS is greater)
884 //
885 // 20 60 66 76 86
886 // | <----+-eifs------>|
887 // | rx | sifs | acktxttime | sifs + aifsn | tx |
888 // | sifs + aifsn |
889 // request access 70 80
890 StartTest (4, 6, 10);
891 AddTxop (1);
892 AddRxErrorEvt (20, 40);
893 AddAccessRequest (70, 2, 86, 0);
894 EndTest ();
895
896 // Test that channel stays busy for first frame's duration after Rx error
897 //
898 // 20 60
899 // | rx |
900 // |
901 // 40 force Rx error
902 StartTest (4, 6, 10);
903 AddTxop (1);
904 AddRxErrorEvt (20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
905 ExpectBusy (41, true); // channel should remain busy for remaining duration
906 ExpectBusy (59, true);
907 ExpectBusy (61, false);
908 EndTest ();
909
910 // Test an EIFS which is interrupted by a successful transmission.
911 //
912 // 20 60 66 69 75 81 85 89 93 97 101 103
913 // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
914 // | | <--eifs-->|
915 // 30 request access. backoff slots: 4
916 StartTest (4, 6, 10);
917 AddTxop (1);
918 AddRxErrorEvt (20, 40);
919 AddAccessRequest (30, 2, 101, 0);
920 ExpectBackoff (30, 4, 0); //backoff: 4 slots
921 AddRxOkEvt (69, 6);
922 EndTest ();
923
924 // Test two DCFs which suffer an internal collision. the first DCF has a higher
925 // priority than the second DCF.
926 //
927 // 20 60 66 70 74 78 88
928 // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
929 // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn | bslot | tx |
930 // 94 98 102 106 110 112
931 StartTest (4, 6, 10);
932 AddTxop (1); //high priority DCF
933 AddTxop (3); //low priority DCF
934 AddRxOkEvt (20, 40);
935 AddAccessRequest (30, 10, 78, 0);
936 ExpectBackoff (30, 2, 0); //backoff: 2 slot
937 AddAccessRequest (40, 2, 110, 1);
938 ExpectBackoff (40, 0, 1); //backoff: 0 slot
939 ExpectInternalCollision (78, 1, 1); //backoff: 1 slot
940 EndTest ();
941
942 // Test of AckTimeout handling: First queue requests access and ack procedure fails,
943 // inside the Ack timeout second queue with higher priority requests access.
944 //
945 // 20 26 34 54 74 80
946 // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
947 // DCF0 - high | | | sifs | tx |
948 // ^ request access
949 StartTest (4, 6, 10);
950 AddTxop (0); //high priority DCF
951 AddTxop (2); //low priority DCF
952 AddAccessRequestWithAckTimeout (20, 20, 34, 1);
953 AddAccessRequest (64, 10, 80, 0);
954 EndTest ();
955
956 // Test of AckTimeout handling:
957 //
958 // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
959 // inside this interval second queue with higher priority requests access.
960 //
961 // 20 26 34 54 56 62
962 // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
963 // DCF0 - high | | | sifs | tx |
964 // ^ request access
965 StartTest (4, 6, 10);
966 AddTxop (0); //high priority DCF
967 AddTxop (2); //low priority DCF
968 AddAccessRequestWithSuccessfullAck (20, 20, 34, 2, 1);
969 AddAccessRequest (55, 10, 62, 0);
970 EndTest ();
971
972 //Repeat the same but with one queue:
973 // 20 26 34 54 60 62 68 76 80
974 // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
975 // ^ request access
976 StartTest (4, 6, 10);
977 AddTxop (2);
978 AddAccessRequest (20, 20, 34, 0);
979 AddRxOkEvt (60, 2); // Ack
980 AddAccessRequest (61, 10, 80, 0);
981 ExpectBackoff (61, 1, 0); // 1 slot
982 EndTest ();
983
984 // test simple NAV count. This scenario models a simple Data+Ack handshake
985 // where the data rate used for the Ack is higher than expected by the Data source
986 // so, the data exchange completes before the end of NAV.
987 StartTest (4, 6, 10);
988 AddTxop (1);
989 AddRxOkEvt (20, 40);
990 AddNavStart (60, 15);
991 AddRxOkEvt (66, 5);
992 AddNavStart (71, 0);
993 AddAccessRequest (30, 10, 93, 0);
994 ExpectBackoff (30, 2, 0); //backoff: 2 slots
995 EndTest ();
996
997 // test more complex NAV handling by a CF-poll. This scenario models a
998 // simple Data+Ack handshake interrupted by a CF-poll which resets the
999 // NAV counter.
1000 StartTest (4, 6, 10);
1001 AddTxop (1);
1002 AddRxOkEvt (20, 40);
1003 AddNavStart (60, 15);
1004 AddRxOkEvt (66, 5);
1005 AddNavReset (71, 2);
1006 AddAccessRequest (30, 10, 91, 0);
1007 ExpectBackoff (30, 2, 0); //backoff: 2 slots
1008 EndTest ();
1009
1010
1011 // 20 60 80 86 94
1012 // | rx | idle | sifs | aifsn | tx |
1013 // ^ request access
1014 StartTest (4, 6, 10);
1015 AddTxop (2);
1016 AddRxOkEvt (20, 40);
1017 AddAccessRequest (80, 10, 94, 0);
1018 EndTest ();
1019
1020
1021 StartTest (4, 6, 10);
1022 AddTxop (2);
1023 AddRxOkEvt (20, 40);
1024 AddRxOkEvt (78, 8);
1025 AddAccessRequest (30, 50, 108, 0);
1026 ExpectBackoff (30, 3, 0); //backoff: 3 slots
1027 EndTest ();
1028
1029
1030 // Channel switching tests
1031
1032 // 0 20 21 24 25 26
1033 // | switching | idle | sifs | aifsn | tx |
1034 // ^ access request.
1035 StartTest (1, 3, 10);
1036 AddTxop (1);
1037 AddSwitchingEvt (0, 20);
1038 AddAccessRequest (21, 1, 25, 0);
1039 EndTest ();
1040
1041 // 20 40 50 53 54 55 56 57
1042 // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
1043 // | |
1044 // 30 busy. 45 access request.
1045 //
1046 StartTest (1, 3, 10);
1047 AddTxop (1);
1048 AddSwitchingEvt (20,20);
1049 AddCcaBusyEvt (30,20);
1050 ExpectBackoff (45, 2, 0); //backoff: 2 slots
1051 AddAccessRequest (45, 1, 56, 0);
1052 EndTest ();
1053
1054 // 20 30 50 51 54 55 56
1055 // | rx | switching | idle | sifs | aifsn | tx |
1056 // ^ access request.
1057 //
1058 StartTest (1, 3, 10);
1059 AddTxop (1);
1060 AddRxStartEvt (20, 40);
1061 AddSwitchingEvt (30, 20);
1062 AddAccessRequest (51, 1, 55, 0);
1063 EndTest ();
1064
1065 // 20 30 50 51 54 55 56
1066 // | busy | switching | idle | sifs | aifsn | tx |
1067 // ^ access request.
1068 //
1069 StartTest (1, 3, 10);
1070 AddTxop (1);
1071 AddCcaBusyEvt (20, 40);
1072 AddSwitchingEvt (30, 20);
1073 AddAccessRequest (51, 1, 55, 0);
1074 EndTest ();
1075
1076 // 20 30 50 51 54 55 56
1077 // | nav | switching | idle | sifs | aifsn | tx |
1078 // ^ access request.
1079 //
1080 StartTest (1, 3, 10);
1081 AddTxop (1);
1082 AddNavStart (20,40);
1083 AddSwitchingEvt (30,20);
1084 AddAccessRequest (51, 1, 55, 0);
1085 EndTest ();
1086
1087 // 20 23 24 44 54 59 60 63 64 65
1088 // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1089 // | |
1090 // 49 access request. ^ access request.
1091 //
1092 StartTest (1, 3, 10);
1093 AddTxop (1);
1094 AddAccessRequestWithAckTimeout (20, 20, 24, 0);
1095 AddAccessRequest (49, 1, 54, 0);
1096 AddSwitchingEvt (54, 5);
1097 AddAccessRequest (60, 1, 64, 0);
1098 EndTest ();
1099
1100 // 20 60 66 70 74 78 80 100 101 107 111 113
1101 // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1102 // | |
1103 // 30 access request. ^ access request.
1104 //
1105 StartTest (4, 6, 10);
1106 AddTxop (1);
1107 AddRxOkEvt (20,40);
1108 AddAccessRequest (30, 2, 80, 0);
1109 ExpectBackoff (30, 4, 0); //backoff: 4 slots
1110 AddSwitchingEvt (80,20);
1111 AddAccessRequest (101, 2, 111, 0);
1112 EndTest ();
1113}
1114
1115/*
1116 * Specialization of DoRun () method for EDCA
1117 */
1118template <>
1119void
1121{
1122 // Check alignment at slot boundary after successful reception (backoff = 0).
1123 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1124 // 20 50 56 60 80
1125 // | cca_busy |
1126 // | rx | sifs | aifsn | tx |
1127 // |
1128 // 52 request access
1129 StartTest (4, 6, 10, 20, 40);
1130 AddTxop (1);
1131 AddRxOkEvt (20, 30);
1132 AddCcaBusyEvt (50, 10, WIFI_CHANLIST_SECONDARY);
1133 AddAccessRequest (52, 20, 60, 0);
1134 EndTest ();
1135
1136 // Check alignment at slot boundary after successful reception (backoff = 0).
1137 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1138 // 20 50 56 60 80
1139 // | cca_busy |
1140 // | rx | sifs | aifsn | tx |
1141 // |
1142 // 58 request access
1143 StartTest (4, 6, 10, 20, 80);
1144 AddTxop (1);
1145 AddRxOkEvt (20, 30);
1146 AddCcaBusyEvt (50, 10, WIFI_CHANLIST_SECONDARY);
1147 AddAccessRequest (58, 20, 60, 0);
1148 EndTest ();
1149
1150 // Check alignment at slot boundary after successful reception (backoff = 0).
1151 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1152 // 20 50 56 60 64 84
1153 // | cca_busy |
1154 // | rx | sifs | aifsn | idle | tx |
1155 // |
1156 // 62 request access
1157 StartTest (4, 6, 10, 20, 80);
1158 AddTxop (1);
1159 AddRxOkEvt (20, 30);
1160 AddCcaBusyEvt (50, 14, WIFI_CHANLIST_SECONDARY40);
1161 AddAccessRequest (62, 20, 64, 0);
1162 EndTest ();
1163
1164 // Check alignment at slot boundary after failed reception (backoff = 0).
1165 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1166 // 20 50 56 66 76 96
1167 // | cca_busy |
1168 // | | <------eifs------>| | |
1169 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1170 // |
1171 // 55 request access
1172 StartTest (4, 6, 10, 20, 160);
1173 AddTxop (1);
1174 AddRxErrorEvt (20, 30);
1175 AddCcaBusyEvt (50, 26, WIFI_CHANLIST_SECONDARY);
1176 AddAccessRequest (55, 20, 76, 0);
1177 EndTest ();
1178
1179 // Check alignment at slot boundary after failed reception (backoff = 0).
1180 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1181 // 20 50 56 66 76 96
1182 // | cca_busy |
1183 // | | <------eifs------>| | |
1184 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1185 // |
1186 // 70 request access
1187 StartTest (4, 6, 10, 20, 160);
1188 AddTxop (1);
1189 AddRxErrorEvt (20, 30);
1190 AddCcaBusyEvt (50, 26, WIFI_CHANLIST_SECONDARY40);
1191 AddAccessRequest (70, 20, 76, 0);
1192 EndTest ();
1193
1194 // Check alignment at slot boundary after failed reception (backoff = 0).
1195 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1196 // 20 50 56 66 76 84
1197 // | cca_busy |
1198 // | | <------eifs------>| | |
1199 // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1200 // |
1201 // 82 request access
1202 StartTest (4, 6, 10, 20, 160);
1203 AddTxop (1);
1204 AddRxErrorEvt (20, 30);
1205 AddCcaBusyEvt (50, 34, WIFI_CHANLIST_SECONDARY80);
1206 AddAccessRequest (82, 20, 84, 0);
1207 EndTest ();
1208
1209 // Check backoff decrement at slot boundaries. Medium idle during backoff
1210 // 20 50 56 60 64 68 72 76 96
1211 // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1212 // | | | | |
1213 // 30 request access. decrement decrement decrement decrement
1214 // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1215 StartTest (4, 6, 10);
1216 AddTxop (1);
1217 AddRxOkEvt (20, 30);
1218 AddAccessRequest (30, 20, 76, 0);
1219 ExpectBackoff (30, 4, 0);
1220 EndTest ();
1221
1222 // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1223 // 20 50 56 60 61 71 77 81 85 87 97 103 107 127
1224 // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs | aifsn | tx |
1225 // | | | |
1226 // 30 request access. decrement decrement decrement
1227 // backoff slots: 3 slots: 2 slots: 1 slots: 0
1228 StartTest (4, 6, 10);
1229 AddTxop (1);
1230 AddRxOkEvt (20, 30);
1231 AddRxOkEvt (61, 10);
1232 AddRxOkEvt (87, 10);
1233 AddAccessRequest (30, 20, 107, 0);
1234 ExpectBackoff (30, 3, 0);
1235 EndTest ();
1236}
1237
1238
1252{
1253public:
1256
1257private:
1258 void DoRun (void) override;
1259
1266 void RunOne (uint16_t chWidth, WifiChannelListType busyChannel);
1267
1270};
1271
1273 : TestCase ("Check calculation of the largest idle primary channel")
1274{
1275}
1276
1277void
1279{
1299
1300 // After 1ms, we are notified of CCA_BUSY for 1ms on the given channel
1301 Time ccaBusyStartDelay = MilliSeconds (1);
1302 Time ccaBusyDuration = MilliSeconds (1);
1303 Simulator::Schedule (ccaBusyStartDelay, &ChannelAccessManager::NotifyCcaBusyStartNow, m_cam,
1304 ccaBusyDuration, busyChannel, std::vector<Time> (chWidth / 20, Seconds (0)));
1305
1306 // During any interval ending within CCA_BUSY period, the idle channel is the
1307 // primary channel contiguous to the busy secondary channel, if the busy channel
1308 // is a secondary channel, or there is no idle channel, otherwise.
1309 uint16_t idleWidth = (busyChannel == WifiChannelListType::WIFI_CHANLIST_PRIMARY)
1310 ? 0 : ((1 << (busyChannel - 1)) * 20);
1311
1312 Time checkTime1 = start + ccaBusyStartDelay + ccaBusyDuration / 2;
1313 Simulator::Schedule (checkTime1 - start,
1314 [=]()
1315 {
1316 Time interval1 = (ccaBusyStartDelay + ccaBusyDuration) / 2;
1318 idleWidth,
1319 "Incorrect width of the idle channel in an interval "
1320 << "ending within CCA_BUSY (channel width: " << chWidth
1321 << " MHz, busy channel: " << busyChannel << ")");
1322 });
1323
1324 // During any interval starting within CCA_BUSY period, the idle channel is the
1325 // same as the previous case
1326 Time ccaBusyRxInterval = MilliSeconds (1);
1327 Time checkTime2 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval / 2;
1328 Simulator::Schedule (checkTime2 - start,
1329 [=]()
1330 {
1331 Time interval2 = (ccaBusyDuration + ccaBusyRxInterval) / 2;
1333 idleWidth,
1334 "Incorrect width of the idle channel in an interval "
1335 << "starting within CCA_BUSY (channel width: " << chWidth
1336 << " MHz, busy channel: " << busyChannel << ")");
1337 });
1338
1339 // Notify RX start
1340 Time rxDuration = MilliSeconds (1);
1341 Simulator::Schedule (ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval,
1342 &ChannelAccessManager::NotifyRxStartNow, m_cam, rxDuration);
1343
1344 // At RX end, we check the status of the channel during an interval immediately
1345 // preceding RX start and overlapping the CCA_BUSY period.
1346 Time checkTime3 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval + rxDuration;
1347 Simulator::Schedule (checkTime3 - start,
1348 [=]()
1349 {
1350 Time interval3 = ccaBusyDuration / 2 + ccaBusyRxInterval;
1351 Time end3 = checkTime3 - rxDuration;
1353 idleWidth,
1354 "Incorrect width of the idle channel in an interval "
1355 << "preceding RX start and overlapping CCA_BUSY "
1356 << "(channel width: " << chWidth
1357 << " MHz, busy channel: " << busyChannel << ")");
1358 });
1359
1360 // At RX end, we check the status of the channel during the interval following
1361 // the CCA_BUSY period and preceding RX start. The entire operating channel is idle.
1362 Time checkTime4 = checkTime3;
1363 Simulator::Schedule (checkTime4 - start,
1364 [=]()
1365 {
1366 Time interval4 = ccaBusyRxInterval;
1367 Time end4 = checkTime4 - rxDuration;
1369 chWidth,
1370 "Incorrect width of the idle channel in the interval "
1371 << "following CCA_BUSY and preceding RX start (channel "
1372 << "width: " << chWidth << " MHz, busy channel: "
1373 << busyChannel << ")");
1374 });
1375
1376 // After RX end, the entire operating channel is idle if the interval does not
1377 // overlap the RX period
1378 Time interval5 = MilliSeconds (1);
1379 Time checkTime5 = checkTime4 + interval5;
1380 Simulator::Schedule (checkTime5 - start,
1381 [=]()
1382 {
1384 chWidth,
1385 "Incorrect width of the idle channel in an interval "
1386 << "following RX end (channel width: " << chWidth
1387 << " MHz, busy channel: " << busyChannel << ")");
1388 });
1389
1390 // After RX end, no channel is idle if the interval overlaps the RX period
1391 Time checkTime6 = checkTime5;
1392 Simulator::Schedule (checkTime6 - start,
1393 [=]()
1394 {
1395 Time interval6 = interval5 + rxDuration / 2;
1397 0,
1398 "Incorrect width of the idle channel in an interval "
1399 << "overlapping RX (channel width: " << chWidth
1400 << " MHz, busy channel: " << busyChannel << ")");
1401 });
1402}
1403
1404
1405void
1407{
1408 m_cam = CreateObject<ChannelAccessManager> ();
1409 uint16_t delay = 0;
1410 uint8_t channel = 0;
1411 std::list<WifiChannelListType> busyChannels;
1412
1413 for (uint16_t chWidth : {20, 40, 80, 160})
1414 {
1415 busyChannels.push_back (static_cast<WifiChannelListType> (channel));
1416
1417 for (const auto busyChannel : busyChannels)
1418 {
1419 Simulator::Schedule (Seconds (delay),
1420 [this, chWidth, busyChannel]()
1421 {
1422 // reset PHY
1423 if (m_phy)
1424 {
1426 m_phy->Dispose ();
1427 }
1428 // create a new PHY operating on a channel of the current width
1429 m_phy = CreateObject<SpectrumWifiPhy> ();
1431 WIFI_PHY_BAND_5GHZ, 0});
1433 // call SetupPhyListener to initialize the ChannelAccessManager
1434 // last busy structs
1436 // run the tests
1437 RunOne (chWidth, busyChannel);
1438 });
1439 delay++;
1440 }
1441 channel++;
1442 }
1443
1444 Simulator::Run ();
1446 m_phy->Dispose ();
1447 m_cam->Dispose ();
1448 Simulator::Destroy ();
1449}
1450
1451
1459{
1460public:
1461 TxopTestSuite ();
1462};
1463
1465 : TestSuite ("wifi-devices-dcf", UNIT)
1466{
1467 AddTestCase (new ChannelAccessManagerTest<Txop>, TestCase::QUICK);
1468}
1469
1471
1479{
1480public:
1482};
1483
1485 : TestSuite ("wifi-devices-edca", UNIT)
1486{
1487 AddTestCase (new ChannelAccessManagerTest<QosTxop>, TestCase::QUICK);
1488}
1489
1491
1499{
1500public:
1502};
1503
1505 : TestSuite ("wifi-channel-access-manager", UNIT)
1506{
1507 AddTestCase (new LargestIdlePrimaryChannelTest, TestCase::QUICK);
1508}
1509
void Run(ObjectFactory &factory, uint32_t pop, uint32_t total, uint32_t runs, Ptr< RandomVariableStream > eventStream, bool calRev)
Perform the runs for a single scheduler type.
static ChannelAccessManagerTestSuite g_camTestSuite
static TxopTestSuite g_dcfTestSuite
static QosTxopTestSuite g_edcaTestSuite
Time GetSifs(void) const override
Return the Short Interframe Space (SIFS) for this PHY.
void SetEifsNoDifs(Time eifsNoDifs)
Set the duration of EIFS - DIFS.
void SetSlot(Time slot)
Set the slot duration.
Time GetSlot(void) const override
Return the slot duration for this PHY.
void SetSifs(Time sifs)
Set the Short Interframe Space (SIFS).
Time GetEifsNoDifs(void) const override
Return the EIFS duration minus a DIFS.
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.
void DoRun(void) override
Implementation to actually run this TestCase.
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 NotifyChannelSwitching(void)
Notify channel switching function.
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 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 EndTest(void)
End test function.
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.
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) override
Request the FrameExchangeManager to start a frame exchange sequence.
Test the calculation of the largest idle primary channel performed by ChannelAccessManager::GetLarges...
void DoRun(void) override
Implementation to actually run this TestCase.
virtual ~LargestIdlePrimaryChannelTest()=default
void RunOne(uint16_t chWidth, WifiChannelListType busyChannel)
Test a specific combination of operating channel width and busy channel type.
Ptr< ChannelAccessManager > m_cam
channel access manager
TxopTest Txop Test.
ExpectedBackoffs m_expectedInternalCollision
expected backoff due to an internal collision
bool HasFramesToTransmit(void) override
Check if the Txop has frames to transmit.
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::pair< uint64_t, uint64_t > ExpectedGrant
the expected grant typedef
void DoDispose(void) override
Destructor implementation.
void NotifyWakeUp(uint8_t linkId) override
When wake up operation occurs on a link, channel access on that link will be restarted.
TxopTest(ChannelAccessManagerTest< TxopType > *test, uint32_t i)
Constructor.
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(void)
Dispose of this Object.
Definition: object.cc:214
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:104
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:542
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:877
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:975
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:838
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#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:240
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1261
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1245
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1253
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:41
@ 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(Ptr< T2 > const &p)
Cast a Ptr.
Definition: ptr.h:533
channel
Definition: third.py:83
mac
Definition: third.py:87
def start()
Definition: core.py:1852