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 * 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: Sébastien Deronne <sebastien.deronne@gmail.com>
18 */
19
20#include "ns3/eht-configuration.h"
21#include "ns3/fcfs-wifi-queue-scheduler.h"
22#include "ns3/he-configuration.h"
23#include "ns3/ht-configuration.h"
24#include "ns3/ht-frame-exchange-manager.h"
25#include "ns3/interference-helper.h"
26#include "ns3/mac-tx-middle.h"
27#include "ns3/mgt-action-headers.h"
28#include "ns3/mobility-helper.h"
29#include "ns3/mpdu-aggregator.h"
30#include "ns3/msdu-aggregator.h"
31#include "ns3/multi-link-element.h"
32#include "ns3/node-container.h"
33#include "ns3/packet-socket-client.h"
34#include "ns3/packet-socket-helper.h"
35#include "ns3/packet-socket-server.h"
36#include "ns3/pointer.h"
37#include "ns3/simulator.h"
38#include "ns3/sta-wifi-mac.h"
39#include "ns3/string.h"
40#include "ns3/test.h"
41#include "ns3/vht-configuration.h"
42#include "ns3/wifi-default-ack-manager.h"
43#include "ns3/wifi-default-protection-manager.h"
44#include "ns3/wifi-mac-queue.h"
45#include "ns3/wifi-net-device.h"
46#include "ns3/wifi-psdu.h"
47#include "ns3/yans-wifi-helper.h"
48#include "ns3/yans-wifi-phy.h"
49#include <ns3/attribute-container.h>
50
51#include <algorithm>
52#include <iterator>
53#include <vector>
54
55using namespace ns3;
56
57/**
58 * \ingroup wifi-test
59 * \ingroup tests
60 *
61 * \brief Ampdu Aggregation Test
62 */
64{
65 public:
67
68 /// Test parameters
69 struct Params
70 {
71 WifiStandard standard; //!< the standard of the device
72 uint8_t nLinks; //!< number of links (>1 only for EHT)
73 std::string dataMode; //!< data mode
74 uint16_t bufferSize; //!< the size (in number of MPDUs) of the BlockAck buffer
75 uint16_t maxAmsduSize; //!< maximum A-MSDU size (bytes)
76 uint32_t maxAmpduSize; //!< maximum A-MPDU size (bytes)
77 Time txopLimit; //!< TXOP limit duration
78 };
79
80 /**
81 * Construct object with non-default test parameters
82 *
83 * \param name the name of the test case
84 * \param params the test parameters
85 */
86 AmpduAggregationTest(const std::string& name, const Params& params);
87
88 protected:
89 /**
90 * Establish a BlockAck agreement.
91 *
92 * \param recipient the recipient MAC address
93 */
94 void EstablishAgreement(const Mac48Address& recipient);
95
96 /**
97 * Enqueue the given number of packets addressed to the given station and of the given size.
98 *
99 * \param count the number of packets
100 * \param size the size (bytes) of each packet
101 * \param dest the destination address
102 */
103 void EnqueuePkts(std::size_t count, uint32_t size, const Mac48Address& dest);
104
105 /**
106 * \return the Best Effort QosTxop
107 */
108 Ptr<QosTxop> GetBeQueue() const;
109
110 /**
111 * Dequeue a PSDU.
112 *
113 * \param mpduList the MPDUs contained in the PSDU
114 */
115 void DequeueMpdus(const std::vector<Ptr<WifiMpdu>>& mpduList);
116
118 std::vector<Ptr<WifiPhy>> m_phys; ///< Phys
119 Params m_params; //!< test parameters
120
121 private:
122 /**
123 * Fired when the MAC discards an MPDU.
124 *
125 * \param reason the reason why the MPDU was discarded
126 * \param mpdu the discarded MPDU
127 */
129
130 void DoSetup() override;
131 void DoRun() override;
132 void DoTeardown() override;
133
134 Ptr<WifiNetDevice> m_device; ///< WifiNetDevice
135 std::vector<Ptr<WifiRemoteStationManager>> m_managers; ///< remote station managers
137 bool m_discarded; ///< whether the packet should be discarded
138};
139
141 : AmpduAggregationTest("Check the correctness of MPDU aggregation operations",
142 Params{.standard = WIFI_STANDARD_80211n,
143 .nLinks = 1,
144 .dataMode = "HtMcs7",
145 .bufferSize = 64,
146 .maxAmsduSize = 0,
147 .maxAmpduSize = 65535,
148 .txopLimit = Seconds(0)})
149{
150}
151
152AmpduAggregationTest::AmpduAggregationTest(const std::string& name, const Params& params)
153 : TestCase(name),
154 m_params(params),
155 m_discarded(false)
156{
157}
158
159void
161{
162 m_discarded = true;
163}
164
165void
167{
168 /*
169 * Create device and attach HT configuration.
170 */
171 m_device = CreateObject<WifiNetDevice>();
173 auto htConfiguration = CreateObject<HtConfiguration>();
174 m_device->SetHtConfiguration(htConfiguration);
176 {
177 auto vhtConfiguration = CreateObject<VhtConfiguration>();
178 m_device->SetVhtConfiguration(vhtConfiguration);
179 auto heConfiguration = CreateObject<HeConfiguration>();
180 m_device->SetHeConfiguration(heConfiguration);
181 }
183 {
184 auto ehtConfiguration = CreateObject<EhtConfiguration>();
185 m_device->SetEhtConfiguration(ehtConfiguration);
186 }
187
188 /*
189 * Create and configure phy layer.
190 */
191 for (uint8_t i = 0; i < m_params.nLinks; i++)
192 {
193 m_phys.emplace_back(CreateObject<YansWifiPhy>());
194 auto interferenceHelper = CreateObject<InterferenceHelper>();
195 m_phys.back()->SetInterferenceHelper(interferenceHelper);
196 m_phys.back()->SetDevice(m_device);
197 m_phys.back()->ConfigureStandard(m_params.standard);
198 }
200
201 /*
202 * Create and configure manager.
203 */
205 m_factory.SetTypeId("ns3::ConstantRateWifiManager");
207 for (uint8_t i = 0; i < m_params.nLinks; i++)
208 {
210 m_managers.back()->SetupPhy(m_phys.at(i));
211 }
213
214 /*
215 * Create and configure mac layer.
216 */
217 m_mac = CreateObjectWithAttributes<StaWifiMac>(
218 "QosSupported",
219 BooleanValue(true),
220 "BE_Txop",
221 PointerValue(CreateObjectWithAttributes<QosTxop>("AcIndex", StringValue("AC_BE"))),
222 "BK_Txop",
223 PointerValue(CreateObjectWithAttributes<QosTxop>("AcIndex", StringValue("AC_BK"))),
224 "VI_Txop",
225 PointerValue(CreateObjectWithAttributes<QosTxop>("AcIndex", StringValue("AC_VI"))),
226 "VO_Txop",
227 PointerValue(CreateObjectWithAttributes<QosTxop>("AcIndex", StringValue("AC_VO"))));
230 for (uint8_t i = 0; i < m_params.nLinks; i++)
231 {
232 m_managers.at(i)->SetupMac(m_mac);
233 }
234 m_mac->SetAddress(Mac48Address("00:00:00:00:00:01"));
237 std::vector<Ptr<ChannelAccessManager>> caManagers;
238 for (uint8_t i = 0; i < m_params.nLinks; i++)
239 {
240 caManagers.emplace_back(CreateObject<ChannelAccessManager>());
241 }
242 m_mac->SetChannelAccessManagers(caManagers);
243 ObjectFactory femFactory;
245 std::vector<Ptr<FrameExchangeManager>> feManagers;
246 for (uint8_t i = 0; i < m_params.nLinks; i++)
247 {
248 auto fem = femFactory.Create<FrameExchangeManager>();
249 feManagers.emplace_back(fem);
250 auto protectionManager = CreateObject<WifiDefaultProtectionManager>();
251 protectionManager->SetWifiMac(m_mac);
252 fem->SetProtectionManager(protectionManager);
253 auto ackManager = CreateObject<WifiDefaultAckManager>();
254 ackManager->SetWifiMac(m_mac);
255 fem->SetAckManager(ackManager);
256 // here we should assign distinct link addresses in case of MLDs, but we don't actually use
257 // link addresses in this test
258 fem->SetAddress(m_mac->GetAddress());
259 }
260 m_mac->SetFrameExchangeManagers(feManagers);
262 if (m_params.nLinks > 1)
263 {
264 // the bssid field of StaLinkEntity must hold a value
265 for (const auto& [id, link] : m_mac->GetLinks())
266 {
268 }
269 }
270 m_mac->SetMacQueueScheduler(CreateObject<FcfsWifiQueueScheduler>());
271
272 /*
273 * Configure A-MSDU and A-MPDU aggregation.
274 */
275 // Make sure that at least 1024 MPDUs are buffered (to test aggregation on EHT devices)
276 m_mac->GetTxopQueue(AC_BE)->SetAttribute("MaxSize", StringValue("2000p"));
280 "TxopLimits",
282
283 if (m_params.nLinks > 1)
284 {
285 auto mleCommonInfo2 = std::make_shared<CommonInfoBasicMle>();
286 mleCommonInfo2->m_mldMacAddress = Mac48Address("00:00:00:00:00:02");
287 for (uint8_t i = 0; i < m_params.nLinks; i++)
288 {
289 // we don't actually use the link addresses of the receiver, so we just use one address
290 // as both the MLD address and the link address of the receiver (the first argument in
291 // the call below should be the link address)
292 m_managers.at(i)->AddStationMleCommonInfo(mleCommonInfo2->m_mldMacAddress,
293 mleCommonInfo2);
294 }
295
296 auto mleCommonInfo3 = std::make_shared<CommonInfoBasicMle>();
297 mleCommonInfo3->m_mldMacAddress = Mac48Address("00:00:00:00:00:03");
298 for (uint8_t i = 0; i < m_params.nLinks; i++)
299 {
300 m_managers.at(i)->AddStationMleCommonInfo(mleCommonInfo3->m_mldMacAddress,
301 mleCommonInfo3);
302 }
303 }
304
305 for (uint8_t i = 0; i < m_params.nLinks; i++)
306 {
307 HtCapabilities htCapabilities;
308 htCapabilities.SetMaxAmsduLength(7935);
309 htCapabilities.SetMaxAmpduLength(65535);
310 m_managers.at(i)->AddStationHtCapabilities(Mac48Address("00:00:00:00:00:02"),
311 htCapabilities);
312 m_managers.at(i)->AddStationHtCapabilities(Mac48Address("00:00:00:00:00:03"),
313 htCapabilities);
314
316 {
317 VhtCapabilities vhtCapabilities;
318 vhtCapabilities.SetMaxMpduLength(11454);
319 m_managers.at(i)->AddStationVhtCapabilities(Mac48Address("00:00:00:00:00:02"),
320 vhtCapabilities);
321 }
323 {
324 HeCapabilities heCapabilities;
325 heCapabilities.SetMaxAmpduLength((1 << 23) - 1);
326 m_managers.at(i)->AddStationHeCapabilities(Mac48Address("00:00:00:00:00:02"),
327 heCapabilities);
328 }
330 {
331 EhtCapabilities ehtCapabilities;
332 ehtCapabilities.SetMaxMpduLength(11454);
333 ehtCapabilities.SetMaxAmpduLength((1 << 24) - 1);
334 m_managers.at(i)->AddStationEhtCapabilities(Mac48Address("00:00:00:00:00:02"),
335 ehtCapabilities);
336 }
337 }
338
339 /*
340 * Establish agreement.
341 */
342 EstablishAgreement(Mac48Address("00:00:00:00:00:02"));
343}
344
347{
348 return m_mac->GetBEQueue();
349}
350
351void
353{
354 std::list<Ptr<const WifiMpdu>> mpdus(mpduList.cbegin(), mpduList.cend());
355 m_mac->GetTxopQueue(AC_BE)->DequeueIfQueued(mpdus);
356}
357
358void
360{
362 reqHdr.SetImmediateBlockAck();
363 reqHdr.SetTid(0);
365 reqHdr.SetTimeout(0);
366 reqHdr.SetStartingSequence(0);
367 GetBeQueue()->GetBaManager()->CreateOriginatorAgreement(reqHdr, recipient);
368
370 StatusCode code;
371 code.SetSuccess();
372 respHdr.SetStatusCode(code);
373 respHdr.SetAmsduSupport(reqHdr.IsAmsduSupported());
374 respHdr.SetImmediateBlockAck();
375 respHdr.SetTid(reqHdr.GetTid());
377 respHdr.SetTimeout(reqHdr.GetTimeout());
378 GetBeQueue()->GetBaManager()->UpdateOriginatorAgreement(respHdr, recipient, 0);
379}
380
381void
382AmpduAggregationTest::EnqueuePkts(std::size_t count, uint32_t size, const Mac48Address& dest)
383{
384 for (std::size_t i = 0; i < count; i++)
385 {
386 auto pkt = Create<Packet>(size);
387 WifiMacHeader hdr;
388
389 hdr.SetAddr1(dest);
390 hdr.SetAddr2(Mac48Address("00:00:00:00:00:01"));
392 hdr.SetQosTid(0);
393
394 GetBeQueue()->GetWifiMacQueue()->Enqueue(Create<WifiMpdu>(pkt, hdr));
395 }
396}
397
398void
400{
401 /*
402 * Test behavior when no other packets are in the queue
403 */
405 auto htFem = DynamicCast<HtFrameExchangeManager>(fem);
406 auto mpduAggregator = htFem->GetMpduAggregator();
407
408 /*
409 * Create a dummy packet of 1500 bytes and fill mac header fields.
410 */
411 EnqueuePkts(1, 1500, Mac48Address("00:00:00:00:00:02"));
412
413 auto peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
414 WifiTxParameters txParams;
415 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
416 peeked->GetHeader(),
417 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
418 auto item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
419
420 auto mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
421
422 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), true, "a single packet should not result in an A-MPDU");
423
424 // the packet has not been "transmitted", release its sequence number
425 m_mac->m_txMiddle->SetSequenceNumberFor(&item->GetHeader());
426 item->UnassignSeqNo();
427
428 //---------------------------------------------------------------------------------------------
429
430 /*
431 * Test behavior when 2 more packets are in the queue
432 */
433 EnqueuePkts(2, 1500, Mac48Address("00:00:00:00:00:02"));
434
435 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
436 mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
437
438 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
439
440 auto psdu = Create<WifiPsdu>(mpduList);
441 DequeueMpdus(mpduList);
442
443 NS_TEST_EXPECT_MSG_EQ(psdu->GetSize(), 4606, "A-MPDU size is not correct");
444 NS_TEST_EXPECT_MSG_EQ(mpduList.size(), 3, "A-MPDU should contain 3 MPDUs");
445 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
446 0,
447 "queue should be empty");
448
449 for (uint32_t i = 0; i < psdu->GetNMpdus(); i++)
450 {
451 NS_TEST_EXPECT_MSG_EQ(psdu->GetHeader(i).GetSequenceNumber(), i, "wrong sequence number");
452 }
453
454 //---------------------------------------------------------------------------------------------
455
456 /*
457 * Test behavior when the 802.11n station and another non-QoS station are associated to the AP.
458 * The AP sends an A-MPDU to the 802.11n station followed by the last retransmission of a
459 * non-QoS data frame to the non-QoS station. This is used to reproduce bug 2224.
460 */
461 EnqueuePkts(1, 1500, Mac48Address("00:00:00:00:00:02"));
462 EnqueuePkts(2, 1500, Mac48Address("00:00:00:00:00:03"));
463
465 txParams.Clear();
466 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
467 peeked->GetHeader(),
468 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
469 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
470
471 mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
472
473 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(),
474 true,
475 "a single packet for this destination should not result in an A-MPDU");
476 // dequeue the MPDU
477 DequeueMpdus({item});
478
480 txParams.Clear();
481 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
482 peeked->GetHeader(),
483 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
484 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
485
486 mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
487
488 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(),
489 true,
490 "no MPDU aggregation should be performed if there is no agreement");
491
493 ->SetMaxSsrc(
494 0); // set to 0 in order to fake that the maximum number of retries has been reached
495 m_mac->TraceConnectWithoutContext("DroppedMpdu",
497 htFem->m_dcf = GetBeQueue();
498 htFem->NormalAckTimeout(item, txParams.m_txVector);
499
500 NS_TEST_EXPECT_MSG_EQ(m_discarded, true, "packet should be discarded");
501 GetBeQueue()->GetWifiMacQueue()->Flush();
502}
503
504void
506{
508
509 for (auto manager : m_managers)
510 {
511 manager->Dispose();
512 }
513 m_managers.clear();
514
515 m_device->Dispose();
516 m_device = nullptr;
517}
518
519/**
520 * \ingroup wifi-test
521 * \ingroup tests
522 *
523 * \brief Two Level Aggregation Test
524 */
526{
527 public:
529
530 private:
531 void DoRun() override;
532};
533
535 : AmpduAggregationTest("Check the correctness of two-level aggregation operations",
536 Params{.standard = WIFI_STANDARD_80211n,
537 .nLinks = 1,
538 .dataMode = "HtMcs2", // 19.5Mbps
539 .bufferSize = 64,
540 .maxAmsduSize = 3050,
541 .maxAmpduSize = 65535,
542 .txopLimit = MicroSeconds(3008)})
543{
544}
545
546void
548{
549 /*
550 * Create dummy packets of 1500 bytes and fill mac header fields that will be used for the
551 * tests.
552 */
553 EnqueuePkts(3, 1500, Mac48Address("00:00:00:00:00:02"));
554
555 //---------------------------------------------------------------------------------------------
556
557 /*
558 * Test MSDU and MPDU aggregation. Three MSDUs are in the queue and the maximum A-MSDU size
559 * is such that only two MSDUs can be aggregated. Therefore, the first MPDU we get contains
560 * an A-MSDU of 2 MSDUs.
561 */
563 auto htFem = DynamicCast<HtFrameExchangeManager>(fem);
564 auto msduAggregator = htFem->GetMsduAggregator();
565 auto mpduAggregator = htFem->GetMpduAggregator();
566
567 auto peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
568 WifiTxParameters txParams;
569 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
570 peeked->GetHeader(),
571 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
572 htFem->TryAddMpdu(peeked, txParams, Time::Min());
573 auto item = msduAggregator->GetNextAmsdu(peeked, txParams, Time::Min());
574
575 bool result{item};
576 NS_TEST_EXPECT_MSG_EQ(result, true, "aggregation failed");
577 NS_TEST_EXPECT_MSG_EQ(item->GetPacketSize(), 3030, "wrong packet size");
578
579 // dequeue the MSDUs
580 DequeueMpdus({item});
581
582 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
583 1,
584 "Unexpected number of MSDUs left in the EDCA queue");
585
586 //---------------------------------------------------------------------------------------------
587
588 /*
589 * A-MSDU aggregation fails when there is just one MSDU in the queue.
590 */
591
593 txParams.Clear();
594 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
595 peeked->GetHeader(),
596 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
597 htFem->TryAddMpdu(peeked, txParams, Time::Min());
598 item = msduAggregator->GetNextAmsdu(peeked, txParams, Time::Min());
599
600 NS_TEST_EXPECT_MSG_EQ(item, nullptr, "A-MSDU aggregation did not fail");
601
602 DequeueMpdus({peeked});
603
604 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
605 0,
606 "queue should be empty");
607
608 //---------------------------------------------------------------------------------------------
609
610 /*
611 * Aggregation of MPDUs is stopped to prevent that the PPDU duration exceeds the TXOP limit.
612 * In this test, a TXOP limit of 3008 microseconds is used.
613 */
614
615 // Add 10 MSDUs to the EDCA queue
616 EnqueuePkts(10, 1300, Mac48Address("00:00:00:00:00:02"));
617
619 txParams.Clear();
620 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
621 peeked->GetHeader(),
622 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
623
624 // Compute the first MPDU to be aggregated in an A-MPDU. It must contain an A-MSDU
625 // aggregating two MSDUs
626 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, m_params.txopLimit, true);
627
628 NS_TEST_EXPECT_MSG_EQ(std::distance(item->begin(), item->end()),
629 2,
630 "There must be 2 MSDUs in the A-MSDU");
631
632 auto mpduList = mpduAggregator->GetNextAmpdu(item, txParams, m_params.txopLimit);
633
634 // The maximum number of bytes that can be transmitted in a TXOP is (approximately, as we
635 // do not consider that the preamble is transmitted at a different rate):
636 // 19.5 Mbps * 3.008 ms = 7332 bytes
637 // Given that the max A-MSDU size is set to 3050, an A-MSDU will contain two MSDUs and have
638 // a size of 2 * 1300 (MSDU size) + 2 * 14 (A-MSDU subframe header size) + 2 (one padding field)
639 // = 2630 bytes Hence, we expect that the A-MPDU will consist of:
640 // - 2 MPDUs containing each an A-MSDU. The size of each MPDU is 2630 (A-MSDU) + 30
641 // (header+trailer) = 2660
642 // - 1 MPDU containing a single MSDU. The size of such MPDU is 1300 (MSDU) + 30 (header+trailer)
643 // = 1330 The size of the A-MPDU is 4 + 2660 + 4 + 2660 + 4 + 1330 = 6662
644 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "aggregation failed");
645 NS_TEST_EXPECT_MSG_EQ(mpduList.size(), 3, "Unexpected number of MPDUs in the A-MPDU");
646 NS_TEST_EXPECT_MSG_EQ(mpduList.at(0)->GetSize(), 2660, "Unexpected size of the first MPDU");
647 NS_TEST_EXPECT_MSG_EQ(mpduList.at(0)->GetHeader().IsQosAmsdu(),
648 true,
649 "Expecting the first MPDU to contain an A-MSDU");
650 NS_TEST_EXPECT_MSG_EQ(mpduList.at(1)->GetSize(), 2660, "Unexpected size of the second MPDU");
651 NS_TEST_EXPECT_MSG_EQ(mpduList.at(1)->GetHeader().IsQosAmsdu(),
652 true,
653 "Expecting the second MPDU to contain an A-MSDU");
654 NS_TEST_EXPECT_MSG_EQ(mpduList.at(2)->GetSize(), 1330, "Unexpected size of the third MPDU");
655 NS_TEST_EXPECT_MSG_EQ(mpduList.at(2)->GetHeader().IsQosAmsdu(),
656 false,
657 "Expecting the third MPDU not to contain an A-MSDU");
658
659 auto psdu = Create<WifiPsdu>(mpduList);
660 NS_TEST_EXPECT_MSG_EQ(psdu->GetSize(), 6662, "Unexpected size of the A-MPDU");
661
662 // we now have two A-MSDUs and 6 MSDUs in the queue (5 MSDUs with no assigned sequence number)
663 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
664 8,
665 "Unexpected number of items left in the EDCA queue");
666
667 // prepare another A-MPDU (e.g., for transmission on another link)
668 peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID, 0, psdu->GetAddr1(), mpduList.at(2));
669 txParams.Clear();
670 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
671 peeked->GetHeader(),
672 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
673
674 // Compute the first MPDU to be aggregated in an A-MPDU. It must contain an A-MSDU
675 // aggregating two MSDUs
676 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, m_params.txopLimit, true);
677
678 NS_TEST_EXPECT_MSG_EQ(std::distance(item->begin(), item->end()),
679 2,
680 "There must be 2 MSDUs in the A-MSDU");
681
682 auto mpduList2 = mpduAggregator->GetNextAmpdu(item, txParams, m_params.txopLimit);
683
684 // we now have two A-MSDUs, one MSDU, two A-MSDUs and one MSDU in the queue (all with assigned
685 // sequence number)
686 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
687 6,
688 "Unexpected number of items left in the EDCA queue");
689
690 // unassign sequence numbers for all MPDUs (emulates an RTS/CTS failure on both links)
691 mpduList.at(0)->UnassignSeqNo();
692 mpduList.at(1)->UnassignSeqNo();
693 mpduList.at(2)->UnassignSeqNo();
694 mpduList2.at(0)->UnassignSeqNo();
695 mpduList2.at(1)->UnassignSeqNo();
696 mpduList2.at(2)->UnassignSeqNo();
697
698 // set A-MSDU max size to a large value
699 m_mac->SetAttribute("BE_MaxAmsduSize", UintegerValue(7000));
700
701 // A-MSDU aggregation now fails because the first item in the queue contain A-MSDUs
703 txParams.Clear();
704 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
705 peeked->GetHeader(),
706 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
707
708 htFem->TryAddMpdu(peeked, txParams, Time::Min());
709 item = msduAggregator->GetNextAmsdu(peeked, txParams, Time::Min());
710
711 NS_TEST_EXPECT_MSG_EQ(item, nullptr, "Expecting not to be able to aggregate A-MSDUs");
712
713 // remove the first two items in the queue (containing A-MSDUs)
714 DequeueMpdus({mpduList.at(0), mpduList.at(1)});
715
716 // we now have one MSDU, two A-MSDUs and one MSDU in the queue
717 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
718 4,
719 "Unexpected number of items left in the EDCA queue");
720
722 txParams.Clear();
723 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
724 peeked->GetHeader(),
725 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
726
727 NS_TEST_EXPECT_MSG_EQ(peeked->GetHeader().IsQosAmsdu(),
728 false,
729 "Expecting the peeked MPDU not to contain an A-MSDU");
730
731 item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
732
733 // A-MSDU aggregation is not attempted because the next item contains an A-MSDU
734 NS_TEST_EXPECT_MSG_EQ(item->GetHeader().IsQosAmsdu(),
735 false,
736 "Expecting the returned MPDU not to contain an A-MSDU");
737}
738
739/**
740 * \ingroup wifi-test
741 * \ingroup tests
742 *
743 * \brief 802.11ax aggregation test which permits 64 or 256 MPDUs in A-MPDU according to the
744 * negotiated buffer size.
745 */
747{
748 public:
749 /**
750 * Constructor.
751 *
752 * \param bufferSize the size (in number of MPDUs) of the BlockAck buffer
753 */
754 HeAggregationTest(uint16_t bufferSize);
755
756 private:
757 void DoRun() override;
758};
759
761 : AmpduAggregationTest("Check the correctness of 802.11ax aggregation operations, size=" +
762 std::to_string(bufferSize),
763 Params{.standard = WIFI_STANDARD_80211ax,
764 .nLinks = 1,
765 .dataMode = "HeMcs11",
766 .bufferSize = bufferSize,
767 .maxAmsduSize = 0,
768 .maxAmpduSize = 65535,
769 .txopLimit = Seconds(0)})
770{
771}
772
773void
775{
776 /*
777 * Test behavior when 300 packets are ready for transmission
778 */
779 EnqueuePkts(300, 100, Mac48Address("00:00:00:00:00:02"));
780
782 auto htFem = DynamicCast<HtFrameExchangeManager>(fem);
783 auto mpduAggregator = htFem->GetMpduAggregator();
784
785 auto peeked = GetBeQueue()->PeekNextMpdu(SINGLE_LINK_OP_ID);
786 WifiTxParameters txParams;
787 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
788 peeked->GetHeader(),
789 m_phys.at(SINGLE_LINK_OP_ID)->GetChannelWidth());
790 auto item = GetBeQueue()->GetNextMpdu(SINGLE_LINK_OP_ID, peeked, txParams, Time::Min(), true);
791
792 auto mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
793 DequeueMpdus(mpduList);
794
795 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
796 NS_TEST_EXPECT_MSG_EQ(mpduList.size(),
798 "A-MPDU contains an unexpected number of MPDUs");
799 uint16_t expectedRemainingPacketsInQueue = 300 - m_params.bufferSize;
800 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
801 expectedRemainingPacketsInQueue,
802 "Queue contains an unexpected number of MPDUs");
803}
804
805/**
806 * \ingroup wifi-test
807 * \ingroup tests
808 *
809 * \brief 802.11be aggregation test which permits up to 1024 MPDUs in A-MPDU according to the
810 * negotiated buffer size.
811 */
813{
814 public:
815 /**
816 * Constructor.
817 *
818 * \param bufferSize the size (in number of MPDUs) of the BlockAck buffer
819 */
820 EhtAggregationTest(uint16_t bufferSize);
821
822 private:
823 void DoRun() override;
824};
825
827 : AmpduAggregationTest("Check the correctness of 802.11be aggregation operations, size=" +
828 std::to_string(bufferSize),
829 Params{.standard = WIFI_STANDARD_80211be,
830 .nLinks = 2,
831 .dataMode = "EhtMcs13",
832 .bufferSize = bufferSize,
833 .maxAmsduSize = 0,
834 .maxAmpduSize = 102000,
835 .txopLimit = Seconds(0)})
836{
837}
838
839void
841{
842 /*
843 * Test behavior when 1200 packets of 100 bytes each are ready for transmission. The max
844 * A-MPDU size limit (102000 B) is computed to have at most 750 MPDUs aggregated in a single
845 * A-MPDU (each MPDU is 130 B, plus 4 B of A-MPDU subframe header, plus 2 B of padding).
846 */
847 EnqueuePkts(1200, 100, Mac48Address("00:00:00:00:00:02"));
848 const std::size_t maxNMpdus = 750;
849
850 for (uint8_t linkId = 0; linkId < m_params.nLinks; linkId++)
851 {
852 auto fem = m_mac->GetFrameExchangeManager(linkId);
853 auto htFem = DynamicCast<HtFrameExchangeManager>(fem);
854 auto mpduAggregator = htFem->GetMpduAggregator();
855 std::vector<Ptr<WifiMpdu>> mpduList;
856
857 auto peeked = GetBeQueue()->PeekNextMpdu(linkId);
858 if (peeked)
859 {
860 WifiTxParameters txParams;
861 txParams.m_txVector = m_mac->GetWifiRemoteStationManager()->GetDataTxVector(
862 peeked->GetHeader(),
863 m_phys.at(linkId)->GetChannelWidth());
864 auto item = GetBeQueue()->GetNextMpdu(linkId, peeked, txParams, Time::Min(), true);
865
866 mpduList = mpduAggregator->GetNextAmpdu(item, txParams, Time::Min());
867 DequeueMpdus(mpduList);
868 }
869
870 uint16_t expectedRemainingPacketsInQueue;
871
872 if (m_params.bufferSize >= maxNMpdus)
873 {
874 // two A-MPDUs are transmitted concurrently on the two links and together saturate
875 // the transmit window
876 switch (linkId)
877 {
878 case 0:
879 // the first A-MPDU includes maxNMpdus MPDUs
880 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
881 NS_TEST_EXPECT_MSG_EQ(mpduList.size(),
882 maxNMpdus,
883 "A-MPDU contains an unexpected number of MPDUs");
884 expectedRemainingPacketsInQueue = 1200 - maxNMpdus;
885 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
886 expectedRemainingPacketsInQueue,
887 "Queue contains an unexpected number of MPDUs");
888 break;
889 case 1:
890 // the second A-MPDU includes bufferSize - maxNMpdus MPDUs
891 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
892 NS_TEST_EXPECT_MSG_EQ(mpduList.size(),
893 m_params.bufferSize - maxNMpdus,
894 "A-MPDU contains an unexpected number of MPDUs");
895 expectedRemainingPacketsInQueue = 1200 - m_params.bufferSize;
896 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
897 expectedRemainingPacketsInQueue,
898 "Queue contains an unexpected number of MPDUs");
899 break;
900 default:
901 NS_TEST_ASSERT_MSG_EQ(true, false, "Unexpected link ID " << +linkId);
902 }
903 }
904 else
905 {
906 // one A-MPDU is transmitted that saturates the transmit window
907 switch (linkId)
908 {
909 case 0:
910 // the first A-MPDU includes bufferSize MPDUs
911 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), false, "MPDU aggregation failed");
912 NS_TEST_EXPECT_MSG_EQ(mpduList.size(),
914 "A-MPDU contains an unexpected number of MPDUs");
915 expectedRemainingPacketsInQueue = 1200 - m_params.bufferSize;
916 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
917 expectedRemainingPacketsInQueue,
918 "Queue contains an unexpected number of MPDUs");
919 break;
920 case 1:
921 // no more MPDUs can be sent, aggregation fails
922 NS_TEST_EXPECT_MSG_EQ(mpduList.empty(), true, "MPDU aggregation did not fail");
923 expectedRemainingPacketsInQueue = 1200 - m_params.bufferSize;
924 NS_TEST_EXPECT_MSG_EQ(GetBeQueue()->GetWifiMacQueue()->GetNPackets(),
925 expectedRemainingPacketsInQueue,
926 "Queue contains an unexpected number of MPDUs");
927 break;
928 default:
929 NS_TEST_ASSERT_MSG_EQ(true, false, "Unexpected link ID " << +linkId);
930 }
931 }
932 }
933}
934
935/**
936 * \ingroup wifi-test
937 * \ingroup tests
938 *
939 * \brief Test for A-MSDU and A-MPDU aggregation
940 *
941 * This test aims to check that the packets passed to the MAC layer (on the sender
942 * side) are forwarded up to the upper layer (on the receiver side) when A-MSDU and
943 * A-MPDU aggregation are used. This test checks that no packet copies are performed,
944 * hence packets can be tracked by means of a pointer.
945 *
946 * In this test, an HT STA sends 8 packets (each of 1000 bytes) to an HT AP.
947 * The block ack threshold is set to 2, hence the first packet is sent as an MPDU
948 * containing a single MSDU because the establishment of a Block Ack agreement is
949 * not triggered yet. The maximum A-MSDU size is set to 4500 bytes and the
950 * maximum A-MPDU size is set to 7500 bytes, hence the remaining packets are sent
951 * in an A-MPDU containing two MPDUs, the first one including 4 MSDUs and the second
952 * one including 3 MPDUs.
953 */
955{
956 public:
958 ~PreservePacketsInAmpdus() override;
959
960 void DoRun() override;
961
962 private:
963 std::list<Ptr<const Packet>> m_packetList; ///< List of packets passed to the MAC
964 std::vector<std::size_t> m_nMpdus; ///< Number of MPDUs in PSDUs passed to the PHY
965 std::vector<std::size_t> m_nMsdus; ///< Number of MSDUs in MPDUs passed to the PHY
966
967 /**
968 * Callback invoked when an MSDU is passed to the MAC
969 * \param packet the MSDU to transmit
970 */
972 /**
973 * Callback invoked when the sender MAC passes a PSDU(s) to the PHY
974 * \param psduMap the PSDU map
975 * \param txVector the TX vector
976 * \param txPowerW the transmit power in Watts
977 */
978 void NotifyPsduForwardedDown(WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW);
979 /**
980 * Callback invoked when the receiver MAC forwards a packet up to the upper layer
981 * \param p the packet
982 */
984};
985
987 : TestCase("Test case to check that the Wifi Mac forwards up the same packets received at "
988 "sender side.")
989{
990}
991
993{
994}
995
996void
998{
999 m_packetList.push_back(packet);
1000}
1001
1002void
1004 WifiTxVector txVector,
1005 double txPowerW)
1006{
1007 NS_TEST_EXPECT_MSG_EQ((psduMap.size() == 1 && psduMap.begin()->first == SU_STA_ID),
1008 true,
1009 "No DL MU PPDU expected");
1010
1011 if (!psduMap[SU_STA_ID]->GetHeader(0).IsQosData())
1012 {
1013 return;
1014 }
1015
1016 m_nMpdus.push_back(psduMap[SU_STA_ID]->GetNMpdus());
1017
1018 for (auto& mpdu : *PeekPointer(psduMap[SU_STA_ID]))
1019 {
1020 std::size_t dist = std::distance(mpdu->begin(), mpdu->end());
1021 // the list of aggregated MSDUs is empty if the MPDU includes a non-aggregated MSDU
1022 m_nMsdus.push_back(dist > 0 ? dist : 1);
1023 }
1024}
1025
1026void
1028{
1029 auto it = std::find(m_packetList.begin(), m_packetList.end(), p);
1030 NS_TEST_EXPECT_MSG_EQ((it != m_packetList.end()), true, "Packet being forwarded up not found");
1031 m_packetList.erase(it);
1032}
1033
1034void
1036{
1037 NodeContainer wifiStaNode;
1038 wifiStaNode.Create(1);
1039
1040 NodeContainer wifiApNode;
1041 wifiApNode.Create(1);
1042
1045 phy.SetChannel(channel.Create());
1046
1047 WifiHelper wifi;
1048 wifi.SetStandard(WIFI_STANDARD_80211n);
1049 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
1050
1051 WifiMacHelper mac;
1052 Ssid ssid = Ssid("ns-3-ssid");
1053 mac.SetType("ns3::StaWifiMac",
1054 "BE_MaxAmsduSize",
1055 UintegerValue(4500),
1056 "BE_MaxAmpduSize",
1057 UintegerValue(7500),
1058 "Ssid",
1059 SsidValue(ssid),
1060 /* setting blockack threshold for sta's BE queue */
1061 "BE_BlockAckThreshold",
1062 UintegerValue(2),
1063 "ActiveProbing",
1064 BooleanValue(false));
1065
1066 NetDeviceContainer staDevices;
1067 staDevices = wifi.Install(phy, mac, wifiStaNode);
1068
1069 mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid), "BeaconGeneration", BooleanValue(true));
1070
1071 NetDeviceContainer apDevices;
1072 apDevices = wifi.Install(phy, mac, wifiApNode);
1073
1074 MobilityHelper mobility;
1075 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
1076
1077 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
1078 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
1079 mobility.SetPositionAllocator(positionAlloc);
1080
1081 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1082 mobility.Install(wifiApNode);
1083 mobility.Install(wifiStaNode);
1084
1085 Ptr<WifiNetDevice> ap_device = DynamicCast<WifiNetDevice>(apDevices.Get(0));
1086 Ptr<WifiNetDevice> sta_device = DynamicCast<WifiNetDevice>(staDevices.Get(0));
1087
1088 PacketSocketAddress socket;
1089 socket.SetSingleDevice(sta_device->GetIfIndex());
1090 socket.SetPhysicalAddress(ap_device->GetAddress());
1091 socket.SetProtocol(1);
1092
1093 // install packet sockets on nodes.
1094 PacketSocketHelper packetSocket;
1095 packetSocket.Install(wifiStaNode);
1096 packetSocket.Install(wifiApNode);
1097
1098 Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
1099 client->SetAttribute("PacketSize", UintegerValue(1000));
1100 client->SetAttribute("MaxPackets", UintegerValue(8));
1101 client->SetAttribute("Interval", TimeValue(Seconds(1)));
1102 client->SetRemote(socket);
1103 wifiStaNode.Get(0)->AddApplication(client);
1104 client->SetStartTime(Seconds(1));
1105 client->SetStopTime(Seconds(3.0));
1107 &PacketSocketClient::SetAttribute,
1108 client,
1109 "Interval",
1111
1112 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
1113 server->SetLocal(socket);
1114 wifiApNode.Get(0)->AddApplication(server);
1115 server->SetStartTime(Seconds(0.0));
1116 server->SetStopTime(Seconds(4.0));
1117
1118 sta_device->GetMac()->TraceConnectWithoutContext(
1119 "MacTx",
1121 sta_device->GetPhy()->TraceConnectWithoutContext(
1122 "PhyTxPsduBegin",
1124 ap_device->GetMac()->TraceConnectWithoutContext(
1125 "MacRx",
1127
1130
1132
1133 // Two packets are transmitted. The first one is an MPDU containing a single MSDU.
1134 // The second one is an A-MPDU containing two MPDUs: the first MPDU contains 4 MSDUs
1135 // and the second MPDU contains 3 MSDUs
1136 NS_TEST_EXPECT_MSG_EQ(m_nMpdus.size(), 2, "Unexpected number of transmitted packets");
1137 NS_TEST_EXPECT_MSG_EQ(m_nMsdus.size(), 3, "Unexpected number of transmitted MPDUs");
1138 NS_TEST_EXPECT_MSG_EQ(m_nMpdus[0], 1, "Unexpected number of MPDUs in the first A-MPDU");
1139 NS_TEST_EXPECT_MSG_EQ(m_nMsdus[0], 1, "Unexpected number of MSDUs in the first MPDU");
1140 NS_TEST_EXPECT_MSG_EQ(m_nMpdus[1], 2, "Unexpected number of MPDUs in the second A-MPDU");
1141 NS_TEST_EXPECT_MSG_EQ(m_nMsdus[1], 4, "Unexpected number of MSDUs in the second MPDU");
1142 NS_TEST_EXPECT_MSG_EQ(m_nMsdus[2], 3, "Unexpected number of MSDUs in the third MPDU");
1143 // All the packets must have been forwarded up at the receiver
1144 NS_TEST_EXPECT_MSG_EQ(m_packetList.empty(), true, "Some packets have not been forwarded up");
1145}
1146
1147/**
1148 * \ingroup wifi-test
1149 * \ingroup tests
1150 *
1151 * \brief Wifi Aggregation Test Suite
1152 */
1154{
1155 public:
1157};
1158
1160 : TestSuite("wifi-aggregation", Type::UNIT)
1161{
1162 AddTestCase(new AmpduAggregationTest, TestCase::Duration::QUICK);
1163 AddTestCase(new TwoLevelAggregationTest, TestCase::Duration::QUICK);
1164 AddTestCase(new HeAggregationTest(64), TestCase::Duration::QUICK);
1165 AddTestCase(new HeAggregationTest(256), TestCase::Duration::QUICK);
1166 AddTestCase(new EhtAggregationTest(512), TestCase::Duration::QUICK);
1167 AddTestCase(new EhtAggregationTest(1024), TestCase::Duration::QUICK);
1168 AddTestCase(new PreservePacketsInAmpdus, TestCase::Duration::QUICK);
1169}
1170
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 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)
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.
std::list< Ptr< const Packet > > m_packetList
List of packets passed to the MAC.
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.
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.
Two Level Aggregation Test.
void DoRun() override
Implementation to actually run this TestCase.
Wifi Aggregation Test Suite.
A container for one type of attribute.
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.
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
Definition: mac48-address.h:46
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:164
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:322
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:211
Instantiate subclasses of ns3::Object.
Ptr< Object > Create() const
Create an Object instance of the configured TypeId.
void Set(const std::string &name, const AttributeValue &value, Args &&... args)
Set an attribute to be set during construction.
void SetTypeId(TypeId tid)
Set the TypeId of the Objects to be created by this factory.
void Dispose()
Dispose of this Object.
Definition: object.cc:258
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
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Ptr< BlockAckManager > GetBaManager()
Get the Block Ack Manager associated with this QosTxop.
Definition: qos-txop.cc:289
Ptr< WifiMpdu > PeekNextMpdu(uint8_t linkId, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< const WifiMpdu > mpdu=nullptr)
Peek the next frame to transmit on the given link to the given receiver and of the given TID from the...
Definition: qos-txop.cc:385
Ptr< WifiMpdu > GetNextMpdu(uint8_t linkId, Ptr< WifiMpdu > peekedItem, WifiTxParameters &txParams, Time availableTime, bool initialFrame)
Prepare the frame to transmit on the given link starting from the MPDU that has been previously peeke...
Definition: qos-txop.cc:502
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
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
void SetState(MacState value)
Set the current MAC state.
void SetWifiPhys(const std::vector< Ptr< WifiPhy > > &phys) override
Status code for association response.
Definition: status-code.h:32
void SetSuccess()
Set success bit to 0 (success).
Definition: status-code.cc:30
Hold variables of type string.
Definition: string.h:56
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
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
Definition: nstime.h:287
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:275
Hold an unsigned integer type.
Definition: uinteger.h:45
The IEEE 802.11ac VHT Capabilities.
void SetMaxMpduLength(uint16_t length)
Set the maximum MPDU length.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
Implements the IEEE 802.11 MAC 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.
Ptr< FrameExchangeManager > GetFrameExchangeManager(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get the Frame Exchange Manager associated with the given link.
Definition: wifi-mac.cc:981
Ptr< QosTxop > GetBEQueue() const
Accessor for the AC_BE channel access function.
Definition: wifi-mac.cc:627
virtual void SetMacQueueScheduler(Ptr< WifiMacQueueScheduler > scheduler)
Set the wifi MAC queue scheduler.
Definition: wifi-mac.cc:663
const std::map< uint8_t, std::unique_ptr< LinkEntity > > & GetLinks() const
Definition: wifi-mac.cc:1057
virtual void SetAddress(Mac48Address address)
Definition: wifi-mac.cc:489
void SetFrameExchangeManagers(const std::vector< Ptr< FrameExchangeManager > > &feManagers)
Definition: wifi-mac.cc:944
void SetChannelAccessManagers(const std::vector< Ptr< ChannelAccessManager > > &caManagers)
Definition: wifi-mac.cc:987
void SetWifiRemoteStationManagers(const std::vector< Ptr< WifiRemoteStationManager > > &stationManagers)
Definition: wifi-mac.cc:1022
Ptr< MacTxMiddle > m_txMiddle
TX middle (aggregation etc.)
Definition: wifi-mac.h:915
virtual Ptr< WifiMacQueue > GetTxopQueue(AcIndex ac) const
Get the wifi MAC queue of the (Qos)Txop associated with the given AC, if such (Qos)Txop is installed,...
Definition: wifi-mac.cc:639
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:1045
void SetDevice(const Ptr< WifiNetDevice > device)
Sets the device this PHY is associated with.
Definition: wifi-mac.cc:472
Mac48Address GetAddress() const
Definition: wifi-mac.cc:496
void SetMac(const Ptr< WifiMac > mac)
void SetPhys(const std::vector< Ptr< WifiPhy > > &phys)
void SetHeConfiguration(Ptr< HeConfiguration > heConfiguration)
void SetHtConfiguration(Ptr< HtConfiguration > htConfiguration)
void SetVhtConfiguration(Ptr< VhtConfiguration > vhtConfiguration)
void SetRemoteStationManagers(const std::vector< Ptr< WifiRemoteStationManager > > &managers)
void SetStandard(WifiStandard standard)
Set the Wifi standard.
void SetEhtConfiguration(Ptr< EhtConfiguration > ehtConfiguration)
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.
#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_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
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:80
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ AC_BE
Best Effort.
Definition: qos-utils.h:75
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:454
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
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
std::string GetFrameExchangeManagerTypeIdName(WifiStandard standard, bool qosSupported)
Get the TypeId name for the FrameExchangeManager corresponding to the given standard.
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:193
@ WIFI_MAC_QOSDATA
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
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