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