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 
153 template <typename TxopType>
154 class ChannelAccessManagerTest : public TestCase
155 {
156 public:
158  virtual void DoRun (void);
159 
164  void NotifyAccessGranted (uint32_t i);
169  void NotifyInternalCollision (uint32_t i);
174  void GenerateBackoff (uint32_t i);
179  void NotifyChannelSwitching (uint32_t i);
180 
181 
182 private:
190  void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue = 20);
195  void AddTxop (uint32_t aifsn);
197  void EndTest (void);
204  void ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from);
211  void ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from);
217  void ExpectBusy (uint64_t time, bool busy);
222  void DoCheckBusy (bool busy);
228  void AddRxOkEvt (uint64_t at, uint64_t duration);
234  void AddRxErrorEvt (uint64_t at, uint64_t duration);
241  void AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError);
247  void AddRxInsideSifsEvt (uint64_t at, uint64_t duration);
253  void AddTxEvt (uint64_t at, uint64_t duration);
259  void AddNavReset (uint64_t at, uint64_t duration);
265  void AddNavStart (uint64_t at, uint64_t duration);
270  void AddAckTimeoutReset (uint64_t at);
278  void AddAccessRequest (uint64_t at, uint64_t txTime,
279  uint64_t expectedGrantTime, uint32_t from);
287  void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
288  uint64_t expectedGrantTime, uint32_t from);
297  void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
298  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
305  void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, Ptr<TxopTest<TxopType>> state);
311  void AddCcaBusyEvt (uint64_t at, uint64_t duration);
317  void AddSwitchingEvt (uint64_t at, uint64_t duration);
323  void AddRxStartEvt (uint64_t at, uint64_t duration);
324 
325  typedef std::vector<Ptr<TxopTest<TxopType>>> TxopTests;
326 
330  uint32_t m_ackTimeoutValue;
331 };
332 
333 template <typename TxopType>
334 void
335 TxopTest<TxopType>::QueueTx (uint64_t txTime, uint64_t expectedGrantTime)
336 {
337  m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime));
338 }
339 
340 template <typename TxopType>
342  : m_test (test),
343  m_i (i),
344  m_accessRequested (false)
345 {
346 }
347 
348 template <typename TxopType>
349 void
351 {
352  m_test = 0;
353  Txop::DoDispose ();
354 }
355 
356 template <typename TxopType>
357 bool
359 {
360  return m_accessRequested;
361 }
362 
363 template <typename TxopType>
364 void
366 {
367  m_accessRequested = true;
368 }
369 
370 template <typename TxopType>
371 void
373 {
374  m_accessRequested = false;
375  m_test->NotifyAccessGranted (m_i);
376 }
377 
378 template <typename TxopType>
379 void
381 {
382  m_test->NotifyInternalCollision (m_i);
383 }
384 
385 template <typename TxopType>
386 void
388 {
389  m_test->GenerateBackoff (m_i);
390 }
391 
392 template <typename TxopType>
393 bool
395 {
396  return !m_expectedGrants.empty ();
397 }
398 
399 template <typename TxopType>
400 void
402 {
403  m_test->NotifyChannelSwitching (m_i);
404 }
405 
406 template <typename TxopType>
407 void
409 {
410 }
411 
412 template <typename TxopType>
413 void
415 {
416 }
417 
418 template <typename TxopType>
420  : TestCase ("ChannelAccessManager")
421 {
422 }
423 
424 template <typename TxopType>
425 void
427 {
428  Ptr<TxopTest<TxopType>> state = m_txop[i];
429  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants");
430  if (!state->m_expectedGrants.empty ())
431  {
432  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
433  state->m_expectedGrants.pop_front ();
434  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected access grant is now");
435  m_ChannelAccessManager->NotifyTxStartNow (MicroSeconds (expected.first));
436  m_ChannelAccessManager->NotifyAckTimeoutStartNow (MicroSeconds (m_ackTimeoutValue + expected.first));
437  }
438 }
439 
440 template <typename TxopType>
441 void
442 ChannelAccessManagerTest<TxopType>::AddTxEvt (uint64_t at, uint64_t duration)
443 {
444  Simulator::Schedule (MicroSeconds (at) - Now (),
445  &ChannelAccessManager::NotifyTxStartNow, m_ChannelAccessManager,
446  MicroSeconds (duration));
447 }
448 
449 template <typename TxopType>
450 void
452 {
453  Ptr<TxopTest<TxopType>> state = m_txop[i];
454  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions");
455  if (!state->m_expectedInternalCollision.empty ())
456  {
457  struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedInternalCollision.front ();
458  state->m_expectedInternalCollision.pop_front ();
459  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now");
460  state->StartBackoffNow (expected.nSlots);
461  }
462 }
463 
464 template <typename TxopType>
465 void
467 {
468  Ptr<TxopTest<TxopType>> state = m_txop[i];
469  NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), false, "Have expected backoffs");
470  if (!state->m_expectedBackoff.empty ())
471  {
472  struct TxopTest<TxopType>::ExpectedBackoff expected = state->m_expectedBackoff.front ();
473  state->m_expectedBackoff.pop_front ();
474  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected backoff is now");
475  state->StartBackoffNow (expected.nSlots);
476  }
477 }
478 
479 template <typename TxopType>
480 void
482 {
483  Ptr<TxopTest<TxopType>> state = m_txop[i];
484  if (!state->m_expectedGrants.empty ())
485  {
486  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
487  state->m_expectedGrants.pop_front ();
488  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected grant is now");
489  }
490  state->m_accessRequested = false;
491 }
492 
493 template <typename TxopType>
494 void
495 ChannelAccessManagerTest<TxopType>::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from)
496 {
497  Ptr<TxopTest<TxopType>> state = m_txop[from];
498  struct TxopTest<TxopType>::ExpectedBackoff col;
499  col.at = time;
500  col.nSlots = nSlots;
501  state->m_expectedInternalCollision.push_back (col);
502 }
503 
504 template <typename TxopType>
505 void
506 ChannelAccessManagerTest<TxopType>::ExpectBackoff (uint64_t time, uint32_t nSlots, uint32_t from)
507 {
508  Ptr<TxopTest<TxopType>> state = m_txop[from];
509  struct TxopTest<TxopType>::ExpectedBackoff backoff;
510  backoff.at = time;
511  backoff.nSlots = nSlots;
512  state->m_expectedBackoff.push_back (backoff);
513 }
514 
515 template <typename TxopType>
516 void
517 ChannelAccessManagerTest<TxopType>::ExpectBusy (uint64_t time, bool busy)
518 {
519  Simulator::Schedule (MicroSeconds (time) - Now (),
521 }
522 
523 template <typename TxopType>
524 void
526 {
527  NS_TEST_EXPECT_MSG_EQ (m_ChannelAccessManager->IsBusy (), busy, "Incorrect busy/idle state");
528 }
529 
530 template <typename TxopType>
531 void
532 ChannelAccessManagerTest<TxopType>::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue)
533 {
534  m_ChannelAccessManager = CreateObject<ChannelAccessManager> ();
535  m_low = CreateObject<MacLowStub> ();
536  m_low->SetSlotTime (MicroSeconds (slotTime));
537  m_low->SetSifs (MicroSeconds (sifs));
538  m_ChannelAccessManager->SetupLow (m_low);
539  m_ChannelAccessManager->SetSlot (MicroSeconds (slotTime));
540  m_ChannelAccessManager->SetSifs (MicroSeconds (sifs));
541  m_ChannelAccessManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs + sifs));
542  m_ackTimeoutValue = ackTimeoutValue;
543 }
544 
545 template <typename TxopType>
546 void
548 {
549  Ptr<TxopTest<TxopType>> txop = CreateObject<TxopTest<TxopType>> (this, m_txop.size ());
550  txop->SetAifsn (aifsn);
551  m_txop.push_back (txop);
552  txop->SetChannelAccessManager (m_ChannelAccessManager);
553  txop->SetMacLow (m_low);
554 }
555 
556 template <typename TxopType>
557 void
559 {
560  Simulator::Run ();
561  Simulator::Destroy ();
562 
563  for (typename TxopTests::const_iterator i = m_txop.begin (); i != m_txop.end (); i++)
564  {
565  Ptr<TxopTest<TxopType>> state = *i;
566  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants");
567  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions");
568  NS_TEST_EXPECT_MSG_EQ (state->m_expectedBackoff.empty (), true, "Have no expected backoffs");
569  state->Dispose ();
570  state = 0;
571  }
572  m_txop.clear ();
573 
574  m_ChannelAccessManager = 0;
575  m_low = 0;
576 }
577 
578 template <typename TxopType>
579 void
580 ChannelAccessManagerTest<TxopType>::AddRxOkEvt (uint64_t at, uint64_t duration)
581 {
582  Simulator::Schedule (MicroSeconds (at) - Now (),
583  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
584  MicroSeconds (duration));
585  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
586  &ChannelAccessManager::NotifyRxEndOkNow, m_ChannelAccessManager);
587 }
588 
589 template <typename TxopType>
590 void
592 {
593  Simulator::Schedule (MicroSeconds (at) - Now (),
594  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
595  MicroSeconds (duration));
596 }
597 
598 template <typename TxopType>
599 void
601 {
602  Simulator::Schedule (MicroSeconds (at) - Now (),
603  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
604  MicroSeconds (duration));
605  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
606  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
607 }
608 
609 template <typename TxopType>
610 void
611 ChannelAccessManagerTest<TxopType>::AddRxErrorEvt (uint64_t at, uint64_t duration, uint64_t timeUntilError)
612 {
613  Simulator::Schedule (MicroSeconds (at) - Now (),
614  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
615  MicroSeconds (duration));
616  Simulator::Schedule (MicroSeconds (at + timeUntilError) - Now (),
617  &ChannelAccessManager::NotifyRxEndErrorNow, m_ChannelAccessManager);
618 }
619 
620 
621 template <typename TxopType>
622 void
623 ChannelAccessManagerTest<TxopType>::AddNavReset (uint64_t at, uint64_t duration)
624 {
625  Simulator::Schedule (MicroSeconds (at) - Now (),
626  &ChannelAccessManager::NotifyNavResetNow, m_ChannelAccessManager,
627  MicroSeconds (duration));
628 }
629 
630 template <typename TxopType>
631 void
632 ChannelAccessManagerTest<TxopType>::AddNavStart (uint64_t at, uint64_t duration)
633 {
634  Simulator::Schedule (MicroSeconds (at) - Now (),
635  &ChannelAccessManager::NotifyNavStartNow, m_ChannelAccessManager,
636  MicroSeconds (duration));
637 }
638 
639 template <typename TxopType>
640 void
642 {
643  Simulator::Schedule (MicroSeconds (at) - Now (),
644  &ChannelAccessManager::NotifyAckTimeoutResetNow, m_ChannelAccessManager);
645 }
646 
647 template <typename TxopType>
648 void
650  uint64_t expectedGrantTime, uint32_t from)
651 {
652  AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from);
653 }
654 
655 template <typename TxopType>
656 void
658  uint64_t expectedGrantTime, uint32_t from)
659 {
660  Simulator::Schedule (MicroSeconds (at) - Now (),
662  txTime, expectedGrantTime, m_txop[from]);
663 }
664 
665 template <typename TxopType>
666 void
668  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
669 {
670  NS_ASSERT (ackDelay < m_ackTimeoutValue);
671  Simulator::Schedule (MicroSeconds (at) - Now (),
673  txTime, expectedGrantTime, m_txop[from]);
674  AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay);
675 }
676 
677 template <typename TxopType>
678 void
679 ChannelAccessManagerTest<TxopType>::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime,
680  Ptr<TxopTest<TxopType>> state)
681 {
682  if (m_ChannelAccessManager->NeedBackoffUponAccess (state))
683  {
684  state->GenerateBackoff ();
685  }
686  state->QueueTx (txTime, expectedGrantTime);
687  m_ChannelAccessManager->RequestAccess (state);
688 }
689 
690 template <typename TxopType>
691 void
693 {
694  Simulator::Schedule (MicroSeconds (at) - Now (),
695  &ChannelAccessManager::NotifyMaybeCcaBusyStartNow, m_ChannelAccessManager,
696  MicroSeconds (duration));
697 }
698 
699 template <typename TxopType>
700 void
702 {
703  Simulator::Schedule (MicroSeconds (at) - Now (),
704  &ChannelAccessManager::NotifySwitchingStartNow, m_ChannelAccessManager,
705  MicroSeconds (duration));
706 }
707 
708 template <typename TxopType>
709 void
711 {
712  Simulator::Schedule (MicroSeconds (at) - Now (),
713  &ChannelAccessManager::NotifyRxStartNow, m_ChannelAccessManager,
714  MicroSeconds (duration));
715 }
716 
717 /*
718  * Specialization of DoRun () method for DCF
719  */
720 template <>
721 void
723 {
724  // DCF immediate access (no backoff)
725  // 1 4 5 6 8 11 12
726  // | sifs | aifsn | tx | idle | sifs | aifsn | tx |
727  //
728  StartTest (1, 3, 10);
729  AddTxop (1);
730  AddAccessRequest (1, 1, 5, 0);
731  AddAccessRequest (8, 2, 12, 0);
732  EndTest ();
733  // Check that receiving inside SIFS shall be cancelled properly:
734  // 1 4 5 6 9 10 14 17 18
735  // | sifs | aifsn | tx | sifs | ack | idle | sifs | aifsn | tx |
736  // |
737  // 7 start rx
738  //
739 
740  StartTest (1, 3, 10);
741  AddTxop (1);
742  AddAccessRequest (1, 1, 5, 0);
743  AddRxInsideSifsEvt (7, 10);
744  AddTxEvt (9, 1);
745  AddAccessRequest (14, 2, 18, 0);
746  EndTest ();
747  // The test below mainly intends to test the case where the medium
748  // becomes busy in the middle of a backoff slot: the backoff counter
749  // must not be decremented for this backoff slot. This is the case
750  // below for the backoff slot starting at time 78us.
751  //
752  // 20 60 66 70 74 78 80 100 106 110 114 118 120
753  // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 | bslot3 | tx |
754  // |
755  // 30 request access. backoff slots: 4
756 
757  StartTest (4, 6, 10);
758  AddTxop (1);
759  AddRxOkEvt (20, 40);
760  AddRxOkEvt (80, 20);
761  AddAccessRequest (30, 2, 118, 0);
762  ExpectBackoff (30, 4, 0); //backoff: 4 slots
763  EndTest ();
764  // Test the case where the backoff slots is zero.
765  //
766  // 20 60 66 70 72
767  // | rx | sifs | aifsn | tx |
768  // |
769  // 30 request access. backoff slots: 0
770 
771  StartTest (4, 6, 10);
772  AddTxop (1);
773  AddRxOkEvt (20, 40);
774  AddAccessRequest (30, 2, 70, 0);
775  ExpectBackoff (30, 0, 0); // backoff: 0 slots
776  EndTest ();
777  // Test shows when two frames are received without interval between
778  // them:
779  // 20 60 100 106 110 112
780  // | rx | rx |sifs | aifsn | tx |
781  // |
782  // 30 request access. backoff slots: 0
783 
784  StartTest (4, 6, 10);
785  AddTxop (1);
786  AddRxOkEvt (20, 40);
787  AddRxOkEvt (60, 40);
788  AddAccessRequest (30, 2, 110, 0);
789  ExpectBackoff (30, 0, 0); //backoff: 0 slots
790  EndTest ();
791 
792  // Requesting access within SIFS interval (DCF immediate access)
793  //
794  // 20 60 62 68 72
795  // | rx | idle | sifs | aifsn | tx |
796  //
797  StartTest (4, 6, 10);
798  AddTxop (1);
799  AddRxOkEvt (20, 40);
800  AddAccessRequest (62, 2, 72, 0);
801  EndTest ();
802 
803  // Requesting access after DIFS (DCF immediate access)
804  //
805  // 20 60 70 76 80
806  // | rx | idle | sifs | aifsn | tx |
807  //
808  StartTest (4, 6, 10);
809  AddTxop (1);
810  AddRxOkEvt (20, 40);
811  AddAccessRequest (70, 2, 80, 0);
812  EndTest ();
813 
814  // Test an EIFS
815  //
816  // 20 60 66 76 86 90 94 98 102 106
817  // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
818  // | | <------eifs------>|
819  // 30 request access. backoff slots: 4
820  StartTest (4, 6, 10);
821  AddTxop (1);
822  AddRxErrorEvt (20, 40);
823  AddAccessRequest (30, 2, 102, 0);
824  ExpectBackoff (30, 4, 0); //backoff: 4 slots
825  EndTest ();
826 
827  // Test DCF immediate access after an EIFS (EIFS is greater)
828  //
829  // 20 60 66 76 86
830  // | <----+-eifs------>|
831  // | rx | sifs | acktxttime | sifs + aifsn | tx |
832  // | sifs + aifsn |
833  // request access 70 80
834  StartTest (4, 6, 10);
835  AddTxop (1);
836  AddRxErrorEvt (20, 40);
837  AddAccessRequest (70, 2, 86, 0);
838  EndTest ();
839 
840  // Test that channel stays busy for first frame's duration after Rx error
841  //
842  // 20 60
843  // | rx |
844  // |
845  // 40 force Rx error
846  StartTest (4, 6, 10);
847  AddTxop (1);
848  AddRxErrorEvt (20, 40, 20); // At time 20, start reception for 40, but force error 20 into frame
849  ExpectBusy (41, true); // channel should remain busy for remaining duration
850  ExpectBusy (59, true);
851  ExpectBusy (61, false);
852  EndTest ();
853 
854  // Test an EIFS which is interrupted by a successful transmission.
855  //
856  // 20 60 66 69 75 81 85 89 93 97 101 103
857  // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
858  // | | <--eifs-->|
859  // 30 request access. backoff slots: 4
860  StartTest (4, 6, 10);
861  AddTxop (1);
862  AddRxErrorEvt (20, 40);
863  AddAccessRequest (30, 2, 101, 0);
864  ExpectBackoff (30, 4, 0); //backoff: 4 slots
865  AddRxOkEvt (69, 6);
866  EndTest ();
867 
868  // Test two DCFs which suffer an internal collision. the first DCF has a higher
869  // priority than the second DCF.
870  //
871  // 20 60 66 70 74 78 88
872  // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
873  // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn | bslot | tx |
874  // 94 98 102 106 110 112
875  StartTest (4, 6, 10);
876  AddTxop (1); //high priority DCF
877  AddTxop (3); //low priority DCF
878  AddRxOkEvt (20, 40);
879  AddAccessRequest (30, 10, 78, 0);
880  ExpectBackoff (30, 2, 0); //backoff: 2 slot
881  AddAccessRequest (40, 2, 110, 1);
882  ExpectBackoff (40, 0, 1); //backoff: 0 slot
883  ExpectInternalCollision (78, 1, 1); //backoff: 1 slot
884  EndTest ();
885 
886  // Test of AckTimeout handling: First queue requests access and ack procedure fails,
887  // inside the Ack timeout second queue with higher priority requests access.
888  //
889  // 20 26 34 54 74 80
890  // DCF1 - low | sifs | aifsn | tx | Ack timeout | sifs | |
891  // DCF0 - high | | | sifs | tx |
892  // ^ request access
893  StartTest (4, 6, 10);
894  AddTxop (0); //high priority DCF
895  AddTxop (2); //low priority DCF
896  AddAccessRequestWithAckTimeout (20, 20, 34, 1);
897  AddAccessRequest (64, 10, 80, 0);
898  EndTest ();
899 
900  // Test of AckTimeout handling:
901  //
902  // First queue requests access and Ack is 2 us delayed (got Ack interval at the picture),
903  // inside this interval second queue with higher priority requests access.
904  //
905  // 20 26 34 54 56 62
906  // DCF1 - low | sifs | aifsn | tx | got Ack | sifs | |
907  // DCF0 - high | | | sifs | tx |
908  // ^ request access
909  StartTest (4, 6, 10);
910  AddTxop (0); //high priority DCF
911  AddTxop (2); //low priority DCF
912  AddAccessRequestWithSuccessfullAck (20, 20, 34, 2, 1);
913  AddAccessRequest (55, 10, 62, 0);
914  EndTest ();
915 
916  //Repeat the same but with one queue:
917  // 20 26 34 54 60 62 68 76 80
918  // DCF0 | sifs | aifsn | tx | sifs | Ack | sifs | aifsn | bslot0 | tx |
919  // ^ request access
920  StartTest (4, 6, 10);
921  AddTxop (2);
922  AddAccessRequest (20, 20, 34, 0);
923  AddRxOkEvt (60, 2); // Ack
924  AddAccessRequest (61, 10, 80, 0);
925  ExpectBackoff (61, 1, 0); // 1 slot
926  EndTest ();
927 
928  // test simple NAV count. This scenario models a simple Data+Ack handshake
929  // where the data rate used for the Ack is higher than expected by the Data source
930  // so, the data exchange completes before the end of NAV.
931  StartTest (4, 6, 10);
932  AddTxop (1);
933  AddRxOkEvt (20, 40);
934  AddNavStart (60, 15);
935  AddRxOkEvt (66, 5);
936  AddNavStart (71, 0);
937  AddAccessRequest (30, 10, 93, 0);
938  ExpectBackoff (30, 2, 0); //backoff: 2 slots
939  EndTest ();
940 
941  // test more complex NAV handling by a CF-poll. This scenario models a
942  // simple Data+Ack handshake interrupted by a CF-poll which resets the
943  // NAV counter.
944  StartTest (4, 6, 10);
945  AddTxop (1);
946  AddRxOkEvt (20, 40);
947  AddNavStart (60, 15);
948  AddRxOkEvt (66, 5);
949  AddNavReset (71, 2);
950  AddAccessRequest (30, 10, 91, 0);
951  ExpectBackoff (30, 2, 0); //backoff: 2 slots
952  EndTest ();
953 
954 
955  // 20 60 80 86 94
956  // | rx | idle | sifs | aifsn | tx |
957  // ^ request access
958  StartTest (4, 6, 10);
959  AddTxop (2);
960  AddRxOkEvt (20, 40);
961  AddAccessRequest (80, 10, 94, 0);
962  EndTest ();
963 
964 
965  StartTest (4, 6, 10);
966  AddTxop (2);
967  AddRxOkEvt (20, 40);
968  AddRxOkEvt (78, 8);
969  AddAccessRequest (30, 50, 108, 0);
970  ExpectBackoff (30, 3, 0); //backoff: 3 slots
971  EndTest ();
972 
973 
974  // Channel switching tests
975 
976  // 0 20 21 24 25 26
977  // | switching | idle | sifs | aifsn | tx |
978  // ^ access request.
979  StartTest (1, 3, 10);
980  AddTxop (1);
981  AddSwitchingEvt (0, 20);
982  AddAccessRequest (21, 1, 25, 0);
983  EndTest ();
984 
985  // 20 40 50 53 54 55 56 57
986  // | switching | busy | sifs | aifsn | bslot0 | bslot 1 | tx |
987  // | |
988  // 30 busy. 45 access request.
989  //
990  StartTest (1, 3, 10);
991  AddTxop (1);
992  AddSwitchingEvt (20,20);
993  AddCcaBusyEvt (30,20);
994  ExpectBackoff (45, 2, 0); //backoff: 2 slots
995  AddAccessRequest (45, 1, 56, 0);
996  EndTest ();
997 
998  // 20 30 50 51 54 55 56
999  // | rx | switching | idle | sifs | aifsn | tx |
1000  // ^ access request.
1001  //
1002  StartTest (1, 3, 10);
1003  AddTxop (1);
1004  AddRxStartEvt (20, 40);
1005  AddSwitchingEvt (30, 20);
1006  AddAccessRequest (51, 1, 55, 0);
1007  EndTest ();
1008 
1009  // 20 30 50 51 54 55 56
1010  // | busy | switching | idle | sifs | aifsn | tx |
1011  // ^ access request.
1012  //
1013  StartTest (1, 3, 10);
1014  AddTxop (1);
1015  AddCcaBusyEvt (20, 40);
1016  AddSwitchingEvt (30, 20);
1017  AddAccessRequest (51, 1, 55, 0);
1018  EndTest ();
1019 
1020  // 20 30 50 51 54 55 56
1021  // | nav | switching | idle | sifs | aifsn | tx |
1022  // ^ access request.
1023  //
1024  StartTest (1, 3, 10);
1025  AddTxop (1);
1026  AddNavStart (20,40);
1027  AddSwitchingEvt (30,20);
1028  AddAccessRequest (51, 1, 55, 0);
1029  EndTest ();
1030 
1031  // 20 23 24 44 54 59 60 63 64 65
1032  // | sifs | aifsn | tx | Ack timeout | switching | idle | sifs | aifsn | tx |
1033  // | |
1034  // 49 access request. ^ access request.
1035  //
1036  StartTest (1, 3, 10);
1037  AddTxop (1);
1038  AddAccessRequestWithAckTimeout (20, 20, 24, 0);
1039  AddAccessRequest (49, 1, 54, 0);
1040  AddSwitchingEvt (54, 5);
1041  AddAccessRequest (60, 1, 64, 0);
1042  EndTest ();
1043 
1044  // 20 60 66 70 74 78 80 100 101 107 111 113
1045  // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | idle | sifs | aifsn | tx |
1046  // | |
1047  // 30 access request. ^ access request.
1048  //
1049  StartTest (4, 6, 10);
1050  AddTxop (1);
1051  AddRxOkEvt (20,40);
1052  AddAccessRequest (30, 2, 80, 0);
1053  ExpectBackoff (30, 4, 0); //backoff: 4 slots
1054  AddSwitchingEvt (80,20);
1055  AddAccessRequest (101, 2, 111, 0);
1056  EndTest ();
1057 }
1058 
1059 /*
1060  * Specialization of DoRun () method for EDCA
1061  */
1062 template <>
1063 void
1065 {
1066  // Check alignment at slot boundary after successful reception (backoff = 0):
1067  // 20 50 56 60 80
1068  // | rx | sifs | aifsn | tx |
1069  // |
1070  // 52 request access
1071  StartTest (4, 6, 10);
1072  AddTxop (1);
1073  AddRxOkEvt (20, 30);
1074  AddAccessRequest (52, 20, 60, 0);
1075  EndTest ();
1076 
1077  // Check alignment at slot boundary after successful reception (backoff = 0):
1078  // 20 50 56 60 80
1079  // | rx | sifs | aifsn | tx |
1080  // |
1081  // 58 request access
1082  StartTest (4, 6, 10);
1083  AddTxop (1);
1084  AddRxOkEvt (20, 30);
1085  AddAccessRequest (52, 20, 60, 0);
1086  EndTest ();
1087 
1088  // Check alignment at slot boundary after successful reception (backoff = 0):
1089  // 20 50 56 60 64 84
1090  // | rx | sifs | aifsn | idle | tx |
1091  // |
1092  // 62 request access
1093  StartTest (4, 6, 10);
1094  AddTxop (1);
1095  AddRxOkEvt (20, 30);
1096  AddAccessRequest (62, 20, 64, 0);
1097  EndTest ();
1098 
1099  // Check alignment at slot boundary after failed reception (backoff = 0):
1100  // 20 50 56 66 76 96
1101  // | | <------eifs------>| | |
1102  // | rx | sifs | acktxttime | sifs + aifsn | tx |
1103  // |
1104  // 55 request access
1105  StartTest (4, 6, 10);
1106  AddTxop (1);
1107  AddRxErrorEvt (20, 30);
1108  AddAccessRequest (55, 20, 76, 0);
1109  EndTest ();
1110 
1111  // Check alignment at slot boundary after failed reception (backoff = 0):
1112  // 20 50 56 66 76 96
1113  // | | <------eifs------>| | |
1114  // | rx | sifs | acktxttime | sifs + aifsn | tx |
1115  // |
1116  // 70 request access
1117  StartTest (4, 6, 10);
1118  AddTxop (1);
1119  AddRxErrorEvt (20, 30);
1120  AddAccessRequest (70, 20, 76, 0);
1121  EndTest ();
1122 
1123  // Check alignment at slot boundary after failed reception (backoff = 0):
1124  // 20 50 56 66 76 84
1125  // | | <------eifs------>| | |
1126  // | rx | sifs | acktxttime | sifs + aifsn | idle | tx |
1127  // |
1128  // 82 request access
1129  StartTest (4, 6, 10);
1130  AddTxop (1);
1131  AddRxErrorEvt (20, 30);
1132  AddAccessRequest (82, 20, 84, 0);
1133  EndTest ();
1134 
1135  // Check backoff decrement at slot boundaries. Medium idle during backoff
1136  // 20 50 56 60 64 68 72 76 96
1137  // | rx | sifs | aifsn | idle | idle | idle | idle | tx |
1138  // | | | | |
1139  // 30 request access. decrement decrement decrement decrement
1140  // backoff slots: 4 slots: 3 slots: 2 slots: 1 slots: 0
1141  StartTest (4, 6, 10);
1142  AddTxop (1);
1143  AddRxOkEvt (20, 30);
1144  AddAccessRequest (30, 20, 76, 0);
1145  ExpectBackoff (30, 4, 0);
1146  EndTest ();
1147 
1148  // Check backoff decrement at slot boundaries. Medium becomes busy during backoff
1149  // 20 50 56 60 61 71 77 81 85 87 97 103 107 127
1150  // | rx | sifs | aifsn | idle | rx | sifs | aifsn | idle | idle | rx | sifs | aifsn | tx |
1151  // | | | |
1152  // 30 request access. decrement decrement decrement
1153  // backoff slots: 3 slots: 2 slots: 1 slots: 0
1154  StartTest (4, 6, 10);
1155  AddTxop (1);
1156  AddRxOkEvt (20, 30);
1157  AddRxOkEvt (61, 10);
1158  AddRxOkEvt (87, 10);
1159  AddAccessRequest (30, 20, 107, 0);
1160  ExpectBackoff (30, 3, 0);
1161  EndTest ();
1162 }
1163 
1170 class TxopTestSuite : public TestSuite
1171 {
1172 public:
1173  TxopTestSuite ();
1174 };
1175 
1177  : TestSuite ("wifi-devices-dcf", UNIT)
1178 {
1179  AddTestCase (new ChannelAccessManagerTest<Txop>, TestCase::QUICK);
1180 }
1181 
1183 
1191 {
1192 public:
1193  QosTxopTestSuite ();
1194 };
1195 
1197  : TestSuite ("wifi-devices-edca", UNIT)
1198 {
1199  AddTestCase (new ChannelAccessManagerTest<QosTxop>, TestCase::QUICK);
1200 }
1201 
Ptr< ChannelAccessManager > m_ChannelAccessManager
the channel access manager
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.
std::list< struct ExpectedBackoff > ExpectedBackoffs
expected backoffs typedef
A suite of tests to run.
Definition: test.h:1341
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
void DoDispose(void)
Inherited.
static TxopTestSuite g_dcfTestSuite
TxopTests m_txop
the vector of Txop test instances
encapsulates test code
Definition: test.h:1153
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
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 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.
void NotifyInternalCollision(void)
Notify the Txop that internal collision has occurred.
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:1080
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:309
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 AddNavReset(uint64_t at, uint64_t duration)
Add NAV reset function.
bool HasFramesToTransmit(void)
Check if the Txop has frames to transmit.