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 (uint8_t linkId) override;
72 void NotifySleep (uint8_t linkId) override;
74 void NotifyWakeUp (uint8_t linkId) override;
76 void GenerateBackoff (uint8_t linkId) override;
77
78 typedef std::pair<uint64_t,uint64_t> ExpectedGrant;
79 typedef std::list<ExpectedGrant> ExpectedGrants;
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 }
189 bool StartTransmission (Ptr<Txop> dcf, uint16_t allowedWidth) override
190 {
191 dcf->NotifyChannelAccessed (0);
192 return true;
193 }
196 {
197 m_test->NotifyInternalCollision (DynamicCast<TxopTest<TxopType>> (txop));
198 }
200 void NotifySwitchingStartNow (Time duration) override
201 {
202 m_test->NotifyChannelSwitching ();
203 }
204
205private:
207};
208
215template <typename TxopType>
217{
218public:
220 void DoRun (void) override;
221
236 void GenerateBackoff (uint32_t i);
240 void NotifyChannelSwitching (void);
241
242
243private:
252 void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue = 20, uint16_t chWidth = 20);
257 void AddTxop (uint32_t aifsn);
259 void EndTest (void);
266 void ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from);
273 void ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from);
279 void ExpectBusy (uint64_t time, bool busy);
284 void DoCheckBusy (bool busy);
290 void AddRxOkEvt (uint64_t at, uint64_t duration);
296 void AddRxErrorEvt (uint64_t at, uint64_t duration);
303 void AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError);
309 void AddRxInsideSifsEvt (uint64_t at, uint64_t duration);
315 void AddTxEvt (uint64_t at, uint64_t duration);
321 void AddNavReset (uint64_t at, uint64_t duration);
327 void AddNavStart (uint64_t at, uint64_t duration);
332 void AddAckTimeoutReset (uint64_t at);
340 void AddAccessRequest (uint64_t at, uint64_t txTime,
341 uint64_t expectedGrantTime, uint32_t from);
349 void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
350 uint64_t expectedGrantTime, uint32_t from);
359 void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
360 uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
367 void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr<TxopTest<TxopType>> state);
375 void AddCcaBusyEvt (uint64_t at, uint64_t duration,
377 const std::vector<Time>& per20MhzDurations = {});
383 void AddSwitchingEvt (uint64_t at, uint64_t duration);
389 void AddRxStartEvt (uint64_t at, uint64_t duration);
390
391 typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests;
392
398};
399
400template <typename TxopType>
401void
402TxopTest<TxopType>::QueueTx (uint64_t txTime, uint64_t expectedGrantTime)
403{
404 m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime));
405}
406
407template <typename TxopType>
409 : m_test (test),
410 m_i (i)
411{
412}
413
414template <typename TxopType>
415void
417{
418 m_test = 0;
419 TxopType::DoDispose ();
420}
421
422template <typename TxopType>
423void
425{
426 Txop::GetLink (0).access = Txop::NOT_REQUESTED;
427 m_test->NotifyAccessGranted (m_i);
428}
429
430template <typename TxopType>
431void
433{
434 m_test->GenerateBackoff (m_i);
435}
436
437template <typename TxopType>
438bool
440{
441 return !m_expectedGrants.empty ();
442}
443
444template <typename TxopType>
445void
447{
448}
449
450template <typename TxopType>
451void
453{
454}
455
456template <typename TxopType>
458 : TestCase ("ChannelAccessManager")
459{
460}
461
462template <typename TxopType>
463void
465{
466 Ptr<TxopTest<TxopType>> state = m_txop[i];
467 NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants");
468 if (!state->m_expectedGrants.empty ())
469 {
470 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
471 state->m_expectedGrants.pop_front ();
472 NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected access grant is now");
473 m_ChannelAccessManager->NotifyTxStartNow (MicroSeconds (expected.first));
474 m_ChannelAccessManager->NotifyAckTimeoutStartNow (MicroSeconds (m_ackTimeoutValue + expected.first));
475 }
476}
477
478template <typename TxopType>
479void
480ChannelAccessManagerTest<TxopType>::AddTxEvt (uint64_t at, uint64_t duration)
481{
482 Simulator::Schedule (MicroSeconds (at) - Now (),
483 &ChannelAccessManager::NotifyTxStartNow, m_ChannelAccessManager,
484 MicroSeconds (duration));
485}
486
487template <typename TxopType>
488void
490{
491 NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions");
492 if (!state->m_expectedInternalCollision.empty ())
493 {
494 struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedInternalCollision.front ();
495 state->m_expectedInternalCollision.pop_front ();
496 NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now");
497 state->StartBackoffNow (expected.nSlots, 0);
498 }
499}
500
501template <typename TxopType>
502void
504{
505 Ptr<TxopTest<TxopType>> state = m_txop[i];
506 NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), false, "Have expected backoffs");
507 if (!state->m_expectedBackoff.empty ())
508 {
509 struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedBackoff.front ();
510 state->m_expectedBackoff.pop_front ();
511 NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected backoff is now");
512 state->StartBackoffNow (expected.nSlots, 0);
513 }
514}
515
516template <typename TxopType>
517void
518ChannelAccessManagerTest<TxopType>::NotifyChannelSwitching (void)
519{
520 for (auto& state : m_txop)
521 {
522 if (!state->m_expectedGrants.empty ())
523 {
524 std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
525 state->m_expectedGrants.pop_front ();
526 NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected grant is now");
527 }
528 state->Txop::GetLink (0).access = Txop::NOT_REQUESTED;
529 }
530}
531
532template <typename TxopType>
533void
535{
536 Ptr<TxopTest<TxopType>> state = m_txop[from];
537 struct TxopTest<TxopType>::ExpectedBackoff col;
538 col.at = time;
539 col.nSlots = nSlots;
540 state->m_expectedInternalCollision.push_back (col);
541}
542
543template <typename TxopType>
544void
545ChannelAccessManagerTest<TxopType>::ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from)
546{
547 Ptr<TxopTest<TxopType>> state = m_txop[from];
548 struct TxopTest<TxopType>::ExpectedBackoff backoff;
549 backoff.at = time;
550 backoff.nSlots = nSlots;
551 state->m_expectedBackoff.push_back (backoff);
552}
553
554template <typename TxopType>
555void
556ChannelAccessManagerTest<TxopType>::ExpectBusy (uint64_t time, bool busy)
557{
558 Simulator::Schedule (MicroSeconds (time) - Now (),
560}
561
562template <typename TxopType>
563void
565{
566 NS_TEST_EXPECT_MSG_EQ (m_ChannelAccessManager->IsBusy (), busy, "Incorrect busy/idle state");
567}
568
569template <typename TxopType>
570void
571ChannelAccessManagerTest<TxopType>::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue, uint16_t chWidth)
572{
573 m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub> ();
574 m_feManager = CreateObject<FrameExchangeManagerStub<TxopType>> (this);
575 m_ChannelAccessManager->SetupFrameExchangeManager (m_feManager);
576 m_ChannelAccessManager->SetSlot (MicroSeconds (slotTime));
577 m_ChannelAccessManager->SetSifs (MicroSeconds (sifs));
578 m_ChannelAccessManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs + sifs));
579 m_ackTimeoutValue = ackTimeoutValue;
580 // the purpose of the following operations is to initialize the last busy struct
581 // of the ChannelAccessManager. Indeed, InitLastBusyStructs(), which is called by
582 // SetupPhyListener(), requires an attached PHY to determine the channel types
583 // to initialize
584 m_phy = CreateObject<SpectrumWifiPhy> ();
585 m_phy->SetOperatingChannel (WifiPhy::ChannelTuple {0, chWidth,
587 m_phy->ConfigureStandard (WIFI_STANDARD_80211ac); // required to use 160 MHz channels
588 m_ChannelAccessManager->SetupPhyListener (m_phy);
589}
590
591template <typename TxopType>
592void
594{
595 Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>> (this, m_txop.size ());
596 m_txop.push_back (txop);
597 m_ChannelAccessManager->Add (txop);
598 // the following causes the creation of a link for the txop object
599 auto mac = CreateObject<AdhocWifiMac> ();
600 mac->SetWifiPhys ({nullptr});
601 txop->SetWifiMac (mac);
602 txop->SetAifsn (aifsn);
603}
604
605template <typename TxopType>
606void
608{
609 Simulator::Run ();
610
611 for (typename TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++)
612 {
613 Ptr<TxopTest<TxopType>> state = *i;
614 NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants");
615 NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions");
616 NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), true, "Have no expected backoffs");
617 state->Dispose ();
618 state = 0;
619 }
620 m_txop.clear ();
621
622 m_ChannelAccessManager->RemovePhyListener (m_phy);
623 m_phy->Dispose ();
624 m_ChannelAccessManager->Dispose ();
625 m_ChannelAccessManager = 0;
626 m_feManager = 0;
627 Simulator::Destroy ();
628}
629
630template <typename TxopType>
631void
633{
634 Simulator::Schedule (MicroSeconds (at) - Now (),
635 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
636 MicroSeconds (duration));
637 Simulator::Schedule (MicroSeconds (at + duration) - Now (),
638 &ChannelAccessManager::NotifyRxEndOkNow, m_ChannelAccessManager);
639}
640
641template <typename TxopType>
642void
644{
645 Simulator::Schedule (MicroSeconds (at) - Now (),
646 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
647 MicroSeconds (duration));
648}
649
650template <typename TxopType>
651void
653{
654 Simulator::Schedule (MicroSeconds (at) - Now (),
655 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
656 MicroSeconds (duration));
657 Simulator::Schedule (MicroSeconds (at + duration) - Now (),
658 &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
659}
660
661template <typename TxopType>
662void
663ChannelAccessManagerTest<TxopType>::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError)
664{
665 Simulator::Schedule (MicroSeconds (at) - Now (),
666 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
667 MicroSeconds (duration));
668 Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
669 &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
670 Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
671 &ChannelAccessManager::NotifyCcaBusyStartNow, m_ChannelAccessManager,
672 MicroSeconds (duration - timeUntilError), WIFI_CHANLIST_PRIMARY, std::vector<Time> {});
673}
674
675
676template <typename TxopType>
677void
679{
680 Simulator::Schedule (MicroSeconds (at) - Now (),
681 &ChannelAccessManager::NotifyNavResetNow, m_ChannelAccessManager,
682 MicroSeconds (duration));
683}
684
685template <typename TxopType>
686void
688{
689 Simulator::Schedule (MicroSeconds (at) - Now (),
690 &ChannelAccessManager::NotifyNavStartNow, m_ChannelAccessManager,
691 MicroSeconds (duration));
692}
693
694template <typename TxopType>
695void
697{
698 Simulator::Schedule (MicroSeconds (at) - Now (),
699 &ChannelAccessManager::NotifyAckTimeoutResetNow, m_ChannelAccessManager);
700}
701
702template <typename TxopType>
703void
705 uint64_t expectedGrantTime, uint32_t from)
706{
707 AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from);
708}
709
710template <typename TxopType>
711void
713 uint64_t expectedGrantTime, uint32_t from)
714{
715 Simulator::Schedule (MicroSeconds (at) - Now (),
717 txTime, expectedGrantTime, m_txop[from]);
718}
719
720template <typename TxopType>
721void
723 uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
724{
725 NS_ASSERT (ackDelay < m_ackTimeoutValue);
726 Simulator::Schedule (MicroSeconds (at) - Now (),
728 txTime, expectedGrantTime, m_txop[from]);
729 AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay);
730}
731
732template <typename TxopType>
733void
734ChannelAccessManagerTest<TxopType>::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime,
735 Ptr<TxopTest<TxopType>> state)
736{
737 if (m_ChannelAccessManager->NeedBackoffUponAccess (state))
738 {
739 state->GenerateBackoff (0);
740 }
741 state->QueueTx (txTime, expectedGrantTime);
742 m_ChannelAccessManager->RequestAccess (state);
743}
744
745template <typename TxopType>
746void
748 WifiChannelListType channelType,
749 const std::vector<Time>& per20MhzDurations)
750{
751 Simulator::Schedule (MicroSeconds (at) - Now (),
752 &ChannelAccessManager::NotifyCcaBusyStartNow, m_ChannelAccessManager,
753 MicroSeconds (duration), channelType, per20MhzDurations);
754}
755
756template <typename TxopType>
757void
759{
760 Simulator::Schedule (MicroSeconds (at) - Now (),
761 &ChannelAccessManager::NotifySwitchingStartNow, m_ChannelAccessManager,
762 MicroSeconds (duration));
763}
764
765template <typename TxopType>
766void
768{
769 Simulator::Schedule (MicroSeconds (at) - Now (),
770 &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
771 MicroSeconds (duration));
772}
773
774/*
775 * Specialization of DoRun () method for DCF
776 */
777template <>
778void
780{
781 // DCF immediate access (no backoff)
782 // 1 4 5 6 8 11 12
783 // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
784 //
785 StartTest (1, 3, 10);
786 AddTxop (1);
787 AddAccessRequest (1, 1, 5, 0);
788 AddAccessRequest (8, 2, 12, 0);
789 EndTest ();
790 // Check that receiving inside SIFS shall be cancelled properly:
791 // 1 4 5 6 9 10 14 17 18
792 // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
793 // |
794 // 7 start rx
795 //
796
797 StartTest (1, 3, 10);
798 AddTxop (1);
799 AddAccessRequest (1, 1, 5, 0);
800 AddRxInsideSifsEvt (7, 10);
801 AddTxEvt (9, 1);
802 AddAccessRequest (14, 2, 18, 0);
803 EndTest ();
804 // The test below mainly intends to test the case where the medium
805 // becomes busy in the middle of a backoff slot: the backoff counter
806 // must not be decremented for this backoff slot. This is the case
807 // below for the backoff slot starting at time 78us.
808 //
809 // 20 60 66 70 74 78 80 100 106 110 114 118 120
810 // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 | bslot3 | tx |
811 // |
812 // 30 request access. backoff slots: 4
813
814 StartTest (4, 6, 10);
815 AddTxop (1);
816 AddRxOkEvt (20, 40);
817 AddRxOkEvt (80, 20);
818 AddAccessRequest (30, 2, 118, 0);
819 ExpectBackoff (30, 4, 0); //backoff: 4 slots
820 EndTest ();
821 // Test the case where the backoff slots is zero.
822 //
823 // 20 60 66 70 72
824 // | rx | sifs | aifsn | tx |
825 // |
826 // 30 request access. backoff slots: 0
827
828 StartTest (4, 6, 10);
829 AddTxop (1);
830 AddRxOkEvt (20, 40);
831 AddAccessRequest (30, 2, 70, 0);
832 ExpectBackoff (30, 0, 0); // backoff: 0 slots
833 EndTest ();
834 // Test shows when two frames are received without interval between
835 // them:
836 // 20 60 100 106 110 112
837 // | rx | rx |sifs | aifsn | tx |
838 // |
839 // 30 request access. backoff slots: 0
840
841 StartTest (4, 6, 10);
842 AddTxop (1);
843 AddRxOkEvt (20, 40);
844 AddRxOkEvt (60, 40);
845 AddAccessRequest (30, 2, 110, 0);
846 ExpectBackoff (30, 0, 0); //backoff: 0 slots
847 EndTest ();
848
849 // Requesting access within SIFS interval (DCF immediate access)
850 //
851 // 20 60 62 68 72
852 // | rx | idle | sifs | aifsn | tx |
853 //
854 StartTest (4, 6, 10);
855 AddTxop (1);
856 AddRxOkEvt (20, 40);
857 AddAccessRequest (62, 2, 72, 0);
858 EndTest ();
859
860 // Requesting access after DIFS (DCF immediate access)
861 //
862 // 20 60 70 76 80
863 // | rx | idle | sifs | aifsn | tx |
864 //
865 StartTest (4, 6, 10);
866 AddTxop (1);
867 AddRxOkEvt (20, 40);
868 AddAccessRequest (70, 2, 80, 0);
869 EndTest ();
870
871 // Test an EIFS
872 //
873 // 20 60 66 76 86 90 94 98 102 106
874 // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
875 // | | <------eifs------>|
876 // 30 request access. backoff slots: 4
877 StartTest (4, 6, 10);
878 AddTxop (1);
879 AddRxErrorEvt (20, 40);
880 AddAccessRequest (30, 2, 102, 0);
881 ExpectBackoff (30, 4, 0); //backoff: 4 slots
882 EndTest ();
883
884 // Test DCF immediate access after an EIFS (EIFS is greater)
885 //
886 // 20 60 66 76 86
887 // | <----+-eifs------>|
888 // | rx | sifs | acktxttime | sifs + aifsn | tx |
889 // | sifs + aifsn |
890 // request access 70 80
891 StartTest (4, 6, 10);
892 AddTxop (1);
893 AddRxErrorEvt (20, 40);
894 AddAccessRequest (70, 2, 86, 0);
895 EndTest ();
896
897 // Test that channel stays busy for first frame's duration after Rx error
898 //
899 // 20 60
900 // | rx |
901 // |
902 // 40 force Rx error
903 StartTest (4, 6, 10);
904 AddTxop (1);
905 AddRxErrorEvt (20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
906 ExpectBusy (41, true); // channel should remain busy for remaining duration
907 ExpectBusy (59, true);
908 ExpectBusy (61, false);
909 EndTest ();
910
911 // Test an EIFS which is interrupted by a successful transmission.
912 //
913 // 20 60 66 69 75 81 85 89 93 97 101 103
914 // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
915 // | | <--eifs-->|
916 // 30 request access. backoff slots: 4
917 StartTest (4, 6, 10);
918 AddTxop (1);
919 AddRxErrorEvt (20, 40);
920 AddAccessRequest (30, 2, 101, 0);
921 ExpectBackoff (30, 4, 0); //backoff: 4 slots
922 AddRxOkEvt (69, 6);
923 EndTest ();
924
925 // Test two DCFs which suffer an internal collision. the first DCF has a higher
926 // priority than the second DCF.
927 //
928 // 20 60 66 70 74 78 88
929 // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
930 // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn | bslot | tx |
931 // 94 98 102 106 110 112
932 StartTest (4, 6, 10);
933 AddTxop (1); //high priority DCF
934 AddTxop (3); //low priority DCF
935 AddRxOkEvt (20, 40);
936 AddAccessRequest (30, 10, 78, 0);
937 ExpectBackoff (30, 2, 0); //backoff: 2 slot
938 AddAccessRequest (40, 2, 110, 1);
939 ExpectBackoff (40, 0, 1); //backoff: 0 slot
940 ExpectInternalCollision (78, 1, 1); //backoff: 1 slot
941 EndTest ();
942
943 // Test of AckTimeout handling: First queue requests access and ack procedure fails,
944 // inside the Ack timeout second queue with higher priority requests access.
945 //
946 // 20 26 34 54 74 80
947 // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
948 // DCF0 - high | | | sifs | tx |
949 // ^ request access
950 StartTest (4, 6, 10);
951 AddTxop (0); //high priority DCF
952 AddTxop (2); //low priority DCF
953 AddAccessRequestWithAckTimeout (20, 20, 34, 1);
954 AddAccessRequest (64, 10, 80, 0);
955 EndTest ();
956
957 // Test of AckTimeout handling:
958 //
959 // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
960 // inside this interval second queue with higher priority requests access.
961 //
962 // 20 26 34 54 56 62
963 // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
964 // DCF0 - high | | | sifs | tx |
965 // ^ request access
966 StartTest (4, 6, 10);
967 AddTxop (0); //high priority DCF
968 AddTxop (2); //low priority DCF
969 AddAccessRequestWithSuccessfullAck (20, 20, 34, 2, 1);
970 AddAccessRequest (55, 10, 62, 0);
971 EndTest ();
972
973 //Repeat the same but with one queue:
974 // 20 26 34 54 60 62 68 76 80
975 // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
976 // ^ request access
977 StartTest (4, 6, 10);
978 AddTxop (2);
979 AddAccessRequest (20, 20, 34, 0);
980 AddRxOkEvt (60, 2); // Ack
981 AddAccessRequest (61, 10, 80, 0);
982 ExpectBackoff (61, 1, 0); // 1 slot
983 EndTest ();
984
985 // test simple NAV count. This scenario models a simple Data+Ack handshake
986 // where the data rate used for the Ack is higher than expected by the Data source
987 // so, the data exchange completes before the end of NAV.
988 StartTest (4, 6, 10);
989 AddTxop (1);
990 AddRxOkEvt (20, 40);
991 AddNavStart (60, 15);
992 AddRxOkEvt (66, 5);
993 AddNavStart (71, 0);
994 AddAccessRequest (30, 10, 93, 0);
995 ExpectBackoff (30, 2, 0); //backoff: 2 slots
996 EndTest ();
997
998 // test more complex NAV handling by a CF-poll. This scenario models a
999 // simple Data+Ack handshake interrupted by a CF-poll which resets the
1000 // NAV counter.
1001 StartTest (4, 6, 10);
1002 AddTxop (1);
1003 AddRxOkEvt (20, 40);
1004 AddNavStart (60, 15);
1005 AddRxOkEvt (66, 5);
1006 AddNavReset (71, 2);
1007 AddAccessRequest (30, 10, 91, 0);
1008 ExpectBackoff (30, 2, 0); //backoff: 2 slots
1009 EndTest ();
1010
1011
1012 // 20 60 80 86 94
1013 // | rx | idle | sifs | aifsn | tx |
1014 // ^ request access
1015 StartTest (4, 6, 10);
1016 AddTxop (2);
1017 AddRxOkEvt (20, 40);
1018 AddAccessRequest (80, 10, 94, 0);
1019 EndTest ();
1020
1021
1022 StartTest (4, 6, 10);
1023 AddTxop (2);
1024 AddRxOkEvt (20, 40);
1025 AddRxOkEvt (78, 8);
1026 AddAccessRequest (30, 50, 108, 0);
1027 ExpectBackoff (30, 3, 0); //backoff: 3 slots
1028 EndTest ();
1029
1030
1031 // Channel switching tests
1032
1033 // 0 20 21 24 25 26
1034 // | switching | idle | sifs | aifsn | tx |
1035 // ^ access request.
1036 StartTest (1, 3, 10);
1037 AddTxop (1);
1038 AddSwitchingEvt (0, 20);
1039 AddAccessRequest (21, 1, 25, 0);
1040 EndTest ();
1041
1042 // 20 40 50 53 54 55 56 57
1043 // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
1044 // | |
1045 // 30 busy. 45 access request.
1046 //
1047 StartTest (1, 3, 10);
1048 AddTxop (1);
1049 AddSwitchingEvt (20,20);
1050 AddCcaBusyEvt (30,20);
1051 ExpectBackoff (45, 2, 0); //backoff: 2 slots
1052 AddAccessRequest (45, 1, 56, 0);
1053 EndTest ();
1054
1055 // 20 30 50 51 54 55 56
1056 // | rx | switching | idle | sifs | aifsn | tx |
1057 // ^ access request.
1058 //
1059 StartTest (1, 3, 10);
1060 AddTxop (1);
1061 AddRxStartEvt (20, 40);
1062 AddSwitchingEvt (30, 20);
1063 AddAccessRequest (51, 1, 55, 0);
1064 EndTest ();
1065
1066 // 20 30 50 51 54 55 56
1067 // | busy | switching | idle | sifs | aifsn | tx |
1068 // ^ access request.
1069 //
1070 StartTest (1, 3, 10);
1071 AddTxop (1);
1072 AddCcaBusyEvt (20, 40);
1073 AddSwitchingEvt (30, 20);
1074 AddAccessRequest (51, 1, 55, 0);
1075 EndTest ();
1076
1077 // 20 30 50 51 54 55 56
1078 // | nav | switching | idle | sifs | aifsn | tx |
1079 // ^ access request.
1080 //
1081 StartTest (1, 3, 10);
1082 AddTxop (1);
1083 AddNavStart (20,40);
1084 AddSwitchingEvt (30,20);
1085 AddAccessRequest (51, 1, 55, 0);
1086 EndTest ();
1087
1088 // 20 23 24 44 54 59 60 63 64 65
1089 // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1090 // | |
1091 // 49 access request. ^ access request.
1092 //
1093 StartTest (1, 3, 10);
1094 AddTxop (1);
1095 AddAccessRequestWithAckTimeout (20, 20, 24, 0);
1096 AddAccessRequest (49, 1, 54, 0);
1097 AddSwitchingEvt (54, 5);
1098 AddAccessRequest (60, 1, 64, 0);
1099 EndTest ();
1100
1101 // 20 60 66 70 74 78 80 100 101 107 111 113
1102 // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1103 // | |
1104 // 30 access request. ^ access request.
1105 //
1106 StartTest (4, 6, 10);
1107 AddTxop (1);
1108 AddRxOkEvt (20,40);
1109 AddAccessRequest (30, 2, 80, 0);
1110 ExpectBackoff (30, 4, 0); //backoff: 4 slots
1111 AddSwitchingEvt (80,20);
1112 AddAccessRequest (101, 2, 111, 0);
1113 EndTest ();
1114}
1115
1116/*
1117 * Specialization of DoRun () method for EDCA
1118 */
1119template <>
1120void
1122{
1123 // Check alignment at slot boundary after successful reception (backoff = 0).
1124 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1125 // 20 50 56 60 80
1126 // | cca_busy |
1127 // | rx | sifs | aifsn | tx |
1128 // |
1129 // 52 request access
1130 StartTest (4, 6, 10, 20, 40);
1131 AddTxop (1);
1132 AddRxOkEvt (20, 30);
1133 AddCcaBusyEvt (50, 10, WIFI_CHANLIST_SECONDARY);
1134 AddAccessRequest (52, 20, 60, 0);
1135 EndTest ();
1136
1137 // Check alignment at slot boundary after successful reception (backoff = 0).
1138 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1139 // 20 50 56 60 80
1140 // | cca_busy |
1141 // | rx | sifs | aifsn | tx |
1142 // |
1143 // 58 request access
1144 StartTest (4, 6, 10, 20, 80);
1145 AddTxop (1);
1146 AddRxOkEvt (20, 30);
1147 AddCcaBusyEvt (50, 10, WIFI_CHANLIST_SECONDARY);
1148 AddAccessRequest (58, 20, 60, 0);
1149 EndTest ();
1150
1151 // Check alignment at slot boundary after successful reception (backoff = 0).
1152 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1153 // 20 50 56 60 64 84
1154 // | cca_busy |
1155 // | rx | sifs | aifsn | idle | tx |
1156 // |
1157 // 62 request access
1158 StartTest (4, 6, 10, 20, 80);
1159 AddTxop (1);
1160 AddRxOkEvt (20, 30);
1161 AddCcaBusyEvt (50, 14, WIFI_CHANLIST_SECONDARY40);
1162 AddAccessRequest (62, 20, 64, 0);
1163 EndTest ();
1164
1165 // Check alignment at slot boundary after failed reception (backoff = 0).
1166 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1167 // 20 50 56 66 76 96
1168 // | cca_busy |
1169 // | | <------eifs------>| | |
1170 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1171 // |
1172 // 55 request access
1173 StartTest (4, 6, 10, 20, 160);
1174 AddTxop (1);
1175 AddRxErrorEvt (20, 30);
1176 AddCcaBusyEvt (50, 26, WIFI_CHANLIST_SECONDARY);
1177 AddAccessRequest (55, 20, 76, 0);
1178 EndTest ();
1179
1180 // Check alignment at slot boundary after failed reception (backoff = 0).
1181 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1182 // 20 50 56 66 76 96
1183 // | cca_busy |
1184 // | | <------eifs------>| | |
1185 // | rx | sifs | acktxttime | sifs + aifsn | tx |
1186 // |
1187 // 70 request access
1188 StartTest (4, 6, 10, 20, 160);
1189 AddTxop (1);
1190 AddRxErrorEvt (20, 30);
1191 AddCcaBusyEvt (50, 26, WIFI_CHANLIST_SECONDARY40);
1192 AddAccessRequest (70, 20, 76, 0);
1193 EndTest ();
1194
1195 // Check alignment at slot boundary after failed reception (backoff = 0).
1196 // Also, check that CCA BUSY on a secondary channel does not affect channel access:
1197 // 20 50 56 66 76 84
1198 // | cca_busy |
1199 // | | <------eifs------>| | |
1200 // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1201 // |
1202 // 82 request access
1203 StartTest (4, 6, 10, 20, 160);
1204 AddTxop (1);
1205 AddRxErrorEvt (20, 30);
1206 AddCcaBusyEvt (50, 34, WIFI_CHANLIST_SECONDARY80);
1207 AddAccessRequest (82, 20, 84, 0);
1208 EndTest ();
1209
1210 // Check backoff decrement at slot boundaries. Medium idle during backoff
1211 // 20 50 56 60 64 68 72 76 96
1212 // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1213 // | | | | |
1214 // 30 request access. decrement decrement decrement decrement
1215 // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1216 StartTest (4, 6, 10);
1217 AddTxop (1);
1218 AddRxOkEvt (20, 30);
1219 AddAccessRequest (30, 20, 76, 0);
1220 ExpectBackoff (30, 4, 0);
1221 EndTest ();
1222
1223 // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1224 // 20 50 56 60 61 71 77 81 85 87 97 103 107 127
1225 // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs | aifsn | tx |
1226 // | | | |
1227 // 30 request access. decrement decrement decrement
1228 // backoff slots: 3 slots: 2 slots: 1 slots: 0
1229 StartTest (4, 6, 10);
1230 AddTxop (1);
1231 AddRxOkEvt (20, 30);
1232 AddRxOkEvt (61, 10);
1233 AddRxOkEvt (87, 10);
1234 AddAccessRequest (30, 20, 107, 0);
1235 ExpectBackoff (30, 3, 0);
1236 EndTest ();
1237}
1238
1239
1253{
1254public:
1257
1258private:
1259 void DoRun (void) override;
1260
1267 void RunOne (uint16_t chWidth, WifiChannelListType busyChannel);
1268
1271};
1272
1274 : TestCase ("Check calculation of the largest idle primary channel")
1275{
1276}
1277
1278void
1280{
1300
1301 // After 1ms, we are notified of CCA_BUSY for 1ms on the given channel
1302 Time ccaBusyStartDelay = MilliSeconds (1);
1303 Time ccaBusyDuration = MilliSeconds (1);
1304 Simulator::Schedule (ccaBusyStartDelay, &ChannelAccessManager::NotifyCcaBusyStartNow, m_cam,
1305 ccaBusyDuration, busyChannel, std::vector<Time> (chWidth / 20, Seconds (0)));
1306
1307 // During any interval ending within CCA_BUSY period, the idle channel is the
1308 // primary channel contiguous to the busy secondary channel, if the busy channel
1309 // is a secondary channel, or there is no idle channel, otherwise.
1310 uint16_t idleWidth = (busyChannel == WifiChannelListType::WIFI_CHANLIST_PRIMARY)
1311 ? 0 : ((1 << (busyChannel - 1)) * 20);
1312
1313 Time checkTime1 = start + ccaBusyStartDelay + ccaBusyDuration / 2;
1314 Simulator::Schedule (checkTime1 - start,
1315 [=]()
1316 {
1317 Time interval1 = (ccaBusyStartDelay + ccaBusyDuration) / 2;
1319 idleWidth,
1320 "Incorrect width of the idle channel in an interval "
1321 << "ending within CCA_BUSY (channel width: " << chWidth
1322 << " MHz, busy channel: " << busyChannel << ")");
1323 });
1324
1325 // During any interval starting within CCA_BUSY period, the idle channel is the
1326 // same as the previous case
1327 Time ccaBusyRxInterval = MilliSeconds (1);
1328 Time checkTime2 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval / 2;
1329 Simulator::Schedule (checkTime2 - start,
1330 [=]()
1331 {
1332 Time interval2 = (ccaBusyDuration + ccaBusyRxInterval) / 2;
1334 idleWidth,
1335 "Incorrect width of the idle channel in an interval "
1336 << "starting within CCA_BUSY (channel width: " << chWidth
1337 << " MHz, busy channel: " << busyChannel << ")");
1338 });
1339
1340 // Notify RX start
1341 Time rxDuration = MilliSeconds (1);
1342 Simulator::Schedule (ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval,
1343 &ChannelAccessManager::NotifyRxStartNow, m_cam, rxDuration);
1344
1345 // At RX end, we check the status of the channel during an interval immediately
1346 // preceding RX start and overlapping the CCA_BUSY period.
1347 Time checkTime3 = start + ccaBusyStartDelay + ccaBusyDuration + ccaBusyRxInterval + rxDuration;
1348 Simulator::Schedule (checkTime3 - start,
1349 [=]()
1350 {
1351 Time interval3 = ccaBusyDuration / 2 + ccaBusyRxInterval;
1352 Time end3 = checkTime3 - rxDuration;
1354 idleWidth,
1355 "Incorrect width of the idle channel in an interval "
1356 << "preceding RX start and overlapping CCA_BUSY "
1357 << "(channel width: " << chWidth
1358 << " MHz, busy channel: " << busyChannel << ")");
1359 });
1360
1361 // At RX end, we check the status of the channel during the interval following
1362 // the CCA_BUSY period and preceding RX start. The entire operating channel is idle.
1363 Time checkTime4 = checkTime3;
1364 Simulator::Schedule (checkTime4 - start,
1365 [=]()
1366 {
1367 Time interval4 = ccaBusyRxInterval;
1368 Time end4 = checkTime4 - rxDuration;
1370 chWidth,
1371 "Incorrect width of the idle channel in the interval "
1372 << "following CCA_BUSY and preceding RX start (channel "
1373 << "width: " << chWidth << " MHz, busy channel: "
1374 << busyChannel << ")");
1375 });
1376
1377 // After RX end, the entire operating channel is idle if the interval does not
1378 // overlap the RX period
1379 Time interval5 = MilliSeconds (1);
1380 Time checkTime5 = checkTime4 + interval5;
1381 Simulator::Schedule (checkTime5 - start,
1382 [=]()
1383 {
1385 chWidth,
1386 "Incorrect width of the idle channel in an interval "
1387 << "following RX end (channel width: " << chWidth
1388 << " MHz, busy channel: " << busyChannel << ")");
1389 });
1390
1391 // After RX end, no channel is idle if the interval overlaps the RX period
1392 Time checkTime6 = checkTime5;
1393 Simulator::Schedule (checkTime6 - start,
1394 [=]()
1395 {
1396 Time interval6 = interval5 + rxDuration / 2;
1398 0,
1399 "Incorrect width of the idle channel in an interval "
1400 << "overlapping RX (channel width: " << chWidth
1401 << " MHz, busy channel: " << busyChannel << ")");
1402 });
1403}
1404
1405
1406void
1408{
1409 m_cam = CreateObject<ChannelAccessManager> ();
1410 uint16_t delay = 0;
1411 uint8_t channel = 0;
1412 std::list<WifiChannelListType> busyChannels;
1413
1414 for (uint16_t chWidth : {20, 40, 80, 160})
1415 {
1416 busyChannels.push_back (static_cast<WifiChannelListType> (channel));
1417
1418 for (const auto busyChannel : busyChannels)
1419 {
1420 Simulator::Schedule (Seconds (delay),
1421 [this, chWidth, busyChannel]()
1422 {
1423 // reset PHY
1424 if (m_phy)
1425 {
1427 m_phy->Dispose ();
1428 }
1429 // create a new PHY operating on a channel of the current width
1430 m_phy = CreateObject<SpectrumWifiPhy> ();
1432 WIFI_PHY_BAND_5GHZ, 0});
1434 // call SetupPhyListener to initialize the ChannelAccessManager
1435 // last busy structs
1437 // run the tests
1438 RunOne (chWidth, busyChannel);
1439 });
1440 delay++;
1441 }
1442 channel++;
1443 }
1444
1445 Simulator::Run ();
1447 m_phy->Dispose ();
1448 m_cam->Dispose ();
1449 Simulator::Destroy ();
1450}
1451
1452
1460{
1461public:
1462 TxopTestSuite ();
1463};
1464
1466 : TestSuite ("wifi-devices-dcf", UNIT)
1467{
1468 AddTestCase (new ChannelAccessManagerTest<Txop>, TestCase::QUICK);
1469}
1470
1472
1480{
1481public:
1483};
1484
1486 : TestSuite ("wifi-devices-edca", UNIT)
1487{
1488 AddTestCase (new ChannelAccessManagerTest<QosTxop>, TestCase::QUICK);
1489}
1490
1492
1500{
1501public:
1503};
1504
1506 : TestSuite ("wifi-channel-access-manager", UNIT)
1507{
1508 AddTestCase (new LargestIdlePrimaryChannelTest, TestCase::QUICK);
1509}
1510
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, uint16_t allowedWidth) override
Request the FrameExchangeManager to start a frame exchange sequence.
Test the calculation of the largest idle primary channel performed by ChannelAccessManager::GetLarges...
void 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
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.
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::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:559
virtual void ConfigureStandard(WifiStandard standard)
Configure the PHY-level parameters for different Wi-Fi standard.
Definition: wifi-phy.cc:883
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:993
std::tuple< uint8_t, uint16_t, int, uint8_t > ChannelTuple
Tuple identifying an operating channel.
Definition: wifi-phy.h:839
#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: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(Ptr< T2 > const &p)
Cast a Ptr.
Definition: ptr.h:621
channel
Definition: third.py:83
mac
Definition: third.py:87
def start()
Definition: core.py:1852