A Discrete-Event Network Simulator
API
block-ack-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2009, 2010 MIRKO BANCHI
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: Mirko Banchi <mk.banchi@gmail.com>
19  */
20 
21 #include "ns3/test.h"
22 #include "ns3/string.h"
23 #include "ns3/qos-utils.h"
24 #include "ns3/ctrl-headers.h"
25 #include "ns3/packet.h"
26 #include "ns3/wifi-net-device.h"
27 #include "ns3/ap-wifi-mac.h"
28 #include "ns3/wifi-mac-header.h"
29 #include "ns3/mobility-helper.h"
30 #include "ns3/yans-wifi-helper.h"
31 #include "ns3/packet-socket-server.h"
32 #include "ns3/packet-socket-client.h"
33 #include "ns3/packet-socket-helper.h"
34 #include "ns3/config.h"
35 #include "ns3/pointer.h"
36 
37 using namespace ns3;
38 
53 //-------------------------------------------------------------------------------------
54 
55 /* ----- = old packets
56  * +++++ = new packets
57  *
58  * CASE A: startSeq < endSeq
59  * - - +
60  * initial buffer state: 0 16 56000
61  *
62  *
63  * 0 4095
64  * |------|++++++++++++++++|-----|
65  * ^ ^
66  * | startSeq | endSeq = 4000
67  *
68  * first received packet's sequence control = 64016 (seqNum = 4001, fragNum = 0) -
69  * second received packet's sequence control = 63984 (seqNum = 3999, fragNum = 0) +
70  * 4001 is older seq number so this packet should be inserted at the buffer's begin.
71  * 3999 is previous element of older of new packets: it should be inserted at the end of buffer.
72  *
73  * expected buffer state: 64016 0 16 56000 63984
74  *
75  */
77 {
78 public:
80  virtual ~PacketBufferingCaseA ();
81 private:
82  virtual void DoRun (void);
83  std::list<uint16_t> m_expectedBuffer;
84 };
85 
87  : TestCase ("Check correct order of buffering when startSequence < endSeq")
88 {
89  m_expectedBuffer.push_back (64016);
90  m_expectedBuffer.push_back (0);
91  m_expectedBuffer.push_back (16);
92  m_expectedBuffer.push_back (56000);
93  m_expectedBuffer.push_back (63984);
94 }
95 
97 {
98 }
99 
100 void
102 {
103  std::list<uint16_t> m_buffer;
104  std::list<uint16_t>::iterator i,j;
105  m_buffer.push_back (0);
106  m_buffer.push_back (16);
107  m_buffer.push_back (56000);
108 
109  uint16_t endSeq = 4000;
110 
111  uint16_t receivedSeq = 4001 * 16;
112  uint32_t mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
113  /* cycle to right position for this packet */
114  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
115  {
116  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
117  {
118  //position found
119  break;
120  }
121  }
122  m_buffer.insert (i, receivedSeq);
123 
124  receivedSeq = 3999 * 16;
125  mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
126  /* cycle to right position for this packet */
127  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
128  {
129  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
130  {
131  //position found
132  break;
133  }
134  }
135  m_buffer.insert (i, receivedSeq);
136 
137  for (i = m_buffer.begin (), j = m_expectedBuffer.begin (); i != m_buffer.end (); i++, j++)
138  {
139  NS_TEST_EXPECT_MSG_EQ (*i, *j, "error in buffer order");
140  }
141 }
142 
143 
174 {
175 public:
177  virtual ~PacketBufferingCaseB ();
178 private:
179  virtual void DoRun (void);
180  std::list<uint16_t> m_expectedBuffer;
181 };
182 
184  : TestCase ("Check correct order of buffering when startSequence > endSeq")
185 {
186  m_expectedBuffer.push_back (240);
187  m_expectedBuffer.push_back (241);
188  m_expectedBuffer.push_back (256);
189  m_expectedBuffer.push_back (64000);
190  m_expectedBuffer.push_back (64800);
191  m_expectedBuffer.push_back (16);
192 }
193 
195 {
196 }
197 
198 void
200 {
201  std::list<uint16_t> m_buffer;
202  std::list<uint16_t>::iterator i,j;
203  m_buffer.push_back (256);
204  m_buffer.push_back (64000);
205  m_buffer.push_back (16);
206 
207  uint16_t endSeq = 10;
208 
209  uint16_t receivedSeq = 15 * 16;
210  uint32_t mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
211  /* cycle to right position for this packet */
212  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
213  {
214  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
215  {
216  //position found
217  break;
218  }
219  }
220  m_buffer.insert (i, receivedSeq);
221 
222  receivedSeq = 15 * 16 + 1;
223  mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
224  /* cycle to right position for this packet */
225  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
226  {
227  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
228  {
229  //position found
230  break;
231  }
232  }
233  m_buffer.insert (i, receivedSeq);
234 
235  receivedSeq = 4050 * 16;
236  mappedSeq = QosUtilsMapSeqControlToUniqueInteger (receivedSeq, endSeq);
237  /* cycle to right position for this packet */
238  for (i = m_buffer.begin (); i != m_buffer.end (); i++)
239  {
240  if (QosUtilsMapSeqControlToUniqueInteger ((*i), endSeq) >= mappedSeq)
241  {
242  //position found
243  break;
244  }
245  }
246  m_buffer.insert (i, receivedSeq);
247 
248  for (i = m_buffer.begin (), j = m_expectedBuffer.begin (); i != m_buffer.end (); i++, j++)
249  {
250  NS_TEST_EXPECT_MSG_EQ (*i, *j, "error in buffer order");
251  }
252 }
253 
261 {
262 public:
264 private:
265  virtual void DoRun ();
266 };
267 
269  : TestCase ("Check the correctness of the originator block ack window")
270 {
271 }
272 
273 void
275 {
276  uint16_t winSize = 16;
277  uint16_t startingSeq = 4090;
278 
279  OriginatorBlockAckAgreement agreement (Mac48Address ("00:00:00:00:00:01"), 0);
280  agreement.SetBufferSize (winSize);
281  agreement.SetStartingSequence (startingSeq);
282  agreement.InitTxWindow ();
283 
284  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.GetWinSize (), winSize, "Incorrect window size");
285  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.GetWinStart (), startingSeq, "Incorrect winStart");
286  // check that all the elements in the window are cleared
287  for (uint16_t i = 0; i < winSize; i++)
288  {
289  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Not all flags are cleared after initialization");
290  }
291 
292  // Notify the acknowledgment of 5 packets
293  WifiMacHeader hdr;
295  Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (Create<Packet> (), hdr);
296  uint16_t seqNumber = startingSeq;
297  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
298  agreement.NotifyAckedMpdu (mpdu);
299 
300  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
301  agreement.NotifyAckedMpdu (mpdu);
302 
303  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
304  agreement.NotifyAckedMpdu (mpdu);
305 
306  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
307  agreement.NotifyAckedMpdu (mpdu);
308 
309  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
310  agreement.NotifyAckedMpdu (mpdu);
311 
312  // the current window must look like this:
313  //
314  // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
315  // ^
316  // |
317  // HEAD
318 
319  startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
320  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 5 acknowledgments");
321  for (uint16_t i = 0; i < winSize; i++)
322  {
323  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Not all flags are cleared after 5 acknowledgments");
324  }
325 
326  // the next MPDU is not acknowledged, hence the window is blocked while the
327  // subsequent 4 MPDUs are acknowledged
328  ++seqNumber %= SEQNO_SPACE_SIZE;
329  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
330  agreement.NotifyAckedMpdu (mpdu);
331 
332  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
333  agreement.NotifyAckedMpdu (mpdu);
334 
335  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
336  agreement.NotifyAckedMpdu (mpdu);
337 
338  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
339  agreement.NotifyAckedMpdu (mpdu);
340 
341  // the current window must look like this:
342  //
343  // |0|0|0|0|0|0|1|1|1|1|0|0|0|0|0|0|
344  // ^
345  // |
346  // HEAD
347 
348  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 1 unacknowledged MPDU");
349  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after 1 unacknowledged MPDU");
350  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), true, "Incorrect flag after 1 unacknowledged MPDU");
351  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after 1 unacknowledged MPDU");
352  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after 1 unacknowledged MPDU");
353  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after 1 unacknowledged MPDU");
354  for (uint16_t i = 5; i < winSize; i++)
355  {
356  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after 1 unacknowledged MPDU");
357  }
358 
359  // the missing MPDU is now acknowledged; the window moves forward and the starting
360  // sequence number is the one of the first unacknowledged MPDU
361  mpdu->GetHeader ().SetSequenceNumber (startingSeq);
362  agreement.NotifyAckedMpdu (mpdu);
363 
364  // the current window must look like this:
365  //
366  // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
367  // ^
368  // |
369  // HEAD
370 
371  startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
372  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after acknowledgment of missing MPDU");
373  for (uint16_t i = 0; i < winSize; i++)
374  {
375  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Not all flags are cleared after acknowledgment of missing MPDU");
376  }
377 
378  // Now, create a hole of 3 MPDUs before 4 acknowledged MPDUs, another hole of 2 MPDUs before 3 acknowledged MPDUs
379  seqNumber = (seqNumber + 4) % SEQNO_SPACE_SIZE;
380  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
381  agreement.NotifyAckedMpdu (mpdu);
382 
383  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
384  agreement.NotifyAckedMpdu (mpdu);
385 
386  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
387  agreement.NotifyAckedMpdu (mpdu);
388 
389  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
390  agreement.NotifyAckedMpdu (mpdu);
391 
392  seqNumber = (seqNumber + 3) % SEQNO_SPACE_SIZE;
393  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
394  agreement.NotifyAckedMpdu (mpdu);
395 
396  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
397  agreement.NotifyAckedMpdu (mpdu);
398 
399  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
400  agreement.NotifyAckedMpdu (mpdu);
401 
402  // the current window must look like this:
403  //
404  // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
405  // ^
406  // |
407  // HEAD
408 
409  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 3 unacknowledged MPDUs");
410  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after 3 unacknowledged MPDUs");
411  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), false, "Incorrect flag after 3 unacknowledged MPDUs");
412  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), false, "Incorrect flag after 3 unacknowledged MPDUs");
413  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after 3 unacknowledged MPDUs");
414  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after 3 unacknowledged MPDUs");
415  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (5), true, "Incorrect flag after 3 unacknowledged MPDUs");
416  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (6), true, "Incorrect flag after 3 unacknowledged MPDUs");
417  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (7), false, "Incorrect flag after 3 unacknowledged MPDUs");
418  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (8), false, "Incorrect flag after 3 unacknowledged MPDUs");
419  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (9), true, "Incorrect flag after 3 unacknowledged MPDUs");
420  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (10), true, "Incorrect flag after 3 unacknowledged MPDUs");
421  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (11), true, "Incorrect flag after 3 unacknowledged MPDUs");
422  for (uint16_t i = 12; i < winSize; i++)
423  {
424  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after 3 unacknowledged MPDUs");
425  }
426 
427  // the transmission of an MPDU beyond the current window (by 2 positions) is
428  // notified, hence the window moves forward 2 positions
429  seqNumber = (agreement.m_txWindow.GetWinEnd () + 2) % SEQNO_SPACE_SIZE;
430  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
431  agreement.NotifyTransmittedMpdu (mpdu);
432 
433  // the current window must look like this:
434  //
435  // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
436  // ^
437  // |
438  // HEAD
439 
440  startingSeq = (startingSeq + 2) % SEQNO_SPACE_SIZE;
441  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
442  "Incorrect starting sequence after transmitting an MPDU beyond the current window");
443  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after transmitting an MPDU beyond the current window");
444  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), true, "Incorrect flag after transmitting an MPDU beyond the current window");
445  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after transmitting an MPDU beyond the current window");
446  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after transmitting an MPDU beyond the current window");
447  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after transmitting an MPDU beyond the current window");
448  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (5), false, "Incorrect flag after transmitting an MPDU beyond the current window");
449  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (6), false, "Incorrect flag after transmitting an MPDU beyond the current window");
450  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (7), true, "Incorrect flag after transmitting an MPDU beyond the current window");
451  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (8), true, "Incorrect flag after transmitting an MPDU beyond the current window");
452  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (9), true, "Incorrect flag after transmitting an MPDU beyond the current window");
453  for (uint16_t i = 10; i < winSize; i++)
454  {
455  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after transmitting an MPDU beyond the current window");
456  }
457 
458  // another MPDU is transmitted beyond the current window. Now, the window advances
459  // until the first unacknowledged MPDU
460  seqNumber = (agreement.m_txWindow.GetWinEnd () + 1) % SEQNO_SPACE_SIZE;
461  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
462  agreement.NotifyTransmittedMpdu (mpdu);
463 
464  // the current window must look like this:
465  //
466  // |0|0|0|1|1|1|0|0|0|0|0|0|0|0|0|0|
467  // ^
468  // |
469  // HEAD
470 
471  startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
472  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
473  "Incorrect starting sequence after transmitting another MPDU beyond the current window");
474  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after transmitting another MPDU beyond the current window");
475  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), false, "Incorrect flag after transmitting another MPDU beyond the current window");
476  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after transmitting another MPDU beyond the current window");
477  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after transmitting another MPDU beyond the current window");
478  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after transmitting another MPDU beyond the current window");
479  for (uint16_t i = 5; i < winSize; i++)
480  {
481  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after transmitting another MPDU beyond the current window");
482  }
483 
484  // the MPDU next to winStart is discarded, hence the window advances to make it an old packet.
485  // Since the subsequent MPDUs have been acknowledged, the window advances further.
486  seqNumber = (startingSeq + 1) % SEQNO_SPACE_SIZE;
487  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
488  agreement.NotifyDiscardedMpdu (mpdu);
489 
490  // the current window must look like this:
491  //
492  // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
493  // ^
494  // |
495  // HEAD
496 
497  startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
498  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
499  "Incorrect starting sequence after discarding an MPDU");
500  for (uint16_t i = 0; i < winSize; i++)
501  {
502  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after discarding an MPDU");
503  }
504 
505  // Finally, check that the window correctly advances when the MPDU with the starting sequence number
506  // is acknowledged after being the only unacknowledged MPDU
507  for (uint16_t i = 1; i < winSize; i++)
508  {
509  mpdu->GetHeader ().SetSequenceNumber ((startingSeq + i) % SEQNO_SPACE_SIZE);
510  agreement.NotifyAckedMpdu (mpdu);
511  }
512 
513  // the current window must look like this:
514  //
515  // |1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|
516  // ^
517  // |
518  // HEAD
519 
520  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
521  "Incorrect starting sequence after acknowledging all but the first MPDU");
522  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after acknowledging all but the first MPDU");
523  for (uint16_t i = 1; i < winSize; i++)
524  {
525  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), true, "Incorrect flag after acknowledging all but the first MPDU");
526  }
527 
528  // acknowledge the first MPDU
529  mpdu->GetHeader ().SetSequenceNumber (startingSeq % SEQNO_SPACE_SIZE);
530  agreement.NotifyAckedMpdu (mpdu);
531 
532  // the current window must look like this:
533  //
534  // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
535  // ^
536  // |
537  // HEAD
538 
539  startingSeq = (startingSeq + winSize) % SEQNO_SPACE_SIZE;
540  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
541  "Incorrect starting sequence after acknowledging the first MPDU");
542  for (uint16_t i = 0; i < winSize; i++)
543  {
544  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after acknowledging the first MPDU");
545  }
546 }
547 
548 
556 {
557 public:
559 private:
560  virtual void DoRun ();
562 };
563 
565  : TestCase ("Check the correctness of block ack compressed bitmap")
566 {
567 }
568 
569 void
571 {
573 
574  //Case 1: startSeq < endSeq
575  // 179 242
577  for (uint16_t i = 179; i < 220; i++)
578  {
580  }
581  for (uint16_t i = 225; i <= 242; i++)
582  {
584  }
585  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0xffffc1ffffffffffLL, "error in compressed bitmap");
587  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0xffffc1ffffffffffLL, "error in compressed bitmap");
588  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (220), false, "error in compressed bitmap");
589  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (225), true, "error in compressed bitmap");
590  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (1500), false, "error in compressed bitmap");
591 
593 
594  //Case 2: startSeq > endSeq
595  // 4090 58
597  for (uint16_t i = 4090; i != 10; i = (i + 1) % 4096)
598  {
600  }
601  for (uint16_t i = 22; i < 25; i++)
602  {
604  }
605  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0x00000000007000ffffLL, "error in compressed bitmap");
607  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0x00000000007000ffffLL, "error in compressed bitmap");
608  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (4090), true, "error in compressed bitmap");
609  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (4095), true, "error in compressed bitmap");
610  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (10), false, "error in compressed bitmap");
611  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (35), false, "error in compressed bitmap");
612  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (80), false, "error in compressed bitmap");
613 }
614 
615 
661 {
666  {
672  void Trace (Time startTime, Time duration);
674  };
675 
676 public:
683 
684  virtual void DoRun (void);
685 
686 
687 private:
688  bool m_txop;
689  uint32_t m_received;
690  uint16_t m_txTotal;
691  uint16_t m_txSinceBar;
692  uint16_t m_nBar;
694  uint16_t m_nBa;
695 
702  void L7Receive (std::string context, Ptr<const Packet> p, const Address &adr);
709  void Transmit (std::string context, Ptr<const Packet> p, double power);
715  void Receive (std::string context, Ptr<const Packet> p);
716 };
717 
718 void
720 {
721  if (duration > m_max)
722  {
723  m_max = duration;
724  }
725 }
726 
728  : TestCase ("Test case for Block Ack Policy with aggregation disabled"),
729  m_txop (txop),
730  m_received (0),
731  m_txTotal (0),
732  m_txSinceBar (0),
733  m_nBar (0),
734  m_nBa (0)
735 {
736 }
737 
739 {
740 }
741 
742 void
744 {
745  if (p->GetSize () == 1400)
746  {
747  m_received++;
748  }
749 }
750 
751 void
752 BlockAckAggregationDisabledTest::Transmit (std::string context, Ptr<const Packet> p, double power)
753 {
754  WifiMacHeader hdr;
755  p->PeekHeader (hdr);
756 
757  if (m_txSinceBar == 9 || m_txTotal == 14)
758  {
759  NS_TEST_ASSERT_MSG_EQ (hdr.IsBlockAckReq (), true, "Didn't get a BlockAckReq when expected");
760  }
761  else
762  {
763  NS_TEST_ASSERT_MSG_EQ (hdr.IsBlockAckReq (), false, "Got a BlockAckReq when not expected");
764  }
765 
766  if (hdr.IsQosData ())
767  {
768  m_txTotal++;
769  if (hdr.IsQosBlockAck ())
770  {
771  m_txSinceBar++;
772  }
773 
774  if (!m_txop)
775  {
776  NS_TEST_EXPECT_MSG_EQ ((m_txTotal == 1 || hdr.IsQosBlockAck ()), true, "Unexpected QoS ack policy");
777  }
778  else
779  {
780  NS_TEST_EXPECT_MSG_EQ ((m_txTotal <= 2 || hdr.IsQosBlockAck ()), true, "Unexpected QoS ack policy");
781  }
782  }
783  else if (hdr.IsBlockAckReq ())
784  {
785  m_txSinceBar = 0;
786  m_nBar++;
787  }
788 }
789 
790 void
792 {
793  WifiMacHeader hdr;
794  p->PeekHeader (hdr);
795 
796  if (hdr.IsBlockAck ())
797  {
798  m_nBa++;
799  }
800 }
801 
802 void
804 {
805  NodeContainer wifiStaNode;
806  wifiStaNode.Create (1);
807 
809  wifiApNode.Create (1);
810 
811  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
813  phy.SetChannel (channel.Create ());
814 
816  wifi.SetStandard (WIFI_STANDARD_80211a);
817  wifi.SetAckPolicySelectorForAc (AC_BE, "ns3::ConstantWifiAckPolicySelector",
818  "BaThreshold", DoubleValue (0.125));
819  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
820 
822  Ssid ssid = Ssid ("ns-3-ssid");
823  mac.SetType ("ns3::StaWifiMac",
824  "QosSupported", BooleanValue (true),
825  "Ssid", SsidValue (ssid),
826  /* setting blockack threshold for sta's BE queue */
827  "BE_BlockAckThreshold", UintegerValue (2),
828  "ActiveProbing", BooleanValue (false));
829 
831  staDevices = wifi.Install (phy, mac, wifiStaNode);
832 
833  mac.SetType ("ns3::ApWifiMac",
834  "QosSupported", BooleanValue (true),
835  "Ssid", SsidValue (ssid),
836  "BeaconGeneration", BooleanValue (true));
837 
839  apDevices = wifi.Install (phy, mac, wifiApNode);
840 
842  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
843 
844  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
845  positionAlloc->Add (Vector (1.0, 0.0, 0.0));
846  mobility.SetPositionAllocator (positionAlloc);
847 
848  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
849  mobility.Install (wifiApNode);
850  mobility.Install (wifiStaNode);
851 
852  Ptr<WifiNetDevice> ap_device = DynamicCast<WifiNetDevice> (apDevices.Get (0));
853  Ptr<WifiNetDevice> sta_device = DynamicCast<WifiNetDevice> (staDevices.Get (0));
854 
855  // Disable A-MPDU aggregation
856  sta_device->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
857  TxopDurationTracer txopTracer;
858 
859  if (m_txop)
860  {
861  PointerValue ptr;
862  sta_device->GetMac ()->GetAttribute ("BE_Txop", ptr);
863  ptr.Get<QosTxop> ()->TraceConnectWithoutContext ("TxopTrace", MakeCallback (&TxopDurationTracer::Trace, &txopTracer));
864 
865  // set the TXOP limit on BE AC
866  Ptr<RegularWifiMac> ap_mac = DynamicCast<RegularWifiMac> (ap_device->GetMac ());
867  NS_ASSERT (ap_mac);
868  ap_mac->GetAttribute ("BE_Txop", ptr);
869  ptr.Get<QosTxop> ()->SetTxopLimit (MicroSeconds (4800));
870  }
871 
872  PacketSocketAddress socket;
873  socket.SetSingleDevice (sta_device->GetIfIndex ());
874  socket.SetPhysicalAddress (ap_device->GetAddress ());
875  socket.SetProtocol (1);
876 
877  // give packet socket powers to nodes.
878  PacketSocketHelper packetSocket;
879  packetSocket.Install (wifiStaNode);
880  packetSocket.Install (wifiApNode);
881 
882  // the first client application generates a single packet, which is sent
883  // with the normal ack policy because there are no other packets queued
884  Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
885  client1->SetAttribute ("PacketSize", UintegerValue (1400));
886  client1->SetAttribute ("MaxPackets", UintegerValue (1));
887  client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
888  client1->SetRemote (socket);
889  wifiStaNode.Get (0)->AddApplication (client1);
890  client1->SetStartTime (Seconds (1));
891  client1->SetStopTime (Seconds (3.0));
892 
893  // the second client application generates 13 packets. Even if when the first
894  // packet is queued the queue is empty, the first packet is not transmitted
895  // immediately, but the EDCAF waits for the next slot boundary. At that time,
896  // other packets have been queued, hence a BA agreement is established first.
897  Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
898  client2->SetAttribute ("PacketSize", UintegerValue (1400));
899  client2->SetAttribute ("MaxPackets", UintegerValue (13));
900  client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
901  client2->SetRemote (socket);
902  wifiStaNode.Get (0)->AddApplication (client2);
903  client2->SetStartTime (Seconds (1.5));
904  client2->SetStopTime (Seconds (3.0));
905 
906  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
907  server->SetLocal (socket);
908  wifiApNode.Get (0)->AddApplication (server);
909  server->SetStartTime (Seconds (0.0));
910  server->SetStopTime (Seconds (4.0));
911 
912  Config::Connect ("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx", MakeCallback (&BlockAckAggregationDisabledTest::L7Receive, this));
913  Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyTxBegin", MakeCallback (&BlockAckAggregationDisabledTest::Transmit, this));
914  Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyRxBegin", MakeCallback (&BlockAckAggregationDisabledTest::Receive, this));
915 
916  Simulator::Stop (Seconds (5));
917  Simulator::Run ();
918 
919  Simulator::Destroy ();
920 
921  // The client applications generate 14 packets, so we expect that the wifi PHY
922  // layer transmits 14 MPDUs, the server application receives 14 packets, and
923  // two BARs are transmitted.
924  NS_TEST_EXPECT_MSG_EQ (m_txTotal, 14, "Unexpected number of transmitted packets");
925  NS_TEST_EXPECT_MSG_EQ (m_received, 14, "Unexpected number of received packets");
926  NS_TEST_EXPECT_MSG_EQ (m_nBar, 2, "Unexpected number of Block Ack Requests");
927  NS_TEST_EXPECT_MSG_EQ (m_nBa, 2, "Unexpected number of Block Ack Responses");
928  if (m_txop)
929  {
930  NS_TEST_EXPECT_MSG_LT (txopTracer.m_max, MicroSeconds (4800), "TXOP duration exceeded!");
931  NS_TEST_EXPECT_MSG_GT (txopTracer.m_max, MicroSeconds (3008), "The maximum TXOP duration is too short!");
932  }
933 }
934 
942 {
943 public:
945 };
946 
948  : TestSuite ("wifi-block-ack", UNIT)
949 {
950  AddTestCase (new PacketBufferingCaseA, TestCase::QUICK);
951  AddTestCase (new PacketBufferingCaseB, TestCase::QUICK);
952  AddTestCase (new OriginatorBlockAckWindowTest, TestCase::QUICK);
953  AddTestCase (new CtrlBAckResponseHeaderTest, TestCase::QUICK);
954  AddTestCase (new BlockAckAggregationDisabledTest (false), TestCase::QUICK);
955  AddTestCase (new BlockAckAggregationDisabledTest (true), TestCase::QUICK);
956 }
957 
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:159
void SetStopTime(Time stop)
Specify application stop time.
Definition: application.cc:75
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
std::list< uint16_t > m_expectedBuffer
expected test buffer
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
AttributeValue implementation for Boolean.
Definition: boolean.h:36
Ptr< T > Get(void) const
Definition: pointer.h:201
void SetLocal(PacketSocketAddress addr)
set the local address and protocol to be used
Maintains the state and information about transmitted MPDUs with Ack Policy set to Block Ack for an o...
void Trace(Time startTime, Time duration)
Callback for the TxopTrace trace.
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
Make it easy to create and manage PHY objects for the YANS model.
A suite of tests to run.
Definition: test.h:1343
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:92
uint32_t m_received
received packets
an address for a packet socket
#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
#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
staDevices
Definition: third.py:103
void Transmit(std::string context, Ptr< const Packet > p, double power)
Callback invoked when PHY transmits a packet.
encapsulates test code
Definition: test.h:1153
Keeps the maximum duration among all TXOPs.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:318
void SetStartingSequence(uint16_t seq)
Set the starting sequence number from the given raw sequence control field.
BlockAckWindow m_txWindow
originator&#39;s transmit window
Best Effort.
Definition: qos-utils.h:41
CtrlBAckResponseHeader m_blockAckHdr
block ack header
Give ns3::PacketSocket powers to ns3::Node.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
uint16_t m_nBar
transmitted BlockAckReq frames
Address GetAddress(void) const
a polymophic address class
Definition: address.h:90
bool IsBlockAck(void) const
Return true if the header is a BlockAck header.
virtual void DoRun(void)
Implementation to actually run this TestCase.
channel
Definition: third.py:92
void NotifyDiscardedMpdu(Ptr< const WifiMacQueueItem > mpdu)
Advance the transmit window beyond the MPDU that has been reported to be discarded.
mobility
Definition: third.py:108
phy
Definition: third.py:93
uint16_t GetWinStart(void) const
Get the current winStart value.
bool IsBlockAckReq(void) const
Return true if the header is a BlockAckRequest header.
const WifiMacHeader & GetHeader(void) const
Get the header stored in this item.
AttributeValue implementation for Time.
Definition: nstime.h:1342
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Hold an unsigned integer type.
Definition: uinteger.h:44
double startTime
ssid
Definition: third.py:100
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition: test.h:166
holds a vector of ns3::NetDevice pointers
mac
Definition: third.py:99
uint64_t GetCompressedBitmap(void) const
Return the compressed bitmap from the BlockAck response header.
bool IsPacketReceived(uint16_t seq) const
Check if the packet with the given sequence number was acknowledged in this BlockAck response...
uint16_t m_txTotal
transmitted data packets
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:290
Headers for BlockAck response.
Definition: ctrl-headers.h:193
wifiApNode
Definition: third.py:90
Test for the originator block ack window.
uint16_t m_nBa
received BlockAck frames
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:918
Packet Buffering Case B.
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
std::vector< bool >::reference At(std::size_t distance)
Get a reference to the element in the window having the given distance from the current winStart...
void NotifyAckedMpdu(Ptr< const WifiMacQueueItem > mpdu)
Record that the given MPDU has been acknowledged and advance the transmit window if possible...
void NotifyTransmittedMpdu(Ptr< const WifiMacQueueItem > mpdu)
Advance the transmit window so as to include the transmitted MPDU, if the latter is not an old packet...
virtual void DoRun(void)
Implementation to actually run this TestCase.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetPhysicalAddress(const Address address)
Set the destination address.
keep track of a set of node pointers.
Hold objects of type Ptr<T>.
Definition: pointer.h:36
void SetType(BlockAckType type)
Set the block ack type.
an EUI-48 address
Definition: mac48-address.h:43
Test for Block Ack Policy with aggregation disabled.
manage and create wifi channel objects for the YANS model.
create MAC layers for a ns3::WifiNetDevice.
void ResetBitmap(void)
Reset the bitmap to 0.
BlockAckAggregationDisabledTest(bool txop)
Constructor.
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
Definition: test.h:1088
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:35
wifi
Definition: third.py:96
Helper class used to assign positions and mobility models to nodes.
void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
bool IsQosBlockAck(void) const
Return if the QoS Ack policy is Block Ack.
void SetReceivedPacket(uint16_t seq)
Set the bitmap that the packet with the given sequence number was received.
Packet Buffering Case A.
Ptr< WifiMac > GetMac(void) const
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
uint16_t GetWinEnd(void) const
Get the current winEnd value.
virtual void DoRun()
Implementation to actually run this TestCase.
std::size_t GetWinSize(void) const
Get the window size.
void SetRemote(PacketSocketAddress addr)
set the remote address and protocol to be used
uint32_t QosUtilsMapSeqControlToUniqueInteger(uint16_t seqControl, uint16_t endSequence)
Next function is useful to correctly sort buffered packets under block ack.
Definition: qos-utils.cc:73
virtual void DoRun()
Implementation to actually run this TestCase.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1278
AttributeValue implementation for Ssid.
Definition: ssid.h:105
void SetProtocol(uint16_t protocol)
Set the protocol.
void Add(Vector v)
Add a position to the list of positions.
Block Ack Test Suite.
bool m_txop
true for non-null TXOP limit
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
Definition: test.h:901
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
const uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition: wifi-utils.h:215
void L7Receive(std::string context, Ptr< const Packet > p, const Address &adr)
Function to trace packets received by the server application.
apDevices
Definition: third.py:106
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
bool IsQosData(void) const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data...
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1294
Test for block ack header.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
void Receive(std::string context, Ptr< const Packet > p)
Callback invoked when PHY receives a packet.
uint16_t GetStartingSequence(void) const
Return the starting sequence number of the transmit window, if a transmit window has been initialized...
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:185
virtual void DoRun(void)
Implementation to actually run this TestCase.
uint16_t m_txSinceBar
packets transmitted since the agreement was established or the last block ack was received ...
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
static BlockAckTestSuite g_blockAckTestSuite
the test suite
std::list< uint16_t > m_expectedBuffer
expected test buffer
void SetStartTime(Time start)
Specify application start time.
Definition: application.cc:69
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
void InitTxWindow(void)
Initialize the originator&#39;s transmit window by setting its size and starting sequence number equal to...
Implements the IEEE 802.11 MAC header.