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