A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
block-ack-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009, 2010 MIRKO BANCHI
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mirko Banchi <mk.banchi@gmail.com>
18 */
19
20#include "ns3/ap-wifi-mac.h"
21#include "ns3/boolean.h"
22#include "ns3/config.h"
23#include "ns3/ctrl-headers.h"
24#include "ns3/double.h"
25#include "ns3/mac-rx-middle.h"
26#include "ns3/mobility-helper.h"
27#include "ns3/originator-block-ack-agreement.h"
28#include "ns3/packet-socket-client.h"
29#include "ns3/packet-socket-helper.h"
30#include "ns3/packet-socket-server.h"
31#include "ns3/packet.h"
32#include "ns3/pointer.h"
33#include "ns3/qos-txop.h"
34#include "ns3/qos-utils.h"
35#include "ns3/recipient-block-ack-agreement.h"
36#include "ns3/string.h"
37#include "ns3/test.h"
38#include "ns3/wifi-mac-header.h"
39#include "ns3/wifi-mpdu.h"
40#include "ns3/wifi-net-device.h"
41#include "ns3/yans-wifi-helper.h"
42
43#include <list>
44
45using namespace ns3;
46
47/**
48 * \ingroup wifi-test
49 * \ingroup tests
50 *
51 * \brief Packet Buffering Case A
52 *
53 * This simple test verifies the correctness of buffering for packets received
54 * under block ack. In order to completely understand this example is important to cite
55 * section 9.10.3 in IEEE802.11 standard:
56 *
57 * "[...] The sequence number space is considered divided into two parts, one of which
58 * is “old” and one of which is “new” by means of a boundary created by adding half the
59 * sequence number range to the current start of receive window (modulo 2^12)."
60 */
61//-------------------------------------------------------------------------------------
62
63/* ----- = old packets
64 * +++++ = new packets
65 *
66 * CASE A: startSeq < endSeq
67 * - - +
68 * initial buffer state: 0 16 56000
69 *
70 *
71 * 0 4095
72 * |------|++++++++++++++++|-----|
73 * ^ ^
74 * | startSeq | endSeq = 4000
75 *
76 * first received packet's sequence control = 64016 (seqNum = 4001, fragNum = 0) -
77 * second received packet's sequence control = 63984 (seqNum = 3999, fragNum = 0) +
78 * 4001 is older seq number so this packet should be inserted at the buffer's begin.
79 * 3999 is previous element of older of new packets: it should be inserted at the end of buffer.
80 *
81 * expected buffer state: 64016 0 16 56000 63984
82 *
83 */
85{
86 public:
88 ~PacketBufferingCaseA() override;
89
90 private:
91 void DoRun() override;
92 std::list<uint16_t> m_expectedBuffer; ///< expected test buffer
93};
94
96 : TestCase("Check correct order of buffering when startSequence < endSeq")
97{
98 m_expectedBuffer.push_back(64016);
99 m_expectedBuffer.push_back(0);
100 m_expectedBuffer.push_back(16);
101 m_expectedBuffer.push_back(56000);
102 m_expectedBuffer.push_back(63984);
103}
104
106{
107}
108
109void
111{
112 std::list<uint16_t> m_buffer;
113 std::list<uint16_t>::iterator i;
114 std::list<uint16_t>::iterator j;
115 m_buffer.push_back(0);
116 m_buffer.push_back(16);
117 m_buffer.push_back(56000);
118
119 uint16_t endSeq = 4000;
120
121 uint16_t receivedSeq = 4001 * 16;
122 uint32_t mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
123 /* cycle to right position for this packet */
124 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
125 {
126 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
127 {
128 // position found
129 break;
130 }
131 }
132 m_buffer.insert(i, receivedSeq);
133
134 receivedSeq = 3999 * 16;
135 mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
136 /* cycle to right position for this packet */
137 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
138 {
139 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
140 {
141 // position found
142 break;
143 }
144 }
145 m_buffer.insert(i, receivedSeq);
146
147 for (i = m_buffer.begin(), j = m_expectedBuffer.begin(); i != m_buffer.end(); i++, j++)
148 {
149 NS_TEST_EXPECT_MSG_EQ(*i, *j, "error in buffer order");
150 }
151}
152
153/**
154 * \ingroup wifi-test
155 * \ingroup tests
156 *
157 * \brief Packet Buffering Case B
158 *
159 * ----- = old packets
160 * +++++ = new packets
161 *
162 * CASE B: startSeq > endSeq
163 * - + +
164 * initial buffer state: 256 64000 16
165 *
166 *
167 * 0 4095
168 * |++++++|----------------|++++++|
169 * ^ ^
170 * | endSeq = 10 | startSeq
171 *
172 * first received packet's sequence control = 240 (seqNum = 15, fragNum = 0) -
173 * second received packet's sequence control = 241 (seqNum = 15, fragNum = 1) -
174 * third received packet's sequence control = 64800 (seqNum = 4050, fragNum = 0) +
175 * 240 is an old packet should be inserted at the buffer's begin.
176 * 241 is an old packet: second segment of the above packet.
177 * 4050 is a new packet: it should be inserted between 64000 and 16.
178 *
179 * expected buffer state: 240 241 256 64000 64800 16
180 *
181 */
183{
184 public:
186 ~PacketBufferingCaseB() override;
187
188 private:
189 void DoRun() override;
190 std::list<uint16_t> m_expectedBuffer; ///< expected test buffer
191};
192
194 : TestCase("Check correct order of buffering when startSequence > endSeq")
195{
196 m_expectedBuffer.push_back(240);
197 m_expectedBuffer.push_back(241);
198 m_expectedBuffer.push_back(256);
199 m_expectedBuffer.push_back(64000);
200 m_expectedBuffer.push_back(64800);
201 m_expectedBuffer.push_back(16);
202}
203
205{
206}
207
208void
210{
211 std::list<uint16_t> m_buffer;
212 std::list<uint16_t>::iterator i;
213 std::list<uint16_t>::iterator j;
214 m_buffer.push_back(256);
215 m_buffer.push_back(64000);
216 m_buffer.push_back(16);
217
218 uint16_t endSeq = 10;
219
220 uint16_t receivedSeq = 15 * 16;
221 uint32_t mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
222 /* cycle to right position for this packet */
223 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
224 {
225 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
226 {
227 // position found
228 break;
229 }
230 }
231 m_buffer.insert(i, receivedSeq);
232
233 receivedSeq = 15 * 16 + 1;
234 mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
235 /* cycle to right position for this packet */
236 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
237 {
238 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
239 {
240 // position found
241 break;
242 }
243 }
244 m_buffer.insert(i, receivedSeq);
245
246 receivedSeq = 4050 * 16;
247 mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
248 /* cycle to right position for this packet */
249 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
250 {
251 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
252 {
253 // position found
254 break;
255 }
256 }
257 m_buffer.insert(i, receivedSeq);
258
259 for (i = m_buffer.begin(), j = m_expectedBuffer.begin(); i != m_buffer.end(); i++, j++)
260 {
261 NS_TEST_EXPECT_MSG_EQ(*i, *j, "error in buffer order");
262 }
263}
264
265/**
266 * \ingroup wifi-test
267 * \ingroup tests
268 *
269 * \brief Test for the originator block ack window
270 */
272{
273 public:
275
276 private:
277 void DoRun() override;
278};
279
281 : TestCase("Check the correctness of the originator block ack window")
282{
283}
284
285void
287{
288 uint16_t winSize = 16;
289 uint16_t startingSeq = 4090;
290
291 OriginatorBlockAckAgreement agreement(Mac48Address("00:00:00:00:00:01"), 0);
292 agreement.SetBufferSize(winSize);
293 agreement.SetStartingSequence(startingSeq);
294 agreement.InitTxWindow();
295
296 NS_TEST_EXPECT_MSG_EQ(agreement.m_txWindow.GetWinSize(), winSize, "Incorrect window size");
297 NS_TEST_EXPECT_MSG_EQ(agreement.m_txWindow.GetWinStart(), startingSeq, "Incorrect winStart");
298 // check that all the elements in the window are cleared
299 for (uint16_t i = 0; i < winSize; i++)
300 {
302 false,
303 "Not all flags are cleared after initialization");
304 }
305
306 // Notify the acknowledgment of 5 packets
307 WifiMacHeader hdr;
309 Ptr<WifiMpdu> mpdu = Create<WifiMpdu>(Create<Packet>(), hdr);
310 uint16_t seqNumber = startingSeq;
311 mpdu->GetHeader().SetSequenceNumber(seqNumber);
312 agreement.NotifyAckedMpdu(mpdu);
313
314 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
315 agreement.NotifyAckedMpdu(mpdu);
316
317 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
318 agreement.NotifyAckedMpdu(mpdu);
319
320 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
321 agreement.NotifyAckedMpdu(mpdu);
322
323 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
324 agreement.NotifyAckedMpdu(mpdu);
325
326 // the current window must look like this:
327 //
328 // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
329 // ^
330 // |
331 // HEAD
332
333 startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
335 startingSeq,
336 "Incorrect starting sequence after 5 acknowledgments");
337 for (uint16_t i = 0; i < winSize; i++)
338 {
340 false,
341 "Not all flags are cleared after 5 acknowledgments");
342 }
343
344 // the next MPDU is not acknowledged, hence the window is blocked while the
345 // subsequent 4 MPDUs are acknowledged
346 ++seqNumber %= SEQNO_SPACE_SIZE;
347 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
348 agreement.NotifyAckedMpdu(mpdu);
349
350 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
351 agreement.NotifyAckedMpdu(mpdu);
352
353 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
354 agreement.NotifyAckedMpdu(mpdu);
355
356 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
357 agreement.NotifyAckedMpdu(mpdu);
358
359 // the current window must look like this:
360 //
361 // |0|0|0|0|0|0|1|1|1|1|0|0|0|0|0|0|
362 // ^
363 // |
364 // HEAD
365
367 startingSeq,
368 "Incorrect starting sequence after 1 unacknowledged MPDU");
370 false,
371 "Incorrect flag after 1 unacknowledged MPDU");
373 true,
374 "Incorrect flag after 1 unacknowledged MPDU");
376 true,
377 "Incorrect flag after 1 unacknowledged MPDU");
379 true,
380 "Incorrect flag after 1 unacknowledged MPDU");
382 true,
383 "Incorrect flag after 1 unacknowledged MPDU");
384 for (uint16_t i = 5; i < winSize; i++)
385 {
387 false,
388 "Incorrect flag after 1 unacknowledged MPDU");
389 }
390
391 // the missing MPDU is now acknowledged; the window moves forward and the starting
392 // sequence number is the one of the first unacknowledged MPDU
393 mpdu->GetHeader().SetSequenceNumber(startingSeq);
394 agreement.NotifyAckedMpdu(mpdu);
395
396 // the current window must look like this:
397 //
398 // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
399 // ^
400 // |
401 // HEAD
402
403 startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
405 startingSeq,
406 "Incorrect starting sequence after acknowledgment of missing MPDU");
407 for (uint16_t i = 0; i < winSize; i++)
408 {
410 false,
411 "Not all flags are cleared after acknowledgment of missing MPDU");
412 }
413
414 // Now, create a hole of 3 MPDUs before 4 acknowledged MPDUs, another hole of 2 MPDUs before 3
415 // acknowledged MPDUs
416 seqNumber = (seqNumber + 4) % SEQNO_SPACE_SIZE;
417 mpdu->GetHeader().SetSequenceNumber(seqNumber);
418 agreement.NotifyAckedMpdu(mpdu);
419
420 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
421 agreement.NotifyAckedMpdu(mpdu);
422
423 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
424 agreement.NotifyAckedMpdu(mpdu);
425
426 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
427 agreement.NotifyAckedMpdu(mpdu);
428
429 seqNumber = (seqNumber + 3) % SEQNO_SPACE_SIZE;
430 mpdu->GetHeader().SetSequenceNumber(seqNumber);
431 agreement.NotifyAckedMpdu(mpdu);
432
433 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
434 agreement.NotifyAckedMpdu(mpdu);
435
436 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
437 agreement.NotifyAckedMpdu(mpdu);
438
439 // the current window must look like this:
440 //
441 // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
442 // ^
443 // |
444 // HEAD
445
447 startingSeq,
448 "Incorrect starting sequence after 3 unacknowledged MPDUs");
450 false,
451 "Incorrect flag after 3 unacknowledged MPDUs");
453 false,
454 "Incorrect flag after 3 unacknowledged MPDUs");
456 false,
457 "Incorrect flag after 3 unacknowledged MPDUs");
459 true,
460 "Incorrect flag after 3 unacknowledged MPDUs");
462 true,
463 "Incorrect flag after 3 unacknowledged MPDUs");
465 true,
466 "Incorrect flag after 3 unacknowledged MPDUs");
468 true,
469 "Incorrect flag after 3 unacknowledged MPDUs");
471 false,
472 "Incorrect flag after 3 unacknowledged MPDUs");
474 false,
475 "Incorrect flag after 3 unacknowledged MPDUs");
477 true,
478 "Incorrect flag after 3 unacknowledged MPDUs");
479 NS_TEST_EXPECT_MSG_EQ(agreement.m_txWindow.At(10),
480 true,
481 "Incorrect flag after 3 unacknowledged MPDUs");
482 NS_TEST_EXPECT_MSG_EQ(agreement.m_txWindow.At(11),
483 true,
484 "Incorrect flag after 3 unacknowledged MPDUs");
485 for (uint16_t i = 12; i < winSize; i++)
486 {
488 false,
489 "Incorrect flag after 3 unacknowledged MPDUs");
490 }
491
492 // the transmission of an MPDU beyond the current window (by 2 positions) is
493 // notified, hence the window moves forward 2 positions
494 seqNumber = (agreement.m_txWindow.GetWinEnd() + 2) % SEQNO_SPACE_SIZE;
495 mpdu->GetHeader().SetSequenceNumber(seqNumber);
496 agreement.NotifyTransmittedMpdu(mpdu);
497
498 // the current window must look like this:
499 //
500 // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
501 // ^
502 // |
503 // HEAD
504
505 startingSeq = (startingSeq + 2) % SEQNO_SPACE_SIZE;
507 agreement.GetStartingSequence(),
508 startingSeq,
509 "Incorrect starting sequence after transmitting an MPDU beyond the current window");
511 false,
512 "Incorrect flag after transmitting an MPDU beyond the current window");
514 true,
515 "Incorrect flag after transmitting an MPDU beyond the current window");
517 true,
518 "Incorrect flag after transmitting an MPDU beyond the current window");
520 true,
521 "Incorrect flag after transmitting an MPDU beyond the current window");
523 true,
524 "Incorrect flag after transmitting an MPDU beyond the current window");
526 false,
527 "Incorrect flag after transmitting an MPDU beyond the current window");
529 false,
530 "Incorrect flag after transmitting an MPDU beyond the current window");
532 true,
533 "Incorrect flag after transmitting an MPDU beyond the current window");
535 true,
536 "Incorrect flag after transmitting an MPDU beyond the current window");
538 true,
539 "Incorrect flag after transmitting an MPDU beyond the current window");
540 for (uint16_t i = 10; i < winSize; i++)
541 {
543 agreement.m_txWindow.At(i),
544 false,
545 "Incorrect flag after transmitting an MPDU beyond the current window");
546 }
547
548 // another MPDU is transmitted beyond the current window. Now, the window advances
549 // until the first unacknowledged MPDU
550 seqNumber = (agreement.m_txWindow.GetWinEnd() + 1) % SEQNO_SPACE_SIZE;
551 mpdu->GetHeader().SetSequenceNumber(seqNumber);
552 agreement.NotifyTransmittedMpdu(mpdu);
553
554 // the current window must look like this:
555 //
556 // |0|0|0|1|1|1|0|0|0|0|0|0|0|0|0|0|
557 // ^
558 // |
559 // HEAD
560
561 startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
563 agreement.GetStartingSequence(),
564 startingSeq,
565 "Incorrect starting sequence after transmitting another MPDU beyond the current window");
567 agreement.m_txWindow.At(0),
568 false,
569 "Incorrect flag after transmitting another MPDU beyond the current window");
571 agreement.m_txWindow.At(1),
572 false,
573 "Incorrect flag after transmitting another MPDU beyond the current window");
575 agreement.m_txWindow.At(2),
576 true,
577 "Incorrect flag after transmitting another MPDU beyond the current window");
579 agreement.m_txWindow.At(3),
580 true,
581 "Incorrect flag after transmitting another MPDU beyond the current window");
583 agreement.m_txWindow.At(4),
584 true,
585 "Incorrect flag after transmitting another MPDU beyond the current window");
586 for (uint16_t i = 5; i < winSize; i++)
587 {
589 agreement.m_txWindow.At(i),
590 false,
591 "Incorrect flag after transmitting another MPDU beyond the current window");
592 }
593
594 // the MPDU next to winStart is discarded, hence the window advances to make it an old packet.
595 // Since the subsequent MPDUs have been acknowledged, the window advances further.
596 seqNumber = (startingSeq + 1) % SEQNO_SPACE_SIZE;
597 mpdu->GetHeader().SetSequenceNumber(seqNumber);
598 agreement.NotifyDiscardedMpdu(mpdu);
599
600 // the current window must look like this:
601 //
602 // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
603 // ^
604 // |
605 // HEAD
606
607 startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
609 startingSeq,
610 "Incorrect starting sequence after discarding an MPDU");
611 for (uint16_t i = 0; i < winSize; i++)
612 {
614 false,
615 "Incorrect flag after discarding an MPDU");
616 }
617
618 // Finally, check that the window correctly advances when the MPDU with the starting sequence
619 // number is acknowledged after being the only unacknowledged MPDU
620 for (uint16_t i = 1; i < winSize; i++)
621 {
622 mpdu->GetHeader().SetSequenceNumber((startingSeq + i) % SEQNO_SPACE_SIZE);
623 agreement.NotifyAckedMpdu(mpdu);
624 }
625
626 // the current window must look like this:
627 //
628 // |1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|
629 // ^
630 // |
631 // HEAD
632
634 startingSeq,
635 "Incorrect starting sequence after acknowledging all but the first MPDU");
637 false,
638 "Incorrect flag after acknowledging all but the first MPDU");
639 for (uint16_t i = 1; i < winSize; i++)
640 {
642 true,
643 "Incorrect flag after acknowledging all but the first MPDU");
644 }
645
646 // acknowledge the first MPDU
647 mpdu->GetHeader().SetSequenceNumber(startingSeq % SEQNO_SPACE_SIZE);
648 agreement.NotifyAckedMpdu(mpdu);
649
650 // the current window must look like this:
651 //
652 // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
653 // ^
654 // |
655 // HEAD
656
657 startingSeq = (startingSeq + winSize) % SEQNO_SPACE_SIZE;
659 startingSeq,
660 "Incorrect starting sequence after acknowledging the first MPDU");
661 for (uint16_t i = 0; i < winSize; i++)
662 {
664 false,
665 "Incorrect flag after acknowledging the first MPDU");
666 }
667}
668
669/**
670 * \ingroup wifi-test
671 * \ingroup tests
672 *
673 * \brief Test for block ack header
674 */
676{
677 public:
679
680 private:
681 void DoRun() override;
683};
684
686 : TestCase("Check the correctness of block ack compressed bitmap")
687{
688}
689
690void
692{
694
695 // Case 1: startSeq < endSeq
696 // 179 242
698 for (uint16_t i = 179; i < 220; i++)
699 {
701 }
702 for (uint16_t i = 225; i <= 242; i++)
703 {
705 }
706 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[0], 0xff, "error in compressed bitmap");
707 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[1], 0xff, "error in compressed bitmap");
708 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[2], 0xff, "error in compressed bitmap");
709 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[3], 0xff, "error in compressed bitmap");
710 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[4], 0xff, "error in compressed bitmap");
711 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[5], 0xc1, "error in compressed bitmap");
712 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[6], 0xff, "error in compressed bitmap");
713 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[7], 0xff, "error in compressed bitmap");
715 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[0], 0xff, "error in compressed bitmap");
716 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[1], 0xff, "error in compressed bitmap");
717 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[2], 0xff, "error in compressed bitmap");
718 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[3], 0xff, "error in compressed bitmap");
719 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[4], 0xff, "error in compressed bitmap");
720 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[5], 0xc1, "error in compressed bitmap");
721 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[6], 0xff, "error in compressed bitmap");
722 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[7], 0xff, "error in compressed bitmap");
723 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(220), false, "error in compressed bitmap");
724 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(225), true, "error in compressed bitmap");
726 false,
727 "error in compressed bitmap");
728
730
731 // Case 2: startSeq > endSeq
732 // 4090 58
734 for (uint16_t i = 4090; i != 10; i = (i + 1) % 4096)
735 {
737 }
738 for (uint16_t i = 22; i < 25; i++)
739 {
741 }
742 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[0], 0xff, "error in compressed bitmap");
743 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[1], 0xff, "error in compressed bitmap");
744 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[2], 0x00, "error in compressed bitmap");
745 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[3], 0x70, "error in compressed bitmap");
746 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[4], 0x00, "error in compressed bitmap");
747 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[5], 0x00, "error in compressed bitmap");
748 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[6], 0x00, "error in compressed bitmap");
749 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[7], 0x00, "error in compressed bitmap");
751 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[0], 0xff, "error in compressed bitmap");
752 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[1], 0xff, "error in compressed bitmap");
753 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[2], 0x00, "error in compressed bitmap");
754 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[3], 0x70, "error in compressed bitmap");
755 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[4], 0x00, "error in compressed bitmap");
756 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[5], 0x00, "error in compressed bitmap");
757 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[6], 0x00, "error in compressed bitmap");
758 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[7], 0x00, "error in compressed bitmap");
759 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(4090), true, "error in compressed bitmap");
760 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(4095), true, "error in compressed bitmap");
761 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(10), false, "error in compressed bitmap");
762 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(35), false, "error in compressed bitmap");
763 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(80), false, "error in compressed bitmap");
764}
765
766/**
767 * \ingroup wifi-test
768 * \ingroup tests
769 *
770 * \brief Test for recipient reordering buffer operations
771 */
773{
774 public:
775 /**
776 * \brief Constructor
777 * \param ssn the Starting Sequence Number used to initialize WinStartB
778 */
779 BlockAckRecipientBufferTest(uint16_t ssn);
781
782 void DoRun() override;
783
784 /**
785 * Keep track of MPDUs received on the given link that are forwarded up.
786 *
787 * \param mpdu an MPDU that is forwarded up
788 * \param linkId the ID of the given link
789 */
790 void ForwardUp(Ptr<const WifiMpdu> mpdu, uint8_t linkId);
791
792 private:
793 uint16_t m_ssn; //!< the Starting Sequence Number used to initialize WinStartB
794 std::list<Ptr<const WifiMpdu>> m_fwup; //!< list of MPDUs that have been forwarded up
795};
796
798 : TestCase("Test case for Block Ack recipient reordering buffer operations"),
799 m_ssn(ssn)
800{
801}
802
804{
805}
806
807void
809{
810 m_fwup.push_back(mpdu);
811}
812
813void
815{
816 Ptr<MacRxMiddle> rxMiddle = Create<MacRxMiddle>();
817 rxMiddle->SetForwardCallback(MakeCallback(&BlockAckRecipientBufferTest::ForwardUp, this));
818
819 RecipientBlockAckAgreement agreement(Mac48Address::Allocate() /* originator */,
820 true /* amsduSupported */,
821 0 /* tid */,
822 10 /* bufferSize */,
823 0 /* timeout */,
824 m_ssn,
825 true /* htSupported */);
826 agreement.SetMacRxMiddle(rxMiddle);
827
828 WifiMacHeader hdr;
831 hdr.SetQosTid(0);
832
833 // Notify the reception of an MPDU with SN = SSN.
835 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
836
837 // This MPDU is forwarded up and WinStartB is set to SSN + 1.
838 NS_TEST_ASSERT_MSG_EQ(m_fwup.size(), 1, "MPDU with SN=SSN must have been forwarded up");
839 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
840 m_ssn,
841 "The MPDU forwarded up is not the expected one");
842
843 m_fwup.clear();
844
845 // Notify the reception of MPDUs with SN = SSN + {4, 2, 5, 3, 10, 7}
846 // Recipient buffer: | |X|X|X|X| |X| | |X|
847 // ^
848 // |
849 // SSN + 1
851 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
853 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
855 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
857 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
859 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
861 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
862
863 // No MPDU is forwarded up because the one with SN = SSN + 1 is missing
864 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
865
866 // Notify the reception of an "old" MPDU (SN = SSN)
868 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
869
870 // No MPDU is forwarded up
871 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
872
873 // Notify the reception of a duplicate MPDU (SN = SSN + 2)
875 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(10), hdr));
876
877 // No MPDU is forwarded up
878 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
879
880 // Notify the reception of an MPDU with SN = SSN + 1
881 // Recipient buffer: |X|X|X|X|X| |X| | |X|
882 // ^
883 // |
884 // SSN + 1
886 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
887
888 // All the MPDUs with SN = SSN + {1, 2, 3, 4, 5} must have been forwarded up in order
889 NS_TEST_ASSERT_MSG_EQ(m_fwup.size(), 5, "5 MPDUs must have been forwarded up");
890
891 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
892 (m_ssn + 1) % SEQNO_SPACE_SIZE,
893 "The MPDU forwarded up is not the expected one");
894 m_fwup.pop_front();
895
896 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
897 (m_ssn + 2) % SEQNO_SPACE_SIZE,
898 "The MPDU forwarded up is not the expected one");
899 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetPacketSize(),
900 0,
901 "The MPDU forwarded up is not the expected one");
902 m_fwup.pop_front();
903
904 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
905 (m_ssn + 3) % SEQNO_SPACE_SIZE,
906 "The MPDU forwarded up is not the expected one");
907 m_fwup.pop_front();
908
909 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
910 (m_ssn + 4) % SEQNO_SPACE_SIZE,
911 "The MPDU forwarded up is not the expected one");
912 m_fwup.pop_front();
913
914 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
915 (m_ssn + 5) % SEQNO_SPACE_SIZE,
916 "The MPDU forwarded up is not the expected one");
917 m_fwup.pop_front();
918
919 // Recipient buffer: | |X| | |X| | | | | |
920 // ^ ^
921 // | |
922 // SSN + 6 SSN + 15
923 // Notify the reception of an MPDU beyond the current window (SN = SSN + 17)
925 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
926
927 // WinStartB is set to SSN + 8 (so that WinEndB = SSN + 17). The MPDU with
928 // SN = SSN + 7 is forwarded up, irrespective of the missed reception of the
929 // MPDU with SN = SSN + 6
930 NS_TEST_ASSERT_MSG_EQ(m_fwup.size(), 1, "One MPDU must have been forwarded up");
931
932 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
933 (m_ssn + 7) % SEQNO_SPACE_SIZE,
934 "The MPDU forwarded up is not the expected one");
935 m_fwup.pop_front();
936
937 // Recipient buffer: | | |X| | | | | | |X|
938 // ^ ^
939 // | |
940 // SSN + 8 SSN + 17
941 // Notify the reception of a BlockAckReq with SSN = SSN + 7
942 agreement.NotifyReceivedBar((m_ssn + 7) % SEQNO_SPACE_SIZE);
943
944 // No MPDU is forwarded up
945 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
946
947 // Notify the reception of a BlockAckReq with SSN = SSN + 8
948 agreement.NotifyReceivedBar((m_ssn + 8) % SEQNO_SPACE_SIZE);
949
950 // No MPDU is forwarded up
951 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
952
953 // Notify the reception of MPDUs with SN = SSN + {9, 11}
954 // Recipient buffer: | |X|X|X| | | | | |X|
955 // ^ ^
956 // | |
957 // SSN + 8 SSN + 17
959 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
961 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
962
963 // No MPDU is forwarded up because the one with SN = SSN + 8 is missing
964 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
965
966 // Notify the reception of a BlockAckReq with SSN = SSN + 10
967 agreement.NotifyReceivedBar((m_ssn + 10) % SEQNO_SPACE_SIZE);
968
969 // Forward up buffered MPDUs with SN < SSN + 10 (the MPDU with SN = SSN + 9)
970 // and then buffered MPDUs with SN >= SSN + 10 until a hole is found (MPDUs
971 // with SN = SSN + 10 and SN = SSN + 11)
972 NS_TEST_ASSERT_MSG_EQ(m_fwup.size(), 3, "3 MPDUs must have been forwarded up");
973
974 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
975 (m_ssn + 9) % SEQNO_SPACE_SIZE,
976 "The MPDU forwarded up is not the expected one");
977 m_fwup.pop_front();
978
979 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
980 (m_ssn + 10) % SEQNO_SPACE_SIZE,
981 "The MPDU forwarded up is not the expected one");
982 m_fwup.pop_front();
983
984 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
985 (m_ssn + 11) % SEQNO_SPACE_SIZE,
986 "The MPDU forwarded up is not the expected one");
987 m_fwup.pop_front();
988
991}
992
993/**
994 * \ingroup wifi-test
995 * \ingroup tests
996 *
997 * \brief Test for Multi-STA block ack header
998 */
1000{
1001 public:
1003
1004 private:
1005 void DoRun() override;
1006};
1007
1009 : TestCase("Check the correctness of Multi-STA block ack")
1010{
1011}
1012
1013void
1015{
1016 // Create a Multi-STA Block Ack with 6 Per AID TID Info subfields
1017 BlockAckType baType(BlockAckType::MULTI_STA, {0, 4, 8, 16, 32, 8});
1018
1019 CtrlBAckResponseHeader blockAck;
1020 blockAck.SetType(baType);
1021
1022 /* 1st Per AID TID Info subfield */
1023 uint16_t aid1 = 100;
1024 bool ackType1 = true;
1025 uint8_t tid1 = 1;
1026
1027 blockAck.SetAid11(aid1, 0);
1028 blockAck.SetAckType(ackType1, 0);
1029 blockAck.SetTidInfo(tid1, 0);
1030
1031 /* 2nd Per AID TID Info subfield */
1032 uint16_t aid2 = 200;
1033 bool ackType2 = false;
1034 uint8_t tid2 = 2;
1035 uint16_t startSeq2 = 1000;
1036
1037 blockAck.SetAid11(aid2, 1);
1038 blockAck.SetAckType(ackType2, 1);
1039 blockAck.SetTidInfo(tid2, 1);
1040 blockAck.SetStartingSequence(startSeq2, 1);
1041 // 1st byte of the bitmap: 01010101
1042 for (uint16_t i = startSeq2; i < startSeq2 + 8; i += 2)
1043 {
1044 blockAck.SetReceivedPacket(i, 1);
1045 }
1046 // 2nd byte of the bitmap: 10101010
1047 for (uint16_t i = startSeq2 + 9; i < startSeq2 + 16; i += 2)
1048 {
1049 blockAck.SetReceivedPacket(i, 1);
1050 }
1051 // 3rd byte of the bitmap: 00000000
1052 // 4th byte of the bitmap: 11111111
1053 for (uint16_t i = startSeq2 + 24; i < startSeq2 + 32; i++)
1054 {
1055 blockAck.SetReceivedPacket(i, 1);
1056 }
1057
1058 /* 3rd Per AID TID Info subfield */
1059 uint16_t aid3 = 300;
1060 bool ackType3 = false;
1061 uint8_t tid3 = 3;
1062 uint16_t startSeq3 = 2000;
1063
1064 blockAck.SetAid11(aid3, 2);
1065 blockAck.SetAckType(ackType3, 2);
1066 blockAck.SetTidInfo(tid3, 2);
1067 blockAck.SetStartingSequence(startSeq3, 2);
1068 // 1st byte of the bitmap: 01010101
1069 for (uint16_t i = startSeq3; i < startSeq3 + 8; i += 2)
1070 {
1071 blockAck.SetReceivedPacket(i, 2);
1072 }
1073 // 2nd byte of the bitmap: 10101010
1074 for (uint16_t i = startSeq3 + 9; i < startSeq3 + 16; i += 2)
1075 {
1076 blockAck.SetReceivedPacket(i, 2);
1077 }
1078 // 3rd byte of the bitmap: 00000000
1079 // 4th byte of the bitmap: 11111111
1080 for (uint16_t i = startSeq3 + 24; i < startSeq3 + 32; i++)
1081 {
1082 blockAck.SetReceivedPacket(i, 2);
1083 }
1084 // 5th byte of the bitmap: 00001111
1085 for (uint16_t i = startSeq3 + 32; i < startSeq3 + 36; i++)
1086 {
1087 blockAck.SetReceivedPacket(i, 2);
1088 }
1089 // 6th byte of the bitmap: 11110000
1090 for (uint16_t i = startSeq3 + 44; i < startSeq3 + 48; i++)
1091 {
1092 blockAck.SetReceivedPacket(i, 2);
1093 }
1094 // 7th byte of the bitmap: 00000000
1095 // 8th byte of the bitmap: 11111111
1096 for (uint16_t i = startSeq3 + 56; i < startSeq3 + 64; i++)
1097 {
1098 blockAck.SetReceivedPacket(i, 2);
1099 }
1100
1101 /* 4th Per AID TID Info subfield */
1102 uint16_t aid4 = 400;
1103 bool ackType4 = false;
1104 uint8_t tid4 = 4;
1105 uint16_t startSeq4 = 3000;
1106
1107 blockAck.SetAid11(aid4, 3);
1108 blockAck.SetAckType(ackType4, 3);
1109 blockAck.SetTidInfo(tid4, 3);
1110 blockAck.SetStartingSequence(startSeq4, 3);
1111 // 1st byte of the bitmap: 01010101
1112 for (uint16_t i = startSeq4; i < startSeq4 + 8; i += 2)
1113 {
1114 blockAck.SetReceivedPacket(i, 3);
1115 }
1116 // 2nd byte of the bitmap: 10101010
1117 for (uint16_t i = startSeq4 + 9; i < startSeq4 + 16; i += 2)
1118 {
1119 blockAck.SetReceivedPacket(i, 3);
1120 }
1121 // 3rd byte of the bitmap: 00000000
1122 // 4th byte of the bitmap: 11111111
1123 for (uint16_t i = startSeq4 + 24; i < startSeq4 + 32; i++)
1124 {
1125 blockAck.SetReceivedPacket(i, 3);
1126 }
1127 // 5th byte of the bitmap: 00001111
1128 for (uint16_t i = startSeq4 + 32; i < startSeq4 + 36; i++)
1129 {
1130 blockAck.SetReceivedPacket(i, 3);
1131 }
1132 // 6th byte of the bitmap: 11110000
1133 for (uint16_t i = startSeq4 + 44; i < startSeq4 + 48; i++)
1134 {
1135 blockAck.SetReceivedPacket(i, 3);
1136 }
1137 // 7th byte of the bitmap: 00000000
1138 // 8th byte of the bitmap: 11111111
1139 for (uint16_t i = startSeq4 + 56; i < startSeq4 + 64; i++)
1140 {
1141 blockAck.SetReceivedPacket(i, 3);
1142 }
1143 // 9th byte of the bitmap: 00000000
1144 // 10th byte of the bitmap: 11111111
1145 for (uint16_t i = startSeq4 + 72; i < startSeq4 + 80; i++)
1146 {
1147 blockAck.SetReceivedPacket(i, 3);
1148 }
1149 // 11th byte of the bitmap: 00000000
1150 // 12th byte of the bitmap: 11111111
1151 for (uint16_t i = startSeq4 + 88; i < startSeq4 + 96; i++)
1152 {
1153 blockAck.SetReceivedPacket(i, 3);
1154 }
1155 // 13th byte of the bitmap: 00000000
1156 // 14th byte of the bitmap: 11111111
1157 for (uint16_t i = startSeq4 + 104; i < startSeq4 + 112; i++)
1158 {
1159 blockAck.SetReceivedPacket(i, 3);
1160 }
1161 // 15th byte of the bitmap: 00000000
1162 // 16th byte of the bitmap: 11111111
1163 for (uint16_t i = startSeq4 + 120; i < startSeq4 + 128; i++)
1164 {
1165 blockAck.SetReceivedPacket(i, 3);
1166 }
1167
1168 /* 5th Per AID TID Info subfield */
1169 uint16_t aid5 = 500;
1170 bool ackType5 = false;
1171 uint8_t tid5 = 5;
1172 uint16_t startSeq5 = 4000;
1173
1174 blockAck.SetAid11(aid5, 4);
1175 blockAck.SetAckType(ackType5, 4);
1176 blockAck.SetTidInfo(tid5, 4);
1177 blockAck.SetStartingSequence(startSeq5, 4);
1178 // 1st byte of the bitmap: 01010101
1179 for (int i = startSeq5; i < startSeq5 + 8; i += 2)
1180 {
1181 blockAck.SetReceivedPacket(i, 4);
1182 }
1183 // 2nd byte of the bitmap: 10101010
1184 for (int i = startSeq5 + 9; i < startSeq5 + 16; i += 2)
1185 {
1186 blockAck.SetReceivedPacket(i, 4);
1187 }
1188 // 3rd byte of the bitmap: 00000000
1189 // 4th byte of the bitmap: 11111111
1190 for (int i = startSeq5 + 24; i < startSeq5 + 32; i++)
1191 {
1192 blockAck.SetReceivedPacket(i, 4);
1193 }
1194 // 5th byte of the bitmap: 00001111
1195 for (int i = startSeq5 + 32; i < startSeq5 + 36; i++)
1196 {
1197 blockAck.SetReceivedPacket(i, 4);
1198 }
1199 // 6th byte of the bitmap: 11110000
1200 for (int i = startSeq5 + 44; i < startSeq5 + 48; i++)
1201 {
1202 blockAck.SetReceivedPacket(i, 4);
1203 }
1204 // 7th byte of the bitmap: 00000000
1205 // 8th byte of the bitmap: 11111111
1206 for (int i = startSeq5 + 56; i < startSeq5 + 64; i++)
1207 {
1208 blockAck.SetReceivedPacket(i, 4);
1209 }
1210 // 9th byte of the bitmap: 00000000
1211 // 10th byte of the bitmap: 11111111
1212 for (int i = startSeq5 + 72; i < startSeq5 + 80; i++)
1213 {
1214 blockAck.SetReceivedPacket(i, 4);
1215 }
1216 // 11th byte of the bitmap: 00000000
1217 // 12th byte of the bitmap: 11111111
1218 for (int i = startSeq5 + 88; i < startSeq5 + 96; i++)
1219 {
1220 blockAck.SetReceivedPacket(i, 4);
1221 }
1222 // 13th byte of the bitmap: 00000000
1223 // 14th byte of the bitmap: 11111111
1224 for (int i = (startSeq5 + 104) % 4096; i < (startSeq5 + 112) % 4096; i++)
1225 {
1226 blockAck.SetReceivedPacket(i, 4);
1227 }
1228 // 15th byte of the bitmap: 00000000
1229 // 16th byte of the bitmap: 11111111
1230 for (int i = (startSeq5 + 120) % 4096; i < (startSeq5 + 128) % 4096; i++)
1231 {
1232 blockAck.SetReceivedPacket(i, 4);
1233 }
1234 // 17th byte of the bitmap: 00000000
1235 // 18th byte of the bitmap: 11111111
1236 for (int i = (startSeq5 + 136) % 4096; i < (startSeq5 + 144) % 4096; i++)
1237 {
1238 blockAck.SetReceivedPacket(i, 4);
1239 }
1240 // 19th byte of the bitmap: 00000000
1241 // 20th byte of the bitmap: 11111111
1242 for (int i = (startSeq5 + 152) % 4096; i < (startSeq5 + 160) % 4096; i++)
1243 {
1244 blockAck.SetReceivedPacket(i, 4);
1245 }
1246 // 21th byte of the bitmap: 00000000
1247 // 22th byte of the bitmap: 11111111
1248 for (int i = (startSeq5 + 168) % 4096; i < (startSeq5 + 176) % 4096; i++)
1249 {
1250 blockAck.SetReceivedPacket(i, 4);
1251 }
1252 // 23th byte of the bitmap: 00000000
1253 // 24th byte of the bitmap: 11111111
1254 for (int i = (startSeq5 + 184) % 4096; i < (startSeq5 + 192) % 4096; i++)
1255 {
1256 blockAck.SetReceivedPacket(i, 4);
1257 }
1258 // 25th byte of the bitmap: 00000000
1259 // 26th byte of the bitmap: 11111111
1260 for (int i = (startSeq5 + 200) % 4096; i < (startSeq5 + 208) % 4096; i++)
1261 {
1262 blockAck.SetReceivedPacket(i, 4);
1263 }
1264 // 27th byte of the bitmap: 00000000
1265 // 28th byte of the bitmap: 11111111
1266 for (int i = (startSeq5 + 216) % 4096; i < (startSeq5 + 224) % 4096; i++)
1267 {
1268 blockAck.SetReceivedPacket(i, 4);
1269 }
1270 // 29th byte of the bitmap: 00000000
1271 // 30th byte of the bitmap: 11111111
1272 for (int i = (startSeq5 + 232) % 4096; i < (startSeq5 + 240) % 4096; i++)
1273 {
1274 blockAck.SetReceivedPacket(i, 4);
1275 }
1276 // 31th byte of the bitmap: 00000000
1277 // 32th byte of the bitmap: 11111111
1278 for (int i = (startSeq5 + 248) % 4096; i < (startSeq5 + 256) % 4096; i++)
1279 {
1280 blockAck.SetReceivedPacket(i, 4);
1281 }
1282
1283 /* 6th Per AID TID Info subfield */
1284 uint16_t aid6 = 2045;
1285 bool ackType6 = true;
1286 uint8_t tid6 = 6;
1287 Mac48Address address6("00:00:00:00:00:01");
1288
1289 blockAck.SetAid11(aid6, 5);
1290 blockAck.SetAckType(ackType6, 5);
1291 blockAck.SetTidInfo(tid6, 5);
1292 blockAck.SetUnassociatedStaAddress(address6, 5);
1293
1294 // Serialize the header
1295 Ptr<Packet> packet = Create<Packet>();
1296 packet->AddHeader(blockAck);
1297
1298 // Deserialize the header
1299 CtrlBAckResponseHeader blockAckCopy;
1300 packet->RemoveHeader(blockAckCopy);
1301
1302 // Check that the header has been correctly deserialized
1303 BlockAckType baTypeCopy = blockAckCopy.GetType();
1304
1307 "Different block ack variant");
1308 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen.size(), 6, "Different number of bitmaps");
1309 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[0], 0, "Different length of the first bitmap");
1310 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[1], 4, "Different length of the second bitmap");
1311 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[2], 8, "Different length of the third bitmap");
1312 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[3], 16, "Different length of the fourth bitmap");
1313 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[4], 32, "Different length of the fifth bitmap");
1314 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[5], 8, "Different length for the sixth bitmap");
1315
1316 /* Check 1st Per AID TID Info subfield */
1317 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(0),
1318 aid1,
1319 "Different AID for the first Per AID TID Info subfield");
1320 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(0),
1321 ackType1,
1322 "Different Ack Type for the first Per AID TID Info subfield");
1323 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(0),
1324 tid1,
1325 "Different TID for the first Per AID TID Info subfield");
1326
1327 /* Check 2nd Per AID TID Info subfield */
1328 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(1),
1329 aid2,
1330 "Different AID for the second Per AID TID Info subfield");
1331 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(1),
1332 ackType2,
1333 "Different Ack Type for the second Per AID TID Info subfield");
1334 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(1),
1335 tid2,
1336 "Different TID for the second Per AID TID Info subfield");
1338 blockAckCopy.GetStartingSequence(1),
1339 startSeq2,
1340 "Different starting sequence number for the second Per AID TID Info subfield");
1341
1342 auto& bitmap2 = blockAckCopy.GetBitmap(1);
1343 NS_TEST_EXPECT_MSG_EQ(bitmap2.size(),
1344 4,
1345 "Different bitmap length for the second Per AID TID Info subfield");
1347 bitmap2[0],
1348 0x55,
1349 "Error in the 1st byte of the bitmap for the second Per AID TID Info subfield");
1351 bitmap2[1],
1352 0xaa,
1353 "Error in the 2nd byte of the bitmap for the second Per AID TID Info subfield");
1355 bitmap2[2],
1356 0x00,
1357 "Error in the 3rd byte of the bitmap for the second Per AID TID Info subfield");
1359 bitmap2[3],
1360 0xff,
1361 "Error in the 4th byte of the bitmap for the second Per AID TID Info subfield");
1362
1363 /* Check 3rd Per AID TID Info subfield */
1364 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(2),
1365 aid3,
1366 "Different AID for the third Per AID TID Info subfield");
1367 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(2),
1368 ackType3,
1369 "Different Ack Type for the third Per AID TID Info subfield");
1370 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(2),
1371 tid3,
1372 "Different TID for the third Per AID TID Info subfield");
1374 blockAckCopy.GetStartingSequence(2),
1375 startSeq3,
1376 "Different starting sequence number for the third Per AID TID Info subfield");
1377
1378 auto& bitmap3 = blockAckCopy.GetBitmap(2);
1379 NS_TEST_EXPECT_MSG_EQ(bitmap3.size(),
1380 8,
1381 "Different bitmap length for the third Per AID TID Info subfield");
1383 bitmap3[0],
1384 0x55,
1385 "Error in the 1st byte of the bitmap for the third Per AID TID Info subfield");
1387 bitmap3[1],
1388 0xaa,
1389 "Error in the 2nd byte of the bitmap for the third Per AID TID Info subfield");
1391 bitmap3[2],
1392 0x00,
1393 "Error in the 3rd byte of the bitmap for the third Per AID TID Info subfield");
1395 bitmap3[3],
1396 0xff,
1397 "Error in the 4th byte of the bitmap for the third Per AID TID Info subfield");
1399 bitmap3[4],
1400 0x0f,
1401 "Error in the 5th byte of the bitmap for the third Per AID TID Info subfield");
1403 bitmap3[5],
1404 0xf0,
1405 "Error in the 6th byte of the bitmap for the third Per AID TID Info subfield");
1407 bitmap3[6],
1408 0x00,
1409 "Error in the 7th byte of the bitmap for the third Per AID TID Info subfield");
1411 bitmap3[7],
1412 0xff,
1413 "Error in the 8th byte of the bitmap for the third Per AID TID Info subfield");
1414
1415 /* Check 4th Per AID TID Info subfield */
1416 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(3),
1417 aid4,
1418 "Different AID for the fourth Per AID TID Info subfield");
1419 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(3),
1420 ackType4,
1421 "Different Ack Type for the fourth Per AID TID Info subfield");
1422 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(3),
1423 tid4,
1424 "Different TID for the fourth Per AID TID Info subfield");
1426 blockAckCopy.GetStartingSequence(3),
1427 startSeq4,
1428 "Different starting sequence number for the fourth Per AID TID Info subfield");
1429
1430 auto& bitmap4 = blockAckCopy.GetBitmap(3);
1431 NS_TEST_EXPECT_MSG_EQ(bitmap4.size(),
1432 16,
1433 "Different bitmap length for the fourth Per AID TID Info subfield");
1435 bitmap4[0],
1436 0x55,
1437 "Error in the 1st byte of the bitmap for the fourth Per AID TID Info subfield");
1439 bitmap4[1],
1440 0xaa,
1441 "Error in the 2nd byte of the bitmap for the fourth Per AID TID Info subfield");
1443 bitmap4[2],
1444 0x00,
1445 "Error in the 3rd byte of the bitmap for the fourth Per AID TID Info subfield");
1447 bitmap4[3],
1448 0xff,
1449 "Error in the 4th byte of the bitmap for the fourth Per AID TID Info subfield");
1451 bitmap4[4],
1452 0x0f,
1453 "Error in the 5th byte of the bitmap for the fourth Per AID TID Info subfield");
1455 bitmap4[5],
1456 0xf0,
1457 "Error in the 6th byte of the bitmap for the fourth Per AID TID Info subfield");
1459 bitmap4[6],
1460 0x00,
1461 "Error in the 7th byte of the bitmap for the fourth Per AID TID Info subfield");
1463 bitmap4[7],
1464 0xff,
1465 "Error in the 8th byte of the bitmap for the fourth Per AID TID Info subfield");
1467 bitmap4[8],
1468 0x00,
1469 "Error in the 9th byte of the bitmap for the fourth Per AID TID Info subfield");
1471 bitmap4[9],
1472 0xff,
1473 "Error in the 10th byte of the bitmap for the fourth Per AID TID Info subfield");
1475 bitmap4[10],
1476 0x00,
1477 "Error in the 11th byte of the bitmap for the fourth Per AID TID Info subfield");
1479 bitmap4[11],
1480 0xff,
1481 "Error in the 12th byte of the bitmap for the fourth Per AID TID Info subfield");
1483 bitmap4[12],
1484 0x00,
1485 "Error in the 13th byte of the bitmap for the fourth Per AID TID Info subfield");
1487 bitmap4[13],
1488 0xff,
1489 "Error in the 14th byte of the bitmap for the fourth Per AID TID Info subfield");
1491 bitmap4[14],
1492 0x00,
1493 "Error in the 15th byte of the bitmap for the fourth Per AID TID Info subfield");
1495 bitmap4[15],
1496 0xff,
1497 "Error in the 16th byte of the bitmap for the fourth Per AID TID Info subfield");
1498
1499 /* Check 5th Per AID TID Info subfield */
1500 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(4),
1501 aid5,
1502 "Different AID for the fifth Per AID TID Info subfield");
1503 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(4),
1504 ackType5,
1505 "Different Ack Type for the fifth Per AID TID Info subfield");
1506 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(4),
1507 tid5,
1508 "Different TID for the fifth Per AID TID Info subfield");
1510 blockAckCopy.GetStartingSequence(4),
1511 startSeq5,
1512 "Different starting sequence number for the fifth Per AID TID Info subfield");
1513
1514 auto& bitmap5 = blockAckCopy.GetBitmap(4);
1515 NS_TEST_EXPECT_MSG_EQ(bitmap5.size(),
1516 32,
1517 "Different bitmap length for the fifth Per AID TID Info subfield");
1519 bitmap5[0],
1520 0x55,
1521 "Error in the 1st byte of the bitmap for the fifth Per AID TID Info subfield");
1523 bitmap5[1],
1524 0xaa,
1525 "Error in the 2nd byte of the bitmap for the fifth Per AID TID Info subfield");
1527 bitmap5[2],
1528 0x00,
1529 "Error in the 3rd byte of the bitmap for the fifth Per AID TID Info subfield");
1531 bitmap5[3],
1532 0xff,
1533 "Error in the 4th byte of the bitmap for the fifth Per AID TID Info subfield");
1535 bitmap5[4],
1536 0x0f,
1537 "Error in the 5th byte of the bitmap for the fifth Per AID TID Info subfield");
1539 bitmap5[5],
1540 0xf0,
1541 "Error in the 6th byte of the bitmap for the fifth Per AID TID Info subfield");
1543 bitmap5[6],
1544 0x00,
1545 "Error in the 7th byte of the bitmap for the fifth Per AID TID Info subfield");
1547 bitmap5[7],
1548 0xff,
1549 "Error in the 8th byte of the bitmap for the fifth Per AID TID Info subfield");
1551 bitmap5[8],
1552 0x00,
1553 "Error in the 9th byte of the bitmap for the fifth Per AID TID Info subfield");
1555 bitmap5[9],
1556 0xff,
1557 "Error in the 10th byte of the bitmap for the fifth Per AID TID Info subfield");
1559 bitmap5[10],
1560 0x00,
1561 "Error in the 11th byte of the bitmap for the fifth Per AID TID Info subfield");
1563 bitmap5[11],
1564 0xff,
1565 "Error in the 12th byte of the bitmap for the fifth Per AID TID Info subfield");
1567 bitmap5[12],
1568 0x00,
1569 "Error in the 13th byte of the bitmap for the fifth Per AID TID Info subfield");
1571 bitmap5[13],
1572 0xff,
1573 "Error in the 14th byte of the bitmap for the fifth Per AID TID Info subfield");
1575 bitmap5[14],
1576 0x00,
1577 "Error in the 15th byte of the bitmap for the fifth Per AID TID Info subfield");
1579 bitmap5[15],
1580 0xff,
1581 "Error in the 16th byte of the bitmap for the fifth Per AID TID Info subfield");
1583 bitmap5[16],
1584 0x00,
1585 "Error in the 17th byte of the bitmap for the fifth Per AID TID Info subfield");
1587 bitmap5[17],
1588 0xff,
1589 "Error in the 18th byte of the bitmap for the fifth Per AID TID Info subfield");
1591 bitmap5[18],
1592 0x00,
1593 "Error in the 19th byte of the bitmap for the fifth Per AID TID Info subfield");
1595 bitmap5[19],
1596 0xff,
1597 "Error in the 20th byte of the bitmap for the fifth Per AID TID Info subfield");
1599 bitmap5[20],
1600 0x00,
1601 "Error in the 21th byte of the bitmap for the fifth Per AID TID Info subfield");
1603 bitmap5[21],
1604 0xff,
1605 "Error in the 22th byte of the bitmap for the fifth Per AID TID Info subfield");
1607 bitmap5[22],
1608 0x00,
1609 "Error in the 23th byte of the bitmap for the fifth Per AID TID Info subfield");
1611 bitmap5[23],
1612 0xff,
1613 "Error in the 24th byte of the bitmap for the fifth Per AID TID Info subfield");
1615 bitmap5[24],
1616 0x00,
1617 "Error in the 25th byte of the bitmap for the fifth Per AID TID Info subfield");
1619 bitmap5[25],
1620 0xff,
1621 "Error in the 26th byte of the bitmap for the fifth Per AID TID Info subfield");
1623 bitmap5[26],
1624 0x00,
1625 "Error in the 27th byte of the bitmap for the fifth Per AID TID Info subfield");
1627 bitmap5[27],
1628 0xff,
1629 "Error in the 28th byte of the bitmap for the fifth Per AID TID Info subfield");
1631 bitmap5[28],
1632 0x00,
1633 "Error in the 29th byte of the bitmap for the fifth Per AID TID Info subfield");
1635 bitmap5[29],
1636 0xff,
1637 "Error in the 30th byte of the bitmap for the fifth Per AID TID Info subfield");
1639 bitmap5[30],
1640 0x00,
1641 "Error in the 31th byte of the bitmap for the fifth Per AID TID Info subfield");
1643 bitmap5[31],
1644 0xff,
1645 "Error in the 32th byte of the bitmap for the fifth Per AID TID Info subfield");
1646
1647 /* Check 6th Per AID TID Info subfield */
1648 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(5),
1649 aid6,
1650 "Different AID for the sixth Per AID TID Info subfield");
1651 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(5),
1652 ackType6,
1653 "Different Ack Type for the sixth Per AID TID Info subfield");
1654 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(5),
1655 tid6,
1656 "Different TID for the sixth Per AID TID Info subfield");
1658 blockAckCopy.GetUnassociatedStaAddress(5),
1659 address6,
1660 "Different starting sequence number for the sixth Per AID TID Info subfield");
1661}
1662
1663/**
1664 * \ingroup wifi-test
1665 * \ingroup tests
1666 *
1667 * \brief Test for Block Ack Policy with aggregation disabled
1668 *
1669 * This test aims to check the Block Ack policy when A-MPDU aggregation is disabled.
1670 * In this case, a QoS station can transmit multiple QoS data frames before requesting
1671 * a Block Ack through a Block Ack Request frame. If the AC is granted a non-null TXOP
1672 * limit, MPDUs can be separated by a SIFS.
1673 *
1674 * In this test, an HT STA sends 14 packets to an HT AP. The ack policy selector is
1675 * configured so that a Block Ack is requested once 8 (= 0.125 * 64) MPDUs are sent
1676 * in addition to the MPDU having the starting sequence number. The block ack threshold
1677 * is set to 2, hence a block ack agreement is established when there are at least two
1678 * packets in the EDCA queue.
1679 *
1680 * When the TXOP limit is null:
1681 * - the first packet is sent with Normal Ack policy because the BA agreement has not
1682 * been established yet (there are no queued packets when the first one arrives);
1683 * - packets from the 2nd to the 10th are sent with Block Ack policy (and hence
1684 * are not immediately acknowledged);
1685 * - after the 10th packet, a Block Ack Request is sent, followed by a Block Ack;
1686 * - the remaining 4 packets are sent with Block Ack policy (and hence
1687 * are not immediately acknowledged);
1688 * - the last packet is followed by a Block Ack Request because there are no more
1689 * packets in the EDCA queue and hence a response is needed independently of
1690 * the number of outstanding MPDUs.
1691 *
1692 * When the TXOP is not null (and long enough to include the transmission of all packets):
1693 * - the first packet is sent with Normal Ack policy because the BA agreement has not
1694 * been established yet (there are no queued packets when the first one arrives);
1695 * - the second packet is sent with Normal Ack Policy because the first packet sent in
1696 * a TXOP shall request an immediate response and no previous MPDUs have to be
1697 * acknowledged;
1698 * - packets from the 3rd to the 11th are sent with Block Ack policy (and hence
1699 * are not immediately acknowledged);
1700 * - after the 11th packet, a Block Ack Request is sent, followed by a Block Ack;
1701 * - the remaining 3 packets are sent with Block Ack policy (and hence
1702 * are not immediately acknowledged);
1703 * - the last packet is followed by a Block Ack Request because there are no more
1704 * packets in the EDCA queue and hence a response is needed independently of
1705 * the number of outstanding MPDUs.
1706 */
1708{
1709 /**
1710 * Keeps the maximum duration among all TXOPs
1711 */
1713 {
1714 /**
1715 * Callback for the TxopTrace trace
1716 * \param startTime TXOP start time
1717 * \param duration TXOP duration
1718 * \param linkId the ID of the link
1719 */
1720 void Trace(Time startTime, Time duration, uint8_t linkId);
1721 Time m_max{Seconds(0)}; ///< max TXOP duration
1722 };
1723
1724 public:
1725 /**
1726 * \brief Constructor
1727 * \param txop true for non-null TXOP limit
1728 */
1731
1732 void DoRun() override;
1733
1734 private:
1735 bool m_txop; ///< true for non-null TXOP limit
1736 uint32_t m_received; ///< received packets
1737 uint16_t m_txTotal; ///< transmitted data packets
1738 uint16_t m_txSinceBar; ///< packets transmitted since the agreement was established
1739 ///< or the last block ack was received
1740 uint16_t m_nBar; ///< transmitted BlockAckReq frames
1741 uint16_t m_nBa; ///< received BlockAck frames
1742
1743 /**
1744 * Function to trace packets received by the server application
1745 * \param context the context
1746 * \param p the packet
1747 * \param adr the address
1748 */
1749 void L7Receive(std::string context, Ptr<const Packet> p, const Address& adr);
1750 /**
1751 * Callback invoked when PHY transmits a packet
1752 * \param context the context
1753 * \param p the packet
1754 * \param power the tx power
1755 */
1756 void Transmit(std::string context, Ptr<const Packet> p, double power);
1757 /**
1758 * Callback invoked when PHY receives a packet
1759 * \param context the context
1760 * \param p the packet
1761 * \param rxPowersW the received power per channel band in watts
1762 */
1763 void Receive(std::string context, Ptr<const Packet> p, RxPowerWattPerChannelBand rxPowersW);
1764};
1765
1766void
1768 Time duration,
1769 uint8_t linkId)
1770{
1771 if (duration > m_max)
1772 {
1773 m_max = duration;
1774 }
1775}
1776
1778 : TestCase("Test case for Block Ack Policy with aggregation disabled"),
1779 m_txop(txop),
1780 m_received(0),
1781 m_txTotal(0),
1782 m_txSinceBar(0),
1783 m_nBar(0),
1784 m_nBa(0)
1785{
1786}
1787
1789{
1790}
1791
1792void
1795 const Address& adr)
1796{
1797 if (p->GetSize() == 1400)
1798 {
1799 m_received++;
1800 }
1801}
1802
1803void
1805{
1806 WifiMacHeader hdr;
1807 p->PeekHeader(hdr);
1808
1809 if (m_nBar < 2 && (m_txSinceBar == 9 || m_txTotal == 14))
1810 {
1811 NS_TEST_ASSERT_MSG_EQ(hdr.IsBlockAckReq(), true, "Didn't get a BlockAckReq when expected");
1812 }
1813 else
1814 {
1815 NS_TEST_ASSERT_MSG_EQ(hdr.IsBlockAckReq(), false, "Got a BlockAckReq when not expected");
1816 }
1817
1818 if (hdr.IsQosData())
1819 {
1820 m_txTotal++;
1821 if (hdr.IsQosBlockAck())
1822 {
1823 m_txSinceBar++;
1824 }
1825
1826 if (!m_txop)
1827 {
1829 true,
1830 "Unexpected QoS ack policy");
1831 }
1832 else
1833 {
1835 true,
1836 "Unexpected QoS ack policy");
1837 }
1838 }
1839 else if (hdr.IsBlockAckReq())
1840 {
1841 m_txSinceBar = 0;
1842 m_nBar++;
1843 }
1844}
1845
1846void
1849 RxPowerWattPerChannelBand rxPowersW)
1850{
1851 WifiMacHeader hdr;
1852 p->PeekHeader(hdr);
1853
1854 if (hdr.IsBlockAck())
1855 {
1856 m_nBa++;
1857 }
1858}
1859
1860void
1862{
1863 NodeContainer wifiStaNode;
1864 wifiStaNode.Create(1);
1865
1866 NodeContainer wifiApNode;
1867 wifiApNode.Create(1);
1868
1871 phy.SetChannel(channel.Create());
1872
1873 WifiHelper wifi;
1874 wifi.SetStandard(WIFI_STANDARD_80211n);
1875 Config::SetDefault("ns3::WifiDefaultAckManager::BaThreshold", DoubleValue(0.125));
1876 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
1877
1878 WifiMacHelper mac;
1879 Ssid ssid = Ssid("ns-3-ssid");
1880 mac.SetType("ns3::StaWifiMac",
1881 "BE_MaxAmsduSize",
1882 UintegerValue(0),
1883 "BE_MaxAmpduSize",
1884 UintegerValue(0),
1885 "Ssid",
1886 SsidValue(ssid),
1887 /* setting blockack threshold for sta's BE queue */
1888 "BE_BlockAckThreshold",
1889 UintegerValue(2),
1890 "ActiveProbing",
1891 BooleanValue(false));
1892
1893 NetDeviceContainer staDevices;
1894 staDevices = wifi.Install(phy, mac, wifiStaNode);
1895
1896 mac.SetType("ns3::ApWifiMac",
1897 "BE_MaxAmsduSize",
1898 UintegerValue(0),
1899 "BE_MaxAmpduSize",
1900 UintegerValue(0),
1901 "Ssid",
1902 SsidValue(ssid),
1903 "BeaconGeneration",
1904 BooleanValue(true));
1905
1906 NetDeviceContainer apDevices;
1907 apDevices = wifi.Install(phy, mac, wifiApNode);
1908
1909 MobilityHelper mobility;
1910 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
1911
1912 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
1913 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
1914 mobility.SetPositionAllocator(positionAlloc);
1915
1916 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1917 mobility.Install(wifiApNode);
1918 mobility.Install(wifiStaNode);
1919
1920 Ptr<WifiNetDevice> ap_device = DynamicCast<WifiNetDevice>(apDevices.Get(0));
1921 Ptr<WifiNetDevice> sta_device = DynamicCast<WifiNetDevice>(staDevices.Get(0));
1922
1923 // Disable A-MPDU aggregation
1924 sta_device->GetMac()->SetAttribute("BE_MaxAmpduSize", UintegerValue(0));
1925 TxopDurationTracer txopTracer;
1926
1927 if (m_txop)
1928 {
1929 PointerValue ptr;
1930 sta_device->GetMac()->GetAttribute("BE_Txop", ptr);
1931 ptr.Get<QosTxop>()->TraceConnectWithoutContext(
1932 "TxopTrace",
1934
1935 // set the TXOP limit on BE AC
1936 ap_device->GetMac()->GetAttribute("BE_Txop", ptr);
1937 ptr.Get<QosTxop>()->SetTxopLimit(MicroSeconds(4800));
1938 }
1939
1940 PacketSocketAddress socket;
1941 socket.SetSingleDevice(sta_device->GetIfIndex());
1942 socket.SetPhysicalAddress(ap_device->GetAddress());
1943 socket.SetProtocol(1);
1944
1945 // give packet socket powers to nodes.
1946 PacketSocketHelper packetSocket;
1947 packetSocket.Install(wifiStaNode);
1948 packetSocket.Install(wifiApNode);
1949
1950 // the first client application generates a single packet, which is sent
1951 // with the normal ack policy because there are no other packets queued
1952 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient>();
1953 client1->SetAttribute("PacketSize", UintegerValue(1400));
1954 client1->SetAttribute("MaxPackets", UintegerValue(1));
1955 client1->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
1956 client1->SetRemote(socket);
1957 wifiStaNode.Get(0)->AddApplication(client1);
1958 client1->SetStartTime(Seconds(1));
1959 client1->SetStopTime(Seconds(3.0));
1960
1961 // the second client application generates 13 packets. Even if when the first
1962 // packet is queued the queue is empty, the first packet is not transmitted
1963 // immediately, but the EDCAF waits for the next slot boundary. At that time,
1964 // other packets have been queued, hence a BA agreement is established first.
1965 Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient>();
1966 client2->SetAttribute("PacketSize", UintegerValue(1400));
1967 client2->SetAttribute("MaxPackets", UintegerValue(13));
1968 client2->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
1969 client2->SetRemote(socket);
1970 wifiStaNode.Get(0)->AddApplication(client2);
1971 client2->SetStartTime(Seconds(1.5));
1972 client2->SetStopTime(Seconds(3.0));
1973
1974 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
1975 server->SetLocal(socket);
1976 wifiApNode.Get(0)->AddApplication(server);
1977 server->SetStartTime(Seconds(0.0));
1978 server->SetStopTime(Seconds(4.0));
1979
1980 Config::Connect("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
1982 Config::Connect("/NodeList/0/DeviceList/0/Phy/PhyTxBegin",
1984 Config::Connect("/NodeList/0/DeviceList/0/Phy/PhyRxBegin",
1986
1989
1991
1992 // The client applications generate 14 packets, so we expect that the wifi PHY
1993 // layer transmits 14 MPDUs, the server application receives 14 packets, and
1994 // two BARs are transmitted.
1995 NS_TEST_EXPECT_MSG_EQ(m_txTotal, 14, "Unexpected number of transmitted packets");
1996 NS_TEST_EXPECT_MSG_EQ(m_received, 14, "Unexpected number of received packets");
1997 NS_TEST_EXPECT_MSG_EQ(m_nBar, 2, "Unexpected number of Block Ack Requests");
1998 NS_TEST_EXPECT_MSG_EQ(m_nBa, 2, "Unexpected number of Block Ack Responses");
1999 if (m_txop)
2000 {
2001 NS_TEST_EXPECT_MSG_LT(txopTracer.m_max, MicroSeconds(4800), "TXOP duration exceeded!");
2002 NS_TEST_EXPECT_MSG_GT(txopTracer.m_max,
2003 MicroSeconds(3008),
2004 "The maximum TXOP duration is too short!");
2005 }
2006}
2007
2008/**
2009 * \ingroup wifi-test
2010 * \ingroup tests
2011 *
2012 * \brief Block Ack Test Suite
2013 */
2015{
2016 public:
2018};
2019
2021 : TestSuite("wifi-block-ack", Type::UNIT)
2022{
2023 AddTestCase(new PacketBufferingCaseA, TestCase::Duration::QUICK);
2024 AddTestCase(new PacketBufferingCaseB, TestCase::Duration::QUICK);
2025 AddTestCase(new OriginatorBlockAckWindowTest, TestCase::Duration::QUICK);
2026 AddTestCase(new CtrlBAckResponseHeaderTest, TestCase::Duration::QUICK);
2027 AddTestCase(new BlockAckRecipientBufferTest(0), TestCase::Duration::QUICK);
2028 AddTestCase(new BlockAckRecipientBufferTest(4090), TestCase::Duration::QUICK);
2029 AddTestCase(new MultiStaCtrlBAckResponseHeaderTest, TestCase::Duration::QUICK);
2030 AddTestCase(new BlockAckAggregationDisabledTest(false), TestCase::Duration::QUICK);
2031 AddTestCase(new BlockAckAggregationDisabledTest(true), TestCase::Duration::QUICK);
2032}
2033
2034static BlockAckTestSuite g_blockAckTestSuite; ///< the test suite
static BlockAckTestSuite g_blockAckTestSuite
the test suite
Test for Block Ack Policy with aggregation disabled.
uint16_t m_nBa
received BlockAck frames
uint16_t m_txTotal
transmitted data packets
void L7Receive(std::string context, Ptr< const Packet > p, const Address &adr)
Function to trace packets received by the server application.
BlockAckAggregationDisabledTest(bool txop)
Constructor.
uint16_t m_nBar
transmitted BlockAckReq frames
void Receive(std::string context, Ptr< const Packet > p, RxPowerWattPerChannelBand rxPowersW)
Callback invoked when PHY receives a packet.
void Transmit(std::string context, Ptr< const Packet > p, double power)
Callback invoked when PHY transmits a packet.
uint16_t m_txSinceBar
packets transmitted since the agreement was established or the last block ack was received
void DoRun() override
Implementation to actually run this TestCase.
bool m_txop
true for non-null TXOP limit
Test for recipient reordering buffer operations.
void DoRun() override
Implementation to actually run this TestCase.
uint16_t m_ssn
the Starting Sequence Number used to initialize WinStartB
BlockAckRecipientBufferTest(uint16_t ssn)
Constructor.
std::list< Ptr< const WifiMpdu > > m_fwup
list of MPDUs that have been forwarded up
void ForwardUp(Ptr< const WifiMpdu > mpdu, uint8_t linkId)
Keep track of MPDUs received on the given link that are forwarded up.
Block Ack Test Suite.
Test for block ack header.
CtrlBAckResponseHeader m_blockAckHdr
block ack header
void DoRun() override
Implementation to actually run this TestCase.
Test for Multi-STA block ack header.
void DoRun() override
Implementation to actually run this TestCase.
Test for the originator block ack window.
void DoRun() override
Implementation to actually run this TestCase.
Packet Buffering Case A.
std::list< uint16_t > m_expectedBuffer
expected test buffer
void DoRun() override
Implementation to actually run this TestCase.
Packet Buffering Case B.
std::list< uint16_t > m_expectedBuffer
expected test buffer
void DoRun() override
Implementation to actually run this TestCase.
a polymophic address class
Definition: address.h:101
void SetStartingSequence(uint16_t seq)
Set starting sequence number.
void SetBufferSize(uint16_t bufferSize)
Set buffer size.
std::size_t GetWinSize() const
Get the window size.
uint16_t GetWinStart() const
Get the current winStart value.
uint16_t GetWinEnd() const
Get the current winEnd value.
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.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAck response.
Definition: ctrl-headers.h:203
void SetStartingSequence(uint16_t seq, std::size_t index=0)
For Block Ack variants other than Multi-STA Block Ack, set the starting sequence number to the given ...
bool IsPacketReceived(uint16_t seq, std::size_t index=0) const
Check if the packet with the given sequence number was acknowledged in this BlockAck response.
uint16_t GetStartingSequence(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the starting sequence number.
Mac48Address GetUnassociatedStaAddress(std::size_t index) const
For Multi-STA Block Acks, get the RA subfield of the Per AID TID Info subfield (with AID11 subfield e...
uint8_t GetTidInfo(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the TID_INFO subfield of the BA Control fi...
const std::vector< uint8_t > & GetBitmap(std::size_t index=0) const
Return a const reference to the bitmap from the BlockAck response header.
void ResetBitmap(std::size_t index=0)
Reset the bitmap to 0.
void SetType(BlockAckType type)
Set the block ack type.
BlockAckType GetType() const
Return the block ack type ID.
void SetReceivedPacket(uint16_t seq, std::size_t index=0)
Record in the bitmap that the packet with the given sequence number was received.
bool GetAckType(std::size_t index) const
For Multi-STA Block Acks, get the Ack Type subfield of the Per AID TID Info subfield identified by th...
uint16_t GetAid11(std::size_t index) const
For Multi-STA Block Acks, get the AID11 subfield of the Per AID TID Info subfield identified by the g...
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
an EUI-48 address
Definition: mac48-address.h:46
static Mac48Address Allocate()
Allocate a new Mac48Address.
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition: node.cc:164
Maintains the state and information about transmitted MPDUs with Ack Policy set to Block Ack for an o...
void NotifyDiscardedMpdu(Ptr< const WifiMpdu > mpdu)
Advance the transmit window beyond the MPDU that has been reported to be discarded.
uint16_t GetStartingSequence() const override
Return the starting sequence number of the transmit window, if a transmit window has been initialized...
BlockAckWindow m_txWindow
originator's transmit window
void NotifyTransmittedMpdu(Ptr< const WifiMpdu > mpdu)
Advance the transmit window so as to include the transmitted MPDU, if the latter is not an old packet...
void NotifyAckedMpdu(Ptr< const WifiMpdu > mpdu)
Record that the given MPDU has been acknowledged and advance the transmit window if possible.
void InitTxWindow()
Initialize the originator's transmit window by setting its size and starting sequence number equal to...
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
AttributeValue implementation for Pointer.
Definition: pointer.h:48
Ptr< T > Get() const
Definition: pointer.h:234
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:74
Maintains the scoreboard and the receive reordering buffer used by a recipient of a Block Ack agreeme...
void NotifyReceivedBar(uint16_t startingSequenceNumber)
Update both the scoreboard and the receive reordering buffer upon reception of a Block Ack Request.
void NotifyReceivedMpdu(Ptr< const WifiMpdu > mpdu)
Update both the scoreboard and the receive reordering buffer upon reception of the given MPDU.
void SetMacRxMiddle(const Ptr< MacRxMiddle > rxMiddle)
Set the MAC RX Middle to use.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Definition: ssid.h:96
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1413
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
Implements the IEEE 802.11 MAC header.
bool IsBlockAckReq() const
Return true if the header is a BlockAckRequest header.
void SetSequenceNumber(uint16_t seq)
Set the sequence number of the header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
bool IsBlockAck() const
Return true if the header is a BlockAck header.
virtual void SetType(WifiMacType type, bool resetToDsFromDs=true)
Set Type/Subtype values with the correct values depending on the given type.
void SetQosTid(uint8_t tid)
Set the TID for the QoS header.
bool IsQosBlockAck() const
Return if the QoS Ack policy is Block Ack.
bool IsQosData() const
Return true if the Type is DATA and Subtype is one of the possible values for QoS Data.
create MAC layers for a ns3::WifiNetDevice.
manage and create wifi channel objects for the YANS model.
static YansWifiChannelHelper Default()
Create a channel helper in a default working state.
Make it easy to create and manage PHY objects for the YANS model.
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:894
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:978
#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:145
#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:791
#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:957
#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:252
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
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:171
@ WIFI_STANDARD_80211n
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
@ WIFI_MAC_QOSDATA
static constexpr uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition: wifi-utils.h:185
std::map< WifiSpectrumBandInfo, double > RxPowerWattPerChannelBand
A map of the received power (Watts) for each band.
Definition: phy-entity.h:77
Keeps the maximum duration among all TXOPs.
void Trace(Time startTime, Time duration, uint8_t linkId)
Callback for the TxopTrace trace.
The different BlockAck variants.
Variant m_variant
Block Ack variant.
std::vector< uint8_t > m_bitmapLen
Length (bytes) of included bitmaps.