A Discrete-Event Network Simulator
API
channel-access-manager-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "ns3/test.h"
22 #include "ns3/simulator.h"
23 #include "ns3/channel-access-manager.h"
24 #include "ns3/qos-txop.h"
25 #include "ns3/mac-low.h"
26 
27 using namespace ns3;
28 
29 template <typename TxopType>
31 
38 template <typename TxopType>
39 class TxopTest : public TxopType
40 {
41 public:
48  TxopTest (ChannelAccessManagerTest<TxopType> *test, uint32_t i);
49 
55  void QueueTx (uint64_t txTime, uint64_t expectedGrantTime);
56 
57 private:
59  friend class ChannelAccessManagerTest<TxopType>;
60 
62  void DoDispose (void);
63 
64  typedef std::pair<uint64_t,uint64_t> ExpectedGrant;
65  typedef std::list<ExpectedGrant> ExpectedGrants;
66  struct ExpectedBackoff
68  {
69  uint64_t at;
70  uint32_t nSlots;
71  };
72  typedef std::list<struct ExpectedBackoff> ExpectedBackoffs;
73 
77 
82  bool IsAccessRequested (void) const;
86  void NotifyAccessRequested (void);
90  void NotifyAccessGranted (void);
94  void NotifyInternalCollision (void);
98  void GenerateBackoff (void);
103  bool HasFramesToTransmit (void);
107  void NotifyChannelSwitching (void);
112  void NotifySleep (void);
116  void NotifyWakeUp (void);
117 
119  uint32_t m_i;
121 };
122 
129 class MacLowStub : public MacLow
130 {
131 public:
133  {
134  }
141  bool IsCfPeriod (void) const
142  {
143  return false;
144  }
145 };
146 
154 {
155 public:
157  {
158  }
164  void SetSifs (Time sifs)
165  {
166  m_sifs = sifs;
167  }
173  void SetSlot (Time slot)
174  {
175  m_slot = slot;
176  }
182  void SetEifsNoDifs (Time eifsNoDifs)
183  {
184  m_eifsNoDifs = eifsNoDifs;
185  }
186 
187 private:
188  // Inherited from base class
189  Time GetSifs (void) const
190  {
191  return m_sifs;
192  }
193 
194  Time GetSlot (void) const
195  {
196  return m_slot;
197  }
198 
199  Time GetEifsNoDifs (void) const
200  {
201  return m_eifsNoDifs;
202  }
203 
204  Time m_slot; // slot duration
205  Time m_sifs; // SIFS duration
206  Time m_eifsNoDifs; // EIFS duration minus a DIFS
207 };
208 
215 template <typename TxopType>
216 class ChannelAccessManagerTest : public TestCase
217 {
218 public:
220  virtual void DoRun (void);
221 
226  void NotifyAccessGranted (uint32_t i);
231  void NotifyInternalCollision (uint32_t i);
236  void GenerateBackoff (uint32_t i);
241  void NotifyChannelSwitching (uint32_t i);
242 
243 
244 private:
252  void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue = 20);
257  void AddTxop (uint32_t aifsn);
259  void EndTest (void);
266  void ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from);
273  void ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from);
279  void ExpectBusy (uint64_t time, bool busy);
284  void DoCheckBusy (bool busy);
290  void AddRxOkEvt (uint64_t at, uint64_t duration);
296  void AddRxErrorEvt (uint64_t at, uint64_t duration);
303  void AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError);
309  void AddRxInsideSifsEvt (uint64_t at, uint64_t duration);
315  void AddTxEvt (uint64_t at, uint64_t duration);
321  void AddNavReset (uint64_t at, uint64_t duration);
327  void AddNavStart (uint64_t at, uint64_t duration);
332  void AddAckTimeoutReset (uint64_t at);
340  void AddAccessRequest (uint64_t at, uint64_t txTime,
341  uint64_t expectedGrantTime, uint32_t from);
349  void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
350  uint64_t expectedGrantTime, uint32_t from);
359  void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
360  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
367  void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr<TxopTest<TxopType>> state);
373  void AddCcaBusyEvt (uint64_t at, uint64_t duration);
379  void AddSwitchingEvt (uint64_t at, uint64_t duration);
385  void AddRxStartEvt (uint64_t at, uint64_t duration);
386 
387  typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests;
388 
392  uint32_t m_ackTimeoutValue;
393 };
394 
395 template <typename TxopType>
396 void
397 TxopTest<TxopType>::QueueTx (uint64_t txTime, uint64_t expectedGrantTime)
398 {
399  m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime));
400 }
401 
402 template <typename TxopType>
404  : m_test (test),
405  m_i (i),
406  m_accessRequested (false)
407 {
408 }
409 
410 template <typename TxopType>
411 void
413 {
414  m_test = 0;
415  Txop::DoDispose ();
416 }
417 
418 template <typename TxopType>
419 bool
421 {
422  return m_accessRequested;
423 }
424 
425 template <typename TxopType>
426 void
428 {
429  m_accessRequested = true;
430 }
431 
432 template <typename TxopType>
433 void
435 {
436  m_accessRequested = false;
437  m_test->NotifyAccessGranted (m_i);
438 }
439 
440 template <typename TxopType>
441 void
443 {
444  m_test->NotifyInternalCollision (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  m_test->NotifyChannelSwitching (m_i);
466 }
467 
468 template <typename TxopType>
469 void
471 {
472 }
473 
474 template <typename TxopType>
475 void
477 {
478 }
479 
480 template <typename TxopType>
482  : TestCase ("ChannelAccessManager")
483 {
484 }
485 
486 template <typename TxopType>
487 void
489 {
490  Ptr<TxopTest<TxopType>> state = m_txop[i];
491  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants");
492  if (!state->m_expectedGrants.empty ())
493  {
494  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
495  state->m_expectedGrants.pop_front ();
496  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected access grant is now");
497  m_ChannelAccessManager->NotifyTxStartNow (MicroSeconds (expected.first));
498  m_ChannelAccessManager->NotifyAckTimeoutStartNow (MicroSeconds (m_ackTimeoutValue + expected.first));
499  }
500 }
501 
502 template <typename TxopType>
503 void
504 ChannelAccessManagerTest<TxopType>::AddTxEvt (uint64_t at, uint64_t duration)
505 {
506  Simulator::Schedule (MicroSeconds (at) - Now (),
507  &ChannelAccessManager::NotifyTxStartNow, m_ChannelAccessManager,
508  MicroSeconds (duration));
509 }
510 
511 template <typename TxopType>
512 void
514 {
515  Ptr<TxopTest<TxopType>> state = m_txop[i];
516  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions");
517  if (!state->m_expectedInternalCollision.empty ())
518  {
519  struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedInternalCollision.front ();
520  state->m_expectedInternalCollision.pop_front ();
521  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now");
522  state->StartBackoffNow (expected.nSlots);
523  }
524 }
525 
526 template <typename TxopType>
527 void
529 {
530  Ptr<TxopTest<TxopType>> state = m_txop[i];
531  NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), false, "Have expected backoffs");
532  if (!state->m_expectedBackoff.empty ())
533  {
534  struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedBackoff.front ();
535  state->m_expectedBackoff.pop_front ();
536  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected backoff is now");
537  state->StartBackoffNow (expected.nSlots);
538  }
539 }
540 
541 template <typename TxopType>
542 void
544 {
545  Ptr<TxopTest<TxopType>> state = m_txop[i];
546  if (!state->m_expectedGrants.empty ())
547  {
548  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
549  state->m_expectedGrants.pop_front ();
550  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected grant is now");
551  }
552  state->m_accessRequested = false;
553 }
554 
555 template <typename TxopType>
556 void
557 ChannelAccessManagerTest<TxopType>::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from)
558 {
559  Ptr<TxopTest<TxopType>> state = m_txop[from];
560  struct TxopTest<TxopType>::ExpectedBackoff col;
561  col.at = time;
562  col.nSlots = nSlots;
563  state->m_expectedInternalCollision.push_back (col);
564 }
565 
566 template <typename TxopType>
567 void
568 ChannelAccessManagerTest<TxopType>::ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from)
569 {
570  Ptr<TxopTest<TxopType>> state = m_txop[from];
571  struct TxopTest<TxopType>::ExpectedBackoff backoff;
572  backoff.at = time;
573  backoff.nSlots = nSlots;
574  state->m_expectedBackoff.push_back (backoff);
575 }
576 
577 template <typename TxopType>
578 void
579 ChannelAccessManagerTest<TxopType>::ExpectBusy (uint64_t time, bool busy)
580 {
581  Simulator::Schedule (MicroSeconds (time) - Now (),
583 }
584 
585 template <typename TxopType>
586 void
588 {
589  NS_TEST_EXPECT_MSG_EQ (m_ChannelAccessManager->IsBusy (), busy, "Incorrect busy/idle state");
590 }
591 
592 template <typename TxopType>
593 void
594 ChannelAccessManagerTest<TxopType>::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue)
595 {
596  m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub> ();
597  m_low = CreateObject<MacLowStub> ();
598  m_ChannelAccessManager->SetupLow (m_low);
599  m_ChannelAccessManager->SetSlot (MicroSeconds (slotTime));
600  m_ChannelAccessManager->SetSifs (MicroSeconds (sifs));
601  m_ChannelAccessManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs + sifs));
602  m_ackTimeoutValue = ackTimeoutValue;
603 }
604 
605 template <typename TxopType>
606 void
608 {
609  Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>> (this, m_txop.size ());
610  txop->SetAifsn (aifsn);
611  m_txop.push_back (txop);
612  txop->SetChannelAccessManager (m_ChannelAccessManager);
613  txop->SetMacLow (m_low);
614 }
615 
616 template <typename TxopType>
617 void
619 {
620  Simulator::Run ();
621  Simulator::Destroy ();
622 
623  for (typename TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++)
624  {
625  Ptr<TxopTest<TxopType>> state = *i;
626  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants");
627  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions");
628  NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), true, "Have no expected backoffs");
629  state->Dispose ();
630  state = 0;
631  }
632  m_txop.clear ();
633 
634  m_ChannelAccessManager = 0;
635  m_low = 0;
636 }
637 
638 template <typename TxopType>
639 void
640 ChannelAccessManagerTest<TxopType>::AddRxOkEvt (uint64_t at, uint64_t duration)
641 {
642  Simulator::Schedule (MicroSeconds (at) - Now (),
643  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
644  MicroSeconds (duration));
645  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
646  &ChannelAccessManager::NotifyRxEndOkNow, m_ChannelAccessManager);
647 }
648 
649 template <typename TxopType>
650 void
652 {
653  Simulator::Schedule (MicroSeconds (at) - Now (),
654  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
655  MicroSeconds (duration));
656 }
657 
658 template <typename TxopType>
659 void
661 {
662  Simulator::Schedule (MicroSeconds (at) - Now (),
663  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
664  MicroSeconds (duration));
665  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
666  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
667 }
668 
669 template <typename TxopType>
670 void
671 ChannelAccessManagerTest<TxopType>::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError)
672 {
673  Simulator::Schedule (MicroSeconds (at) - Now (),
674  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
675  MicroSeconds (duration));
676  Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
677  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
678 }
679 
680 
681 template <typename TxopType>
682 void
683 ChannelAccessManagerTest<TxopType>::AddNavReset (uint64_t at, uint64_t duration)
684 {
685  Simulator::Schedule (MicroSeconds (at) - Now (),
686  &ChannelAccessManager::NotifyNavResetNow, m_ChannelAccessManager,
687  MicroSeconds (duration));
688 }
689 
690 template <typename TxopType>
691 void
692 ChannelAccessManagerTest<TxopType>::AddNavStart (uint64_t at, uint64_t duration)
693 {
694  Simulator::Schedule (MicroSeconds (at) - Now (),
695  &ChannelAccessManager::NotifyNavStartNow, m_ChannelAccessManager,
696  MicroSeconds (duration));
697 }
698 
699 template <typename TxopType>
700 void
702 {
703  Simulator::Schedule (MicroSeconds (at) - Now (),
704  &ChannelAccessManager::NotifyAckTimeoutResetNow, m_ChannelAccessManager);
705 }
706 
707 template <typename TxopType>
708 void
710  uint64_t expectedGrantTime, uint32_t from)
711 {
712  AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from);
713 }
714 
715 template <typename TxopType>
716 void
718  uint64_t expectedGrantTime, uint32_t from)
719 {
720  Simulator::Schedule (MicroSeconds (at) - Now (),
722  txTime, expectedGrantTime, m_txop[from]);
723 }
724 
725 template <typename TxopType>
726 void
728  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
729 {
730  NS_ASSERT (ackDelay < m_ackTimeoutValue);
731  Simulator::Schedule (MicroSeconds (at) - Now (),
733  txTime, expectedGrantTime, m_txop[from]);
734  AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay);
735 }
736 
737 template <typename TxopType>
738 void
739 ChannelAccessManagerTest<TxopType>::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime,
740  Ptr<TxopTest<TxopType>> state)
741 {
742  if (m_ChannelAccessManager->NeedBackoffUponAccess (state))
743  {
744  state->GenerateBackoff ();
745  }
746  state->QueueTx (txTime, expectedGrantTime);
747  m_ChannelAccessManager->RequestAccess (state);
748 }
749 
750 template <typename TxopType>
751 void
753 {
754  Simulator::Schedule (MicroSeconds (at) - Now (),
755  &ChannelAccessManager::NotifyMaybeCcaBusyStartNow, m_ChannelAccessManager,
756  MicroSeconds (duration));
757 }
758 
759 template <typename TxopType>
760 void
762 {
763  Simulator::Schedule (MicroSeconds (at) - Now (),
764  &ChannelAccessManager::NotifySwitchingStartNow, m_ChannelAccessManager,
765  MicroSeconds (duration));
766 }
767 
768 template <typename TxopType>
769 void
771 {
772  Simulator::Schedule (MicroSeconds (at) - Now (),
773  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
774  MicroSeconds (duration));
775 }
776 
777 /*
778  * Specialization of DoRun () method for DCF
779  */
780 template <>
781 void
783 {
784  // DCF immediate access (no backoff)
785  // 1 4 5 6 8 11 12
786  // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
787  //
788  StartTest (1, 3, 10);
789  AddTxop (1);
790  AddAccessRequest (1, 1, 5, 0);
791  AddAccessRequest (8, 2, 12, 0);
792  EndTest ();
793  // Check that receiving inside SIFS shall be cancelled properly:
794  // 1 4 5 6 9 10 14 17 18
795  // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
796  // |
797  // 7 start rx
798  //
799 
800  StartTest (1, 3, 10);
801  AddTxop (1);
802  AddAccessRequest (1, 1, 5, 0);
803  AddRxInsideSifsEvt (7, 10);
804  AddTxEvt (9, 1);
805  AddAccessRequest (14, 2, 18, 0);
806  EndTest ();
807  // The test below mainly intends to test the case where the medium
808  // becomes busy in the middle of a backoff slot: the backoff counter
809  // must not be decremented for this backoff slot. This is the case
810  // below for the backoff slot starting at time 78us.
811  //
812  // 20 60 66 70 74 78 80 100 106 110 114 118 120
813  // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 | bslot3 | tx |
814  // |
815  // 30 request access. backoff slots: 4
816 
817  StartTest (4, 6, 10);
818  AddTxop (1);
819  AddRxOkEvt (20, 40);
820  AddRxOkEvt (80, 20);
821  AddAccessRequest (30, 2, 118, 0);
822  ExpectBackoff (30, 4, 0); //backoff: 4 slots
823  EndTest ();
824  // Test the case where the backoff slots is zero.
825  //
826  // 20 60 66 70 72
827  // | rx | sifs | aifsn | tx |
828  // |
829  // 30 request access. backoff slots: 0
830 
831  StartTest (4, 6, 10);
832  AddTxop (1);
833  AddRxOkEvt (20, 40);
834  AddAccessRequest (30, 2, 70, 0);
835  ExpectBackoff (30, 0, 0); // backoff: 0 slots
836  EndTest ();
837  // Test shows when two frames are received without interval between
838  // them:
839  // 20 60 100 106 110 112
840  // | rx | rx |sifs | aifsn | tx |
841  // |
842  // 30 request access. backoff slots: 0
843 
844  StartTest (4, 6, 10);
845  AddTxop (1);
846  AddRxOkEvt (20, 40);
847  AddRxOkEvt (60, 40);
848  AddAccessRequest (30, 2, 110, 0);
849  ExpectBackoff (30, 0, 0); //backoff: 0 slots
850  EndTest ();
851 
852  // Requesting access within SIFS interval (DCF immediate access)
853  //
854  // 20 60 62 68 72
855  // | rx | idle | sifs | aifsn | tx |
856  //
857  StartTest (4, 6, 10);
858  AddTxop (1);
859  AddRxOkEvt (20, 40);
860  AddAccessRequest (62, 2, 72, 0);
861  EndTest ();
862 
863  // Requesting access after DIFS (DCF immediate access)
864  //
865  // 20 60 70 76 80
866  // | rx | idle | sifs | aifsn | tx |
867  //
868  StartTest (4, 6, 10);
869  AddTxop (1);
870  AddRxOkEvt (20, 40);
871  AddAccessRequest (70, 2, 80, 0);
872  EndTest ();
873 
874  // Test an EIFS
875  //
876  // 20 60 66 76 86 90 94 98 102 106
877  // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
878  // | | <------eifs------>|
879  // 30 request access. backoff slots: 4
880  StartTest (4, 6, 10);
881  AddTxop (1);
882  AddRxErrorEvt (20, 40);
883  AddAccessRequest (30, 2, 102, 0);
884  ExpectBackoff (30, 4, 0); //backoff: 4 slots
885  EndTest ();
886 
887  // Test DCF immediate access after an EIFS (EIFS is greater)
888  //
889  // 20 60 66 76 86
890  // | <----+-eifs------>|
891  // | rx | sifs | acktxttime | sifs + aifsn | tx |
892  // | sifs + aifsn |
893  // request access 70 80
894  StartTest (4, 6, 10);
895  AddTxop (1);
896  AddRxErrorEvt (20, 40);
897  AddAccessRequest (70, 2, 86, 0);
898  EndTest ();
899 
900  // Test that channel stays busy for first frame's duration after Rx error
901  //
902  // 20 60
903  // | rx |
904  // |
905  // 40 force Rx error
906  StartTest (4, 6, 10);
907  AddTxop (1);
908  AddRxErrorEvt (20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
909  ExpectBusy (41, true); // channel should remain busy for remaining duration
910  ExpectBusy (59, true);
911  ExpectBusy (61, false);
912  EndTest ();
913 
914  // Test an EIFS which is interrupted by a successful transmission.
915  //
916  // 20 60 66 69 75 81 85 89 93 97 101 103
917  // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
918  // | | <--eifs-->|
919  // 30 request access. backoff slots: 4
920  StartTest (4, 6, 10);
921  AddTxop (1);
922  AddRxErrorEvt (20, 40);
923  AddAccessRequest (30, 2, 101, 0);
924  ExpectBackoff (30, 4, 0); //backoff: 4 slots
925  AddRxOkEvt (69, 6);
926  EndTest ();
927 
928  // Test two DCFs which suffer an internal collision. the first DCF has a higher
929  // priority than the second DCF.
930  //
931  // 20 60 66 70 74 78 88
932  // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
933  // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn | bslot | tx |
934  // 94 98 102 106 110 112
935  StartTest (4, 6, 10);
936  AddTxop (1); //high priority DCF
937  AddTxop (3); //low priority DCF
938  AddRxOkEvt (20, 40);
939  AddAccessRequest (30, 10, 78, 0);
940  ExpectBackoff (30, 2, 0); //backoff: 2 slot
941  AddAccessRequest (40, 2, 110, 1);
942  ExpectBackoff (40, 0, 1); //backoff: 0 slot
943  ExpectInternalCollision (78, 1, 1); //backoff: 1 slot
944  EndTest ();
945 
946  // Test of AckTimeout handling: First queue requests access and ack procedure fails,
947  // inside the Ack timeout second queue with higher priority requests access.
948  //
949  // 20 26 34 54 74 80
950  // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
951  // DCF0 - high | | | sifs | tx |
952  // ^ request access
953  StartTest (4, 6, 10);
954  AddTxop (0); //high priority DCF
955  AddTxop (2); //low priority DCF
956  AddAccessRequestWithAckTimeout (20, 20, 34, 1);
957  AddAccessRequest (64, 10, 80, 0);
958  EndTest ();
959 
960  // Test of AckTimeout handling:
961  //
962  // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
963  // inside this interval second queue with higher priority requests access.
964  //
965  // 20 26 34 54 56 62
966  // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
967  // DCF0 - high | | | sifs | tx |
968  // ^ request access
969  StartTest (4, 6, 10);
970  AddTxop (0); //high priority DCF
971  AddTxop (2); //low priority DCF
972  AddAccessRequestWithSuccessfullAck (20, 20, 34, 2, 1);
973  AddAccessRequest (55, 10, 62, 0);
974  EndTest ();
975 
976  //Repeat the same but with one queue:
977  // 20 26 34 54 60 62 68 76 80
978  // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
979  // ^ request access
980  StartTest (4, 6, 10);
981  AddTxop (2);
982  AddAccessRequest (20, 20, 34, 0);
983  AddRxOkEvt (60, 2); // Ack
984  AddAccessRequest (61, 10, 80, 0);
985  ExpectBackoff (61, 1, 0); // 1 slot
986  EndTest ();
987 
988  // test simple NAV count. This scenario models a simple Data+Ack handshake
989  // where the data rate used for the Ack is higher than expected by the Data source
990  // so, the data exchange completes before the end of NAV.
991  StartTest (4, 6, 10);
992  AddTxop (1);
993  AddRxOkEvt (20, 40);
994  AddNavStart (60, 15);
995  AddRxOkEvt (66, 5);
996  AddNavStart (71, 0);
997  AddAccessRequest (30, 10, 93, 0);
998  ExpectBackoff (30, 2, 0); //backoff: 2 slots
999  EndTest ();
1000 
1001  // test more complex NAV handling by a CF-poll. This scenario models a
1002  // simple Data+Ack handshake interrupted by a CF-poll which resets the
1003  // NAV counter.
1004  StartTest (4, 6, 10);
1005  AddTxop (1);
1006  AddRxOkEvt (20, 40);
1007  AddNavStart (60, 15);
1008  AddRxOkEvt (66, 5);
1009  AddNavReset (71, 2);
1010  AddAccessRequest (30, 10, 91, 0);
1011  ExpectBackoff (30, 2, 0); //backoff: 2 slots
1012  EndTest ();
1013 
1014 
1015  // 20 60 80 86 94
1016  // | rx | idle | sifs | aifsn | tx |
1017  // ^ request access
1018  StartTest (4, 6, 10);
1019  AddTxop (2);
1020  AddRxOkEvt (20, 40);
1021  AddAccessRequest (80, 10, 94, 0);
1022  EndTest ();
1023 
1024 
1025  StartTest (4, 6, 10);
1026  AddTxop (2);
1027  AddRxOkEvt (20, 40);
1028  AddRxOkEvt (78, 8);
1029  AddAccessRequest (30, 50, 108, 0);
1030  ExpectBackoff (30, 3, 0); //backoff: 3 slots
1031  EndTest ();
1032 
1033 
1034  // Channel switching tests
1035 
1036  // 0 20 21 24 25 26
1037  // | switching | idle | sifs | aifsn | tx |
1038  // ^ access request.
1039  StartTest (1, 3, 10);
1040  AddTxop (1);
1041  AddSwitchingEvt (0, 20);
1042  AddAccessRequest (21, 1, 25, 0);
1043  EndTest ();
1044 
1045  // 20 40 50 53 54 55 56 57
1046  // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
1047  // | |
1048  // 30 busy. 45 access request.
1049  //
1050  StartTest (1, 3, 10);
1051  AddTxop (1);
1052  AddSwitchingEvt (20,20);
1053  AddCcaBusyEvt (30,20);
1054  ExpectBackoff (45, 2, 0); //backoff: 2 slots
1055  AddAccessRequest (45, 1, 56, 0);
1056  EndTest ();
1057 
1058  // 20 30 50 51 54 55 56
1059  // | rx | switching | idle | sifs | aifsn | tx |
1060  // ^ access request.
1061  //
1062  StartTest (1, 3, 10);
1063  AddTxop (1);
1064  AddRxStartEvt (20, 40);
1065  AddSwitchingEvt (30, 20);
1066  AddAccessRequest (51, 1, 55, 0);
1067  EndTest ();
1068 
1069  // 20 30 50 51 54 55 56
1070  // | busy | switching | idle | sifs | aifsn | tx |
1071  // ^ access request.
1072  //
1073  StartTest (1, 3, 10);
1074  AddTxop (1);
1075  AddCcaBusyEvt (20, 40);
1076  AddSwitchingEvt (30, 20);
1077  AddAccessRequest (51, 1, 55, 0);
1078  EndTest ();
1079 
1080  // 20 30 50 51 54 55 56
1081  // | nav | switching | idle | sifs | aifsn | tx |
1082  // ^ access request.
1083  //
1084  StartTest (1, 3, 10);
1085  AddTxop (1);
1086  AddNavStart (20,40);
1087  AddSwitchingEvt (30,20);
1088  AddAccessRequest (51, 1, 55, 0);
1089  EndTest ();
1090 
1091  // 20 23 24 44 54 59 60 63 64 65
1092  // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1093  // | |
1094  // 49 access request. ^ access request.
1095  //
1096  StartTest (1, 3, 10);
1097  AddTxop (1);
1098  AddAccessRequestWithAckTimeout (20, 20, 24, 0);
1099  AddAccessRequest (49, 1, 54, 0);
1100  AddSwitchingEvt (54, 5);
1101  AddAccessRequest (60, 1, 64, 0);
1102  EndTest ();
1103 
1104  // 20 60 66 70 74 78 80 100 101 107 111 113
1105  // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1106  // | |
1107  // 30 access request. ^ access request.
1108  //
1109  StartTest (4, 6, 10);
1110  AddTxop (1);
1111  AddRxOkEvt (20,40);
1112  AddAccessRequest (30, 2, 80, 0);
1113  ExpectBackoff (30, 4, 0); //backoff: 4 slots
1114  AddSwitchingEvt (80,20);
1115  AddAccessRequest (101, 2, 111, 0);
1116  EndTest ();
1117 }
1118 
1119 /*
1120  * Specialization of DoRun () method for EDCA
1121  */
1122 template <>
1123 void
1125 {
1126  // Check alignment at slot boundary after successful reception (backoff = 0):
1127  // 20 50 56 60 80
1128  // | rx | sifs | aifsn | tx |
1129  // |
1130  // 52 request access
1131  StartTest (4, 6, 10);
1132  AddTxop (1);
1133  AddRxOkEvt (20, 30);
1134  AddAccessRequest (52, 20, 60, 0);
1135  EndTest ();
1136 
1137  // Check alignment at slot boundary after successful reception (backoff = 0):
1138  // 20 50 56 60 80
1139  // | rx | sifs | aifsn | tx |
1140  // |
1141  // 58 request access
1142  StartTest (4, 6, 10);
1143  AddTxop (1);
1144  AddRxOkEvt (20, 30);
1145  AddAccessRequest (52, 20, 60, 0);
1146  EndTest ();
1147 
1148  // Check alignment at slot boundary after successful reception (backoff = 0):
1149  // 20 50 56 60 64 84
1150  // | rx | sifs | aifsn | idle | tx |
1151  // |
1152  // 62 request access
1153  StartTest (4, 6, 10);
1154  AddTxop (1);
1155  AddRxOkEvt (20, 30);
1156  AddAccessRequest (62, 20, 64, 0);
1157  EndTest ();
1158 
1159  // Check alignment at slot boundary after failed reception (backoff = 0):
1160  // 20 50 56 66 76 96
1161  // | | <------eifs------>| | |
1162  // | rx | sifs | acktxttime | sifs + aifsn | tx |
1163  // |
1164  // 55 request access
1165  StartTest (4, 6, 10);
1166  AddTxop (1);
1167  AddRxErrorEvt (20, 30);
1168  AddAccessRequest (55, 20, 76, 0);
1169  EndTest ();
1170 
1171  // Check alignment at slot boundary after failed reception (backoff = 0):
1172  // 20 50 56 66 76 96
1173  // | | <------eifs------>| | |
1174  // | rx | sifs | acktxttime | sifs + aifsn | tx |
1175  // |
1176  // 70 request access
1177  StartTest (4, 6, 10);
1178  AddTxop (1);
1179  AddRxErrorEvt (20, 30);
1180  AddAccessRequest (70, 20, 76, 0);
1181  EndTest ();
1182 
1183  // Check alignment at slot boundary after failed reception (backoff = 0):
1184  // 20 50 56 66 76 84
1185  // | | <------eifs------>| | |
1186  // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1187  // |
1188  // 82 request access
1189  StartTest (4, 6, 10);
1190  AddTxop (1);
1191  AddRxErrorEvt (20, 30);
1192  AddAccessRequest (82, 20, 84, 0);
1193  EndTest ();
1194 
1195  // Check backoff decrement at slot boundaries. Medium idle during backoff
1196  // 20 50 56 60 64 68 72 76 96
1197  // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1198  // | | | | |
1199  // 30 request access. decrement decrement decrement decrement
1200  // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1201  StartTest (4, 6, 10);
1202  AddTxop (1);
1203  AddRxOkEvt (20, 30);
1204  AddAccessRequest (30, 20, 76, 0);
1205  ExpectBackoff (30, 4, 0);
1206  EndTest ();
1207 
1208  // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1209  // 20 50 56 60 61 71 77 81 85 87 97 103 107 127
1210  // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs | aifsn | tx |
1211  // | | | |
1212  // 30 request access. decrement decrement decrement
1213  // backoff slots: 3 slots: 2 slots: 1 slots: 0
1214  StartTest (4, 6, 10);
1215  AddTxop (1);
1216  AddRxOkEvt (20, 30);
1217  AddRxOkEvt (61, 10);
1218  AddRxOkEvt (87, 10);
1219  AddAccessRequest (30, 20, 107, 0);
1220  ExpectBackoff (30, 3, 0);
1221  EndTest ();
1222 }
1223 
1230 class TxopTestSuite : public TestSuite
1231 {
1232 public:
1233  TxopTestSuite ();
1234 };
1235 
1237  : TestSuite ("wifi-devices-dcf", UNIT)
1238 {
1239  AddTestCase (new ChannelAccessManagerTest<Txop>, TestCase::QUICK);
1240 }
1241 
1243 
1251 {
1252 public:
1253  QosTxopTestSuite ();
1254 };
1255 
1257  : TestSuite ("wifi-devices-edca", UNIT)
1258 {
1259  AddTestCase (new ChannelAccessManagerTest<QosTxop>, TestCase::QUICK);
1260 }
1261 
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
ExpectedBackoffs m_expectedBackoff
expected backoff (not due to an internal collision)
TxopTest(ChannelAccessManagerTest< TxopType > *test, uint32_t i)
Constructor.
void AddSwitchingEvt(uint64_t at, uint64_t duration)
Add switching event function.
void AddRxOkEvt(uint64_t at, uint64_t duration)
Add receive OK event function.
TxopTest Txop Test.
Time GetSifs(void) const
Return the Short Interframe Space (SIFS) for this PHY.
std::list< struct ExpectedBackoff > ExpectedBackoffs
expected backoffs typedef
A suite of tests to run.
Definition: test.h:1343
void AddNavStart(uint64_t at, uint64_t duration)
Add NAV start function.
std::list< ExpectedGrant > ExpectedGrants
the collection of expected grants typedef
bool IsCfPeriod(void) const
This function indicates whether Simulator::Now is in the CF period.
void AddAccessRequestWithSuccessfullAck(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
Add access request with successful ack.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
void QueueTx(uint64_t txTime, uint64_t expectedGrantTime)
Queue transmit function.
void DoAccessRequest(uint64_t txTime, uint64_t expectedGrantTime, Ptr< TxopTest< TxopType >> state)
Add access request with successful Ack.
#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:283
Manage a set of ns3::TxopHandle a set of independent ns3::Txop, each of which represents a single DCF...
void DoDispose(void)
Inherited.
static TxopTestSuite g_dcfTestSuite
TxopTests m_txop
the vector of Txop test instances
encapsulates test code
Definition: test.h:1153
void SetSifs(Time sifs)
Set the Short Interframe Space (SIFS).
ExpectedGrants m_expectedGrants
expected grants
void AddTxop(uint32_t aifsn)
Add Txop function.
ExpectedBackoff structure.
bool IsAccessRequested(void) const
void NotifyAccessRequested(void)
Notify that access request has been received.
void NotifyChannelSwitching(void)
When a channel switching occurs, enqueued packets are removed.
bool m_accessRequested
true if access requested
void AddCcaBusyEvt(uint64_t at, uint64_t duration)
Add CCA busy event function.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
static QosTxopTestSuite g_edcaTestSuite
std::vector< Ptr< TxopTest< TxopType > > > TxopTests
the TXOP tests typedef
Channel Access Manager Test.
void AddRxStartEvt(uint64_t at, uint64_t duration)
Add receive start event function.
uint32_t m_ackTimeoutValue
the Ack timeout value
Time GetSlot(void) const
Return the slot duration for this PHY.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void AddAckTimeoutReset(uint64_t at)
Add Ack timeout reset function.
void NotifyAccessGranted(uint32_t i)
Notify access granted function.
void SetEifsNoDifs(Time eifsNoDifs)
Set the duration of EIFS - DIFS.
void AddTxEvt(uint64_t at, uint64_t duration)
Add transmit event function.
void EndTest(void)
End test function.
std::pair< uint64_t, uint64_t > ExpectedGrant
the expected grant typedef
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ChannelAccessManager Stub.
void NotifyInternalCollision(void)
Notify the Txop that internal collision has occurred.
Time GetEifsNoDifs(void) const
Return the EIFS duration minus a DIFS.
Ptr< ChannelAccessManagerStub > m_ChannelAccessManager
the channel access manager
void NotifyAccessGranted(void)
Notify the Txop that access has been granted.
handle RTS/CTS/Data/Ack transactions.
Definition: mac-low.h:59
void AddRxInsideSifsEvt(uint64_t at, uint64_t duration)
Add receive inside SIFS event function.
void NotifyWakeUp(void)
When wake up operation occurs, channel access will be restarted.
void AddRxErrorEvt(uint64_t at, uint64_t duration)
Add receive error event function for error at end of frame.
uint32_t m_i
the index of the Txop
void ExpectInternalCollision(uint64_t time, uint32_t nSlots, uint32_t from)
Expect internal collision function.
Ptr< MacLowStub > m_low
the MAC low stubbed
void NotifySleep(void)
When sleep operation occurs, if there is a pending packet transmission, it will be reinserted to the ...
void DoCheckBusy(bool busy)
Perform check that channel access manager is busy or idle.
void NotifyInternalCollision(uint32_t i)
Notify internal collision function.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1294
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
void GenerateBackoff(void)
Generate a new backoff now.
void AddAccessRequestWithAckTimeout(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Add access request with Ack timeout.
ExpectedBackoffs m_expectedInternalCollision
expected backoff due to an internal collision
void AddAccessRequest(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Add access function.
void StartTest(uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue=20)
Start test function.
ChannelAccessManagerTest< TxopType > * m_test
the test DCF/EDCA manager
void SetSlot(Time slot)
Set the slot duration.
void AddNavReset(uint64_t at, uint64_t duration)
Add NAV reset function.
bool HasFramesToTransmit(void)
Check if the Txop has frames to transmit.