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/frame-exchange-manager.h"
25 #include "ns3/qos-txop.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  void NotifyChannelAccessed (Time txopDuration = Seconds (0));
64 
65  typedef std::pair<uint64_t,uint64_t> ExpectedGrant;
66  typedef std::list<ExpectedGrant> ExpectedGrants;
67  struct ExpectedBackoff
69  {
70  uint64_t at;
71  uint32_t nSlots;
72  };
73  typedef std::list<struct ExpectedBackoff> ExpectedBackoffs;
74 
78 
82  void NotifyInternalCollision (void);
86  void GenerateBackoff (void);
91  bool HasFramesToTransmit (void);
95  void NotifyChannelSwitching (void);
100  void NotifySleep (void);
104  void NotifyWakeUp (void);
105 
107  uint32_t m_i;
108 };
109 
117 {
118 public:
120  {
121  }
127  void SetSifs (Time sifs)
128  {
129  m_sifs = sifs;
130  }
136  void SetSlot (Time slot)
137  {
138  m_slot = slot;
139  }
145  void SetEifsNoDifs (Time eifsNoDifs)
146  {
147  m_eifsNoDifs = eifsNoDifs;
148  }
149 
150 private:
151  // Inherited from base class
152  Time GetSifs (void) const
153  {
154  return m_sifs;
155  }
156 
157  Time GetSlot (void) const
158  {
159  return m_slot;
160  }
161 
162  Time GetEifsNoDifs (void) const
163  {
164  return m_eifsNoDifs;
165  }
166 
167  Time m_slot; // slot duration
168  Time m_sifs; // SIFS duration
169  Time m_eifsNoDifs; // EIFS duration minus a DIFS
170 };
171 
179 {
180 public:
182  {
183  }
192  {
193  dcf->NotifyChannelAccessed ();
194  return true;
195  }
196 };
197 
204 template <typename TxopType>
205 class ChannelAccessManagerTest : public TestCase
206 {
207 public:
209  virtual void DoRun (void);
210 
215  void NotifyAccessGranted (uint32_t i);
220  void NotifyInternalCollision (uint32_t i);
225  void GenerateBackoff (uint32_t i);
230  void NotifyChannelSwitching (uint32_t i);
231 
232 
233 private:
241  void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue = 20);
246  void AddTxop (uint32_t aifsn);
248  void EndTest (void);
255  void ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from);
262  void ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from);
268  void ExpectBusy (uint64_t time, bool busy);
273  void DoCheckBusy (bool busy);
279  void AddRxOkEvt (uint64_t at, uint64_t duration);
285  void AddRxErrorEvt (uint64_t at, uint64_t duration);
292  void AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError);
298  void AddRxInsideSifsEvt (uint64_t at, uint64_t duration);
304  void AddTxEvt (uint64_t at, uint64_t duration);
310  void AddNavReset (uint64_t at, uint64_t duration);
316  void AddNavStart (uint64_t at, uint64_t duration);
321  void AddAckTimeoutReset (uint64_t at);
329  void AddAccessRequest (uint64_t at, uint64_t txTime,
330  uint64_t expectedGrantTime, uint32_t from);
338  void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
339  uint64_t expectedGrantTime, uint32_t from);
348  void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
349  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
356  void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr<TxopTest<TxopType>> state);
362  void AddCcaBusyEvt (uint64_t at, uint64_t duration);
368  void AddSwitchingEvt (uint64_t at, uint64_t duration);
374  void AddRxStartEvt (uint64_t at, uint64_t duration);
375 
376  typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests;
377 
381  uint32_t m_ackTimeoutValue;
382 };
383 
384 template <typename TxopType>
385 void
386 TxopTest<TxopType>::QueueTx (uint64_t txTime, uint64_t expectedGrantTime)
387 {
388  m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime));
389 }
390 
391 template <typename TxopType>
393  : m_test (test),
394  m_i (i)
395 {
396 }
397 
398 template <typename TxopType>
399 void
401 {
402  m_test = 0;
403  TxopType::DoDispose ();
404 }
405 
406 template <typename TxopType>
407 void
409 {
410  Txop::m_access = Txop::NOT_REQUESTED;
411  m_test->NotifyAccessGranted (m_i);
412 }
413 
414 template <typename TxopType>
415 void
417 {
418  m_test->NotifyInternalCollision (m_i);
419 }
420 
421 template <typename TxopType>
422 void
424 {
425  m_test->GenerateBackoff (m_i);
426 }
427 
428 template <typename TxopType>
429 bool
431 {
432  return !m_expectedGrants.empty ();
433 }
434 
435 template <typename TxopType>
436 void
438 {
439  m_test->NotifyChannelSwitching (m_i);
440 }
441 
442 template <typename TxopType>
443 void
445 {
446 }
447 
448 template <typename TxopType>
449 void
451 {
452 }
453 
454 template <typename TxopType>
456  : TestCase ("ChannelAccessManager")
457 {
458 }
459 
460 template <typename TxopType>
461 void
463 {
464  Ptr<TxopTest<TxopType>> state = m_txop[i];
465  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants");
466  if (!state->m_expectedGrants.empty ())
467  {
468  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
469  state->m_expectedGrants.pop_front ();
470  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected access grant is now");
471  m_ChannelAccessManager->NotifyTxStartNow (MicroSeconds (expected.first));
472  m_ChannelAccessManager->NotifyAckTimeoutStartNow (MicroSeconds (m_ackTimeoutValue + expected.first));
473  }
474 }
475 
476 template <typename TxopType>
477 void
478 ChannelAccessManagerTest<TxopType>::AddTxEvt (uint64_t at, uint64_t duration)
479 {
480  Simulator::Schedule (MicroSeconds (at) - Now (),
481  &ChannelAccessManager::NotifyTxStartNow, m_ChannelAccessManager,
482  MicroSeconds (duration));
483 }
484 
485 template <typename TxopType>
486 void
488 {
489  Ptr<TxopTest<TxopType>> state = m_txop[i];
490  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions");
491  if (!state->m_expectedInternalCollision.empty ())
492  {
493  struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedInternalCollision.front ();
494  state->m_expectedInternalCollision.pop_front ();
495  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now");
496  state->StartBackoffNow (expected.nSlots);
497  }
498 }
499 
500 template <typename TxopType>
501 void
503 {
504  Ptr<TxopTest<TxopType>> state = m_txop[i];
505  NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), false, "Have expected backoffs");
506  if (!state->m_expectedBackoff.empty ())
507  {
508  struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedBackoff.front ();
509  state->m_expectedBackoff.pop_front ();
510  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected backoff is now");
511  state->StartBackoffNow (expected.nSlots);
512  }
513 }
514 
515 template <typename TxopType>
516 void
518 {
519  Ptr<TxopTest<TxopType>> state = m_txop[i];
520  if (!state->m_expectedGrants.empty ())
521  {
522  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
523  state->m_expectedGrants.pop_front ();
524  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected grant is now");
525  }
526  state->Txop::m_access = Txop::NOT_REQUESTED;
527 }
528 
529 template <typename TxopType>
530 void
531 ChannelAccessManagerTest<TxopType>::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from)
532 {
533  Ptr<TxopTest<TxopType>> state = m_txop[from];
534  struct TxopTest<TxopType>::ExpectedBackoff col;
535  col.at = time;
536  col.nSlots = nSlots;
537  state->m_expectedInternalCollision.push_back (col);
538 }
539 
540 template <typename TxopType>
541 void
542 ChannelAccessManagerTest<TxopType>::ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from)
543 {
544  Ptr<TxopTest<TxopType>> state = m_txop[from];
545  struct TxopTest<TxopType>::ExpectedBackoff backoff;
546  backoff.at = time;
547  backoff.nSlots = nSlots;
548  state->m_expectedBackoff.push_back (backoff);
549 }
550 
551 template <typename TxopType>
552 void
553 ChannelAccessManagerTest<TxopType>::ExpectBusy (uint64_t time, bool busy)
554 {
555  Simulator::Schedule (MicroSeconds (time) - Now (),
557 }
558 
559 template <typename TxopType>
560 void
562 {
563  NS_TEST_EXPECT_MSG_EQ (m_ChannelAccessManager->IsBusy (), busy, "Incorrect busy/idle state");
564 }
565 
566 template <typename TxopType>
567 void
568 ChannelAccessManagerTest<TxopType>::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue)
569 {
570  m_ChannelAccessManager = CreateObject<ChannelAccessManagerStub> ();
571  m_feManager = CreateObject<FrameExchangeManagerStub> ();
572  m_ChannelAccessManager->SetupFrameExchangeManager (m_feManager);
573  m_ChannelAccessManager->SetSlot (MicroSeconds (slotTime));
574  m_ChannelAccessManager->SetSifs (MicroSeconds (sifs));
575  m_ChannelAccessManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs + sifs));
576  m_ackTimeoutValue = ackTimeoutValue;
577 }
578 
579 template <typename TxopType>
580 void
582 {
583  Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>> (this, m_txop.size ());
584  txop->SetAifsn (aifsn);
585  m_txop.push_back (txop);
586  txop->SetChannelAccessManager (m_ChannelAccessManager);
587 }
588 
589 template <typename TxopType>
590 void
592 {
593  Simulator::Run ();
594 
595  for (typename TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++)
596  {
597  Ptr<TxopTest<TxopType>> state = *i;
598  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants");
599  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions");
600  NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), true, "Have no expected backoffs");
601  state->Dispose ();
602  state = 0;
603  }
604  m_txop.clear ();
605 
606  m_ChannelAccessManager->Dispose ();
607  m_ChannelAccessManager = 0;
608  m_feManager = 0;
609  Simulator::Destroy ();
610 }
611 
612 template <typename TxopType>
613 void
614 ChannelAccessManagerTest<TxopType>::AddRxOkEvt (uint64_t at, uint64_t duration)
615 {
616  Simulator::Schedule (MicroSeconds (at) - Now (),
617  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
618  MicroSeconds (duration));
619  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
620  &ChannelAccessManager::NotifyRxEndOkNow, m_ChannelAccessManager);
621 }
622 
623 template <typename TxopType>
624 void
626 {
627  Simulator::Schedule (MicroSeconds (at) - Now (),
628  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
629  MicroSeconds (duration));
630 }
631 
632 template <typename TxopType>
633 void
635 {
636  Simulator::Schedule (MicroSeconds (at) - Now (),
637  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
638  MicroSeconds (duration));
639  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
640  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
641 }
642 
643 template <typename TxopType>
644 void
645 ChannelAccessManagerTest<TxopType>::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError)
646 {
647  Simulator::Schedule (MicroSeconds (at) - Now (),
648  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
649  MicroSeconds (duration));
650  Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
651  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
652 }
653 
654 
655 template <typename TxopType>
656 void
657 ChannelAccessManagerTest<TxopType>::AddNavReset (uint64_t at, uint64_t duration)
658 {
659  Simulator::Schedule (MicroSeconds (at) - Now (),
660  &ChannelAccessManager::NotifyNavResetNow, m_ChannelAccessManager,
661  MicroSeconds (duration));
662 }
663 
664 template <typename TxopType>
665 void
666 ChannelAccessManagerTest<TxopType>::AddNavStart (uint64_t at, uint64_t duration)
667 {
668  Simulator::Schedule (MicroSeconds (at) - Now (),
669  &ChannelAccessManager::NotifyNavStartNow, m_ChannelAccessManager,
670  MicroSeconds (duration));
671 }
672 
673 template <typename TxopType>
674 void
676 {
677  Simulator::Schedule (MicroSeconds (at) - Now (),
678  &ChannelAccessManager::NotifyAckTimeoutResetNow, m_ChannelAccessManager);
679 }
680 
681 template <typename TxopType>
682 void
684  uint64_t expectedGrantTime, uint32_t from)
685 {
686  AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from);
687 }
688 
689 template <typename TxopType>
690 void
692  uint64_t expectedGrantTime, uint32_t from)
693 {
694  Simulator::Schedule (MicroSeconds (at) - Now (),
696  txTime, expectedGrantTime, m_txop[from]);
697 }
698 
699 template <typename TxopType>
700 void
702  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
703 {
704  NS_ASSERT (ackDelay < m_ackTimeoutValue);
705  Simulator::Schedule (MicroSeconds (at) - Now (),
707  txTime, expectedGrantTime, m_txop[from]);
708  AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay);
709 }
710 
711 template <typename TxopType>
712 void
713 ChannelAccessManagerTest<TxopType>::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime,
714  Ptr<TxopTest<TxopType>> state)
715 {
716  if (m_ChannelAccessManager->NeedBackoffUponAccess (state))
717  {
718  state->GenerateBackoff ();
719  }
720  state->QueueTx (txTime, expectedGrantTime);
721  m_ChannelAccessManager->RequestAccess (state);
722 }
723 
724 template <typename TxopType>
725 void
727 {
728  Simulator::Schedule (MicroSeconds (at) - Now (),
729  &ChannelAccessManager::NotifyMaybeCcaBusyStartNow, m_ChannelAccessManager,
730  MicroSeconds (duration));
731 }
732 
733 template <typename TxopType>
734 void
736 {
737  Simulator::Schedule (MicroSeconds (at) - Now (),
738  &ChannelAccessManager::NotifySwitchingStartNow, m_ChannelAccessManager,
739  MicroSeconds (duration));
740 }
741 
742 template <typename TxopType>
743 void
745 {
746  Simulator::Schedule (MicroSeconds (at) - Now (),
747  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
748  MicroSeconds (duration));
749 }
750 
751 /*
752  * Specialization of DoRun () method for DCF
753  */
754 template <>
755 void
757 {
758  // DCF immediate access (no backoff)
759  // 1 4 5 6 8 11 12
760  // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
761  //
762  StartTest (1, 3, 10);
763  AddTxop (1);
764  AddAccessRequest (1, 1, 5, 0);
765  AddAccessRequest (8, 2, 12, 0);
766  EndTest ();
767  // Check that receiving inside SIFS shall be cancelled properly:
768  // 1 4 5 6 9 10 14 17 18
769  // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
770  // |
771  // 7 start rx
772  //
773 
774  StartTest (1, 3, 10);
775  AddTxop (1);
776  AddAccessRequest (1, 1, 5, 0);
777  AddRxInsideSifsEvt (7, 10);
778  AddTxEvt (9, 1);
779  AddAccessRequest (14, 2, 18, 0);
780  EndTest ();
781  // The test below mainly intends to test the case where the medium
782  // becomes busy in the middle of a backoff slot: the backoff counter
783  // must not be decremented for this backoff slot. This is the case
784  // below for the backoff slot starting at time 78us.
785  //
786  // 20 60 66 70 74 78 80 100 106 110 114 118 120
787  // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 | bslot3 | tx |
788  // |
789  // 30 request access. backoff slots: 4
790 
791  StartTest (4, 6, 10);
792  AddTxop (1);
793  AddRxOkEvt (20, 40);
794  AddRxOkEvt (80, 20);
795  AddAccessRequest (30, 2, 118, 0);
796  ExpectBackoff (30, 4, 0); //backoff: 4 slots
797  EndTest ();
798  // Test the case where the backoff slots is zero.
799  //
800  // 20 60 66 70 72
801  // | rx | sifs | aifsn | tx |
802  // |
803  // 30 request access. backoff slots: 0
804 
805  StartTest (4, 6, 10);
806  AddTxop (1);
807  AddRxOkEvt (20, 40);
808  AddAccessRequest (30, 2, 70, 0);
809  ExpectBackoff (30, 0, 0); // backoff: 0 slots
810  EndTest ();
811  // Test shows when two frames are received without interval between
812  // them:
813  // 20 60 100 106 110 112
814  // | rx | rx |sifs | aifsn | tx |
815  // |
816  // 30 request access. backoff slots: 0
817 
818  StartTest (4, 6, 10);
819  AddTxop (1);
820  AddRxOkEvt (20, 40);
821  AddRxOkEvt (60, 40);
822  AddAccessRequest (30, 2, 110, 0);
823  ExpectBackoff (30, 0, 0); //backoff: 0 slots
824  EndTest ();
825 
826  // Requesting access within SIFS interval (DCF immediate access)
827  //
828  // 20 60 62 68 72
829  // | rx | idle | sifs | aifsn | tx |
830  //
831  StartTest (4, 6, 10);
832  AddTxop (1);
833  AddRxOkEvt (20, 40);
834  AddAccessRequest (62, 2, 72, 0);
835  EndTest ();
836 
837  // Requesting access after DIFS (DCF immediate access)
838  //
839  // 20 60 70 76 80
840  // | rx | idle | sifs | aifsn | tx |
841  //
842  StartTest (4, 6, 10);
843  AddTxop (1);
844  AddRxOkEvt (20, 40);
845  AddAccessRequest (70, 2, 80, 0);
846  EndTest ();
847 
848  // Test an EIFS
849  //
850  // 20 60 66 76 86 90 94 98 102 106
851  // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
852  // | | <------eifs------>|
853  // 30 request access. backoff slots: 4
854  StartTest (4, 6, 10);
855  AddTxop (1);
856  AddRxErrorEvt (20, 40);
857  AddAccessRequest (30, 2, 102, 0);
858  ExpectBackoff (30, 4, 0); //backoff: 4 slots
859  EndTest ();
860 
861  // Test DCF immediate access after an EIFS (EIFS is greater)
862  //
863  // 20 60 66 76 86
864  // | <----+-eifs------>|
865  // | rx | sifs | acktxttime | sifs + aifsn | tx |
866  // | sifs + aifsn |
867  // request access 70 80
868  StartTest (4, 6, 10);
869  AddTxop (1);
870  AddRxErrorEvt (20, 40);
871  AddAccessRequest (70, 2, 86, 0);
872  EndTest ();
873 
874  // Test that channel stays busy for first frame's duration after Rx error
875  //
876  // 20 60
877  // | rx |
878  // |
879  // 40 force Rx error
880  StartTest (4, 6, 10);
881  AddTxop (1);
882  AddRxErrorEvt (20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
883  ExpectBusy (41, true); // channel should remain busy for remaining duration
884  ExpectBusy (59, true);
885  ExpectBusy (61, false);
886  EndTest ();
887 
888  // Test an EIFS which is interrupted by a successful transmission.
889  //
890  // 20 60 66 69 75 81 85 89 93 97 101 103
891  // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
892  // | | <--eifs-->|
893  // 30 request access. backoff slots: 4
894  StartTest (4, 6, 10);
895  AddTxop (1);
896  AddRxErrorEvt (20, 40);
897  AddAccessRequest (30, 2, 101, 0);
898  ExpectBackoff (30, 4, 0); //backoff: 4 slots
899  AddRxOkEvt (69, 6);
900  EndTest ();
901 
902  // Test two DCFs which suffer an internal collision. the first DCF has a higher
903  // priority than the second DCF.
904  //
905  // 20 60 66 70 74 78 88
906  // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
907  // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn | bslot | tx |
908  // 94 98 102 106 110 112
909  StartTest (4, 6, 10);
910  AddTxop (1); //high priority DCF
911  AddTxop (3); //low priority DCF
912  AddRxOkEvt (20, 40);
913  AddAccessRequest (30, 10, 78, 0);
914  ExpectBackoff (30, 2, 0); //backoff: 2 slot
915  AddAccessRequest (40, 2, 110, 1);
916  ExpectBackoff (40, 0, 1); //backoff: 0 slot
917  ExpectInternalCollision (78, 1, 1); //backoff: 1 slot
918  EndTest ();
919 
920  // Test of AckTimeout handling: First queue requests access and ack procedure fails,
921  // inside the Ack timeout second queue with higher priority requests access.
922  //
923  // 20 26 34 54 74 80
924  // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
925  // DCF0 - high | | | sifs | tx |
926  // ^ request access
927  StartTest (4, 6, 10);
928  AddTxop (0); //high priority DCF
929  AddTxop (2); //low priority DCF
930  AddAccessRequestWithAckTimeout (20, 20, 34, 1);
931  AddAccessRequest (64, 10, 80, 0);
932  EndTest ();
933 
934  // Test of AckTimeout handling:
935  //
936  // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
937  // inside this interval second queue with higher priority requests access.
938  //
939  // 20 26 34 54 56 62
940  // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
941  // DCF0 - high | | | sifs | tx |
942  // ^ request access
943  StartTest (4, 6, 10);
944  AddTxop (0); //high priority DCF
945  AddTxop (2); //low priority DCF
946  AddAccessRequestWithSuccessfullAck (20, 20, 34, 2, 1);
947  AddAccessRequest (55, 10, 62, 0);
948  EndTest ();
949 
950  //Repeat the same but with one queue:
951  // 20 26 34 54 60 62 68 76 80
952  // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
953  // ^ request access
954  StartTest (4, 6, 10);
955  AddTxop (2);
956  AddAccessRequest (20, 20, 34, 0);
957  AddRxOkEvt (60, 2); // Ack
958  AddAccessRequest (61, 10, 80, 0);
959  ExpectBackoff (61, 1, 0); // 1 slot
960  EndTest ();
961 
962  // test simple NAV count. This scenario models a simple Data+Ack handshake
963  // where the data rate used for the Ack is higher than expected by the Data source
964  // so, the data exchange completes before the end of NAV.
965  StartTest (4, 6, 10);
966  AddTxop (1);
967  AddRxOkEvt (20, 40);
968  AddNavStart (60, 15);
969  AddRxOkEvt (66, 5);
970  AddNavStart (71, 0);
971  AddAccessRequest (30, 10, 93, 0);
972  ExpectBackoff (30, 2, 0); //backoff: 2 slots
973  EndTest ();
974 
975  // test more complex NAV handling by a CF-poll. This scenario models a
976  // simple Data+Ack handshake interrupted by a CF-poll which resets the
977  // NAV counter.
978  StartTest (4, 6, 10);
979  AddTxop (1);
980  AddRxOkEvt (20, 40);
981  AddNavStart (60, 15);
982  AddRxOkEvt (66, 5);
983  AddNavReset (71, 2);
984  AddAccessRequest (30, 10, 91, 0);
985  ExpectBackoff (30, 2, 0); //backoff: 2 slots
986  EndTest ();
987 
988 
989  // 20 60 80 86 94
990  // | rx | idle | sifs | aifsn | tx |
991  // ^ request access
992  StartTest (4, 6, 10);
993  AddTxop (2);
994  AddRxOkEvt (20, 40);
995  AddAccessRequest (80, 10, 94, 0);
996  EndTest ();
997 
998 
999  StartTest (4, 6, 10);
1000  AddTxop (2);
1001  AddRxOkEvt (20, 40);
1002  AddRxOkEvt (78, 8);
1003  AddAccessRequest (30, 50, 108, 0);
1004  ExpectBackoff (30, 3, 0); //backoff: 3 slots
1005  EndTest ();
1006 
1007 
1008  // Channel switching tests
1009 
1010  // 0 20 21 24 25 26
1011  // | switching | idle | sifs | aifsn | tx |
1012  // ^ access request.
1013  StartTest (1, 3, 10);
1014  AddTxop (1);
1015  AddSwitchingEvt (0, 20);
1016  AddAccessRequest (21, 1, 25, 0);
1017  EndTest ();
1018 
1019  // 20 40 50 53 54 55 56 57
1020  // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
1021  // | |
1022  // 30 busy. 45 access request.
1023  //
1024  StartTest (1, 3, 10);
1025  AddTxop (1);
1026  AddSwitchingEvt (20,20);
1027  AddCcaBusyEvt (30,20);
1028  ExpectBackoff (45, 2, 0); //backoff: 2 slots
1029  AddAccessRequest (45, 1, 56, 0);
1030  EndTest ();
1031 
1032  // 20 30 50 51 54 55 56
1033  // | rx | switching | idle | sifs | aifsn | tx |
1034  // ^ access request.
1035  //
1036  StartTest (1, 3, 10);
1037  AddTxop (1);
1038  AddRxStartEvt (20, 40);
1039  AddSwitchingEvt (30, 20);
1040  AddAccessRequest (51, 1, 55, 0);
1041  EndTest ();
1042 
1043  // 20 30 50 51 54 55 56
1044  // | busy | switching | idle | sifs | aifsn | tx |
1045  // ^ access request.
1046  //
1047  StartTest (1, 3, 10);
1048  AddTxop (1);
1049  AddCcaBusyEvt (20, 40);
1050  AddSwitchingEvt (30, 20);
1051  AddAccessRequest (51, 1, 55, 0);
1052  EndTest ();
1053 
1054  // 20 30 50 51 54 55 56
1055  // | nav | switching | idle | sifs | aifsn | tx |
1056  // ^ access request.
1057  //
1058  StartTest (1, 3, 10);
1059  AddTxop (1);
1060  AddNavStart (20,40);
1061  AddSwitchingEvt (30,20);
1062  AddAccessRequest (51, 1, 55, 0);
1063  EndTest ();
1064 
1065  // 20 23 24 44 54 59 60 63 64 65
1066  // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1067  // | |
1068  // 49 access request. ^ access request.
1069  //
1070  StartTest (1, 3, 10);
1071  AddTxop (1);
1072  AddAccessRequestWithAckTimeout (20, 20, 24, 0);
1073  AddAccessRequest (49, 1, 54, 0);
1074  AddSwitchingEvt (54, 5);
1075  AddAccessRequest (60, 1, 64, 0);
1076  EndTest ();
1077 
1078  // 20 60 66 70 74 78 80 100 101 107 111 113
1079  // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1080  // | |
1081  // 30 access request. ^ access request.
1082  //
1083  StartTest (4, 6, 10);
1084  AddTxop (1);
1085  AddRxOkEvt (20,40);
1086  AddAccessRequest (30, 2, 80, 0);
1087  ExpectBackoff (30, 4, 0); //backoff: 4 slots
1088  AddSwitchingEvt (80,20);
1089  AddAccessRequest (101, 2, 111, 0);
1090  EndTest ();
1091 }
1092 
1093 /*
1094  * Specialization of DoRun () method for EDCA
1095  */
1096 template <>
1097 void
1099 {
1100  // Check alignment at slot boundary after successful reception (backoff = 0):
1101  // 20 50 56 60 80
1102  // | rx | sifs | aifsn | tx |
1103  // |
1104  // 52 request access
1105  StartTest (4, 6, 10);
1106  AddTxop (1);
1107  AddRxOkEvt (20, 30);
1108  AddAccessRequest (52, 20, 60, 0);
1109  EndTest ();
1110 
1111  // Check alignment at slot boundary after successful reception (backoff = 0):
1112  // 20 50 56 60 80
1113  // | rx | sifs | aifsn | tx |
1114  // |
1115  // 58 request access
1116  StartTest (4, 6, 10);
1117  AddTxop (1);
1118  AddRxOkEvt (20, 30);
1119  AddAccessRequest (52, 20, 60, 0);
1120  EndTest ();
1121 
1122  // Check alignment at slot boundary after successful reception (backoff = 0):
1123  // 20 50 56 60 64 84
1124  // | rx | sifs | aifsn | idle | tx |
1125  // |
1126  // 62 request access
1127  StartTest (4, 6, 10);
1128  AddTxop (1);
1129  AddRxOkEvt (20, 30);
1130  AddAccessRequest (62, 20, 64, 0);
1131  EndTest ();
1132 
1133  // Check alignment at slot boundary after failed reception (backoff = 0):
1134  // 20 50 56 66 76 96
1135  // | | <------eifs------>| | |
1136  // | rx | sifs | acktxttime | sifs + aifsn | tx |
1137  // |
1138  // 55 request access
1139  StartTest (4, 6, 10);
1140  AddTxop (1);
1141  AddRxErrorEvt (20, 30);
1142  AddAccessRequest (55, 20, 76, 0);
1143  EndTest ();
1144 
1145  // Check alignment at slot boundary after failed reception (backoff = 0):
1146  // 20 50 56 66 76 96
1147  // | | <------eifs------>| | |
1148  // | rx | sifs | acktxttime | sifs + aifsn | tx |
1149  // |
1150  // 70 request access
1151  StartTest (4, 6, 10);
1152  AddTxop (1);
1153  AddRxErrorEvt (20, 30);
1154  AddAccessRequest (70, 20, 76, 0);
1155  EndTest ();
1156 
1157  // Check alignment at slot boundary after failed reception (backoff = 0):
1158  // 20 50 56 66 76 84
1159  // | | <------eifs------>| | |
1160  // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1161  // |
1162  // 82 request access
1163  StartTest (4, 6, 10);
1164  AddTxop (1);
1165  AddRxErrorEvt (20, 30);
1166  AddAccessRequest (82, 20, 84, 0);
1167  EndTest ();
1168 
1169  // Check backoff decrement at slot boundaries. Medium idle during backoff
1170  // 20 50 56 60 64 68 72 76 96
1171  // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1172  // | | | | |
1173  // 30 request access. decrement decrement decrement decrement
1174  // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1175  StartTest (4, 6, 10);
1176  AddTxop (1);
1177  AddRxOkEvt (20, 30);
1178  AddAccessRequest (30, 20, 76, 0);
1179  ExpectBackoff (30, 4, 0);
1180  EndTest ();
1181 
1182  // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1183  // 20 50 56 60 61 71 77 81 85 87 97 103 107 127
1184  // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs | aifsn | tx |
1185  // | | | |
1186  // 30 request access. decrement decrement decrement
1187  // backoff slots: 3 slots: 2 slots: 1 slots: 0
1188  StartTest (4, 6, 10);
1189  AddTxop (1);
1190  AddRxOkEvt (20, 30);
1191  AddRxOkEvt (61, 10);
1192  AddRxOkEvt (87, 10);
1193  AddAccessRequest (30, 20, 107, 0);
1194  ExpectBackoff (30, 3, 0);
1195  EndTest ();
1196 }
1197 
1204 class TxopTestSuite : public TestSuite
1205 {
1206 public:
1207  TxopTestSuite ();
1208 };
1209 
1211  : TestSuite ("wifi-devices-dcf", UNIT)
1212 {
1213  AddTestCase (new ChannelAccessManagerTest<Txop>, TestCase::QUICK);
1214 }
1215 
1217 
1225 {
1226 public:
1227  QosTxopTestSuite ();
1228 };
1229 
1231  : TestSuite ("wifi-devices-edca", UNIT)
1232 {
1233  AddTestCase (new ChannelAccessManagerTest<QosTxop>, TestCase::QUICK);
1234 }
1235 
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
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
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.
void NotifyChannelSwitching(void)
When a channel switching occurs, enqueued packets are removed.
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.
FrameExchangeManager is a base class handling the basic frame exchange sequences for non-QoS stations...
Ptr< ChannelAccessManagerStub > m_ChannelAccessManager
the channel access manager
virtual void NotifyChannelAccessed(Time txopDuration=Seconds(0))
Called by the FrameExchangeManager to notify that channel access has been granted for the given amoun...
Definition: txop.cc:342
void AddRxInsideSifsEvt(uint64_t at, uint64_t duration)
Add receive inside SIFS event function.
Ptr< FrameExchangeManagerStub > m_feManager
the Frame Exchange Manager stubbed
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.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
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.
Frame Exchange Manager Stub.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
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
bool StartTransmission(Ptr< Txop > dcf)
Request the FrameExchangeManager to start a frame exchange sequence.
void NotifyChannelAccessed(Time txopDuration=Seconds(0))
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.