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