A Discrete-Event Network Simulator
API
dcf-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/dcf-manager.h"
24 
25 using namespace ns3;
26 
27 class DcfManagerTest;
28 
29 class DcfStateTest : public DcfState
30 {
31 public:
32  DcfStateTest (DcfManagerTest *test, uint32_t i);
33  void QueueTx (uint64_t txTime, uint64_t expectedGrantTime);
34  bool IsEdca (void) const;
35 
36 
37 private:
38  friend class DcfManagerTest;
39  virtual void DoNotifyAccessGranted (void);
40  virtual void DoNotifyInternalCollision (void);
41  virtual void DoNotifyCollision (void);
42  virtual void DoNotifyChannelSwitching (void);
43  virtual void DoNotifySleep (void);
44  virtual void DoNotifyWakeUp (void);
45 
46  typedef std::pair<uint64_t,uint64_t> ExpectedGrant;
47  typedef std::list<ExpectedGrant> ExpectedGrants;
49  {
50  uint64_t at;
51  uint32_t nSlots;
52  };
53  typedef std::list<struct ExpectedCollision> ExpectedCollisions;
54 
55  ExpectedCollisions m_expectedInternalCollision;
56  ExpectedCollisions m_expectedCollision;
57  ExpectedGrants m_expectedGrants;
59  uint32_t m_i;
60 };
61 
62 
63 class DcfManagerTest : public TestCase
64 {
65 public:
66  DcfManagerTest ();
67  virtual void DoRun (void);
68 
69  void NotifyAccessGranted (uint32_t i);
70  void NotifyInternalCollision (uint32_t i);
71  void NotifyCollision (uint32_t i);
72  void NotifyChannelSwitching (uint32_t i);
73 
74 
75 private:
76  void StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue = 20);
77  void AddDcfState (uint32_t aifsn);
78  void EndTest (void);
79  void ExpectInternalCollision (uint64_t time, uint32_t from, uint32_t nSlots);
80  void ExpectCollision (uint64_t time, uint32_t from, uint32_t nSlots);
81  void AddRxOkEvt (uint64_t at, uint64_t duration);
82  void AddRxErrorEvt (uint64_t at, uint64_t duration);
83  void AddRxInsideSifsEvt (uint64_t at, uint64_t duration);
84  void AddTxEvt (uint64_t at, uint64_t duration);
85  void AddNavReset (uint64_t at, uint64_t duration);
86  void AddNavStart (uint64_t at, uint64_t duration);
87  void AddAckTimeoutReset (uint64_t at);
88  void AddAccessRequest (uint64_t at, uint64_t txTime,
89  uint64_t expectedGrantTime, uint32_t from);
90  void AddAccessRequestWithAckTimeout (uint64_t at, uint64_t txTime,
91  uint64_t expectedGrantTime, uint32_t from);
97  void AddAccessRequestWithSuccessfullAck (uint64_t at, uint64_t txTime,
98  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from);
99  void DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, DcfStateTest *state);
100  void AddCcaBusyEvt (uint64_t at, uint64_t duration);
101  void AddSwitchingEvt (uint64_t at, uint64_t duration);
102  void AddRxStartEvt (uint64_t at, uint64_t duration);
103 
104  typedef std::vector<DcfStateTest *> DcfStates;
105 
107  DcfStates m_dcfStates;
109 };
110 
112  : m_test (test),
113  m_i (i)
114 {
115 }
116 
117 bool
119 {
120  return false;
121 }
122 
123 void
124 DcfStateTest::QueueTx (uint64_t txTime, uint64_t expectedGrantTime)
125 {
126  m_expectedGrants.push_back (std::make_pair (txTime, expectedGrantTime));
127 }
128 
129 void
131 {
133 }
134 
135 void
137 {
139 }
140 
141 void
143 {
145 }
146 
147 void
149 {
151 }
152 
153 void
155 {
156 }
157 
158 void
160 {
161 }
162 
164  : TestCase ("DcfManager")
165 {
166 }
167 
168 void
170 {
171  DcfStateTest *state = m_dcfStates[i];
172  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), false, "Have expected grants");
173  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
174  state->m_expectedGrants.pop_front ();
175  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected access grant is now");
176  m_dcfManager->NotifyTxStartNow (MicroSeconds (expected.first));
178 }
179 
180 void
181 DcfManagerTest::AddTxEvt (uint64_t at, uint64_t duration)
182 {
183  Simulator::Schedule (MicroSeconds (at) - Now (),
184  &DcfManager::NotifyTxStartNow, m_dcfManager,
185  MicroSeconds (duration));
186 }
187 
188 void
190 {
191  DcfStateTest *state = m_dcfStates[i];
192  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), false, "Have expected internal collisions");
193  struct DcfStateTest::ExpectedCollision expected = state->m_expectedInternalCollision.front ();
194  state->m_expectedInternalCollision.pop_front ();
195  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected internal collision time is now");
196  state->StartBackoffNow (expected.nSlots);
197 }
198 
199 void
201 {
202  DcfStateTest *state = m_dcfStates[i];
203  NS_TEST_EXPECT_MSG_EQ (state->m_expectedCollision.empty (), false, "Have expected collisions");
204  struct DcfStateTest::ExpectedCollision expected = state->m_expectedCollision.front ();
205  state->m_expectedCollision.pop_front ();
206  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.at), "Expected collision is now");
207  state->StartBackoffNow (expected.nSlots);
208 }
209 
210 void
212 {
213  DcfStateTest *state = m_dcfStates[i];
214  if (!state->m_expectedGrants.empty ())
215  {
216  std::pair<uint64_t, uint64_t> expected = state->m_expectedGrants.front ();
217  state->m_expectedGrants.pop_front ();
218  NS_TEST_EXPECT_MSG_EQ (Simulator::Now (), MicroSeconds (expected.second), "Expected grant is now");
219  }
220 }
221 
222 void
223 DcfManagerTest::ExpectInternalCollision (uint64_t time, uint32_t nSlots, uint32_t from)
224 {
225  DcfStateTest *state = m_dcfStates[from];
227  col.at = time;
228  col.nSlots = nSlots;
229  state->m_expectedInternalCollision.push_back (col);
230 }
231 
232 void
233 DcfManagerTest::ExpectCollision (uint64_t time, uint32_t nSlots, uint32_t from)
234 {
235  DcfStateTest *state = m_dcfStates[from];
237  col.at = time;
238  col.nSlots = nSlots;
239  state->m_expectedCollision.push_back (col);
240 }
241 
242 void
243 DcfManagerTest::StartTest (uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue)
244 {
245  m_dcfManager = new DcfManager ();
246  m_dcfManager->SetSlot (MicroSeconds (slotTime));
248  m_dcfManager->SetEifsNoDifs (MicroSeconds (eifsNoDifsNoSifs + sifs));
249  m_ackTimeoutValue = ackTimeoutValue;
250 }
251 
252 void
254 {
255  DcfStateTest *state = new DcfStateTest (this, m_dcfStates.size ());
256  state->SetAifsn (aifsn);
257  m_dcfStates.push_back (state);
258  m_dcfManager->Add (state);
259 }
260 
261 void
263 {
264  Simulator::Run ();
265  Simulator::Destroy ();
266  for (DcfStates::const_iterator i = m_dcfStates.begin (); i != m_dcfStates.end (); i++)
267  {
268  DcfStateTest *state = *i;
269  NS_TEST_EXPECT_MSG_EQ (state->m_expectedGrants.empty (), true, "Have no expected grants");
270  NS_TEST_EXPECT_MSG_EQ (state->m_expectedInternalCollision.empty (), true, "Have no internal collisions");
271  NS_TEST_EXPECT_MSG_EQ (state->m_expectedCollision.empty (), true, "Have no expected collisions");
272  delete state;
273  }
274  m_dcfStates.clear ();
275  delete m_dcfManager;
276 }
277 
278 void
279 DcfManagerTest::AddRxOkEvt (uint64_t at, uint64_t duration)
280 {
281  Simulator::Schedule (MicroSeconds (at) - Now (),
282  &DcfManager::NotifyRxStartNow, m_dcfManager,
283  MicroSeconds (duration));
284  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
285  &DcfManager::NotifyRxEndOkNow, m_dcfManager);
286 }
287 
288 void
289 DcfManagerTest::AddRxInsideSifsEvt (uint64_t at, uint64_t duration)
290 {
291  Simulator::Schedule (MicroSeconds (at) - Now (),
292  &DcfManager::NotifyRxStartNow, m_dcfManager,
293  MicroSeconds (duration));
294 }
295 
296 void
297 DcfManagerTest::AddRxErrorEvt (uint64_t at, uint64_t duration)
298 {
299  Simulator::Schedule (MicroSeconds (at) - Now (),
300  &DcfManager::NotifyRxStartNow, m_dcfManager,
301  MicroSeconds (duration));
302  Simulator::Schedule (MicroSeconds (at + duration) - Now (),
303  &DcfManager::NotifyRxEndErrorNow, m_dcfManager);
304 }
305 
306 void
307 DcfManagerTest::AddNavReset (uint64_t at, uint64_t duration)
308 {
309  Simulator::Schedule (MicroSeconds (at) - Now (),
310  &DcfManager::NotifyNavResetNow, m_dcfManager,
311  MicroSeconds (duration));
312 }
313 
314 void
315 DcfManagerTest::AddNavStart (uint64_t at, uint64_t duration)
316 {
317  Simulator::Schedule (MicroSeconds (at) - Now (),
318  &DcfManager::NotifyNavStartNow, m_dcfManager,
319  MicroSeconds (duration));
320 }
321 
322 void
324 {
325  Simulator::Schedule (MicroSeconds (at) - Now (),
326  &DcfManager::NotifyAckTimeoutResetNow, m_dcfManager);
327 }
328 
329 void
330 DcfManagerTest::AddAccessRequest (uint64_t at, uint64_t txTime,
331  uint64_t expectedGrantTime, uint32_t from)
332 {
333  AddAccessRequestWithSuccessfullAck (at, txTime, expectedGrantTime, 0, from);
334 }
335 
336 void
338  uint64_t expectedGrantTime, uint32_t from)
339 {
340  Simulator::Schedule (MicroSeconds (at) - Now (),
342  txTime, expectedGrantTime, m_dcfStates[from]);
343 }
344 
345 void
347  uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
348 {
349  NS_ASSERT (ackDelay < m_ackTimeoutValue);
350  Simulator::Schedule (MicroSeconds (at) - Now (),
352  txTime, expectedGrantTime, m_dcfStates[from]);
353  AddAckTimeoutReset (expectedGrantTime + txTime + ackDelay);
354 }
355 
356 void
357 DcfManagerTest::DoAccessRequest (uint64_t txTime, uint64_t expectedGrantTime, DcfStateTest *state)
358 {
359  state->QueueTx (txTime, expectedGrantTime);
360  m_dcfManager->RequestAccess (state);
361 }
362 
363 void
364 DcfManagerTest::AddCcaBusyEvt (uint64_t at, uint64_t duration)
365 {
366  Simulator::Schedule (MicroSeconds (at) - Now (),
367  &DcfManager::NotifyMaybeCcaBusyStartNow, m_dcfManager,
368  MicroSeconds (duration));
369 }
370 
371 void
372 DcfManagerTest::AddSwitchingEvt (uint64_t at, uint64_t duration)
373 {
374  Simulator::Schedule (MicroSeconds (at) - Now (),
375  &DcfManager::NotifySwitchingStartNow, m_dcfManager,
376  MicroSeconds (duration));
377 }
378 
379 void
380 DcfManagerTest::AddRxStartEvt (uint64_t at, uint64_t duration)
381 {
382  Simulator::Schedule (MicroSeconds (at) - Now (),
383  &DcfManager::NotifyRxStartNow, m_dcfManager,
384  MicroSeconds (duration));
385 }
386 
387 void
389 {
390  // 0 3 4 5 8 9 10 12
391  // | sifs | aifsn | tx | sifs | aifsn | | tx |
392  //
393  StartTest (1, 3, 10);
394  AddDcfState (1);
395  AddAccessRequest (1, 1, 4, 0);
396  AddAccessRequest (10, 2, 10, 0);
397  EndTest ();
398  // Check that receiving inside SIFS shall be cancelled properly:
399  // 0 3 4 5 8 9 12 13 14
400  // | sifs | aifsn | tx | sifs | ack | sifs | aifsn | |tx |
401  //
402 
403  StartTest (1, 3, 10);
404  AddDcfState (1);
405  AddAccessRequest (1, 1, 4, 0);
406  AddRxInsideSifsEvt (6, 10);
407  AddTxEvt (8, 1);
408  AddAccessRequest (14, 2, 14, 0);
409  EndTest ();
410  // The test below mainly intends to test the case where the medium
411  // becomes busy in the middle of a backoff slot: the backoff counter
412  // must not be decremented for this backoff slot. This is the case
413  // below for the backoff slot starting at time 78us.
414  //
415  // 20 60 66 70 74 78 80 100 106 110 114 118 120
416  // | rx | sifs | aifsn | bslot0 | bslot1 | | rx | sifs | aifsn | bslot2 | bslot3 | tx |
417  // |
418  // 30 request access. backoff slots: 4
419 
420  StartTest (4, 6, 10);
421  AddDcfState (1);
422  AddRxOkEvt (20, 40);
423  AddRxOkEvt (80, 20);
424  AddAccessRequest (30, 2, 118, 0);
425  ExpectCollision (30, 4, 0); //backoff: 4 slots
426  EndTest ();
427  // Test the case where the backoff slots is zero.
428  //
429  // 20 60 66 70 72
430  // | rx | sifs | aifsn | tx |
431  // |
432  // 30 request access. backoff slots: 0
433 
434  StartTest (4, 6, 10);
435  AddDcfState (1);
436  AddRxOkEvt (20, 40);
437  AddAccessRequest (30, 2, 70, 0);
438  ExpectCollision (30, 0, 0); // backoff: 0 slots
439  EndTest ();
440  // Test shows when two frames are received without interval between
441  // them:
442  // 20 60 100 106 110 112
443  // | rx | rx |sifs | aifsn | tx |
444  // |
445  // 30 request access. backoff slots: 0
446 
447  StartTest (4, 6, 10);
448  AddDcfState (1);
449  AddRxOkEvt (20, 40);
450  AddRxOkEvt (60, 40);
451  AddAccessRequest (30, 2, 110, 0);
452  ExpectCollision (30, 0, 0); //backoff: 0 slots
453  EndTest ();
454 
455  // The test below is subject to some discussion because I am
456  // not sure I understand the intent of the spec here.
457  // i.e., what happens if you make a request to get access
458  // to the medium during the difs idle time after a busy period ?
459  // do you need to start a backoff ? Or do you need to wait until
460  // the end of difs and access the medium ?
461  // Here, we wait until the end of difs and access the medium.
462  //
463  // 20 60 66 70 72
464  // | rx | sifs | aifsn | tx |
465  // |
466  // 62 request access.
467  //
468  StartTest (4, 6, 10);
469  AddDcfState (1);
470  AddRxOkEvt (20, 40);
471  AddAccessRequest (62, 2, 70, 0);
472  EndTest ();
473 
474  // Test an EIFS
475  //
476  // 20 60 66 76 86 90 94 98 102 106
477  // | rx | sifs | acktxttime | sifs + aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
478  // | | <------eifs------>|
479  // 30 request access. backoff slots: 4
480  StartTest (4, 6, 10);
481  AddDcfState (1);
482  AddRxErrorEvt (20, 40);
483  AddAccessRequest (30, 2, 102, 0);
484  ExpectCollision (30, 4, 0); //backoff: 4 slots
485  EndTest ();
486 
487  // Test an EIFS which is interupted by a successfull transmission.
488  //
489  // 20 60 66 69 75 81 85 89 93 97 101 103
490  // | rx | sifs | | rx | sifs | aifsn | bslot0 | bslot1 | bslot2 | bslot3 | tx |
491  // | | <--eifs-->|
492  // 30 request access. backoff slots: 4
493  StartTest (4, 6, 10);
494  AddDcfState (1);
495  AddRxErrorEvt (20, 40);
496  AddAccessRequest (30, 2, 101, 0);
497  ExpectCollision (30, 4, 0); //backoff: 4 slots
498  AddRxOkEvt (69, 6);
499  EndTest ();
500 
501  // Test two DCFs which suffer an internal collision. the first DCF has a higher
502  // priority than the second DCF.
503  //
504  // 20 60 66 70 74 78 88
505  // DCF0 | rx | sifs | aifsn | bslot0 | bslot1 | tx |
506  // DCF1 | rx | sifs | aifsn | aifsn | aifsn | | sifs | aifsn | aifsn | aifsn | bslot | tx |
507  // 94 98 102 106 110 112
508  StartTest (4, 6, 10);
509  AddDcfState (1); //high priority DCF
510  AddDcfState (3); //low priority DCF
511  AddRxOkEvt (20, 40);
512  AddAccessRequest (30, 10, 78, 0);
513  ExpectCollision (30, 2, 0); //backoff: 2 slot
514  AddAccessRequest (40, 2, 110, 1);
515  ExpectCollision (40, 0, 1); //backoff: 0 slot
516  ExpectInternalCollision (78, 1, 1); //backoff: 1 slot
517  EndTest ();
518 
519  // Test of AckTimeout handling: First queue requests access and ack procedure fails,
520  // inside the ack timeout second queue with higher priority requests access.
521  //
522  // 20 40 50 60 66 76
523  // DCF0 - low | tx | ack timeout |sifs| |
524  // DCF1 - high | | |sifs| tx |
525  // ^ request access
526  StartTest (4, 6, 10);
527  AddDcfState (2); //high priority DCF
528  AddDcfState (0); //low priority DCF
529  AddAccessRequestWithAckTimeout (20, 20, 20, 0);
530  AddAccessRequest (50, 10, 66, 1);
531  EndTest ();
532 
533  // Test of AckTimeout handling:
534  //
535  // First queue requests access and ack is 2 us delayed (got ack interval at the picture),
536  // inside this interval second queue with higher priority requests access.
537  //
538  // 20 40 41 42 48 58
539  // DCF0 - low | tx |got ack |sifs| |
540  // DCF1 - high | | |sifs| tx |
541  // ^ request access
542  StartTest (4, 6, 10);
543  AddDcfState (2); //high priority DCF
544  AddDcfState (0); //low priority DCF
545  AddAccessRequestWithSuccessfullAck (20, 20, 20, 2, 0);
546  AddAccessRequest (41, 10, 48, 1);
547  EndTest ();
548 
549  //Repeat the same but with one queue:
550  // 20 40 41 42 48 58
551  // DCF0 - low | tx |got ack |sifs| |
552  // ^ request access
553  StartTest (4, 6, 10);
554  AddDcfState (2);
555  AddAccessRequestWithSuccessfullAck (20, 20, 20, 2, 0);
556  AddAccessRequest (41, 10, 56, 0);
557  EndTest ();
558 
559  //Repeat the same when ack was delayed:
560  //and request the next access before previous tx end:
561  // 20 39 40 42 64 74
562  // DCF0 - low | tx |got ack |sifs + 4 * slot| |
563  // ^ request access
564  StartTest (4, 6, 10);
565  AddDcfState (2);
566  AddAccessRequestWithSuccessfullAck (20, 20, 20, 2, 0);
567  AddAccessRequest (39, 10, 64, 0);
568  ExpectCollision (39, 2, 0); //backoff: 2 slot
569  EndTest ();
570 
571  // test simple NAV count. This scenario modelizes a simple DATA+ACK handshake
572  // where the data rate used for the ACK is higher than expected by the DATA source
573  // so, the data exchange completes before the end of nav.
574  StartTest (4, 6, 10);
575  AddDcfState (1);
576  AddRxOkEvt (20, 40);
577  AddNavStart (60, 15);
578  AddRxOkEvt (66, 5);
579  AddNavStart (71, 0);
580  AddAccessRequest (30, 10, 93, 0);
581  ExpectCollision (30, 2, 0); //backoff: 2 slot
582  EndTest ();
583 
584  // test more complex NAV handling by a CF-poll. This scenario modelizes a
585  // simple DATA+ACK handshake interrupted by a CF-poll which resets the
586  // NAV counter.
587  StartTest (4, 6, 10);
588  AddDcfState (1);
589  AddRxOkEvt (20, 40);
590  AddNavStart (60, 15);
591  AddRxOkEvt (66, 5);
592  AddNavReset (71, 2);
593  AddAccessRequest (30, 10, 91, 0);
594  ExpectCollision (30, 2, 0); //backoff: 2 slot
595  EndTest ();
596 
597 
598  StartTest (4, 6, 10);
599  AddDcfState (2);
600  AddRxOkEvt (20, 40);
601  AddAccessRequest (80, 10, 80, 0);
602  EndTest ();
603 
604 
605  StartTest (4, 6, 10);
606  AddDcfState (2);
607  AddRxOkEvt (20, 40);
608  AddRxOkEvt (78, 8);
609  AddAccessRequest (30, 50, 108, 0);
610  ExpectCollision (30, 3, 0); //backoff: 3 slots
611  EndTest ();
612 
613 
614  // Channel switching tests
615 
616  // 0 20 23 24 25
617  // | switching | sifs | aifsn | tx |
618  // |
619  // 21 access request.
620  StartTest (1, 3, 10);
621  AddDcfState (1);
622  AddSwitchingEvt (0,20);
623  AddAccessRequest (21, 1, 24, 0);
624  EndTest ();
625 
626  // 20 40 50 53 54 55
627  // | switching | busy | sifs | aifsn | tx |
628  // | |
629  // 30 busy. 45 access request.
630  //
631  StartTest (1, 3, 10);
632  AddDcfState (1);
633  AddSwitchingEvt (20,20);
634  AddCcaBusyEvt (30,20);
635  AddAccessRequest (45, 1, 54, 0);
636  EndTest ();
637 
638  // 20 30 50 53 54 55
639  // | rx | switching | sifs | aifsn | tx |
640  // |
641  // 51 access request.
642  //
643  StartTest (1, 3, 10);
644  AddDcfState (1);
645  AddRxStartEvt (20,40);
646  AddSwitchingEvt (30,20);
647  AddAccessRequest (51, 1, 54, 0);
648  EndTest ();
649 
650  // 20 30 50 53 54 55
651  // | busy | switching | sifs | aifsn | tx |
652  // |
653  // 51 access request.
654  //
655  StartTest (1, 3, 10);
656  AddDcfState (1);
657  AddCcaBusyEvt (20,40);
658  AddSwitchingEvt (30,20);
659  AddAccessRequest (51, 1, 54, 0);
660  EndTest ();
661 
662  // 20 30 50 53 54 55
663  // | nav | switching | sifs | aifsn | tx |
664  // |
665  // 51 access request.
666  //
667  StartTest (1, 3, 10);
668  AddDcfState (1);
669  AddNavStart (20,40);
670  AddSwitchingEvt (30,20);
671  AddAccessRequest (51, 1, 54, 0);
672  EndTest ();
673 
674  // 20 40 50 55 58 59 60
675  // | tx | ack timeout | switching | sifs | aifsn | tx |
676  // | |
677  // 45 access request. 56 access request.
678  //
679  StartTest (1, 3, 10);
680  AddDcfState (1);
681  AddAccessRequestWithAckTimeout (20, 20, 20, 0);
682  AddAccessRequest (45, 1, 50, 0);
683  AddSwitchingEvt (50,5);
684  AddAccessRequest (56, 1, 59, 0);
685  EndTest ();
686 
687  // 20 60 66 70 74 78 80 100 106 110 112
688  // | rx | sifs | aifsn | bslot0 | bslot1 | | switching | sifs | aifsn | tx |
689  // | |
690  // 30 access request. 101 access request.
691  //
692  StartTest (4, 6, 10);
693  AddDcfState (1);
694  AddRxOkEvt (20,40);
695  AddAccessRequest (30, 2, 80, 0);
696  ExpectCollision (30, 4, 0); //backoff: 4 slots
697  AddSwitchingEvt (80,20);
698  AddAccessRequest (101, 2, 110, 0);
699  EndTest ();
700 }
701 
702 
703 class DcfTestSuite : public TestSuite
704 {
705 public:
706  DcfTestSuite ();
707 };
708 
710  : TestSuite ("devices-wifi-dcf", UNIT)
711 {
712  AddTestCase (new DcfManagerTest, TestCase::QUICK);
713 }
714 
std::pair< uint64_t, uint64_t > ExpectedGrant
DcfManager * m_dcfManager
bool IsEdca(void) const
virtual void DoNotifyAccessGranted(void)
Called by DcfManager to notify a DcfState subclass that access to the medium is granted and can start...
static DcfTestSuite g_dcfTestSuite
A suite of tests to run.
Definition: test.h:1333
void RequestAccess(DcfState *state)
Definition: dcf-manager.cc:487
ExpectedCollisions m_expectedInternalCollision
#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 AddRxOkEvt(uint64_t at, uint64_t duration)
void AddAccessRequestWithAckTimeout(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
DcfStateTest(DcfManagerTest *test, uint32_t i)
void AddSwitchingEvt(uint64_t at, uint64_t duration)
#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:278
void SetAifsn(uint32_t aifsn)
Definition: dcf-manager.cc:56
std::list< ExpectedGrant > ExpectedGrants
void AddTxEvt(uint64_t at, uint64_t duration)
encapsulates test code
Definition: test.h:1147
void ExpectInternalCollision(uint64_t time, uint32_t from, uint32_t nSlots)
virtual void DoNotifyCollision(void)
Called by DcfManager to notify a DcfState subclass that a normal collision occured, that is, that the medium was busy when access was requested.
void DoAccessRequest(uint64_t txTime, uint64_t expectedGrantTime, DcfStateTest *state)
void AddRxInsideSifsEvt(uint64_t at, uint64_t duration)
void Add(DcfState *dcf)
Definition: dcf-manager.cc:405
void NotifyChannelSwitching(uint32_t i)
void StartTest(uint64_t slotTime, uint64_t sifs, uint64_t eifsNoDifsNoSifs, uint32_t ackTimeoutValue=20)
ExpectedCollisions m_expectedCollision
void AddAckTimeoutReset(uint64_t at)
virtual void DoNotifySleep(void)
Called by DcfManager to notify a DcfState subclass that the device has begun to sleep.
void AddTestCase(TestCase *testCase, enum TestDuration duration)
Add an individual child TestCase to this test suite.
Definition: test.cc:297
void NotifyTxStartNow(Time duration)
Definition: dcf-manager.cc:743
void NotifyAckTimeoutStartNow(Time duration)
Notify that ACK timer has started for the given duration.
Definition: dcf-manager.cc:906
Manage a set of ns3::DcfStateHandle a set of independent ns3::DcfState, each of which represents a si...
Definition: dcf-manager.h:262
void NotifyCollision(uint32_t i)
keep track of the state needed for a single DCF function.
Definition: dcf-manager.h:46
void AddNavReset(uint64_t at, uint64_t duration)
void AddCcaBusyEvt(uint64_t at, uint64_t duration)
friend class DcfManager
Definition: dcf-manager.h:132
virtual void DoNotifyWakeUp(void)
Called by DcfManager to notify a DcfState subclass that the device has begun to wake up...
void StartBackoffNow(uint32_t nSlots)
Definition: dcf-manager.cc:123
Every class exported by the ns3 library is enclosed in the ns3 namespace.
ExpectedGrants m_expectedGrants
void SetEifsNoDifs(Time eifsNoDifs)
Definition: dcf-manager.cc:391
uint32_t m_ackTimeoutValue
void AddRxStartEvt(uint64_t at, uint64_t duration)
std::list< struct ExpectedCollision > ExpectedCollisions
void SetSlot(Time slotTime)
Definition: dcf-manager.cc:377
void ExpectCollision(uint64_t time, uint32_t from, uint32_t nSlots)
DcfManagerTest * m_test
void NotifyAccessGranted(uint32_t i)
virtual void DoNotifyChannelSwitching(void)
Called by DcfManager to notify a DcfState subclass that a channel switching occured.
void NotifyInternalCollision(uint32_t i)
void AddNavStart(uint64_t at, uint64_t duration)
void AddAccessRequest(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t from)
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:911
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:330
virtual void DoNotifyInternalCollision(void)
Called by DcfManager to notify a DcfState subclass that an 'internal' collision occured, that is, that the backoff timer of a higher priority DcfState expired at the same time and that access was granted to this higher priority DcfState.
void AddDcfState(uint32_t aifsn)
void AddAccessRequestWithSuccessfullAck(uint64_t at, uint64_t txTime, uint64_t expectedGrantTime, uint32_t ackDelay, uint32_t from)
std::vector< DcfStateTest * > DcfStates
void AddRxErrorEvt(uint64_t at, uint64_t duration)
void test(void)
Example use of ns3::SystemThread.
void SetSifs(Time sifs)
Definition: dcf-manager.cc:384
void QueueTx(uint64_t txTime, uint64_t expectedGrantTime)
virtual void DoRun(void)
Implementation to actually run this TestCase.