A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-aggregation-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "ns3/attribute-container.h"
10#include "ns3/config.h"
11#include "ns3/eht-configuration.h"
12#include "ns3/fcfs-wifi-queue-scheduler.h"
13#include "ns3/he-configuration.h"
14#include "ns3/ht-configuration.h"
15#include "ns3/ht-frame-exchange-manager.h"
16#include "ns3/interference-helper.h"
17#include "ns3/mac-tx-middle.h"
18#include "ns3/mgt-action-headers.h"
19#include "ns3/mobility-helper.h"
20#include "ns3/mpdu-aggregator.h"
21#include "ns3/msdu-aggregator.h"
22#include "ns3/multi-link-element.h"
23#include "ns3/node-container.h"
24#include "ns3/packet-socket-client.h"
25#include "ns3/packet-socket-helper.h"
26#include "ns3/packet-socket-server.h"
27#include "ns3/pointer.h"
28#include "ns3/simulator.h"
29#include "ns3/sta-wifi-mac.h"
30#include "ns3/string.h"
31#include "ns3/test.h"
32#include "ns3/vht-configuration.h"
33#include "ns3/wifi-default-ack-manager.h"
34#include "ns3/wifi-default-protection-manager.h"
35#include "ns3/wifi-mac-queue.h"
36#include "ns3/wifi-net-device.h"
37#include "ns3/wifi-psdu.h"
38#include "ns3/yans-wifi-helper.h"
39#include "ns3/yans-wifi-phy.h"
40
41#include <algorithm>
42#include <iterator>
43#include <vector>
44
45using namespace ns3;
46
47namespace
48{
49
50/// Map standard to aPSDUMaxLength
57} // namespace
58
59/**
60 * @ingroup wifi-test
61 * @ingroup tests
62 *
63 * @brief Ampdu Aggregation Test
64 */
66{
67 public:
69
70 /// Test parameters
71 struct Params
72 {
73 WifiStandard standard; //!< the standard of the device
74 uint8_t nLinks; //!< number of links (>1 only for EHT)
75 std::string dataMode; //!< data mode
76 uint16_t bufferSize; //!< the size (in number of MPDUs) of the BlockAck buffer
77 uint16_t maxAmsduSize; //!< maximum A-MSDU size (bytes)
78 uint32_t maxAmpduSize; //!< maximum A-MPDU size (bytes)
79 Time txopLimit; //!< TXOP limit duration
80 };
81
82 /**
83 * Construct object with non-default test parameters
84 *
85 * @param name the name of the test case
86 * @param params the test parameters
87 */
88 AmpduAggregationTest(const std::string& name, const Params& params);
89
90 protected:
91 /**
92 * Establish a BlockAck agreement.
93 *
94 * @param recipient the recipient MAC address
95 */
96 void EstablishAgreement(const Mac48Address& recipient);
97
98 /**
99 * Enqueue the given number of packets addressed to the given station and of the given size.
100 *
101 * @param count the number of packets
102 * @param size the size (bytes) of each packet
103 * @param dest the destination address
104 */
105 void EnqueuePkts(std::size_t count, uint32_t size, const Mac48Address& dest);
106
107 /**
108 * Check the maximum PSDU size
109 *
110 * @param phy the PHY
111 * @param fem the HT frame exchange manager
112 */
114
115 /**
116 * @return the Best Effort QosTxop
117 */
118 Ptr<QosTxop> GetBeQueue() const;
119
120 /**
121 * Dequeue a PSDU.
122 *
123 * @param mpduList the MPDUs contained in the PSDU
124 */
125 void DequeueMpdus(const std::vector<Ptr<WifiMpdu>>& mpduList);
126
128 std::vector<Ptr<WifiPhy>> m_phys; ///< Phys
129 Params m_params; //!< test parameters
130
131 private:
132 /**
133 * Fired when the MAC discards an MPDU.
134 *
135 * @param reason the reason why the MPDU was discarded
136 * @param mpdu the discarded MPDU
137 */
139
140 void DoSetup() override;
141 void DoRun() override;
142 void DoTeardown() override;
143
144 Ptr<WifiNetDevice> m_device; ///< WifiNetDevice
145 std::vector<Ptr<WifiRemoteStationManager>> m_managers; ///< remote station managers
147 bool m_discarded; ///< whether the packet should be discarded
148};
149
151 : AmpduAggregationTest("Check the correctness of MPDU aggregation operations",
152 Params{.standard = WIFI_STANDARD_80211n,
153 .nLinks = 1,
154 .dataMode = "HtMcs7",
155 .bufferSize = 64,
156 .maxAmsduSize = 0,
157 .maxAmpduSize = 65535,
158 .txopLimit = Seconds(0)})
159{
160}
161
162AmpduAggregationTest::AmpduAggregationTest(const std::string& name, const Params& params)
163 : TestCase(name),
164 m_params(params),
165 m_discarded(false)
166{
167}
168
169void
174
175void
177{
178 /*
179 * Create device and attach HT configuration.
180 */
182 m_device->SetStandard(m_params.standard);
183 auto htConfiguration = CreateObject<HtConfiguration>();
184 m_device->SetHtConfiguration(htConfiguration);
185 if (m_params.standard >= WIFI_STANDARD_80211ax)
186 {
187 auto vhtConfiguration = CreateObject<VhtConfiguration>();
188 m_device->SetVhtConfiguration(vhtConfiguration);
189 auto heConfiguration = CreateObject<HeConfiguration>();
190 m_device->SetHeConfiguration(heConfiguration);
191 }
192 if (m_params.standard >= WIFI_STANDARD_80211be)
193 {
194 auto ehtConfiguration = CreateObject<EhtConfiguration>();
195 m_device->SetEhtConfiguration(ehtConfiguration);
196 }
197
198 /*
199 * Create and configure phy layer.
200 */
201 for (uint8_t i = 0; i < m_params.nLinks; i++)
202 {
203 m_phys.emplace_back(CreateObject<YansWifiPhy>());
204 auto interferenceHelper = CreateObject<InterferenceHelper>();
205 m_phys.back()->SetInterferenceHelper(interferenceHelper);
206 m_phys.back()->SetDevice(m_device);
207 m_phys.back()->ConfigureStandard(m_params.standard);
208 }
209 m_device->SetPhys(m_phys);
210
211 /*
212 * Create and configure manager.
213 */
215 m_factory.SetTypeId("ns3::ConstantRateWifiManager");
216 m_factory.Set("DataMode", StringValue(m_params.dataMode));
217 for (uint8_t i = 0; i < m_params.nLinks; i++)
218 {
219 m_managers.emplace_back(m_factory.Create<WifiRemoteStationManager>());
220 m_managers.back()->SetupPhy(m_phys.at(i));
221 }
222 m_device->SetRemoteStationManagers(m_managers);
223
224 /*
225 * Create and configure mac layer.
226 */
228 "QosSupported",
229 BooleanValue(true),
230 "BE_Txop",
232 "BK_Txop",
234 "VI_Txop",
236 "VO_Txop",
238 m_mac->SetDevice(m_device);
239 m_mac->SetWifiRemoteStationManagers(m_managers);
240 for (uint8_t i = 0; i < m_params.nLinks; i++)
241 {
242 m_managers.at(i)->SetupMac(m_mac);
243 }
244 m_mac->SetAddress(Mac48Address("00:00:00:00:00:01"));
245 m_device->SetMac(m_mac);
246 m_mac->SetWifiPhys(m_phys);
247 std::vector<Ptr<ChannelAccessManager>> caManagers;
248 caManagers.reserve(m_params.nLinks);
249 for (uint8_t i = 0; i < m_params.nLinks; i++)
250 {
251 caManagers.emplace_back(CreateObject<ChannelAccessManager>());
252 }
253 m_mac->SetChannelAccessManagers(caManagers);
254 ObjectFactory femFactory;
255 femFactory.SetTypeId(GetFrameExchangeManagerTypeIdName(m_params.standard, true));
256 std::vector<Ptr<FrameExchangeManager>> feManagers;
257 for (uint8_t i = 0; i < m_params.nLinks; i++)
258 {
259 auto fem = femFactory.Create<FrameExchangeManager>();
260 feManagers.emplace_back(fem);
261 auto protectionManager = CreateObject<WifiDefaultProtectionManager>();
262 protectionManager->SetWifiMac(m_mac);
263 fem->SetProtectionManager(protectionManager);
264 auto ackManager = CreateObject<WifiDefaultAckManager>();
265 ackManager->SetWifiMac(m_mac);
266 fem->SetAckManager(ackManager);
267 // here we should assign distinct link addresses in case of MLDs, but we don't actually use
268 // link addresses in this test
269 fem->SetAddress(m_mac->GetAddress());
270 }
271 m_mac->SetFrameExchangeManagers(feManagers);
272 m_mac->SetState(StaWifiMac::ASSOCIATED);
273 if (m_params.nLinks > 1)
274 {
275 // the bssid field of StaLinkEntity must hold a value
276 for (const auto& [id, link] : m_mac->GetLinks())
277 {
279 }
280 }
281 m_mac->SetMacQueueScheduler(CreateObject<FcfsWifiQueueScheduler>());
282
283 /*
284 * Configure A-MSDU and A-MPDU aggregation.
285 */
286 // Make sure that at least 1024 MPDUs are buffered (to test aggregation on EHT devices)
287 m_mac->GetTxopQueue(AC_BE)->SetAttribute("MaxSize", StringValue("2000p"));
288 m_mac->SetAttribute("BE_MaxAmsduSize", UintegerValue(m_params.maxAmsduSize));
289 m_mac->SetAttribute("BE_MaxAmpduSize", UintegerValue(m_params.maxAmpduSize));
290 GetBeQueue()->SetAttribute(
291 "TxopLimits",
292 AttributeContainerValue<TimeValue>(std::vector<Time>(m_params.nLinks, m_params.txopLimit)));
293
294 if (m_params.nLinks > 1)
295 {
296 auto mleCommonInfo2 = std::make_shared<CommonInfoBasicMle>();
297 mleCommonInfo2->m_mldMacAddress = Mac48Address("00:00:00:00:00:02");
298 for (uint8_t i = 0; i < m_params.nLinks; i++)
299 {
300 // we don't actually use the link addresses of the receiver, so we just use one address
301 // as both the MLD address and the link address of the receiver (the first argument in
302 // the call below should be the link address)
303 m_managers.at(i)->AddStationMleCommonInfo(mleCommonInfo2->m_mldMacAddress,
304 mleCommonInfo2);
305 }
306
307 auto mleCommonInfo3 = std::make_shared<CommonInfoBasicMle>();
308 mleCommonInfo3->m_mldMacAddress = Mac48Address("00:00:00:00:00:03");
309 for (uint8_t i = 0; i < m_params.nLinks; i++)
310 {
311 m_managers.at(i)->AddStationMleCommonInfo(mleCommonInfo3->m_mldMacAddress,
312 mleCommonInfo3);
313 }
314 }
315
316 for (uint8_t i = 0; i < m_params.nLinks; i++)
317 {
318 HtCapabilities htCapabilities;
319 htCapabilities.SetMaxAmsduLength(7935);
320 htCapabilities.SetMaxAmpduLength(65535);
321 m_managers.at(i)->AddStationHtCapabilities(Mac48Address("00:00:00:00:00:02"),
322 htCapabilities);
323 m_managers.at(i)->AddStationHtCapabilities(Mac48Address("00:00:00:00:00:03"),
324 htCapabilities);
325
326 if (m_params.standard >= WIFI_STANDARD_80211ac)
327 {
328 VhtCapabilities vhtCapabilities;
329 vhtCapabilities.SetMaxMpduLength(11454);
330 m_managers.at(i)->AddStationVhtCapabilities(Mac48Address("00:00:00:00:00:02"),
331 vhtCapabilities);
332 }
333 if (m_params.standard >= WIFI_STANDARD_80211ax)
334 {
335 HeCapabilities heCapabilities;
336 heCapabilities.SetChannelWidthSet(0x1);
337 heCapabilities.SetMaxAmpduLength((1 << 23) - 1);
338 m_managers.at(i)->AddStationHeCapabilities(Mac48Address("00:00:00:00:00:02"),
339 heCapabilities);
340 }
341 if (m_params.standard >= WIFI_STANDARD_80211be)
342 {
343 EhtCapabilities ehtCapabilities;
344 ehtCapabilities.SetMaxMpduLength(11454);
345 ehtCapabilities.SetMaxAmpduLength((1 << 24) - 1);
346 m_managers.at(i)->AddStationEhtCapabilities(Mac48Address("00:00:00:00:00:02"),
347 ehtCapabilities);
348 }
349 }
350
351 /*
352 * Establish agreement.
353 */
354 EstablishAgreement(Mac48Address("00:00:00:00:00:02"));
355}
356
359{
360 return m_mac->GetBEQueue();
361}
362
363void
365{
366 std::list<Ptr<const WifiMpdu>> mpdus(mpduList.cbegin(), mpduList.cend());
367 m_mac->GetTxopQueue(AC_BE)->DequeueIfQueued(mpdus);
368}
369
370void
372{
374 reqHdr.SetImmediateBlockAck();
375 reqHdr.SetTid(0);
376 reqHdr.SetBufferSize(m_params.bufferSize);
377 reqHdr.SetTimeout(0);
378 reqHdr.SetStartingSequence(0);
379 GetBeQueue()->GetBaManager()->CreateOriginatorAgreement(reqHdr, recipient);
380
382 StatusCode code;
383 code.SetSuccess();
384 respHdr.SetStatusCode(code);
385 respHdr.SetAmsduSupport(reqHdr.IsAmsduSupported());
386 respHdr.SetImmediateBlockAck();
387 respHdr.SetTid(reqHdr.GetTid());
388 respHdr.SetBufferSize(m_params.bufferSize);
389 respHdr.SetTimeout(reqHdr.GetTimeout());
390 GetBeQueue()->GetBaManager()->UpdateOriginatorAgreement(respHdr, recipient, 0);
391}
392
393void
394AmpduAggregationTest::EnqueuePkts(std::size_t count, uint32_t size, const Mac48Address& dest)
395{
396 for (std::size_t i = 0; i < count; i++)
397 {
398 auto pkt = Create<Packet>(size);
399 WifiMacHeader hdr;
400
401 hdr.SetAddr1(dest);
402 hdr.SetAddr2(Mac48Address("00:00:00:00:00:01"));
404 hdr.SetQosTid(0);
405
406 GetBeQueue()->GetWifiMacQueue()->Enqueue(Create<WifiMpdu>(pkt, hdr));
407 }
408}
409
410void
412{
413 const auto expectedMaxPsduLength = maxPsduLengths.at(phy->GetStandard());
414 const auto mc = phy->GetMaxModulationClassSupported();
415
416 NS_TEST_EXPECT_MSG_EQ(phy->GetMaxPsduSize(mc),
417 expectedMaxPsduLength,
418 "Unexpected aPSDUMaxLength");
419
420 const auto maxAmpduSize = std::min(m_params.maxAmpduSize, expectedMaxPsduLength);
421 const auto recipient = Mac48Address("00:00:00:00:00:02");
422
423 auto isWithinAmpduSizeLimit = fem->IsWithinAmpduSizeLimit(maxAmpduSize, recipient, 0, mc);
424 NS_TEST_EXPECT_MSG_EQ(isWithinAmpduSizeLimit,
425 true,
426 "A-MPDU size limit check failed when the size is smaller than the limit");
427
428 isWithinAmpduSizeLimit = fem->IsWithinAmpduSizeLimit(maxAmpduSize + 1, recipient, 0, mc);
429 NS_TEST_EXPECT_MSG_EQ(isWithinAmpduSizeLimit,
430 false,
431 "A-MPDU size limit check failed when the size is larger than the limit");
432}
433
434void
436{
437 /*
438 * Test behavior when no other packets are in the queue
439 */
440 auto phy = m_phys.at(SINGLE_LINK_OP_ID);
441 auto fem = m_mac->GetFrameExchangeManager(SINGLE_LINK_OP_ID);
442 auto htFem = DynamicCast<HtFrameExchangeManager>(fem);
443 auto mpduAggregator = htFem->GetMpduAggregator();
444
445 CheckMaxPsduSize(phy, htFem);
446
447 /*
448 * Create a dummy packet of 1500 bytes and fill mac header fields.
449 */
450 EnqueuePkts(1, 1500, Mac48Address("00:00:00:00:00:02"));
451
452 auto peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
453 WifiTxParameters txParams;
454 txParams.m_txVector =
455 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
456 phy->GetChannelWidth());
457 auto item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
458
459 auto mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
460
461 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), true, "a single packet should not result in an A-MPDU");
462
463 // the packet has not been "transmitted", release its sequence number
464 m_mac->m_txMiddle->SetSequenceNumberFor(&item->GetHeader());
465 item->UnassignSeqNo();
466
467 //---------------------------------------------------------------------------------------------
468
469 /*
470 * Test behavior when 2 more packets are in the queue
471 */
472 EnqueuePkts(2, 1500, Mac48Address("00:00:00:00:00:02"));
473
474 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
475 mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
476
477 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
478
479 auto psdu = Create<WifiPsdu>(mpduList);
480 DequeueMpdus(mpduList);
481
482 NS_TEST_EXPECT_MSG_EQ(psdu->GetSize(), 4606, "A-MPDU size is not correct");
483 NS_TEST_EXPECT_MSG_EQ(mpduList.size(), 3, "A-MPDU should contain 3 MPDUs");
484 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
485 0,
486 "queue should be empty");
487
488 for (uint32_t i = 0; i < psdu->GetNMpdus(); i++)
489 {
490 NS_TEST_EXPECT_MSG_EQ(psdu->GetHeader(i).GetSequenceNumber(), i, "wrong sequence number");
491 }
492
493 //---------------------------------------------------------------------------------------------
494
495 /*
496 * Test behavior when the 802.11n station and another non-QoS station are associated to the AP.
497 * The AP sends an A-MPDU to the 802.11n station followed by the last retransmission of a
498 * non-QoS data frame to the non-QoS station. This is used to reproduce bug 2224.
499 */
500 EnqueuePkts(1, 1500, Mac48Address("00:00:00:00:00:02"));
501 EnqueuePkts(2, 1500, Mac48Address("00:00:00:00:00:03"));
502
503 peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
504 txParams.Clear();
505 txParams.m_txVector =
506 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
507 phy->GetChannelWidth());
508 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
509
510 mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
511
512 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(),
513 true,
514 "a single packet for this destination should not result in an A-MPDU");
515 // dequeue the MPDU
516 DequeueMpdus({item});
517
518 peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
519 txParams.Clear();
520 txParams.m_txVector =
521 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
522 phy->GetChannelWidth());
523 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
524
525 mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
526
527 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(),
528 true,
529 "no MPDU aggregation should be performed if there is no agreement");
530
531 m_mac->SetFrameRetryLimit(1); // fake that the maximum number of retries has been reached
532 m_mac->TraceConnectWithoutContext("DroppedMpdu",
534 htFem->m_dcf = GetBeQueue();
535 htFem->NormalAckTimeout(item, txParams.m_txVector);
536
537 NS_TEST_EXPECT_MSG_EQ(m_discarded, true, "packet should be discarded");
538 GetBeQueue()->GetWifiMacQueue()->Flush();
539}
540
541void
543{
545
546 for (auto manager : m_managers)
547 {
548 manager->Dispose();
549 }
550 m_managers.clear();
551
552 m_device->Dispose();
553 m_device = nullptr;
554}
555
556/**
557 * @ingroup wifi-test
558 * @ingroup tests
559 *
560 * @brief Two Level Aggregation Test
561 */
563{
564 public:
566
567 private:
568 void DoRun() override;
569};
570
572 : AmpduAggregationTest("Check the correctness of two-level aggregation operations",
573 Params{.standard = WIFI_STANDARD_80211n,
574 .nLinks = 1,
575 .dataMode = "HtMcs2", // 19.5Mbps
576 .bufferSize = 64,
577 .maxAmsduSize = 3050,
578 .maxAmpduSize = 65535,
579 .txopLimit = MicroSeconds(3008)})
580{
581}
582
583void
585{
586 /*
587 * Create dummy packets of 1500 bytes and fill mac header fields that will be used for the
588 * tests.
589 */
590 EnqueuePkts(3, 1500, Mac48Address("00:00:00:00:00:02"));
591
592 //---------------------------------------------------------------------------------------------
593
594 /*
595 * Test MSDU and MPDU aggregation. Three MSDUs are in the queue and the maximum A-MSDU size
596 * is such that only two MSDUs can be aggregated. Therefore, the first MPDU we get contains
597 * an A-MSDU of 2 MSDUs.
598 */
599 auto phy = m_phys.at(SINGLE_LINK_OP_ID);
600 auto fem = m_mac->GetFrameExchangeManager(SINGLE_LINK_OP_ID);
601 auto htFem = DynamicCast<HtFrameExchangeManager>(fem);
602 auto msduAggregator = htFem->GetMsduAggregator();
603 auto mpduAggregator = htFem->GetMpduAggregator();
604
605 CheckMaxPsduSize(phy, htFem);
606
607 auto peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
608 WifiTxParameters txParams;
609 txParams.m_txVector =
610 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
611 phy->GetChannelWidth());
612 htFem->TryAddMpdu(peeked, txParams, Time::Min());
613 auto item = msduAggregator->GetNextAmsdu(peeked, txParams, Time::Min());
614
615 bool result{item};
616 NS_TEST_EXPECT_MSG_EQ(result, true, "aggregation failed");
617 NS_TEST_EXPECT_MSG_EQ(item->GetPacketSize(), 3030, "wrong packet size");
618
619 // dequeue the MSDUs
620 DequeueMpdus({item});
621
622 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
623 1,
624 "Unexpected number of MSDUs left in the EDCA queue");
625
626 //---------------------------------------------------------------------------------------------
627
628 /*
629 * A-MSDU aggregation fails when there is just one MSDU in the queue.
630 */
631
632 peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
633 txParams.Clear();
634 txParams.m_txVector =
635 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
636 phy->GetChannelWidth());
637 htFem->TryAddMpdu(peeked, txParams, Time::Min());
638 item = msduAggregator->GetNextAmsdu(peeked, txParams, Time::Min());
639
640 NS_TEST_EXPECT_MSG_EQ(item, nullptr, "A-MSDU aggregation did not fail");
641
642 DequeueMpdus({peeked});
643
644 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
645 0,
646 "queue should be empty");
647
648 //---------------------------------------------------------------------------------------------
649
650 /*
651 * Aggregation of MPDUs is stopped to prevent that the PPDU duration exceeds the TXOP limit.
652 * In this test, a TXOP limit of 3008 microseconds is used.
653 */
654
655 // Add 10 MSDUs to the EDCA queue
656 EnqueuePkts(10, 1300, Mac48Address("00:00:00:00:00:02"));
657
658 peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
659 txParams.Clear();
660 txParams.m_txVector =
661 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
662 phy->GetChannelWidth());
663
664 // Compute the first MPDU to be aggregated in an A-MPDU. It must contain an A-MSDU
665 // aggregating two MSDUs
666 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, m_params.txopLimit, true);
667
668 NS_TEST_EXPECT_MSG_EQ(std::distance(item->begin(), item->end()),
669 2,
670 "There must be 2 MSDUs in the A-MSDU");
671
672 auto mpduList = mpduAggregator->GetNextAmpdu(item, txParams, m_params.txopLimit);
673
674 // The maximum number of bytes that can be transmitted in a TXOP is (approximately, as we
675 // do not consider that the preamble is transmitted at a different rate):
676 // 19.5 Mbps * 3.008 ms = 7332 bytes
677 // Given that the max A-MSDU size is set to 3050, an A-MSDU will contain two MSDUs and have
678 // a size of 2 * 1300 (MSDU size) + 2 * 14 (A-MSDU subframe header size) + 2 (one padding field)
679 // = 2630 bytes Hence, we expect that the A-MPDU will consist of:
680 // - 2 MPDUs containing each an A-MSDU. The size of each MPDU is 2630 (A-MSDU) + 30
681 // (header+trailer) = 2660
682 // - 1 MPDU containing a single MSDU. The size of such MPDU is 1300 (MSDU) + 30 (header+trailer)
683 // = 1330 The size of the A-MPDU is 4 + 2660 + 4 + 2660 + 4 + 1330 = 6662
684 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "aggregation failed");
685 NS_TEST_EXPECT_MSG_EQ(mpduList.size(), 3, "Unexpected number of MPDUs in the A-MPDU");
686 NS_TEST_EXPECT_MSG_EQ(mpduList.at(0)->GetSize(), 2660, "Unexpected size of the first MPDU");
687 NS_TEST_EXPECT_MSG_EQ(mpduList.at(0)->GetHeader().IsQosAmsdu(),
688 true,
689 "Expecting the first MPDU to contain an A-MSDU");
690 NS_TEST_EXPECT_MSG_EQ(mpduList.at(1)->GetSize(), 2660, "Unexpected size of the second MPDU");
691 NS_TEST_EXPECT_MSG_EQ(mpduList.at(1)->GetHeader().IsQosAmsdu(),
692 true,
693 "Expecting the second MPDU to contain an A-MSDU");
694 NS_TEST_EXPECT_MSG_EQ(mpduList.at(2)->GetSize(), 1330, "Unexpected size of the third MPDU");
695 NS_TEST_EXPECT_MSG_EQ(mpduList.at(2)->GetHeader().IsQosAmsdu(),
696 false,
697 "Expecting the third MPDU not to contain an A-MSDU");
698
699 auto psdu = Create<WifiPsdu>(mpduList);
700 NS_TEST_EXPECT_MSG_EQ(psdu->GetSize(), 6662, "Unexpected size of the A-MPDU");
701
702 // we now have two A-MSDUs and 6 MSDUs in the queue (5 MSDUs with no assigned sequence number)
703 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
704 8,
705 "Unexpected number of items left in the EDCA queue");
706
707 // prepare another A-MPDU (e.g., for transmission on another link)
708 peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID, 0, psdu->GetAddr1(), mpduList.at(2));
709 txParams.Clear();
710 txParams.m_txVector =
711 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
712 phy->GetChannelWidth());
713
714 // Compute the first MPDU to be aggregated in an A-MPDU. It must contain an A-MSDU
715 // aggregating two MSDUs
716 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, m_params.txopLimit, true);
717
718 NS_TEST_EXPECT_MSG_EQ(std::distance(item->begin(), item->end()),
719 2,
720 "There must be 2 MSDUs in the A-MSDU");
721
722 auto mpduList2 = mpduAggregator->GetNextAmpdu(item, txParams, m_params.txopLimit);
723
724 // we now have two A-MSDUs, one MSDU, two A-MSDUs and one MSDU in the queue (all with assigned
725 // sequence number)
726 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
727 6,
728 "Unexpected number of items left in the EDCA queue");
729
730 // unassign sequence numbers for all MPDUs (emulates an RTS/CTS failure on both links)
731 mpduList.at(0)->UnassignSeqNo();
732 mpduList.at(1)->UnassignSeqNo();
733 mpduList.at(2)->UnassignSeqNo();
734 mpduList2.at(0)->UnassignSeqNo();
735 mpduList2.at(1)->UnassignSeqNo();
736 mpduList2.at(2)->UnassignSeqNo();
737
738 // set A-MSDU max size to a large value
739 m_mac->SetAttribute("BE_MaxAmsduSize", UintegerValue(7000));
740
741 // A-MSDU aggregation now fails because the first item in the queue contain A-MSDUs
742 peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
743 txParams.Clear();
744 txParams.m_txVector =
745 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
746 phy->GetChannelWidth());
747
748 htFem->TryAddMpdu(peeked, txParams, Time::Min());
749 item = msduAggregator->GetNextAmsdu(peeked, txParams, Time::Min());
750
751 NS_TEST_EXPECT_MSG_EQ(item, nullptr, "Expecting not to be able to aggregate A-MSDUs");
752
753 // remove the first two items in the queue (containing A-MSDUs)
754 DequeueMpdus({mpduList.at(0), mpduList.at(1)});
755
756 // we now have one MSDU, two A-MSDUs and one MSDU in the queue
757 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
758 4,
759 "Unexpected number of items left in the EDCA queue");
760
761 peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
762 txParams.Clear();
763 txParams.m_txVector =
764 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
765 phy->GetChannelWidth());
766
767 NS_TEST_EXPECT_MSG_EQ(peeked->GetHeader().IsQosAmsdu(),
768 false,
769 "Expecting the peeked MPDU not to contain an A-MSDU");
770
771 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
772
773 // A-MSDU aggregation is not attempted because the next item contains an A-MSDU
774 NS_TEST_EXPECT_MSG_EQ(item->GetHeader().IsQosAmsdu(),
775 false,
776 "Expecting the returned MPDU not to contain an A-MSDU");
777}
778
779/**
780 * @ingroup wifi-test
781 * @ingroup tests
782 *
783 * @brief 802.11ax aggregation test which permits 64 or 256 MPDUs in A-MPDU according to the
784 * negotiated buffer size.
785 */
787{
788 public:
789 /**
790 * Constructor.
791 *
792 * @param bufferSize the size (in number of MPDUs) of the BlockAck buffer
793 */
794 HeAggregationTest(uint16_t bufferSize);
795
796 private:
797 void DoRun() override;
798};
799
802 "Check the correctness of 802.11ax aggregation operations, buffer size=" +
803 std::to_string(bufferSize),
804 Params{.standard = WIFI_STANDARD_80211ax,
805 .nLinks = 1,
806 .dataMode = "HeMcs11",
807 .bufferSize = bufferSize,
808 .maxAmsduSize = 0,
809 .maxAmpduSize = 6500631,
810 .txopLimit = Seconds(0)})
811{
812}
813
814void
816{
817 /*
818 * Test behavior when 300 packets are ready for transmission
819 */
820 const std::size_t numPackets = 300;
821 EnqueuePkts(numPackets, 100, Mac48Address("00:00:00:00:00:02"));
822
823 auto phy = m_phys.at(SINGLE_LINK_OP_ID);
824 auto fem = m_mac->GetFrameExchangeManager(SINGLE_LINK_OP_ID);
825 auto htFem = DynamicCast<HtFrameExchangeManager>(fem);
826 auto mpduAggregator = htFem->GetMpduAggregator();
827
828 CheckMaxPsduSize(phy, htFem);
829
830 auto peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
831 WifiTxParameters txParams;
832 txParams.m_txVector =
833 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
834 phy->GetChannelWidth());
835 auto item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
836
837 auto mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
838 DequeueMpdus(mpduList);
839
840 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
841 NS_TEST_EXPECT_MSG_EQ(mpduList.size(),
842 m_params.bufferSize,
843 "A-MPDU contains an unexpected number of MPDUs");
844 uint16_t expectedRemainingPacketsInQueue = numPackets - m_params.bufferSize;
845 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
846 expectedRemainingPacketsInQueue,
847 "Queue contains an unexpected number of MPDUs");
848}
849
850/**
851 * @ingroup wifi-test
852 * @ingroup tests
853 *
854 * @brief 802.11be aggregation test which permits up to 1024 MPDUs in A-MPDU according to the
855 * negotiated buffer size.
856 */
858{
859 public:
860 /**
861 * Constructor.
862 *
863 * @param bufferSize the size (in number of MPDUs) of the BlockAck buffer
864 * @param maxAmpduSize the maximum size (in bytes) allowed per A-MPDU
865 */
866 EhtAggregationTest(uint16_t bufferSize, uint32_t maxAmpduSize);
867
868 private:
869 void DoRun() override;
870};
871
872EhtAggregationTest::EhtAggregationTest(uint16_t bufferSize, uint32_t maxAmpduSize)
874 "Check the correctness of 802.11be aggregation operations, buffer size=" +
875 std::to_string(bufferSize) + ", max A-MPDU size=" + std::to_string(maxAmpduSize),
876 Params{.standard = WIFI_STANDARD_80211be,
877 .nLinks = 2,
878 .dataMode = "EhtMcs13",
879 .bufferSize = bufferSize,
880 .maxAmsduSize = 0,
881 .maxAmpduSize = maxAmpduSize,
882 .txopLimit = Seconds(0)})
883{
884}
885
886void
888{
889 /*
890 * Test behavior when 1200 packets of 100 bytes each are ready for transmission. In the first
891 * tests, the max A-MPDU size limit (102000 B) is computed to have at most 750 MPDUs aggregated
892 * in a single A-MPDU (each MPDU is 130 B, plus 4 B of A-MPDU subframe header, plus 2 B of
893 * padding). In the last test, the max A-MPDU size limit is the upper bound allowed by the
894 * standard (6500631 B), which allows to aggregate 1024 MPDUs (the buffer size) in a single
895 * A-MPDU.
896 */
897 const std::size_t numPackets = 1200;
898 EnqueuePkts(numPackets, 100, Mac48Address("00:00:00:00:00:02"));
899 const auto maxNMpdus = std::min<std::size_t>(m_params.maxAmpduSize / 136, m_params.bufferSize);
900
901 for (uint8_t linkId = 0; linkId < m_params.nLinks; linkId++)
902 {
903 auto phy = m_phys.at(linkId);
904 auto fem = m_mac->GetFrameExchangeManager(linkId);
905 auto htFem = DynamicCast<HtFrameExchangeManager>(fem);
906 auto mpduAggregator = htFem->GetMpduAggregator();
907 std::vector<Ptr<WifiMpdu>> mpduList;
908
909 CheckMaxPsduSize(phy, htFem);
910
911 auto peeked = GetBeQueue()->PeekNextMpdu(linkId);
912 if (peeked)
913 {
914 WifiTxParameters txParams;
915 txParams.m_txVector =
916 m_mac->GetWifiRemoteStationManager()->GetDataTxVector(peeked->GetHeader(),
917 phy->GetChannelWidth());
918 auto item = GetBeQueue()->GetNextMpdu(linkId, peeked, txParams, Time::Min(), true);
919
920 mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
921 DequeueMpdus(mpduList);
922 }
923
924 uint16_t expectedRemainingPacketsInQueue;
925
926 if (m_params.bufferSize > maxNMpdus)
927 {
928 // two A-MPDUs are transmitted concurrently on the two links and together saturate
929 // the transmit window
930 switch (linkId)
931 {
932 case 0:
933 // the first A-MPDU includes maxNMpdus MPDUs
934 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
935 NS_TEST_EXPECT_MSG_EQ(mpduList.size(),
936 maxNMpdus,
937 "A-MPDU contains an unexpected number of MPDUs");
938 expectedRemainingPacketsInQueue = numPackets - maxNMpdus;
939 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
940 expectedRemainingPacketsInQueue,
941 "Queue contains an unexpected number of MPDUs");
942 break;
943 case 1:
944 // the second A-MPDU includes bufferSize - maxNMpdus MPDUs
945 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
946 NS_TEST_EXPECT_MSG_EQ(mpduList.size(),
947 m_params.bufferSize - maxNMpdus,
948 "A-MPDU contains an unexpected number of MPDUs");
949 expectedRemainingPacketsInQueue = numPackets - m_params.bufferSize;
950 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
951 expectedRemainingPacketsInQueue,
952 "Queue contains an unexpected number of MPDUs");
953 break;
954 default:
955 NS_TEST_ASSERT_MSG_EQ(true, false, "Unexpected link ID " << +linkId);
956 }
957 }
958 else
959 {
960 // one A-MPDU is transmitted that saturates the transmit window
961 switch (linkId)
962 {
963 case 0:
964 // the first A-MPDU includes bufferSize MPDUs
965 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
966 NS_TEST_EXPECT_MSG_EQ(mpduList.size(),
967 m_params.bufferSize,
968 "A-MPDU contains an unexpected number of MPDUs");
969 expectedRemainingPacketsInQueue = numPackets - m_params.bufferSize;
970 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
971 expectedRemainingPacketsInQueue,
972 "Queue contains an unexpected number of MPDUs");
973 break;
974 case 1:
975 // no more MPDUs can be sent, aggregation fails
976 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), true, "MPDU aggregation did not fail");
977 expectedRemainingPacketsInQueue = numPackets - m_params.bufferSize;
978 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
979 expectedRemainingPacketsInQueue,
980 "Queue contains an unexpected number of MPDUs");
981 break;
982 default:
983 NS_TEST_ASSERT_MSG_EQ(true, false, "Unexpected link ID " << +linkId);
984 }
985 }
986 }
987}
988
989/**
990 * @ingroup wifi-test
991 * @ingroup tests
992 *
993 * @brief Test for A-MSDU and A-MPDU aggregation
994 *
995 * This test aims to check that the packets passed to the MAC layer (on the sender
996 * side) are forwarded up to the upper layer (on the receiver side) when A-MSDU and
997 * A-MPDU aggregation are used. This test checks that no packet copies are performed,
998 * hence packets can be tracked by means of a pointer.
999 *
1000 * In this test, an HT STA sends 8 packets (each of 1000 bytes) to an HT AP.
1001 * The block ack threshold is set to 2, hence the first packet is sent as an MPDU
1002 * containing a single MSDU because the establishment of a Block Ack agreement is
1003 * not triggered yet. The maximum A-MSDU size is set to 4500 bytes and the
1004 * maximum A-MPDU size is set to 7500 bytes, hence the remaining packets are sent
1005 * in an A-MPDU containing two MPDUs, the first one including 4 MSDUs and the second
1006 * one including 3 MPDUs.
1007 *
1008 * It is also checked that the MAC header of every MPDU is notified to the FrameExchangeManager
1009 * while the PSDU is being transmitted.
1010 */
1012{
1013 public:
1014 /**
1015 * Constructor.
1016 *
1017 * @param notifyMacHdrRxEnd whether notification of MAC header reception end is enabled
1018 */
1019 PreservePacketsInAmpdus(bool notifyMacHdrRxEnd);
1020 ~PreservePacketsInAmpdus() override;
1021
1022 void DoRun() override;
1023
1024 private:
1025 std::list<Ptr<const Packet>> m_packetList; ///< List of packets passed to the MAC
1026 std::vector<std::size_t> m_nMpdus; ///< Number of MPDUs in PSDUs passed to the PHY
1027 std::vector<std::size_t> m_nMsdus; ///< Number of MSDUs in MPDUs passed to the PHY
1028 Ptr<const WifiPsdu> m_txPsdu; ///< PSDU being transmitted
1029 std::vector<Ptr<WifiMpdu>>::const_iterator
1030 m_expectedMpdu; ///< next MPDU expected to be received
1031 std::size_t m_nMacHdrs{0}; ///< Number of notified MAC headers in QoS data frames
1032 bool m_notifyMacHdrRxEnd; ///< whether notification of MAC header reception end is enabled
1033
1034 /**
1035 * Callback invoked when an MSDU is passed to the MAC
1036 * @param packet the MSDU to transmit
1037 */
1039 /**
1040 * Callback invoked when the sender MAC passes a PSDU(s) to the PHY
1041 * @param psduMap the PSDU map
1042 * @param txVector the TX vector
1043 * @param txPowerW the transmit power in Watts
1044 */
1045 void NotifyPsduForwardedDown(WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW);
1046 /**
1047 * Callback invoked when the reception of the MAC header of an MPDU is completed.
1048 * @param mac the MAC to which the reception of the MAC header is notified
1049 * @param macHdr the MAC header of the MPDU being received
1050 * @param txVector the TXVECTOR used to transmit the PSDU
1051 * @param psduDuration the remaining duration of the PSDU
1052 */
1054 const WifiMacHeader& macHdr,
1055 const WifiTxVector& txVector,
1056 Time psduDuration);
1057 /**
1058 * Callback invoked when the receiver MAC forwards a packet up to the upper layer
1059 * @param p the packet
1060 */
1062};
1063
1065 : TestCase("Test case to check that the Wifi Mac forwards up the same packets received at "
1066 "sender side."),
1067 m_notifyMacHdrRxEnd(notifyMacHdrRxEnd)
1068{
1069}
1070
1074
1075void
1080
1081void
1083 WifiTxVector txVector,
1084 double txPowerW)
1085{
1086 NS_TEST_EXPECT_MSG_EQ((psduMap.size() == 1 && psduMap.begin()->first == SU_STA_ID),
1087 true,
1088 "No DL MU PPDU expected");
1089
1090 // m_txPsdu is reset when the MAC header of the last MPDU in the PSDU is notified. By
1091 // checking that m_txPsdu is nullptr when starting the transmission of a PSDU, we ensure
1092 // that MAC headers are notified to the FEM while receiving MPDUs.
1094 {
1096 nullptr,
1097 "Missing MAC header notification: m_txPsdu was not reset");
1098 }
1099
1100 m_txPsdu = psduMap.at(SU_STA_ID);
1101 m_expectedMpdu = m_txPsdu->begin();
1102
1103 if (!psduMap[SU_STA_ID]->GetHeader(0).IsQosData())
1104 {
1105 return;
1106 }
1107
1108 m_nMpdus.push_back(psduMap[SU_STA_ID]->GetNMpdus());
1109
1110 for (auto& mpdu : *PeekPointer(psduMap[SU_STA_ID]))
1111 {
1112 std::size_t dist = std::distance(mpdu->begin(), mpdu->end());
1113 // the list of aggregated MSDUs is empty if the MPDU includes a non-aggregated MSDU
1114 m_nMsdus.push_back(dist > 0 ? dist : 1);
1115 }
1116}
1117
1118void
1120 const WifiMacHeader& macHdr,
1121 const WifiTxVector& txVector,
1122 Time psduDuration)
1123{
1125 nullptr,
1126 "Notified of MAC header RX end while no PSDU is being transmitted");
1127 // check that the FEM stores the expected MAC header (in a nanosecond, to avoid issues
1128 // with the ordering of the callbacks connected to the trace source)
1129 auto expectedHdr = (*m_expectedMpdu)->GetHeader();
1130 Simulator::Schedule(NanoSeconds(1), [=, this]() {
1131 auto macHdr = mac->GetFrameExchangeManager()->GetReceivedMacHdr();
1132 NS_TEST_ASSERT_MSG_EQ(macHdr.has_value(),
1133 true,
1134 "Expected the FEM to store the MAC header being received");
1136 expectedHdr.GetSequenceNumber(),
1137 "Wrong sequence number in the MAC header stored by the FEM");
1138 });
1139
1140 if (expectedHdr.IsQosData())
1141 {
1142 m_nMacHdrs++;
1143 }
1144
1145 if (++m_expectedMpdu == m_txPsdu->end())
1146 {
1147 m_txPsdu = nullptr;
1148 // check that the FEM stores no MAC header right after PSDU end
1149 Simulator::Schedule(psduDuration + NanoSeconds(1), [=, this]() {
1150 auto macHeader = mac->GetFrameExchangeManager()->GetReceivedMacHdr();
1151 NS_TEST_EXPECT_MSG_EQ(macHeader.has_value(),
1152 false,
1153 "Expected the FEM to store no MAC header");
1154 });
1155 }
1156}
1157
1158void
1160{
1161 auto it = std::find(m_packetList.begin(), m_packetList.end(), p);
1162 NS_TEST_EXPECT_MSG_EQ((it != m_packetList.end()), true, "Packet being forwarded up not found");
1163 m_packetList.erase(it);
1164}
1165
1166void
1168{
1169 Config::SetDefault("ns3::WifiPhy::NotifyMacHdrRxEnd", BooleanValue(m_notifyMacHdrRxEnd));
1170
1171 NodeContainer wifiStaNode;
1172 wifiStaNode.Create(1);
1173
1174 NodeContainer wifiApNode;
1175 wifiApNode.Create(1);
1176
1179 phy.SetChannel(channel.Create());
1180
1181 WifiHelper wifi;
1182 wifi.SetStandard(WIFI_STANDARD_80211n);
1183 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
1184
1185 WifiMacHelper mac;
1186 Ssid ssid = Ssid("ns-3-ssid");
1187 mac.SetType("ns3::StaWifiMac",
1188 "BE_MaxAmsduSize",
1189 UintegerValue(4500),
1190 "BE_MaxAmpduSize",
1191 UintegerValue(7500),
1192 "Ssid",
1193 SsidValue(ssid),
1194 /* setting blockack threshold for sta's BE queue */
1195 "BE_BlockAckThreshold",
1196 UintegerValue(2),
1197 "ActiveProbing",
1198 BooleanValue(false));
1199
1200 NetDeviceContainer staDevices;
1201 staDevices = wifi.Install(phy, mac, wifiStaNode);
1202
1203 mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid), "BeaconGeneration", BooleanValue(true));
1204
1205 NetDeviceContainer apDevices;
1206 apDevices = wifi.Install(phy, mac, wifiApNode);
1207
1208 MobilityHelper mobility;
1210
1211 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
1212 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
1213 mobility.SetPositionAllocator(positionAlloc);
1214
1215 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1216 mobility.Install(wifiApNode);
1217 mobility.Install(wifiStaNode);
1218
1219 Ptr<WifiNetDevice> ap_device = DynamicCast<WifiNetDevice>(apDevices.Get(0));
1220 Ptr<WifiNetDevice> sta_device = DynamicCast<WifiNetDevice>(staDevices.Get(0));
1221
1222 PacketSocketAddress socket;
1223 socket.SetSingleDevice(sta_device->GetIfIndex());
1224 socket.SetPhysicalAddress(ap_device->GetAddress());
1225 socket.SetProtocol(1);
1226
1227 // install packet sockets on nodes.
1228 PacketSocketHelper packetSocket;
1229 packetSocket.Install(wifiStaNode);
1230 packetSocket.Install(wifiApNode);
1231
1233 client->SetAttribute("PacketSize", UintegerValue(1000));
1234 client->SetAttribute("MaxPackets", UintegerValue(8));
1235 client->SetAttribute("Interval", TimeValue(Seconds(1)));
1236 client->SetRemote(socket);
1237 wifiStaNode.Get(0)->AddApplication(client);
1238 client->SetStartTime(Seconds(1));
1239 client->SetStopTime(Seconds(3));
1242 client,
1243 "Interval",
1245
1247 server->SetLocal(socket);
1248 wifiApNode.Get(0)->AddApplication(server);
1249 server->SetStartTime(Seconds(0));
1250 server->SetStopTime(Seconds(4));
1251
1252 sta_device->GetMac()->TraceConnectWithoutContext(
1253 "MacTx",
1255 sta_device->GetPhy()->TraceConnectWithoutContext(
1256 "PhyTxPsduBegin",
1258 ap_device->GetPhy()->TraceConnectWithoutContext(
1259 "PhyRxMacHeaderEnd",
1261 .Bind(ap_device->GetMac()));
1262 ap_device->GetMac()->TraceConnectWithoutContext(
1263 "MacRx",
1265
1268
1270
1271 // Two packets are transmitted. The first one is an MPDU containing a single MSDU.
1272 // The second one is an A-MPDU containing two MPDUs: the first MPDU contains 4 MSDUs
1273 // and the second MPDU contains 3 MSDUs
1274 NS_TEST_EXPECT_MSG_EQ(m_nMpdus.size(), 2, "Unexpected number of transmitted packets");
1275 NS_TEST_EXPECT_MSG_EQ(m_nMsdus.size(), 3, "Unexpected number of transmitted MPDUs");
1276 NS_TEST_EXPECT_MSG_EQ(m_nMpdus[0], 1, "Unexpected number of MPDUs in the first A-MPDU");
1277 NS_TEST_EXPECT_MSG_EQ(m_nMsdus[0], 1, "Unexpected number of MSDUs in the first MPDU");
1278 NS_TEST_EXPECT_MSG_EQ(m_nMpdus[1], 2, "Unexpected number of MPDUs in the second A-MPDU");
1279 NS_TEST_EXPECT_MSG_EQ(m_nMsdus[1], 4, "Unexpected number of MSDUs in the second MPDU");
1280 NS_TEST_EXPECT_MSG_EQ(m_nMsdus[2], 3, "Unexpected number of MSDUs in the third MPDU");
1281 // Three MPDUs (of type QoS data) have been transmitted, so we expect that 3 MAC headers
1282 // have been notified to the FEM
1284 (m_notifyMacHdrRxEnd ? 3 : 0),
1285 "Unexpected number of MAC headers notified to the FEM");
1286 // All the packets must have been forwarded up at the receiver
1287 NS_TEST_EXPECT_MSG_EQ(m_packetList.empty(), true, "Some packets have not been forwarded up");
1288}
1289
1290/**
1291 * @ingroup wifi-test
1292 * @ingroup tests
1293 *
1294 * @brief Wifi Aggregation Test Suite
1295 */
1297{
1298 public:
1300};
1301
1315
return result
Ampdu Aggregation Test.
bool m_discarded
whether the packet should be discarded
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Ptr< QosTxop > GetBeQueue() const
void DoSetup() override
Implementation to do any local setup required for this TestCase.
ObjectFactory m_factory
factory
Params m_params
test parameters
void CheckMaxPsduSize(Ptr< WifiPhy > phy, Ptr< HtFrameExchangeManager > fem)
Check the maximum PSDU size.
void EnqueuePkts(std::size_t count, uint32_t size, const Mac48Address &dest)
Enqueue the given number of packets addressed to the given station and of the given size.
std::vector< Ptr< WifiRemoteStationManager > > m_managers
remote station managers
void DoRun() override
Implementation to actually run this TestCase.
Ptr< WifiNetDevice > m_device
WifiNetDevice.
void DequeueMpdus(const std::vector< Ptr< WifiMpdu > > &mpduList)
Dequeue a PSDU.
void EstablishAgreement(const Mac48Address &recipient)
Establish a BlockAck agreement.
void MpduDiscarded(WifiMacDropReason reason, Ptr< const WifiMpdu > mpdu)
Fired when the MAC discards an MPDU.
std::vector< Ptr< WifiPhy > > m_phys
Phys.
Ptr< StaWifiMac > m_mac
Mac.
802.11be aggregation test which permits up to 1024 MPDUs in A-MPDU according to the negotiated buffer...
void DoRun() override
Implementation to actually run this TestCase.
EhtAggregationTest(uint16_t bufferSize, uint32_t maxAmpduSize)
Constructor.
802.11ax aggregation test which permits 64 or 256 MPDUs in A-MPDU according to the negotiated buffer ...
HeAggregationTest(uint16_t bufferSize)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
Test for A-MSDU and A-MPDU aggregation.
void DoRun() override
Implementation to actually run this TestCase.
void NotifyPsduForwardedDown(WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when the sender MAC passes a PSDU(s) to the PHY.
void NotifyMacHeaderEndRx(Ptr< WifiMac > mac, const WifiMacHeader &macHdr, const WifiTxVector &txVector, Time psduDuration)
Callback invoked when the reception of the MAC header of an MPDU is completed.
std::list< Ptr< const Packet > > m_packetList
List of packets passed to the MAC.
PreservePacketsInAmpdus(bool notifyMacHdrRxEnd)
Constructor.
std::vector< std::size_t > m_nMsdus
Number of MSDUs in MPDUs passed to the PHY.
std::vector< std::size_t > m_nMpdus
Number of MPDUs in PSDUs passed to the PHY.
std::vector< Ptr< WifiMpdu > >::const_iterator m_expectedMpdu
next MPDU expected to be received
std::size_t m_nMacHdrs
Number of notified MAC headers in QoS data frames.
void NotifyMacForwardUp(Ptr< const Packet > p)
Callback invoked when the receiver MAC forwards a packet up to the upper layer.
void NotifyMacTransmit(Ptr< const Packet > packet)
Callback invoked when an MSDU is passed to the MAC.
bool m_notifyMacHdrRxEnd
whether notification of MAC header reception end is enabled
Ptr< const WifiPsdu > m_txPsdu
PSDU being transmitted.
Two Level Aggregation Test.
void DoRun() override
Implementation to actually run this TestCase.
Wifi Aggregation Test Suite.
A container for one type of attribute.
AttributeValue implementation for Boolean.
Definition boolean.h:26
The IEEE 802.11be EHT Capabilities.
void SetMaxMpduLength(uint16_t length)
Set the maximum MPDU length.
void SetMaxAmpduLength(uint32_t maxAmpduLength)
Set the maximum A-MPDU length.
FrameExchangeManager is a base class handling the basic frame exchange sequences for non-QoS stations...
The IEEE 802.11ax HE Capabilities.
void SetMaxAmpduLength(uint32_t maxAmpduLength)
Set the maximum AMPDU length.
void SetChannelWidthSet(uint8_t channelWidthSet)
Set channel width set.
The HT Capabilities Information Element.
void SetMaxAmsduLength(uint16_t maxAmsduLength)
Set the maximum AMSDU length.
void SetMaxAmpduLength(uint32_t maxAmpduLength)
Set the maximum AMPDU length.
an EUI-48 address
static Mac48Address GetBroadcast()
Implement the header for management frames of type Add Block Ack request.
void SetBufferSize(uint16_t size)
Set buffer size.
void SetImmediateBlockAck()
Enable immediate BlockAck.
uint16_t GetTimeout() const
Return the timeout.
uint8_t GetTid() const
Return the Traffic ID (TID).
bool IsAmsduSupported() const
Return whether A-MSDU capability is supported.
void SetTimeout(uint16_t timeout)
Set timeout.
void SetTid(uint8_t tid)
Set Traffic ID (TID).
void SetStartingSequence(uint16_t seq)
Set the starting sequence number.
Implement the header for management frames of type Add Block Ack response.
void SetTid(uint8_t tid)
Set Traffic ID (TID).
void SetTimeout(uint16_t timeout)
Set timeout.
void SetBufferSize(uint16_t size)
Set buffer size.
void SetStatusCode(StatusCode code)
Set the status code.
void SetAmsduSupport(bool supported)
Enable or disable A-MSDU support.
void SetImmediateBlockAck()
Enable immediate BlockAck.
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:153
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Instantiate subclasses of ns3::Object.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
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:37
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:67
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
Status code for association response.
Definition status-code.h:21
void SetSuccess()
Set success bit to 0 (success).
Hold variables of type string.
Definition string.h:45
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:293
@ QUICK
Fast test.
Definition test.h:1054
TestCase(const TestCase &)=delete
Type
Type of test.
Definition test.h:1257
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:491
Simulation virtual time values and global simulation resolution.
Definition nstime.h:96
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition nstime.h:278
AttributeValue implementation for Time.
Definition nstime.h:1456
Hold an unsigned integer type.
Definition uinteger.h:34
The IEEE 802.11ac VHT Capabilities.
void SetMaxMpduLength(uint16_t length)
Set the maximum MPDU length.
helps to create WifiNetDevice objects
Implements the IEEE 802.11 MAC header.
uint16_t GetSequenceNumber() const
Return the sequence number of the header.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
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.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
create MAC layers for a ns3::WifiNetDevice.
hold a list of per-remote-station state.
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
WifiTxVector m_txVector
TXVECTOR of the frame being prepared.
void Clear()
Reset the TX parameters.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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:886
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:439
#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:133
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
Definition test.h:655
#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:240
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1393
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1405
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiMacDropReason
The reason why an MPDU was dropped.
Definition wifi-mac.h:71
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ AC_BE
Best Effort.
Definition qos-utils.h:65
const std::map< WifiStandard, uint32_t > maxPsduLengths
Map standard to aPSDUMaxLength.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:448
static constexpr uint32_t WIFI_PSDU_MAX_LENGTH_HE
The value for aPSDUMaxLength in Table 27-54 (HE PHY characteristics) of 802.11ax-2021.
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:684
static constexpr uint32_t WIFI_PSDU_MAX_LENGTH_HT
The value for aPSDUMaxLength in Table 19-25 (HT PHY characteristics) of 802.11-2020.
std::string GetFrameExchangeManagerTypeIdName(WifiStandard standard, bool qosSupported)
Get the TypeId name for the FrameExchangeManager corresponding to the given standard.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:585
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
Definition wifi-utils.h:295
static constexpr uint32_t WIFI_PSDU_MAX_LENGTH_VHT
The value for aPSDUMaxLength in Table 21-28 (VHT PHY characteristics) of 802.11-2020.
@ WIFI_MAC_QOSDATA
static constexpr uint32_t WIFI_PSDU_MAX_LENGTH_EHT
The value for aPSDUMaxLength in Table 36-70 (EHT PHY characteristics) of 802.11be D7....
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU).
STL namespace.
uint8_t nLinks
number of links (>1 only for EHT)
uint32_t maxAmpduSize
maximum A-MPDU size (bytes)
uint16_t bufferSize
the size (in number of MPDUs) of the BlockAck buffer
WifiStandard standard
the standard of the device
uint16_t maxAmsduSize
maximum A-MSDU size (bytes)
Time txopLimit
TXOP limit duration.
static WifiAggregationTestSuite g_wifiAggregationTestSuite
the test suite