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  Ptr<WifiMacQueueItem> mpdu = Create<WifiMacQueueItem> (Create<Packet> (), WifiMacHeader ());
294  uint16_t seqNumber = startingSeq;
295  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
296  agreement.NotifyAckedMpdu (mpdu);
297 
298  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
299  agreement.NotifyAckedMpdu (mpdu);
300 
301  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
302  agreement.NotifyAckedMpdu (mpdu);
303 
304  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
305  agreement.NotifyAckedMpdu (mpdu);
306 
307  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
308  agreement.NotifyAckedMpdu (mpdu);
309 
310  // the current window must look like this:
311  //
312  // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
313  // ^
314  // |
315  // HEAD
316 
317  startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
318  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 5 acknowledgments");
319  for (uint16_t i = 0; i < winSize; i++)
320  {
321  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Not all flags are cleared after 5 acknowledgments");
322  }
323 
324  // the next MPDU is not acknowledged, hence the window is blocked while the
325  // subsequent 4 MPDUs are acknowledged
326  ++seqNumber %= SEQNO_SPACE_SIZE;
327  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
328  agreement.NotifyAckedMpdu (mpdu);
329 
330  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
331  agreement.NotifyAckedMpdu (mpdu);
332 
333  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
334  agreement.NotifyAckedMpdu (mpdu);
335 
336  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
337  agreement.NotifyAckedMpdu (mpdu);
338 
339  // the current window must look like this:
340  //
341  // |0|0|0|0|0|0|1|1|1|1|0|0|0|0|0|0|
342  // ^
343  // |
344  // HEAD
345 
346  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 1 unacknowledged MPDU");
347  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after 1 unacknowledged MPDU");
348  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), true, "Incorrect flag after 1 unacknowledged MPDU");
349  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after 1 unacknowledged MPDU");
350  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after 1 unacknowledged MPDU");
351  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after 1 unacknowledged MPDU");
352  for (uint16_t i = 5; i < winSize; i++)
353  {
354  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after 1 unacknowledged MPDU");
355  }
356 
357  // the missing MPDU is now acknowledged; the window moves forward and the starting
358  // sequence number is the one of the first unacknowledged MPDU
359  mpdu->GetHeader ().SetSequenceNumber (startingSeq);
360  agreement.NotifyAckedMpdu (mpdu);
361 
362  // the current window must look like this:
363  //
364  // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
365  // ^
366  // |
367  // HEAD
368 
369  startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
370  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after acknowledgment of missing MPDU");
371  for (uint16_t i = 0; i < winSize; i++)
372  {
373  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Not all flags are cleared after acknowledgment of missing MPDU");
374  }
375 
376  // Now, create a hole of 3 MPDUs before 4 acknowledged MPDUs, another hole of 2 MPDUs before 3 acknowledged MPDUs
377  seqNumber = (seqNumber + 4) % SEQNO_SPACE_SIZE;
378  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
379  agreement.NotifyAckedMpdu (mpdu);
380 
381  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
382  agreement.NotifyAckedMpdu (mpdu);
383 
384  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
385  agreement.NotifyAckedMpdu (mpdu);
386 
387  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
388  agreement.NotifyAckedMpdu (mpdu);
389 
390  seqNumber = (seqNumber + 3) % SEQNO_SPACE_SIZE;
391  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
392  agreement.NotifyAckedMpdu (mpdu);
393 
394  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
395  agreement.NotifyAckedMpdu (mpdu);
396 
397  mpdu->GetHeader ().SetSequenceNumber (++seqNumber %= SEQNO_SPACE_SIZE);
398  agreement.NotifyAckedMpdu (mpdu);
399 
400  // the current window must look like this:
401  //
402  // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
403  // ^
404  // |
405  // HEAD
406 
407  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq, "Incorrect starting sequence after 3 unacknowledged MPDUs");
408  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after 3 unacknowledged MPDUs");
409  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), false, "Incorrect flag after 3 unacknowledged MPDUs");
410  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), false, "Incorrect flag after 3 unacknowledged MPDUs");
411  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after 3 unacknowledged MPDUs");
412  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after 3 unacknowledged MPDUs");
413  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (5), true, "Incorrect flag after 3 unacknowledged MPDUs");
414  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (6), true, "Incorrect flag after 3 unacknowledged MPDUs");
415  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (7), false, "Incorrect flag after 3 unacknowledged MPDUs");
416  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (8), false, "Incorrect flag after 3 unacknowledged MPDUs");
417  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (9), true, "Incorrect flag after 3 unacknowledged MPDUs");
418  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (10), true, "Incorrect flag after 3 unacknowledged MPDUs");
419  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (11), true, "Incorrect flag after 3 unacknowledged MPDUs");
420  for (uint16_t i = 12; i < winSize; i++)
421  {
422  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after 3 unacknowledged MPDUs");
423  }
424 
425  // the transmission of an MPDU beyond the current window (by 2 positions) is
426  // notified, hence the window moves forward 2 positions
427  seqNumber = (agreement.m_txWindow.GetWinEnd () + 2) % SEQNO_SPACE_SIZE;
428  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
429  agreement.NotifyTransmittedMpdu (mpdu);
430 
431  // the current window must look like this:
432  //
433  // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
434  // ^
435  // |
436  // HEAD
437 
438  startingSeq = (startingSeq + 2) % SEQNO_SPACE_SIZE;
439  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
440  "Incorrect starting sequence after transmitting an MPDU beyond the current window");
441  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after transmitting an MPDU beyond the current window");
442  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), true, "Incorrect flag after transmitting an MPDU beyond the current window");
443  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after transmitting an MPDU beyond the current window");
444  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after transmitting an MPDU beyond the current window");
445  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after transmitting an MPDU beyond the current window");
446  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (5), false, "Incorrect flag after transmitting an MPDU beyond the current window");
447  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (6), false, "Incorrect flag after transmitting an MPDU beyond the current window");
448  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (7), true, "Incorrect flag after transmitting an MPDU beyond the current window");
449  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (8), true, "Incorrect flag after transmitting an MPDU beyond the current window");
450  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (9), true, "Incorrect flag after transmitting an MPDU beyond the current window");
451  for (uint16_t i = 10; i < winSize; i++)
452  {
453  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after transmitting an MPDU beyond the current window");
454  }
455 
456  // another MPDU is transmitted beyond the current window. Now, the window advances
457  // until the first unacknowledged MPDU
458  seqNumber = (agreement.m_txWindow.GetWinEnd () + 1) % SEQNO_SPACE_SIZE;
459  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
460  agreement.NotifyTransmittedMpdu (mpdu);
461 
462  // the current window must look like this:
463  //
464  // |0|0|0|1|1|1|0|0|0|0|0|0|0|0|0|0|
465  // ^
466  // |
467  // HEAD
468 
469  startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
470  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
471  "Incorrect starting sequence after transmitting another MPDU beyond the current window");
472  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after transmitting another MPDU beyond the current window");
473  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (1), false, "Incorrect flag after transmitting another MPDU beyond the current window");
474  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (2), true, "Incorrect flag after transmitting another MPDU beyond the current window");
475  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (3), true, "Incorrect flag after transmitting another MPDU beyond the current window");
476  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (4), true, "Incorrect flag after transmitting another MPDU beyond the current window");
477  for (uint16_t i = 5; i < winSize; i++)
478  {
479  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after transmitting another MPDU beyond the current window");
480  }
481 
482  // the MPDU next to winStart is discarded, hence the window advances to make it an old packet.
483  // Since the subsequent MPDUs have been acknowledged, the window advances further.
484  seqNumber = (startingSeq + 1) % SEQNO_SPACE_SIZE;
485  mpdu->GetHeader ().SetSequenceNumber (seqNumber);
486  agreement.NotifyDiscardedMpdu (mpdu);
487 
488  // the current window must look like this:
489  //
490  // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
491  // ^
492  // |
493  // HEAD
494 
495  startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
496  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
497  "Incorrect starting sequence after discarding an MPDU");
498  for (uint16_t i = 0; i < winSize; i++)
499  {
500  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after discarding an MPDU");
501  }
502 
503  // Finally, check that the window correctly advances when the MPDU with the starting sequence number
504  // is acknowledged after being the only unacknowledged MPDU
505  for (uint16_t i = 1; i < winSize; i++)
506  {
507  mpdu->GetHeader ().SetSequenceNumber ((startingSeq + i) % SEQNO_SPACE_SIZE);
508  agreement.NotifyAckedMpdu (mpdu);
509  }
510 
511  // the current window must look like this:
512  //
513  // |1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|
514  // ^
515  // |
516  // HEAD
517 
518  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
519  "Incorrect starting sequence after acknowledging all but the first MPDU");
520  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (0), false, "Incorrect flag after acknowledging all but the first MPDU");
521  for (uint16_t i = 1; i < winSize; i++)
522  {
523  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), true, "Incorrect flag after acknowledging all but the first MPDU");
524  }
525 
526  // acknowledge the first MPDU
527  mpdu->GetHeader ().SetSequenceNumber (startingSeq % SEQNO_SPACE_SIZE);
528  agreement.NotifyAckedMpdu (mpdu);
529 
530  // the current window must look like this:
531  //
532  // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
533  // ^
534  // |
535  // HEAD
536 
537  startingSeq = (startingSeq + winSize) % SEQNO_SPACE_SIZE;
538  NS_TEST_EXPECT_MSG_EQ (agreement.GetStartingSequence (), startingSeq,
539  "Incorrect starting sequence after acknowledging the first MPDU");
540  for (uint16_t i = 0; i < winSize; i++)
541  {
542  NS_TEST_EXPECT_MSG_EQ (agreement.m_txWindow.At (i), false, "Incorrect flag after acknowledging the first MPDU");
543  }
544 }
545 
546 
554 {
555 public:
557 private:
558  virtual void DoRun ();
560 };
561 
563  : TestCase ("Check the correctness of block ack compressed bitmap")
564 {
565 }
566 
567 void
569 {
571 
572  //Case 1: startSeq < endSeq
573  // 179 242
575  for (uint16_t i = 179; i < 220; i++)
576  {
578  }
579  for (uint16_t i = 225; i <= 242; i++)
580  {
582  }
583  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0xffffc1ffffffffffLL, "error in compressed bitmap");
585  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0xffffc1ffffffffffLL, "error in compressed bitmap");
586  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (220), false, "error in compressed bitmap");
587  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (225), true, "error in compressed bitmap");
588  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (1500), false, "error in compressed bitmap");
589 
591 
592  //Case 2: startSeq > endSeq
593  // 4090 58
595  for (uint16_t i = 4090; i != 10; i = (i + 1) % 4096)
596  {
598  }
599  for (uint16_t i = 22; i < 25; i++)
600  {
602  }
603  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0x00000000007000ffffLL, "error in compressed bitmap");
605  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.GetCompressedBitmap (), 0x00000000007000ffffLL, "error in compressed bitmap");
606  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (4090), true, "error in compressed bitmap");
607  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (4095), true, "error in compressed bitmap");
608  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (10), false, "error in compressed bitmap");
609  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (35), false, "error in compressed bitmap");
610  NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (80), false, "error in compressed bitmap");
611 }
612 
613 
628 {
633  {
634  void Trace (Time startTime, Time duration);
636  };
637 
638 public:
641 
642  virtual void DoRun (void);
643 
644 
645 private:
646  uint32_t m_received;
647  uint16_t m_txTotal;
648  uint16_t m_nBar;
649  uint16_t m_nBa;
650 
657  void L7Receive (std::string context, Ptr<const Packet> p, const Address &adr);
664  void Transmit (std::string context, Ptr<const Packet> p, double power);
670  void Receive (std::string context, Ptr<const Packet> p);
671 };
672 
673 void
675 {
676  if (duration > m_max)
677  {
678  m_max = duration;
679  }
680 }
681 
683  : TestCase ("Test case for Block Ack Policy with aggregation disabled"),
684  m_received (0),
685  m_txTotal (0),
686  m_nBar (0),
687  m_nBa (0)
688 {
689 }
690 
692 {
693 }
694 
695 void
697 {
698  if (p->GetSize () == 1400)
699  {
700  m_received++;
701  }
702 }
703 
704 void
705 BlockAckAggregationDisabledTest::Transmit (std::string context, Ptr<const Packet> p, double power)
706 {
707  WifiMacHeader hdr;
708  p->PeekHeader (hdr);
709 
710  if (hdr.IsQosData ())
711  {
712  m_txTotal++;
713  NS_TEST_EXPECT_MSG_EQ ((m_txTotal == 1 || hdr.IsQosBlockAck ()), true, "Unexpected QoS ack policy");
714  }
715  else if (hdr.IsBlockAckReq ())
716  {
717  m_nBar++;
718  }
719 }
720 
721 void
723 {
724  WifiMacHeader hdr;
725  p->PeekHeader (hdr);
726 
727  if (hdr.IsBlockAck ())
728  {
729  m_nBa++;
730  }
731 }
732 
733 void
735 {
736  NodeContainer wifiStaNode;
737  wifiStaNode.Create (1);
738 
740  wifiApNode.Create (1);
741 
742  YansWifiChannelHelper channel = YansWifiChannelHelper::Default ();
743  YansWifiPhyHelper phy = YansWifiPhyHelper::Default ();
744  phy.SetChannel (channel.Create ());
745 
747  wifi.SetStandard (WIFI_PHY_STANDARD_80211a);
748  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
749 
751  Ssid ssid = Ssid ("ns-3-ssid");
752  mac.SetType ("ns3::StaWifiMac",
753  "QosSupported", BooleanValue (true),
754  "Ssid", SsidValue (ssid),
755  /* setting blockack threshold for sta's BE queue */
756  "BE_BlockAckThreshold", UintegerValue (2),
757  "ActiveProbing", BooleanValue (false));
758 
760  staDevices = wifi.Install (phy, mac, wifiStaNode);
761 
762  mac.SetType ("ns3::ApWifiMac",
763  "QosSupported", BooleanValue (true),
764  "Ssid", SsidValue (ssid),
765  "BeaconGeneration", BooleanValue (true));
766 
768  apDevices = wifi.Install (phy, mac, wifiApNode);
769 
771  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
772 
773  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
774  positionAlloc->Add (Vector (1.0, 0.0, 0.0));
775  mobility.SetPositionAllocator (positionAlloc);
776 
777  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
778  mobility.Install (wifiApNode);
779  mobility.Install (wifiStaNode);
780 
781  Ptr<WifiNetDevice> ap_device = DynamicCast<WifiNetDevice> (apDevices.Get (0));
782  Ptr<WifiNetDevice> sta_device = DynamicCast<WifiNetDevice> (staDevices.Get (0));
783 
784  // Disable A-MPDU aggregation
785  sta_device->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0));
786  TxopDurationTracer txopTracer;
787 
788  PacketSocketAddress socket;
789  socket.SetSingleDevice (sta_device->GetIfIndex ());
790  socket.SetPhysicalAddress (ap_device->GetAddress ());
791  socket.SetProtocol (1);
792 
793  // give packet socket powers to nodes.
794  PacketSocketHelper packetSocket;
795  packetSocket.Install (wifiStaNode);
796  packetSocket.Install (wifiApNode);
797 
798  Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient> ();
799  client->SetAttribute ("PacketSize", UintegerValue (1400));
800  client->SetAttribute ("MaxPackets", UintegerValue (14));
801  client->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
802  client->SetRemote (socket);
803  wifiStaNode.Get (0)->AddApplication (client);
804  client->SetStartTime (Seconds (1));
805  client->SetStopTime (Seconds (3.0));
806 
807  Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
808  server->SetLocal (socket);
809  wifiApNode.Get (0)->AddApplication (server);
810  server->SetStartTime (Seconds (0.0));
811  server->SetStopTime (Seconds (4.0));
812 
813  Config::Connect ("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx", MakeCallback (&BlockAckAggregationDisabledTest::L7Receive, this));
814  Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyTxBegin", MakeCallback (&BlockAckAggregationDisabledTest::Transmit, this));
815  Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyRxBegin", MakeCallback (&BlockAckAggregationDisabledTest::Receive, this));
816 
817  Simulator::Stop (Seconds (5));
818  Simulator::Run ();
819 
820  Simulator::Destroy ();
821 
822  // The client application generates 14 packets, so we expect that the wifi PHY
823  // layer transmits 14 MPDUs, the server application receives 14 packets, and
824  // a BAR is transmitted after each MPDU but the first one (because a BA agreement
825  // is established before transmitting the second MPDU).
826  NS_TEST_EXPECT_MSG_EQ (m_txTotal, 14, "Unexpected number of transmitted packets");
827  NS_TEST_EXPECT_MSG_EQ (m_received, 14, "Unexpected number of received packets");
828  NS_TEST_EXPECT_MSG_EQ (m_nBar, 13, "Unexpected number of Block Ack Requests");
829  NS_TEST_EXPECT_MSG_EQ (m_nBa, 13, "Unexpected number of Block Ack Responses");
830 }
831 
839 {
840 public:
842 };
843 
845  : TestSuite ("wifi-block-ack", UNIT)
846 {
847  AddTestCase (new PacketBufferingCaseA, TestCase::QUICK);
848  AddTestCase (new PacketBufferingCaseB, TestCase::QUICK);
849  AddTestCase (new OriginatorBlockAckWindowTest, TestCase::QUICK);
850  AddTestCase (new CtrlBAckResponseHeaderTest, TestCase::QUICK);
851  AddTestCase (new BlockAckAggregationDisabledTest, TestCase::QUICK);
852 }
853 
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:157
void SetStopTime(Time stop)
Specify application stop time.
Definition: application.cc:75
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
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
void SetLocal(PacketSocketAddress addr)
set the local address and protocol to be used
Maintains the state and information about transmitted MPDUs with ack policy block ack for an originat...
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:1342
uint32_t m_received
received packets
an address for a packet socket
#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:285
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:1155
Keeps the maximum duration among all TXOPs.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:299
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
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 Block ACK 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 Block ACK Request header.
const WifiMacHeader & GetHeader(void) const
Get the header stored in this item.
AttributeValue implementation for Time.
Definition: nstime.h:1124
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
holds a vector of ns3::NetDevice pointers
mac
Definition: third.py:99
uint64_t GetCompressedBitmap(void) const
Return the compressed bitmap from the block ACK response header.
bool IsPacketReceived(uint16_t seq) const
Check if the packet with the given sequence number was ACKed in this Block ACK 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 Block ack response.
Definition: ctrl-headers.h:193
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1489
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:871
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.
OFDM PHY for the 5 GHz band (Clause 17)
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.
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.
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.
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:1062
AttributeValue implementation for Ssid.
Definition: ssid.h:110
void SetProtocol(uint16_t protocol)
Set the protocol.
void Add(Vector v)
Add a position to the list of positions.
Block Ack Test Suite.
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:198
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:1078
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...
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.
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
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.