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/attribute-container.h"
22#include "ns3/boolean.h"
23#include "ns3/config.h"
24#include "ns3/ctrl-headers.h"
25#include "ns3/double.h"
26#include "ns3/mac-rx-middle.h"
27#include "ns3/mobility-helper.h"
28#include "ns3/originator-block-ack-agreement.h"
29#include "ns3/packet-socket-client.h"
30#include "ns3/packet-socket-helper.h"
31#include "ns3/packet-socket-server.h"
32#include "ns3/packet.h"
33#include "ns3/pointer.h"
34#include "ns3/qos-txop.h"
35#include "ns3/qos-utils.h"
36#include "ns3/recipient-block-ack-agreement.h"
37#include "ns3/string.h"
38#include "ns3/test.h"
39#include "ns3/wifi-mac-header.h"
40#include "ns3/wifi-mpdu.h"
41#include "ns3/wifi-net-device.h"
42#include "ns3/yans-wifi-helper.h"
43
44#include <list>
45
46using namespace ns3;
47
48/**
49 * \ingroup wifi-test
50 * \ingroup tests
51 *
52 * \brief Packet Buffering Case A
53 *
54 * This simple test verifies the correctness of buffering for packets received
55 * under block ack. In order to completely understand this example is important to cite
56 * section 9.10.3 in IEEE802.11 standard:
57 *
58 * "[...] The sequence number space is considered divided into two parts, one of which
59 * is “old” and one of which is “new” by means of a boundary created by adding half the
60 * sequence number range to the current start of receive window (modulo 2^12)."
61 */
62//-------------------------------------------------------------------------------------
63
64/* ----- = old packets
65 * +++++ = new packets
66 *
67 * CASE A: startSeq < endSeq
68 * - - +
69 * initial buffer state: 0 16 56000
70 *
71 *
72 * 0 4095
73 * |------|++++++++++++++++|-----|
74 * ^ ^
75 * | startSeq | endSeq = 4000
76 *
77 * first received packet's sequence control = 64016 (seqNum = 4001, fragNum = 0) -
78 * second received packet's sequence control = 63984 (seqNum = 3999, fragNum = 0) +
79 * 4001 is older seq number so this packet should be inserted at the buffer's begin.
80 * 3999 is previous element of older of new packets: it should be inserted at the end of buffer.
81 *
82 * expected buffer state: 64016 0 16 56000 63984
83 *
84 */
86{
87 public:
89 ~PacketBufferingCaseA() override;
90
91 private:
92 void DoRun() override;
93 std::list<uint16_t> m_expectedBuffer; ///< expected test buffer
94};
95
97 : TestCase("Check correct order of buffering when startSequence < endSeq")
98{
99 m_expectedBuffer.push_back(64016);
100 m_expectedBuffer.push_back(0);
101 m_expectedBuffer.push_back(16);
102 m_expectedBuffer.push_back(56000);
103 m_expectedBuffer.push_back(63984);
104}
105
107{
108}
109
110void
112{
113 std::list<uint16_t> m_buffer;
114 std::list<uint16_t>::iterator i;
115 std::list<uint16_t>::iterator j;
116 m_buffer.push_back(0);
117 m_buffer.push_back(16);
118 m_buffer.push_back(56000);
119
120 uint16_t endSeq = 4000;
121
122 uint16_t receivedSeq = 4001 * 16;
123 uint32_t mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
124 /* cycle to right position for this packet */
125 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
126 {
127 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
128 {
129 // position found
130 break;
131 }
132 }
133 m_buffer.insert(i, receivedSeq);
134
135 receivedSeq = 3999 * 16;
136 mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
137 /* cycle to right position for this packet */
138 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
139 {
140 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
141 {
142 // position found
143 break;
144 }
145 }
146 m_buffer.insert(i, receivedSeq);
147
148 for (i = m_buffer.begin(), j = m_expectedBuffer.begin(); i != m_buffer.end(); i++, j++)
149 {
150 NS_TEST_EXPECT_MSG_EQ(*i, *j, "error in buffer order");
151 }
152}
153
154/**
155 * \ingroup wifi-test
156 * \ingroup tests
157 *
158 * \brief Packet Buffering Case B
159 *
160 * ----- = old packets
161 * +++++ = new packets
162 *
163 * CASE B: startSeq > endSeq
164 * - + +
165 * initial buffer state: 256 64000 16
166 *
167 *
168 * 0 4095
169 * |++++++|----------------|++++++|
170 * ^ ^
171 * | endSeq = 10 | startSeq
172 *
173 * first received packet's sequence control = 240 (seqNum = 15, fragNum = 0) -
174 * second received packet's sequence control = 241 (seqNum = 15, fragNum = 1) -
175 * third received packet's sequence control = 64800 (seqNum = 4050, fragNum = 0) +
176 * 240 is an old packet should be inserted at the buffer's begin.
177 * 241 is an old packet: second segment of the above packet.
178 * 4050 is a new packet: it should be inserted between 64000 and 16.
179 *
180 * expected buffer state: 240 241 256 64000 64800 16
181 *
182 */
184{
185 public:
187 ~PacketBufferingCaseB() override;
188
189 private:
190 void DoRun() override;
191 std::list<uint16_t> m_expectedBuffer; ///< expected test buffer
192};
193
195 : TestCase("Check correct order of buffering when startSequence > endSeq")
196{
197 m_expectedBuffer.push_back(240);
198 m_expectedBuffer.push_back(241);
199 m_expectedBuffer.push_back(256);
200 m_expectedBuffer.push_back(64000);
201 m_expectedBuffer.push_back(64800);
202 m_expectedBuffer.push_back(16);
203}
204
206{
207}
208
209void
211{
212 std::list<uint16_t> m_buffer;
213 std::list<uint16_t>::iterator i;
214 std::list<uint16_t>::iterator j;
215 m_buffer.push_back(256);
216 m_buffer.push_back(64000);
217 m_buffer.push_back(16);
218
219 uint16_t endSeq = 10;
220
221 uint16_t receivedSeq = 15 * 16;
222 uint32_t mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
223 /* cycle to right position for this packet */
224 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
225 {
226 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
227 {
228 // position found
229 break;
230 }
231 }
232 m_buffer.insert(i, receivedSeq);
233
234 receivedSeq = 15 * 16 + 1;
235 mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
236 /* cycle to right position for this packet */
237 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
238 {
239 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
240 {
241 // position found
242 break;
243 }
244 }
245 m_buffer.insert(i, receivedSeq);
246
247 receivedSeq = 4050 * 16;
248 mappedSeq = QosUtilsMapSeqControlToUniqueInteger(receivedSeq, endSeq);
249 /* cycle to right position for this packet */
250 for (i = m_buffer.begin(); i != m_buffer.end(); i++)
251 {
252 if (QosUtilsMapSeqControlToUniqueInteger((*i), endSeq) >= mappedSeq)
253 {
254 // position found
255 break;
256 }
257 }
258 m_buffer.insert(i, receivedSeq);
259
260 for (i = m_buffer.begin(), j = m_expectedBuffer.begin(); i != m_buffer.end(); i++, j++)
261 {
262 NS_TEST_EXPECT_MSG_EQ(*i, *j, "error in buffer order");
263 }
264}
265
266/**
267 * \ingroup wifi-test
268 * \ingroup tests
269 *
270 * \brief Test for the originator block ack window
271 */
273{
274 public:
276
277 private:
278 void DoRun() override;
279};
280
282 : TestCase("Check the correctness of the originator block ack window")
283{
284}
285
286void
288{
289 uint16_t winSize = 16;
290 uint16_t startingSeq = 4090;
291
292 OriginatorBlockAckAgreement agreement(Mac48Address("00:00:00:00:00:01"), 0);
293 agreement.SetBufferSize(winSize);
294 agreement.SetStartingSequence(startingSeq);
295 agreement.InitTxWindow();
296
297 NS_TEST_EXPECT_MSG_EQ(agreement.m_txWindow.GetWinSize(), winSize, "Incorrect window size");
298 NS_TEST_EXPECT_MSG_EQ(agreement.m_txWindow.GetWinStart(), startingSeq, "Incorrect winStart");
299 // check that all the elements in the window are cleared
300 for (uint16_t i = 0; i < winSize; i++)
301 {
303 false,
304 "Not all flags are cleared after initialization");
305 }
306
307 // Notify the acknowledgment of 5 packets
308 WifiMacHeader hdr;
310 Ptr<WifiMpdu> mpdu = Create<WifiMpdu>(Create<Packet>(), hdr);
311 uint16_t seqNumber = startingSeq;
312 mpdu->GetHeader().SetSequenceNumber(seqNumber);
313 agreement.NotifyAckedMpdu(mpdu);
314
315 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
316 agreement.NotifyAckedMpdu(mpdu);
317
318 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
319 agreement.NotifyAckedMpdu(mpdu);
320
321 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
322 agreement.NotifyAckedMpdu(mpdu);
323
324 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
325 agreement.NotifyAckedMpdu(mpdu);
326
327 // the current window must look like this:
328 //
329 // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
330 // ^
331 // |
332 // HEAD
333
334 startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
336 startingSeq,
337 "Incorrect starting sequence after 5 acknowledgments");
338 for (uint16_t i = 0; i < winSize; i++)
339 {
341 false,
342 "Not all flags are cleared after 5 acknowledgments");
343 }
344
345 // the next MPDU is not acknowledged, hence the window is blocked while the
346 // subsequent 4 MPDUs are acknowledged
347 ++seqNumber %= SEQNO_SPACE_SIZE;
348 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
349 agreement.NotifyAckedMpdu(mpdu);
350
351 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
352 agreement.NotifyAckedMpdu(mpdu);
353
354 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
355 agreement.NotifyAckedMpdu(mpdu);
356
357 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
358 agreement.NotifyAckedMpdu(mpdu);
359
360 // the current window must look like this:
361 //
362 // |0|0|0|0|0|0|1|1|1|1|0|0|0|0|0|0|
363 // ^
364 // |
365 // HEAD
366
368 startingSeq,
369 "Incorrect starting sequence after 1 unacknowledged MPDU");
371 false,
372 "Incorrect flag after 1 unacknowledged MPDU");
374 true,
375 "Incorrect flag after 1 unacknowledged MPDU");
377 true,
378 "Incorrect flag after 1 unacknowledged MPDU");
380 true,
381 "Incorrect flag after 1 unacknowledged MPDU");
383 true,
384 "Incorrect flag after 1 unacknowledged MPDU");
385 for (uint16_t i = 5; i < winSize; i++)
386 {
388 false,
389 "Incorrect flag after 1 unacknowledged MPDU");
390 }
391
392 // the missing MPDU is now acknowledged; the window moves forward and the starting
393 // sequence number is the one of the first unacknowledged MPDU
394 mpdu->GetHeader().SetSequenceNumber(startingSeq);
395 agreement.NotifyAckedMpdu(mpdu);
396
397 // the current window must look like this:
398 //
399 // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
400 // ^
401 // |
402 // HEAD
403
404 startingSeq = (seqNumber + 1) % SEQNO_SPACE_SIZE;
406 startingSeq,
407 "Incorrect starting sequence after acknowledgment of missing MPDU");
408 for (uint16_t i = 0; i < winSize; i++)
409 {
411 false,
412 "Not all flags are cleared after acknowledgment of missing MPDU");
413 }
414
415 // Now, create a hole of 3 MPDUs before 4 acknowledged MPDUs, another hole of 2 MPDUs before 3
416 // acknowledged MPDUs
417 seqNumber = (seqNumber + 4) % SEQNO_SPACE_SIZE;
418 mpdu->GetHeader().SetSequenceNumber(seqNumber);
419 agreement.NotifyAckedMpdu(mpdu);
420
421 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
422 agreement.NotifyAckedMpdu(mpdu);
423
424 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
425 agreement.NotifyAckedMpdu(mpdu);
426
427 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
428 agreement.NotifyAckedMpdu(mpdu);
429
430 seqNumber = (seqNumber + 3) % SEQNO_SPACE_SIZE;
431 mpdu->GetHeader().SetSequenceNumber(seqNumber);
432 agreement.NotifyAckedMpdu(mpdu);
433
434 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
435 agreement.NotifyAckedMpdu(mpdu);
436
437 mpdu->GetHeader().SetSequenceNumber(++seqNumber %= SEQNO_SPACE_SIZE);
438 agreement.NotifyAckedMpdu(mpdu);
439
440 // the current window must look like this:
441 //
442 // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
443 // ^
444 // |
445 // HEAD
446
448 startingSeq,
449 "Incorrect starting sequence after 3 unacknowledged MPDUs");
451 false,
452 "Incorrect flag after 3 unacknowledged MPDUs");
454 false,
455 "Incorrect flag after 3 unacknowledged MPDUs");
457 false,
458 "Incorrect flag after 3 unacknowledged MPDUs");
460 true,
461 "Incorrect flag after 3 unacknowledged MPDUs");
463 true,
464 "Incorrect flag after 3 unacknowledged MPDUs");
466 true,
467 "Incorrect flag after 3 unacknowledged MPDUs");
469 true,
470 "Incorrect flag after 3 unacknowledged MPDUs");
472 false,
473 "Incorrect flag after 3 unacknowledged MPDUs");
475 false,
476 "Incorrect flag after 3 unacknowledged MPDUs");
478 true,
479 "Incorrect flag after 3 unacknowledged MPDUs");
480 NS_TEST_EXPECT_MSG_EQ(agreement.m_txWindow.At(10),
481 true,
482 "Incorrect flag after 3 unacknowledged MPDUs");
483 NS_TEST_EXPECT_MSG_EQ(agreement.m_txWindow.At(11),
484 true,
485 "Incorrect flag after 3 unacknowledged MPDUs");
486 for (uint16_t i = 12; i < winSize; i++)
487 {
489 false,
490 "Incorrect flag after 3 unacknowledged MPDUs");
491 }
492
493 // the transmission of an MPDU beyond the current window (by 2 positions) is
494 // notified, hence the window moves forward 2 positions
495 seqNumber = (agreement.m_txWindow.GetWinEnd() + 2) % SEQNO_SPACE_SIZE;
496 mpdu->GetHeader().SetSequenceNumber(seqNumber);
497 agreement.NotifyTransmittedMpdu(mpdu);
498
499 // the current window must look like this:
500 //
501 // |1|0|0|1|1|1|0|0|0|0|0|0|0|1|1|1|
502 // ^
503 // |
504 // HEAD
505
506 startingSeq = (startingSeq + 2) % SEQNO_SPACE_SIZE;
508 agreement.GetStartingSequence(),
509 startingSeq,
510 "Incorrect starting sequence after transmitting an MPDU beyond the current window");
512 false,
513 "Incorrect flag after transmitting an MPDU beyond the current window");
515 true,
516 "Incorrect flag after transmitting an MPDU beyond the current window");
518 true,
519 "Incorrect flag after transmitting an MPDU beyond the current window");
521 true,
522 "Incorrect flag after transmitting an MPDU beyond the current window");
524 true,
525 "Incorrect flag after transmitting an MPDU beyond the current window");
527 false,
528 "Incorrect flag after transmitting an MPDU beyond the current window");
530 false,
531 "Incorrect flag after transmitting an MPDU beyond the current window");
533 true,
534 "Incorrect flag after transmitting an MPDU beyond the current window");
536 true,
537 "Incorrect flag after transmitting an MPDU beyond the current window");
539 true,
540 "Incorrect flag after transmitting an MPDU beyond the current window");
541 for (uint16_t i = 10; i < winSize; i++)
542 {
544 agreement.m_txWindow.At(i),
545 false,
546 "Incorrect flag after transmitting an MPDU beyond the current window");
547 }
548
549 // another MPDU is transmitted beyond the current window. Now, the window advances
550 // until the first unacknowledged MPDU
551 seqNumber = (agreement.m_txWindow.GetWinEnd() + 1) % SEQNO_SPACE_SIZE;
552 mpdu->GetHeader().SetSequenceNumber(seqNumber);
553 agreement.NotifyTransmittedMpdu(mpdu);
554
555 // the current window must look like this:
556 //
557 // |0|0|0|1|1|1|0|0|0|0|0|0|0|0|0|0|
558 // ^
559 // |
560 // HEAD
561
562 startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
564 agreement.GetStartingSequence(),
565 startingSeq,
566 "Incorrect starting sequence after transmitting another MPDU beyond the current window");
568 agreement.m_txWindow.At(0),
569 false,
570 "Incorrect flag after transmitting another MPDU beyond the current window");
572 agreement.m_txWindow.At(1),
573 false,
574 "Incorrect flag after transmitting another MPDU beyond the current window");
576 agreement.m_txWindow.At(2),
577 true,
578 "Incorrect flag after transmitting another MPDU beyond the current window");
580 agreement.m_txWindow.At(3),
581 true,
582 "Incorrect flag after transmitting another MPDU beyond the current window");
584 agreement.m_txWindow.At(4),
585 true,
586 "Incorrect flag after transmitting another MPDU beyond the current window");
587 for (uint16_t i = 5; i < winSize; i++)
588 {
590 agreement.m_txWindow.At(i),
591 false,
592 "Incorrect flag after transmitting another MPDU beyond the current window");
593 }
594
595 // the MPDU next to winStart is discarded, hence the window advances to make it an old packet.
596 // Since the subsequent MPDUs have been acknowledged, the window advances further.
597 seqNumber = (startingSeq + 1) % SEQNO_SPACE_SIZE;
598 mpdu->GetHeader().SetSequenceNumber(seqNumber);
599 agreement.NotifyDiscardedMpdu(mpdu);
600
601 // the current window must look like this:
602 //
603 // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
604 // ^
605 // |
606 // HEAD
607
608 startingSeq = (startingSeq + 5) % SEQNO_SPACE_SIZE;
610 startingSeq,
611 "Incorrect starting sequence after discarding an MPDU");
612 for (uint16_t i = 0; i < winSize; i++)
613 {
615 false,
616 "Incorrect flag after discarding an MPDU");
617 }
618
619 // Finally, check that the window correctly advances when the MPDU with the starting sequence
620 // number is acknowledged after being the only unacknowledged MPDU
621 for (uint16_t i = 1; i < winSize; i++)
622 {
623 mpdu->GetHeader().SetSequenceNumber((startingSeq + i) % SEQNO_SPACE_SIZE);
624 agreement.NotifyAckedMpdu(mpdu);
625 }
626
627 // the current window must look like this:
628 //
629 // |1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|
630 // ^
631 // |
632 // HEAD
633
635 startingSeq,
636 "Incorrect starting sequence after acknowledging all but the first MPDU");
638 false,
639 "Incorrect flag after acknowledging all but the first MPDU");
640 for (uint16_t i = 1; i < winSize; i++)
641 {
643 true,
644 "Incorrect flag after acknowledging all but the first MPDU");
645 }
646
647 // acknowledge the first MPDU
648 mpdu->GetHeader().SetSequenceNumber(startingSeq % SEQNO_SPACE_SIZE);
649 agreement.NotifyAckedMpdu(mpdu);
650
651 // the current window must look like this:
652 //
653 // |0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
654 // ^
655 // |
656 // HEAD
657
658 startingSeq = (startingSeq + winSize) % SEQNO_SPACE_SIZE;
660 startingSeq,
661 "Incorrect starting sequence after acknowledging the first MPDU");
662 for (uint16_t i = 0; i < winSize; i++)
663 {
665 false,
666 "Incorrect flag after acknowledging the first MPDU");
667 }
668}
669
670/**
671 * \ingroup wifi-test
672 * \ingroup tests
673 *
674 * \brief Test for block ack header
675 */
677{
678 public:
680
681 private:
682 void DoRun() override;
684};
685
687 : TestCase("Check the correctness of block ack compressed bitmap")
688{
689}
690
691void
693{
695
696 // Case 1: startSeq < endSeq
697 // 179 242
699 for (uint16_t i = 179; i < 220; i++)
700 {
702 }
703 for (uint16_t i = 225; i <= 242; i++)
704 {
706 }
707 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[0], 0xff, "error in compressed bitmap");
708 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[1], 0xff, "error in compressed bitmap");
709 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[2], 0xff, "error in compressed bitmap");
710 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[3], 0xff, "error in compressed bitmap");
711 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[4], 0xff, "error in compressed bitmap");
712 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[5], 0xc1, "error in compressed bitmap");
713 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[6], 0xff, "error in compressed bitmap");
714 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[7], 0xff, "error in compressed bitmap");
716 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[0], 0xff, "error in compressed bitmap");
717 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[1], 0xff, "error in compressed bitmap");
718 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[2], 0xff, "error in compressed bitmap");
719 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[3], 0xff, "error in compressed bitmap");
720 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[4], 0xff, "error in compressed bitmap");
721 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[5], 0xc1, "error in compressed bitmap");
722 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[6], 0xff, "error in compressed bitmap");
723 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[7], 0xff, "error in compressed bitmap");
724 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(220), false, "error in compressed bitmap");
725 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(225), true, "error in compressed bitmap");
727 false,
728 "error in compressed bitmap");
729
731
732 // Case 2: startSeq > endSeq
733 // 4090 58
735 for (uint16_t i = 4090; i != 10; i = (i + 1) % 4096)
736 {
738 }
739 for (uint16_t i = 22; i < 25; i++)
740 {
742 }
743 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[0], 0xff, "error in compressed bitmap");
744 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[1], 0xff, "error in compressed bitmap");
745 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[2], 0x00, "error in compressed bitmap");
746 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[3], 0x70, "error in compressed bitmap");
747 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[4], 0x00, "error in compressed bitmap");
748 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[5], 0x00, "error in compressed bitmap");
749 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[6], 0x00, "error in compressed bitmap");
750 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[7], 0x00, "error in compressed bitmap");
752 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[0], 0xff, "error in compressed bitmap");
753 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[1], 0xff, "error in compressed bitmap");
754 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[2], 0x00, "error in compressed bitmap");
755 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[3], 0x70, "error in compressed bitmap");
756 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[4], 0x00, "error in compressed bitmap");
757 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[5], 0x00, "error in compressed bitmap");
758 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[6], 0x00, "error in compressed bitmap");
759 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.GetBitmap()[7], 0x00, "error in compressed bitmap");
760 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(4090), true, "error in compressed bitmap");
761 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(4095), true, "error in compressed bitmap");
762 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(10), false, "error in compressed bitmap");
763 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(35), false, "error in compressed bitmap");
764 NS_TEST_EXPECT_MSG_EQ(m_blockAckHdr.IsPacketReceived(80), false, "error in compressed bitmap");
765}
766
767/**
768 * \ingroup wifi-test
769 * \ingroup tests
770 *
771 * \brief Test for recipient reordering buffer operations
772 */
774{
775 public:
776 /**
777 * \brief Constructor
778 * \param ssn the Starting Sequence Number used to initialize WinStartB
779 */
780 BlockAckRecipientBufferTest(uint16_t ssn);
782
783 void DoRun() override;
784
785 /**
786 * Keep track of MPDUs received on the given link that are forwarded up.
787 *
788 * \param mpdu an MPDU that is forwarded up
789 * \param linkId the ID of the given link
790 */
791 void ForwardUp(Ptr<const WifiMpdu> mpdu, uint8_t linkId);
792
793 private:
794 uint16_t m_ssn; //!< the Starting Sequence Number used to initialize WinStartB
795 std::list<Ptr<const WifiMpdu>> m_fwup; //!< list of MPDUs that have been forwarded up
796};
797
799 : TestCase("Test case for Block Ack recipient reordering buffer operations"),
800 m_ssn(ssn)
801{
802}
803
805{
806}
807
808void
810{
811 m_fwup.push_back(mpdu);
812}
813
814void
816{
817 Ptr<MacRxMiddle> rxMiddle = Create<MacRxMiddle>();
818 rxMiddle->SetForwardCallback(MakeCallback(&BlockAckRecipientBufferTest::ForwardUp, this));
819
820 RecipientBlockAckAgreement agreement(Mac48Address::Allocate() /* originator */,
821 true /* amsduSupported */,
822 0 /* tid */,
823 10 /* bufferSize */,
824 0 /* timeout */,
825 m_ssn,
826 true /* htSupported */);
827 agreement.SetMacRxMiddle(rxMiddle);
828
829 WifiMacHeader hdr;
832 hdr.SetQosTid(0);
833
834 // Notify the reception of an MPDU with SN = SSN.
836 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
837
838 // This MPDU is forwarded up and WinStartB is set to SSN + 1.
839 NS_TEST_ASSERT_MSG_EQ(m_fwup.size(), 1, "MPDU with SN=SSN must have been forwarded up");
840 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
841 m_ssn,
842 "The MPDU forwarded up is not the expected one");
843
844 m_fwup.clear();
845
846 // Notify the reception of MPDUs with SN = SSN + {4, 2, 5, 3, 10, 7}
847 // Recipient buffer: | |X|X|X|X| |X| | |X|
848 // ^
849 // |
850 // SSN + 1
852 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
854 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
856 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
858 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
860 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
862 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
863
864 // No MPDU is forwarded up because the one with SN = SSN + 1 is missing
865 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
866
867 // Notify the reception of an "old" MPDU (SN = SSN)
869 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
870
871 // No MPDU is forwarded up
872 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
873
874 // Notify the reception of a duplicate MPDU (SN = SSN + 2)
876 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(10), hdr));
877
878 // No MPDU is forwarded up
879 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
880
881 // Notify the reception of an MPDU with SN = SSN + 1
882 // Recipient buffer: |X|X|X|X|X| |X| | |X|
883 // ^
884 // |
885 // SSN + 1
887 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
888
889 // All the MPDUs with SN = SSN + {1, 2, 3, 4, 5} must have been forwarded up in order
890 NS_TEST_ASSERT_MSG_EQ(m_fwup.size(), 5, "5 MPDUs must have been forwarded up");
891
892 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
893 (m_ssn + 1) % SEQNO_SPACE_SIZE,
894 "The MPDU forwarded up is not the expected one");
895 m_fwup.pop_front();
896
897 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
898 (m_ssn + 2) % SEQNO_SPACE_SIZE,
899 "The MPDU forwarded up is not the expected one");
900 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetPacketSize(),
901 0,
902 "The MPDU forwarded up is not the expected one");
903 m_fwup.pop_front();
904
905 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
906 (m_ssn + 3) % SEQNO_SPACE_SIZE,
907 "The MPDU forwarded up is not the expected one");
908 m_fwup.pop_front();
909
910 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
911 (m_ssn + 4) % SEQNO_SPACE_SIZE,
912 "The MPDU forwarded up is not the expected one");
913 m_fwup.pop_front();
914
915 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
916 (m_ssn + 5) % SEQNO_SPACE_SIZE,
917 "The MPDU forwarded up is not the expected one");
918 m_fwup.pop_front();
919
920 // Recipient buffer: | |X| | |X| | | | | |
921 // ^ ^
922 // | |
923 // SSN + 6 SSN + 15
924 // Notify the reception of an MPDU beyond the current window (SN = SSN + 17)
926 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
927
928 // WinStartB is set to SSN + 8 (so that WinEndB = SSN + 17). The MPDU with
929 // SN = SSN + 7 is forwarded up, irrespective of the missed reception of the
930 // MPDU with SN = SSN + 6
931 NS_TEST_ASSERT_MSG_EQ(m_fwup.size(), 1, "One MPDU must have been forwarded up");
932
933 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
934 (m_ssn + 7) % SEQNO_SPACE_SIZE,
935 "The MPDU forwarded up is not the expected one");
936 m_fwup.pop_front();
937
938 // Recipient buffer: | | |X| | | | | | |X|
939 // ^ ^
940 // | |
941 // SSN + 8 SSN + 17
942 // Notify the reception of a BlockAckReq with SSN = SSN + 7
943 agreement.NotifyReceivedBar((m_ssn + 7) % SEQNO_SPACE_SIZE);
944
945 // No MPDU is forwarded up
946 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
947
948 // Notify the reception of a BlockAckReq with SSN = SSN + 8
949 agreement.NotifyReceivedBar((m_ssn + 8) % SEQNO_SPACE_SIZE);
950
951 // No MPDU is forwarded up
952 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
953
954 // Notify the reception of MPDUs with SN = SSN + {9, 11}
955 // Recipient buffer: | |X|X|X| | | | | |X|
956 // ^ ^
957 // | |
958 // SSN + 8 SSN + 17
960 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
962 agreement.NotifyReceivedMpdu(Create<WifiMpdu>(Create<Packet>(), hdr));
963
964 // No MPDU is forwarded up because the one with SN = SSN + 8 is missing
965 NS_TEST_ASSERT_MSG_EQ(m_fwup.empty(), true, "No MPDU must have been forwarded up");
966
967 // Notify the reception of a BlockAckReq with SSN = SSN + 10
968 agreement.NotifyReceivedBar((m_ssn + 10) % SEQNO_SPACE_SIZE);
969
970 // Forward up buffered MPDUs with SN < SSN + 10 (the MPDU with SN = SSN + 9)
971 // and then buffered MPDUs with SN >= SSN + 10 until a hole is found (MPDUs
972 // with SN = SSN + 10 and SN = SSN + 11)
973 NS_TEST_ASSERT_MSG_EQ(m_fwup.size(), 3, "3 MPDUs must have been forwarded up");
974
975 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
976 (m_ssn + 9) % SEQNO_SPACE_SIZE,
977 "The MPDU forwarded up is not the expected one");
978 m_fwup.pop_front();
979
980 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
981 (m_ssn + 10) % SEQNO_SPACE_SIZE,
982 "The MPDU forwarded up is not the expected one");
983 m_fwup.pop_front();
984
985 NS_TEST_ASSERT_MSG_EQ(m_fwup.front()->GetHeader().GetSequenceNumber(),
986 (m_ssn + 11) % SEQNO_SPACE_SIZE,
987 "The MPDU forwarded up is not the expected one");
988 m_fwup.pop_front();
989
992}
993
994/**
995 * \ingroup wifi-test
996 * \ingroup tests
997 *
998 * \brief Test for Multi-STA block ack header
999 */
1001{
1002 public:
1004
1005 private:
1006 void DoRun() override;
1007};
1008
1010 : TestCase("Check the correctness of Multi-STA block ack")
1011{
1012}
1013
1014void
1016{
1017 // Create a Multi-STA Block Ack with 6 Per AID TID Info subfields
1018 BlockAckType baType(BlockAckType::MULTI_STA, {0, 4, 8, 16, 32, 8});
1019
1020 CtrlBAckResponseHeader blockAck;
1021 blockAck.SetType(baType);
1022
1023 /* 1st Per AID TID Info subfield */
1024 uint16_t aid1 = 100;
1025 bool ackType1 = true;
1026 uint8_t tid1 = 1;
1027
1028 blockAck.SetAid11(aid1, 0);
1029 blockAck.SetAckType(ackType1, 0);
1030 blockAck.SetTidInfo(tid1, 0);
1031
1032 /* 2nd Per AID TID Info subfield */
1033 uint16_t aid2 = 200;
1034 bool ackType2 = false;
1035 uint8_t tid2 = 2;
1036 uint16_t startSeq2 = 1000;
1037
1038 blockAck.SetAid11(aid2, 1);
1039 blockAck.SetAckType(ackType2, 1);
1040 blockAck.SetTidInfo(tid2, 1);
1041 blockAck.SetStartingSequence(startSeq2, 1);
1042 // 1st byte of the bitmap: 01010101
1043 for (uint16_t i = startSeq2; i < startSeq2 + 8; i += 2)
1044 {
1045 blockAck.SetReceivedPacket(i, 1);
1046 }
1047 // 2nd byte of the bitmap: 10101010
1048 for (uint16_t i = startSeq2 + 9; i < startSeq2 + 16; i += 2)
1049 {
1050 blockAck.SetReceivedPacket(i, 1);
1051 }
1052 // 3rd byte of the bitmap: 00000000
1053 // 4th byte of the bitmap: 11111111
1054 for (uint16_t i = startSeq2 + 24; i < startSeq2 + 32; i++)
1055 {
1056 blockAck.SetReceivedPacket(i, 1);
1057 }
1058
1059 /* 3rd Per AID TID Info subfield */
1060 uint16_t aid3 = 300;
1061 bool ackType3 = false;
1062 uint8_t tid3 = 3;
1063 uint16_t startSeq3 = 2000;
1064
1065 blockAck.SetAid11(aid3, 2);
1066 blockAck.SetAckType(ackType3, 2);
1067 blockAck.SetTidInfo(tid3, 2);
1068 blockAck.SetStartingSequence(startSeq3, 2);
1069 // 1st byte of the bitmap: 01010101
1070 for (uint16_t i = startSeq3; i < startSeq3 + 8; i += 2)
1071 {
1072 blockAck.SetReceivedPacket(i, 2);
1073 }
1074 // 2nd byte of the bitmap: 10101010
1075 for (uint16_t i = startSeq3 + 9; i < startSeq3 + 16; i += 2)
1076 {
1077 blockAck.SetReceivedPacket(i, 2);
1078 }
1079 // 3rd byte of the bitmap: 00000000
1080 // 4th byte of the bitmap: 11111111
1081 for (uint16_t i = startSeq3 + 24; i < startSeq3 + 32; i++)
1082 {
1083 blockAck.SetReceivedPacket(i, 2);
1084 }
1085 // 5th byte of the bitmap: 00001111
1086 for (uint16_t i = startSeq3 + 32; i < startSeq3 + 36; i++)
1087 {
1088 blockAck.SetReceivedPacket(i, 2);
1089 }
1090 // 6th byte of the bitmap: 11110000
1091 for (uint16_t i = startSeq3 + 44; i < startSeq3 + 48; i++)
1092 {
1093 blockAck.SetReceivedPacket(i, 2);
1094 }
1095 // 7th byte of the bitmap: 00000000
1096 // 8th byte of the bitmap: 11111111
1097 for (uint16_t i = startSeq3 + 56; i < startSeq3 + 64; i++)
1098 {
1099 blockAck.SetReceivedPacket(i, 2);
1100 }
1101
1102 /* 4th Per AID TID Info subfield */
1103 uint16_t aid4 = 400;
1104 bool ackType4 = false;
1105 uint8_t tid4 = 4;
1106 uint16_t startSeq4 = 3000;
1107
1108 blockAck.SetAid11(aid4, 3);
1109 blockAck.SetAckType(ackType4, 3);
1110 blockAck.SetTidInfo(tid4, 3);
1111 blockAck.SetStartingSequence(startSeq4, 3);
1112 // 1st byte of the bitmap: 01010101
1113 for (uint16_t i = startSeq4; i < startSeq4 + 8; i += 2)
1114 {
1115 blockAck.SetReceivedPacket(i, 3);
1116 }
1117 // 2nd byte of the bitmap: 10101010
1118 for (uint16_t i = startSeq4 + 9; i < startSeq4 + 16; i += 2)
1119 {
1120 blockAck.SetReceivedPacket(i, 3);
1121 }
1122 // 3rd byte of the bitmap: 00000000
1123 // 4th byte of the bitmap: 11111111
1124 for (uint16_t i = startSeq4 + 24; i < startSeq4 + 32; i++)
1125 {
1126 blockAck.SetReceivedPacket(i, 3);
1127 }
1128 // 5th byte of the bitmap: 00001111
1129 for (uint16_t i = startSeq4 + 32; i < startSeq4 + 36; i++)
1130 {
1131 blockAck.SetReceivedPacket(i, 3);
1132 }
1133 // 6th byte of the bitmap: 11110000
1134 for (uint16_t i = startSeq4 + 44; i < startSeq4 + 48; i++)
1135 {
1136 blockAck.SetReceivedPacket(i, 3);
1137 }
1138 // 7th byte of the bitmap: 00000000
1139 // 8th byte of the bitmap: 11111111
1140 for (uint16_t i = startSeq4 + 56; i < startSeq4 + 64; i++)
1141 {
1142 blockAck.SetReceivedPacket(i, 3);
1143 }
1144 // 9th byte of the bitmap: 00000000
1145 // 10th byte of the bitmap: 11111111
1146 for (uint16_t i = startSeq4 + 72; i < startSeq4 + 80; i++)
1147 {
1148 blockAck.SetReceivedPacket(i, 3);
1149 }
1150 // 11th byte of the bitmap: 00000000
1151 // 12th byte of the bitmap: 11111111
1152 for (uint16_t i = startSeq4 + 88; i < startSeq4 + 96; i++)
1153 {
1154 blockAck.SetReceivedPacket(i, 3);
1155 }
1156 // 13th byte of the bitmap: 00000000
1157 // 14th byte of the bitmap: 11111111
1158 for (uint16_t i = startSeq4 + 104; i < startSeq4 + 112; i++)
1159 {
1160 blockAck.SetReceivedPacket(i, 3);
1161 }
1162 // 15th byte of the bitmap: 00000000
1163 // 16th byte of the bitmap: 11111111
1164 for (uint16_t i = startSeq4 + 120; i < startSeq4 + 128; i++)
1165 {
1166 blockAck.SetReceivedPacket(i, 3);
1167 }
1168
1169 /* 5th Per AID TID Info subfield */
1170 uint16_t aid5 = 500;
1171 bool ackType5 = false;
1172 uint8_t tid5 = 5;
1173 uint16_t startSeq5 = 4000;
1174
1175 blockAck.SetAid11(aid5, 4);
1176 blockAck.SetAckType(ackType5, 4);
1177 blockAck.SetTidInfo(tid5, 4);
1178 blockAck.SetStartingSequence(startSeq5, 4);
1179 // 1st byte of the bitmap: 01010101
1180 for (int i = startSeq5; i < startSeq5 + 8; i += 2)
1181 {
1182 blockAck.SetReceivedPacket(i, 4);
1183 }
1184 // 2nd byte of the bitmap: 10101010
1185 for (int i = startSeq5 + 9; i < startSeq5 + 16; i += 2)
1186 {
1187 blockAck.SetReceivedPacket(i, 4);
1188 }
1189 // 3rd byte of the bitmap: 00000000
1190 // 4th byte of the bitmap: 11111111
1191 for (int i = startSeq5 + 24; i < startSeq5 + 32; i++)
1192 {
1193 blockAck.SetReceivedPacket(i, 4);
1194 }
1195 // 5th byte of the bitmap: 00001111
1196 for (int i = startSeq5 + 32; i < startSeq5 + 36; i++)
1197 {
1198 blockAck.SetReceivedPacket(i, 4);
1199 }
1200 // 6th byte of the bitmap: 11110000
1201 for (int i = startSeq5 + 44; i < startSeq5 + 48; i++)
1202 {
1203 blockAck.SetReceivedPacket(i, 4);
1204 }
1205 // 7th byte of the bitmap: 00000000
1206 // 8th byte of the bitmap: 11111111
1207 for (int i = startSeq5 + 56; i < startSeq5 + 64; i++)
1208 {
1209 blockAck.SetReceivedPacket(i, 4);
1210 }
1211 // 9th byte of the bitmap: 00000000
1212 // 10th byte of the bitmap: 11111111
1213 for (int i = startSeq5 + 72; i < startSeq5 + 80; i++)
1214 {
1215 blockAck.SetReceivedPacket(i, 4);
1216 }
1217 // 11th byte of the bitmap: 00000000
1218 // 12th byte of the bitmap: 11111111
1219 for (int i = startSeq5 + 88; i < startSeq5 + 96; i++)
1220 {
1221 blockAck.SetReceivedPacket(i, 4);
1222 }
1223 // 13th byte of the bitmap: 00000000
1224 // 14th byte of the bitmap: 11111111
1225 for (int i = (startSeq5 + 104) % 4096; i < (startSeq5 + 112) % 4096; i++)
1226 {
1227 blockAck.SetReceivedPacket(i, 4);
1228 }
1229 // 15th byte of the bitmap: 00000000
1230 // 16th byte of the bitmap: 11111111
1231 for (int i = (startSeq5 + 120) % 4096; i < (startSeq5 + 128) % 4096; i++)
1232 {
1233 blockAck.SetReceivedPacket(i, 4);
1234 }
1235 // 17th byte of the bitmap: 00000000
1236 // 18th byte of the bitmap: 11111111
1237 for (int i = (startSeq5 + 136) % 4096; i < (startSeq5 + 144) % 4096; i++)
1238 {
1239 blockAck.SetReceivedPacket(i, 4);
1240 }
1241 // 19th byte of the bitmap: 00000000
1242 // 20th byte of the bitmap: 11111111
1243 for (int i = (startSeq5 + 152) % 4096; i < (startSeq5 + 160) % 4096; i++)
1244 {
1245 blockAck.SetReceivedPacket(i, 4);
1246 }
1247 // 21th byte of the bitmap: 00000000
1248 // 22th byte of the bitmap: 11111111
1249 for (int i = (startSeq5 + 168) % 4096; i < (startSeq5 + 176) % 4096; i++)
1250 {
1251 blockAck.SetReceivedPacket(i, 4);
1252 }
1253 // 23th byte of the bitmap: 00000000
1254 // 24th byte of the bitmap: 11111111
1255 for (int i = (startSeq5 + 184) % 4096; i < (startSeq5 + 192) % 4096; i++)
1256 {
1257 blockAck.SetReceivedPacket(i, 4);
1258 }
1259 // 25th byte of the bitmap: 00000000
1260 // 26th byte of the bitmap: 11111111
1261 for (int i = (startSeq5 + 200) % 4096; i < (startSeq5 + 208) % 4096; i++)
1262 {
1263 blockAck.SetReceivedPacket(i, 4);
1264 }
1265 // 27th byte of the bitmap: 00000000
1266 // 28th byte of the bitmap: 11111111
1267 for (int i = (startSeq5 + 216) % 4096; i < (startSeq5 + 224) % 4096; i++)
1268 {
1269 blockAck.SetReceivedPacket(i, 4);
1270 }
1271 // 29th byte of the bitmap: 00000000
1272 // 30th byte of the bitmap: 11111111
1273 for (int i = (startSeq5 + 232) % 4096; i < (startSeq5 + 240) % 4096; i++)
1274 {
1275 blockAck.SetReceivedPacket(i, 4);
1276 }
1277 // 31th byte of the bitmap: 00000000
1278 // 32th byte of the bitmap: 11111111
1279 for (int i = (startSeq5 + 248) % 4096; i < (startSeq5 + 256) % 4096; i++)
1280 {
1281 blockAck.SetReceivedPacket(i, 4);
1282 }
1283
1284 /* 6th Per AID TID Info subfield */
1285 uint16_t aid6 = 2045;
1286 bool ackType6 = true;
1287 uint8_t tid6 = 6;
1288 Mac48Address address6("00:00:00:00:00:01");
1289
1290 blockAck.SetAid11(aid6, 5);
1291 blockAck.SetAckType(ackType6, 5);
1292 blockAck.SetTidInfo(tid6, 5);
1293 blockAck.SetUnassociatedStaAddress(address6, 5);
1294
1295 // Serialize the header
1296 Ptr<Packet> packet = Create<Packet>();
1297 packet->AddHeader(blockAck);
1298
1299 // Deserialize the header
1300 CtrlBAckResponseHeader blockAckCopy;
1301 packet->RemoveHeader(blockAckCopy);
1302
1303 // Check that the header has been correctly deserialized
1304 BlockAckType baTypeCopy = blockAckCopy.GetType();
1305
1308 "Different block ack variant");
1309 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen.size(), 6, "Different number of bitmaps");
1310 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[0], 0, "Different length of the first bitmap");
1311 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[1], 4, "Different length of the second bitmap");
1312 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[2], 8, "Different length of the third bitmap");
1313 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[3], 16, "Different length of the fourth bitmap");
1314 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[4], 32, "Different length of the fifth bitmap");
1315 NS_TEST_EXPECT_MSG_EQ(baTypeCopy.m_bitmapLen[5], 8, "Different length for the sixth bitmap");
1316
1317 /* Check 1st Per AID TID Info subfield */
1318 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(0),
1319 aid1,
1320 "Different AID for the first Per AID TID Info subfield");
1321 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(0),
1322 ackType1,
1323 "Different Ack Type for the first Per AID TID Info subfield");
1324 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(0),
1325 tid1,
1326 "Different TID for the first Per AID TID Info subfield");
1327
1328 /* Check 2nd Per AID TID Info subfield */
1329 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(1),
1330 aid2,
1331 "Different AID for the second Per AID TID Info subfield");
1332 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(1),
1333 ackType2,
1334 "Different Ack Type for the second Per AID TID Info subfield");
1335 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(1),
1336 tid2,
1337 "Different TID for the second Per AID TID Info subfield");
1339 blockAckCopy.GetStartingSequence(1),
1340 startSeq2,
1341 "Different starting sequence number for the second Per AID TID Info subfield");
1342
1343 auto& bitmap2 = blockAckCopy.GetBitmap(1);
1344 NS_TEST_EXPECT_MSG_EQ(bitmap2.size(),
1345 4,
1346 "Different bitmap length for the second Per AID TID Info subfield");
1348 bitmap2[0],
1349 0x55,
1350 "Error in the 1st byte of the bitmap for the second Per AID TID Info subfield");
1352 bitmap2[1],
1353 0xaa,
1354 "Error in the 2nd byte of the bitmap for the second Per AID TID Info subfield");
1356 bitmap2[2],
1357 0x00,
1358 "Error in the 3rd byte of the bitmap for the second Per AID TID Info subfield");
1360 bitmap2[3],
1361 0xff,
1362 "Error in the 4th byte of the bitmap for the second Per AID TID Info subfield");
1363
1364 /* Check 3rd Per AID TID Info subfield */
1365 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(2),
1366 aid3,
1367 "Different AID for the third Per AID TID Info subfield");
1368 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(2),
1369 ackType3,
1370 "Different Ack Type for the third Per AID TID Info subfield");
1371 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(2),
1372 tid3,
1373 "Different TID for the third Per AID TID Info subfield");
1375 blockAckCopy.GetStartingSequence(2),
1376 startSeq3,
1377 "Different starting sequence number for the third Per AID TID Info subfield");
1378
1379 auto& bitmap3 = blockAckCopy.GetBitmap(2);
1380 NS_TEST_EXPECT_MSG_EQ(bitmap3.size(),
1381 8,
1382 "Different bitmap length for the third Per AID TID Info subfield");
1384 bitmap3[0],
1385 0x55,
1386 "Error in the 1st byte of the bitmap for the third Per AID TID Info subfield");
1388 bitmap3[1],
1389 0xaa,
1390 "Error in the 2nd byte of the bitmap for the third Per AID TID Info subfield");
1392 bitmap3[2],
1393 0x00,
1394 "Error in the 3rd byte of the bitmap for the third Per AID TID Info subfield");
1396 bitmap3[3],
1397 0xff,
1398 "Error in the 4th byte of the bitmap for the third Per AID TID Info subfield");
1400 bitmap3[4],
1401 0x0f,
1402 "Error in the 5th byte of the bitmap for the third Per AID TID Info subfield");
1404 bitmap3[5],
1405 0xf0,
1406 "Error in the 6th byte of the bitmap for the third Per AID TID Info subfield");
1408 bitmap3[6],
1409 0x00,
1410 "Error in the 7th byte of the bitmap for the third Per AID TID Info subfield");
1412 bitmap3[7],
1413 0xff,
1414 "Error in the 8th byte of the bitmap for the third Per AID TID Info subfield");
1415
1416 /* Check 4th Per AID TID Info subfield */
1417 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(3),
1418 aid4,
1419 "Different AID for the fourth Per AID TID Info subfield");
1420 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(3),
1421 ackType4,
1422 "Different Ack Type for the fourth Per AID TID Info subfield");
1423 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(3),
1424 tid4,
1425 "Different TID for the fourth Per AID TID Info subfield");
1427 blockAckCopy.GetStartingSequence(3),
1428 startSeq4,
1429 "Different starting sequence number for the fourth Per AID TID Info subfield");
1430
1431 auto& bitmap4 = blockAckCopy.GetBitmap(3);
1432 NS_TEST_EXPECT_MSG_EQ(bitmap4.size(),
1433 16,
1434 "Different bitmap length for the fourth Per AID TID Info subfield");
1436 bitmap4[0],
1437 0x55,
1438 "Error in the 1st byte of the bitmap for the fourth Per AID TID Info subfield");
1440 bitmap4[1],
1441 0xaa,
1442 "Error in the 2nd byte of the bitmap for the fourth Per AID TID Info subfield");
1444 bitmap4[2],
1445 0x00,
1446 "Error in the 3rd byte of the bitmap for the fourth Per AID TID Info subfield");
1448 bitmap4[3],
1449 0xff,
1450 "Error in the 4th byte of the bitmap for the fourth Per AID TID Info subfield");
1452 bitmap4[4],
1453 0x0f,
1454 "Error in the 5th byte of the bitmap for the fourth Per AID TID Info subfield");
1456 bitmap4[5],
1457 0xf0,
1458 "Error in the 6th byte of the bitmap for the fourth Per AID TID Info subfield");
1460 bitmap4[6],
1461 0x00,
1462 "Error in the 7th byte of the bitmap for the fourth Per AID TID Info subfield");
1464 bitmap4[7],
1465 0xff,
1466 "Error in the 8th byte of the bitmap for the fourth Per AID TID Info subfield");
1468 bitmap4[8],
1469 0x00,
1470 "Error in the 9th byte of the bitmap for the fourth Per AID TID Info subfield");
1472 bitmap4[9],
1473 0xff,
1474 "Error in the 10th byte of the bitmap for the fourth Per AID TID Info subfield");
1476 bitmap4[10],
1477 0x00,
1478 "Error in the 11th byte of the bitmap for the fourth Per AID TID Info subfield");
1480 bitmap4[11],
1481 0xff,
1482 "Error in the 12th byte of the bitmap for the fourth Per AID TID Info subfield");
1484 bitmap4[12],
1485 0x00,
1486 "Error in the 13th byte of the bitmap for the fourth Per AID TID Info subfield");
1488 bitmap4[13],
1489 0xff,
1490 "Error in the 14th byte of the bitmap for the fourth Per AID TID Info subfield");
1492 bitmap4[14],
1493 0x00,
1494 "Error in the 15th byte of the bitmap for the fourth Per AID TID Info subfield");
1496 bitmap4[15],
1497 0xff,
1498 "Error in the 16th byte of the bitmap for the fourth Per AID TID Info subfield");
1499
1500 /* Check 5th Per AID TID Info subfield */
1501 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(4),
1502 aid5,
1503 "Different AID for the fifth Per AID TID Info subfield");
1504 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(4),
1505 ackType5,
1506 "Different Ack Type for the fifth Per AID TID Info subfield");
1507 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(4),
1508 tid5,
1509 "Different TID for the fifth Per AID TID Info subfield");
1511 blockAckCopy.GetStartingSequence(4),
1512 startSeq5,
1513 "Different starting sequence number for the fifth Per AID TID Info subfield");
1514
1515 auto& bitmap5 = blockAckCopy.GetBitmap(4);
1516 NS_TEST_EXPECT_MSG_EQ(bitmap5.size(),
1517 32,
1518 "Different bitmap length for the fifth Per AID TID Info subfield");
1520 bitmap5[0],
1521 0x55,
1522 "Error in the 1st byte of the bitmap for the fifth Per AID TID Info subfield");
1524 bitmap5[1],
1525 0xaa,
1526 "Error in the 2nd byte of the bitmap for the fifth Per AID TID Info subfield");
1528 bitmap5[2],
1529 0x00,
1530 "Error in the 3rd byte of the bitmap for the fifth Per AID TID Info subfield");
1532 bitmap5[3],
1533 0xff,
1534 "Error in the 4th byte of the bitmap for the fifth Per AID TID Info subfield");
1536 bitmap5[4],
1537 0x0f,
1538 "Error in the 5th byte of the bitmap for the fifth Per AID TID Info subfield");
1540 bitmap5[5],
1541 0xf0,
1542 "Error in the 6th byte of the bitmap for the fifth Per AID TID Info subfield");
1544 bitmap5[6],
1545 0x00,
1546 "Error in the 7th byte of the bitmap for the fifth Per AID TID Info subfield");
1548 bitmap5[7],
1549 0xff,
1550 "Error in the 8th byte of the bitmap for the fifth Per AID TID Info subfield");
1552 bitmap5[8],
1553 0x00,
1554 "Error in the 9th byte of the bitmap for the fifth Per AID TID Info subfield");
1556 bitmap5[9],
1557 0xff,
1558 "Error in the 10th byte of the bitmap for the fifth Per AID TID Info subfield");
1560 bitmap5[10],
1561 0x00,
1562 "Error in the 11th byte of the bitmap for the fifth Per AID TID Info subfield");
1564 bitmap5[11],
1565 0xff,
1566 "Error in the 12th byte of the bitmap for the fifth Per AID TID Info subfield");
1568 bitmap5[12],
1569 0x00,
1570 "Error in the 13th byte of the bitmap for the fifth Per AID TID Info subfield");
1572 bitmap5[13],
1573 0xff,
1574 "Error in the 14th byte of the bitmap for the fifth Per AID TID Info subfield");
1576 bitmap5[14],
1577 0x00,
1578 "Error in the 15th byte of the bitmap for the fifth Per AID TID Info subfield");
1580 bitmap5[15],
1581 0xff,
1582 "Error in the 16th byte of the bitmap for the fifth Per AID TID Info subfield");
1584 bitmap5[16],
1585 0x00,
1586 "Error in the 17th byte of the bitmap for the fifth Per AID TID Info subfield");
1588 bitmap5[17],
1589 0xff,
1590 "Error in the 18th byte of the bitmap for the fifth Per AID TID Info subfield");
1592 bitmap5[18],
1593 0x00,
1594 "Error in the 19th byte of the bitmap for the fifth Per AID TID Info subfield");
1596 bitmap5[19],
1597 0xff,
1598 "Error in the 20th byte of the bitmap for the fifth Per AID TID Info subfield");
1600 bitmap5[20],
1601 0x00,
1602 "Error in the 21th byte of the bitmap for the fifth Per AID TID Info subfield");
1604 bitmap5[21],
1605 0xff,
1606 "Error in the 22th byte of the bitmap for the fifth Per AID TID Info subfield");
1608 bitmap5[22],
1609 0x00,
1610 "Error in the 23th byte of the bitmap for the fifth Per AID TID Info subfield");
1612 bitmap5[23],
1613 0xff,
1614 "Error in the 24th byte of the bitmap for the fifth Per AID TID Info subfield");
1616 bitmap5[24],
1617 0x00,
1618 "Error in the 25th byte of the bitmap for the fifth Per AID TID Info subfield");
1620 bitmap5[25],
1621 0xff,
1622 "Error in the 26th byte of the bitmap for the fifth Per AID TID Info subfield");
1624 bitmap5[26],
1625 0x00,
1626 "Error in the 27th byte of the bitmap for the fifth Per AID TID Info subfield");
1628 bitmap5[27],
1629 0xff,
1630 "Error in the 28th byte of the bitmap for the fifth Per AID TID Info subfield");
1632 bitmap5[28],
1633 0x00,
1634 "Error in the 29th byte of the bitmap for the fifth Per AID TID Info subfield");
1636 bitmap5[29],
1637 0xff,
1638 "Error in the 30th byte of the bitmap for the fifth Per AID TID Info subfield");
1640 bitmap5[30],
1641 0x00,
1642 "Error in the 31th byte of the bitmap for the fifth Per AID TID Info subfield");
1644 bitmap5[31],
1645 0xff,
1646 "Error in the 32th byte of the bitmap for the fifth Per AID TID Info subfield");
1647
1648 /* Check 6th Per AID TID Info subfield */
1649 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAid11(5),
1650 aid6,
1651 "Different AID for the sixth Per AID TID Info subfield");
1652 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetAckType(5),
1653 ackType6,
1654 "Different Ack Type for the sixth Per AID TID Info subfield");
1655 NS_TEST_EXPECT_MSG_EQ(blockAckCopy.GetTidInfo(5),
1656 tid6,
1657 "Different TID for the sixth Per AID TID Info subfield");
1659 blockAckCopy.GetUnassociatedStaAddress(5),
1660 address6,
1661 "Different starting sequence number for the sixth Per AID TID Info subfield");
1662}
1663
1664/**
1665 * \ingroup wifi-test
1666 * \ingroup tests
1667 *
1668 * \brief Test for Block Ack Policy with aggregation disabled
1669 *
1670 * This test aims to check the Block Ack policy when A-MPDU aggregation is disabled.
1671 * In this case, a QoS station can transmit multiple QoS data frames before requesting
1672 * a Block Ack through a Block Ack Request frame. If the AC is granted a non-null TXOP
1673 * limit, MPDUs can be separated by a SIFS.
1674 *
1675 * In this test, an HT STA sends 14 packets to an HT AP. The ack policy selector is
1676 * configured so that a Block Ack is requested once 8 (= 0.125 * 64) MPDUs are sent
1677 * in addition to the MPDU having the starting sequence number. The block ack threshold
1678 * is set to 2, hence a block ack agreement is established when there are at least two
1679 * packets in the EDCA queue.
1680 *
1681 * When the TXOP limit is null:
1682 * - the first packet is sent with Normal Ack policy because the BA agreement has not
1683 * been established yet (there are no queued packets when the first one arrives);
1684 * - packets from the 2nd to the 10th are sent with Block Ack policy (and hence
1685 * are not immediately acknowledged);
1686 * - after the 10th packet, a Block Ack Request is sent, followed by a Block Ack;
1687 * - the remaining 4 packets are sent with Block Ack policy (and hence
1688 * are not immediately acknowledged);
1689 * - the last packet is followed by a Block Ack Request because there are no more
1690 * packets in the EDCA queue and hence a response is needed independently of
1691 * the number of outstanding MPDUs.
1692 *
1693 * When the TXOP is not null (and long enough to include the transmission of all packets):
1694 * - the first packet is sent with Normal Ack policy because the BA agreement has not
1695 * been established yet (there are no queued packets when the first one arrives);
1696 * - the second packet is sent with Normal Ack Policy because the first packet sent in
1697 * a TXOP shall request an immediate response and no previous MPDUs have to be
1698 * acknowledged;
1699 * - packets from the 3rd to the 11th are sent with Block Ack policy (and hence
1700 * are not immediately acknowledged);
1701 * - after the 11th packet, a Block Ack Request is sent, followed by a Block Ack;
1702 * - the remaining 3 packets are sent with Block Ack policy (and hence
1703 * are not immediately acknowledged);
1704 * - the last packet is followed by a Block Ack Request because there are no more
1705 * packets in the EDCA queue and hence a response is needed independently of
1706 * the number of outstanding MPDUs.
1707 */
1709{
1710 /**
1711 * Keeps the maximum duration among all TXOPs
1712 */
1714 {
1715 /**
1716 * Callback for the TxopTrace trace
1717 * \param startTime TXOP start time
1718 * \param duration TXOP duration
1719 * \param linkId the ID of the link
1720 */
1721 void Trace(Time startTime, Time duration, uint8_t linkId);
1722 Time m_max{Seconds(0)}; ///< max TXOP duration
1723 };
1724
1725 public:
1726 /**
1727 * \brief Constructor
1728 * \param txop true for non-null TXOP limit
1729 */
1732
1733 void DoRun() override;
1734
1735 private:
1736 bool m_txop; ///< true for non-null TXOP limit
1737 uint32_t m_received; ///< received packets
1738 uint16_t m_txTotal; ///< transmitted data packets
1739 uint16_t m_txSinceBar; ///< packets transmitted since the agreement was established
1740 ///< or the last block ack was received
1741 uint16_t m_nBar; ///< transmitted BlockAckReq frames
1742 uint16_t m_nBa; ///< received BlockAck frames
1743
1744 /**
1745 * Function to trace packets received by the server application
1746 * \param context the context
1747 * \param p the packet
1748 * \param adr the address
1749 */
1750 void L7Receive(std::string context, Ptr<const Packet> p, const Address& adr);
1751 /**
1752 * Callback invoked when PHY transmits a packet
1753 * \param context the context
1754 * \param p the packet
1755 * \param power the tx power
1756 */
1757 void Transmit(std::string context, Ptr<const Packet> p, double power);
1758 /**
1759 * Callback invoked when PHY receives a packet
1760 * \param context the context
1761 * \param p the packet
1762 * \param rxPowersW the received power per channel band in watts
1763 */
1764 void Receive(std::string context, Ptr<const Packet> p, RxPowerWattPerChannelBand rxPowersW);
1765};
1766
1767void
1769 Time duration,
1770 uint8_t linkId)
1771{
1772 if (duration > m_max)
1773 {
1774 m_max = duration;
1775 }
1776}
1777
1779 : TestCase("Test case for Block Ack Policy with aggregation disabled"),
1780 m_txop(txop),
1781 m_received(0),
1782 m_txTotal(0),
1783 m_txSinceBar(0),
1784 m_nBar(0),
1785 m_nBa(0)
1786{
1787}
1788
1790{
1791}
1792
1793void
1796 const Address& adr)
1797{
1798 if (p->GetSize() == 1400)
1799 {
1800 m_received++;
1801 }
1802}
1803
1804void
1806{
1807 WifiMacHeader hdr;
1808 p->PeekHeader(hdr);
1809
1810 if (m_nBar < 2 && (m_txSinceBar == 9 || m_txTotal == 14))
1811 {
1812 NS_TEST_ASSERT_MSG_EQ(hdr.IsBlockAckReq(), true, "Didn't get a BlockAckReq when expected");
1813 }
1814 else
1815 {
1816 NS_TEST_ASSERT_MSG_EQ(hdr.IsBlockAckReq(), false, "Got a BlockAckReq when not expected");
1817 }
1818
1819 if (hdr.IsQosData())
1820 {
1821 m_txTotal++;
1822 if (hdr.IsQosBlockAck())
1823 {
1824 m_txSinceBar++;
1825 }
1826
1827 if (!m_txop)
1828 {
1830 true,
1831 "Unexpected QoS ack policy");
1832 }
1833 else
1834 {
1836 true,
1837 "Unexpected QoS ack policy");
1838 }
1839 }
1840 else if (hdr.IsBlockAckReq())
1841 {
1842 m_txSinceBar = 0;
1843 m_nBar++;
1844 }
1845}
1846
1847void
1850 RxPowerWattPerChannelBand rxPowersW)
1851{
1852 WifiMacHeader hdr;
1853 p->PeekHeader(hdr);
1854
1855 if (hdr.IsBlockAck())
1856 {
1857 m_nBa++;
1858 }
1859}
1860
1861void
1863{
1864 NodeContainer wifiStaNode;
1865 wifiStaNode.Create(1);
1866
1867 NodeContainer wifiApNode;
1868 wifiApNode.Create(1);
1869
1872 phy.SetChannel(channel.Create());
1873
1874 WifiHelper wifi;
1875 wifi.SetStandard(WIFI_STANDARD_80211n);
1876 Config::SetDefault("ns3::WifiDefaultAckManager::BaThreshold", DoubleValue(0.125));
1877 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
1878
1879 WifiMacHelper mac;
1880 Ssid ssid = Ssid("ns-3-ssid");
1881 mac.SetType("ns3::StaWifiMac",
1882 "BE_MaxAmsduSize",
1883 UintegerValue(0),
1884 "BE_MaxAmpduSize",
1885 UintegerValue(0),
1886 "Ssid",
1887 SsidValue(ssid),
1888 /* setting blockack threshold for sta's BE queue */
1889 "BE_BlockAckThreshold",
1890 UintegerValue(2),
1891 "ActiveProbing",
1892 BooleanValue(false));
1893
1894 NetDeviceContainer staDevices;
1895 staDevices = wifi.Install(phy, mac, wifiStaNode);
1896
1897 mac.SetType("ns3::ApWifiMac",
1898 "BE_MaxAmsduSize",
1899 UintegerValue(0),
1900 "BE_MaxAmpduSize",
1901 UintegerValue(0),
1902 "Ssid",
1903 SsidValue(ssid),
1904 "BeaconGeneration",
1905 BooleanValue(true));
1906
1907 if (m_txop)
1908 {
1909 // set the TXOP limit on BE AC
1910 mac.SetEdca(AC_BE,
1911 "TxopLimits",
1913 }
1914
1915 NetDeviceContainer apDevices;
1916 apDevices = wifi.Install(phy, mac, wifiApNode);
1917
1918 MobilityHelper mobility;
1919 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
1920
1921 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
1922 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
1923 mobility.SetPositionAllocator(positionAlloc);
1924
1925 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1926 mobility.Install(wifiApNode);
1927 mobility.Install(wifiStaNode);
1928
1929 Ptr<WifiNetDevice> ap_device = DynamicCast<WifiNetDevice>(apDevices.Get(0));
1930 Ptr<WifiNetDevice> sta_device = DynamicCast<WifiNetDevice>(staDevices.Get(0));
1931
1932 // Disable A-MPDU aggregation
1933 sta_device->GetMac()->SetAttribute("BE_MaxAmpduSize", UintegerValue(0));
1934 TxopDurationTracer txopTracer;
1935
1936 if (m_txop)
1937 {
1938 PointerValue ptr;
1939 sta_device->GetMac()->GetAttribute("BE_Txop", ptr);
1940 ptr.Get<QosTxop>()->TraceConnectWithoutContext(
1941 "TxopTrace",
1943 }
1944
1945 PacketSocketAddress socket;
1946 socket.SetSingleDevice(sta_device->GetIfIndex());
1947 socket.SetPhysicalAddress(ap_device->GetAddress());
1948 socket.SetProtocol(1);
1949
1950 // give packet socket powers to nodes.
1951 PacketSocketHelper packetSocket;
1952 packetSocket.Install(wifiStaNode);
1953 packetSocket.Install(wifiApNode);
1954
1955 // the first client application generates a single packet, which is sent
1956 // with the normal ack policy because there are no other packets queued
1957 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient>();
1958 client1->SetAttribute("PacketSize", UintegerValue(1400));
1959 client1->SetAttribute("MaxPackets", UintegerValue(1));
1960 client1->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
1961 client1->SetRemote(socket);
1962 wifiStaNode.Get(0)->AddApplication(client1);
1963 client1->SetStartTime(Seconds(1));
1964 client1->SetStopTime(Seconds(3.0));
1965
1966 // the second client application generates 13 packets. Even if when the first
1967 // packet is queued the queue is empty, the first packet is not transmitted
1968 // immediately, but the EDCAF waits for the next slot boundary. At that time,
1969 // other packets have been queued, hence a BA agreement is established first.
1970 Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient>();
1971 client2->SetAttribute("PacketSize", UintegerValue(1400));
1972 client2->SetAttribute("MaxPackets", UintegerValue(13));
1973 client2->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
1974 client2->SetRemote(socket);
1975 wifiStaNode.Get(0)->AddApplication(client2);
1976 client2->SetStartTime(Seconds(1.5));
1977 client2->SetStopTime(Seconds(3.0));
1978
1979 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
1980 server->SetLocal(socket);
1981 wifiApNode.Get(0)->AddApplication(server);
1982 server->SetStartTime(Seconds(0.0));
1983 server->SetStopTime(Seconds(4.0));
1984
1985 Config::Connect("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
1987 Config::Connect("/NodeList/0/DeviceList/0/Phy/PhyTxBegin",
1989 Config::Connect("/NodeList/0/DeviceList/0/Phy/PhyRxBegin",
1991
1994
1996
1997 // The client applications generate 14 packets, so we expect that the wifi PHY
1998 // layer transmits 14 MPDUs, the server application receives 14 packets, and
1999 // two BARs are transmitted.
2000 NS_TEST_EXPECT_MSG_EQ(m_txTotal, 14, "Unexpected number of transmitted packets");
2001 NS_TEST_EXPECT_MSG_EQ(m_received, 14, "Unexpected number of received packets");
2002 NS_TEST_EXPECT_MSG_EQ(m_nBar, 2, "Unexpected number of Block Ack Requests");
2003 NS_TEST_EXPECT_MSG_EQ(m_nBa, 2, "Unexpected number of Block Ack Responses");
2004 if (m_txop)
2005 {
2006 NS_TEST_EXPECT_MSG_LT(txopTracer.m_max, MicroSeconds(4800), "TXOP duration exceeded!");
2007 NS_TEST_EXPECT_MSG_GT(txopTracer.m_max,
2008 MicroSeconds(3008),
2009 "The maximum TXOP duration is too short!");
2010 }
2011}
2012
2013/**
2014 * \ingroup wifi-test
2015 * \ingroup tests
2016 *
2017 * \brief Block Ack Test Suite
2018 */
2020{
2021 public:
2023};
2024
2026 : TestSuite("wifi-block-ack", Type::UNIT)
2027{
2028 AddTestCase(new PacketBufferingCaseA, TestCase::Duration::QUICK);
2029 AddTestCase(new PacketBufferingCaseB, TestCase::Duration::QUICK);
2030 AddTestCase(new OriginatorBlockAckWindowTest, TestCase::Duration::QUICK);
2031 AddTestCase(new CtrlBAckResponseHeaderTest, TestCase::Duration::QUICK);
2032 AddTestCase(new BlockAckRecipientBufferTest(0), TestCase::Duration::QUICK);
2033 AddTestCase(new BlockAckRecipientBufferTest(4090), TestCase::Duration::QUICK);
2034 AddTestCase(new MultiStaCtrlBAckResponseHeaderTest, TestCase::Duration::QUICK);
2035 AddTestCase(new BlockAckAggregationDisabledTest(false), TestCase::Duration::QUICK);
2036 AddTestCase(new BlockAckAggregationDisabledTest(true), TestCase::Duration::QUICK);
2037}
2038
2039static 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
A container for one type of attribute.
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.
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
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:302
A suite of tests to run.
Definition: test.h:1273
Type
Type of test.
Definition: test.h:1280
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
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:1343
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
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
@ AC_BE
Best Effort.
Definition: qos-utils.h:75
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:700
@ WIFI_MAC_QOSDATA
static constexpr uint16_t SEQNO_SPACE_SIZE
Size of the space of sequence numbers.
Definition: wifi-utils.h:186
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.