A Discrete-Event Network Simulator
API
wifi-mac-ofdma-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
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: Stefano Avallone <stavallo@unina.it>
18 */
19
20#include "ns3/config.h"
21#include "ns3/he-configuration.h"
22#include "ns3/he-frame-exchange-manager.h"
23#include "ns3/he-phy.h"
24#include "ns3/mobility-helper.h"
25#include "ns3/multi-model-spectrum-channel.h"
26#include "ns3/multi-user-scheduler.h"
27#include "ns3/packet-socket-client.h"
28#include "ns3/packet-socket-helper.h"
29#include "ns3/packet-socket-server.h"
30#include "ns3/packet.h"
31#include "ns3/qos-utils.h"
32#include "ns3/rng-seed-manager.h"
33#include "ns3/spectrum-wifi-helper.h"
34#include "ns3/string.h"
35#include "ns3/test.h"
36#include "ns3/wifi-acknowledgment.h"
37#include "ns3/wifi-mac-header.h"
38#include "ns3/wifi-mac-queue.h"
39#include "ns3/wifi-net-device.h"
40#include "ns3/wifi-protection.h"
41#include "ns3/wifi-psdu.h"
42
43using namespace ns3;
44
45NS_LOG_COMPONENT_DEFINE("WifiMacOfdmaTestSuite");
46
60{
61 public:
66 static TypeId GetTypeId();
68 ~TestMultiUserScheduler() override;
69
70 private:
71 // Implementation of pure virtual methods of MultiUserScheduler class
72 TxFormat SelectTxFormat() override;
73 DlMuInfo ComputeDlMuInfo() override;
74 UlMuInfo ComputeUlMuInfo() override;
75
80
88};
89
91
94{
95 static TypeId tid = TypeId("ns3::TestMultiUserScheduler")
97 .SetGroupName("Wifi")
98 .AddConstructor<TestMultiUserScheduler>();
99 return tid;
100}
101
103 : m_txFormat(SU_TX),
104 m_ulTriggerType(TriggerFrameType::BSRP_TRIGGER)
105{
106 NS_LOG_FUNCTION(this);
107}
108
110{
112}
113
116{
117 NS_LOG_FUNCTION(this);
118
119 // Do not use OFDMA if a BA agreement has not been established with all the stations
120 if (Simulator::Now() < Seconds(1.5))
121 {
122 NS_LOG_DEBUG("Return SU_TX");
123 return SU_TX;
124 }
125
127
128 if (m_txFormat == SU_TX || m_txFormat == DL_MU_TX ||
130 {
131 // try to send a Trigger Frame
132 TriggerFrameType ulTriggerType =
135
136 m_trigger = CtrlTriggerHeader(ulTriggerType, m_txVector);
137
138 WifiTxVector txVector = m_txVector;
140
141 uint32_t ampduSize = (ulTriggerType == TriggerFrameType::BSRP_TRIGGER)
143 : 3500; // allows aggregation of 2 MPDUs in TB PPDUs
144
145 Time duration = WifiPhy::CalculateTxDuration(ampduSize,
146 txVector,
148 m_apMac->GetStaList().begin()->first);
149
150 uint16_t length;
151 std::tie(length, duration) = HePhy::ConvertHeTbPpduDurationToLSigLength(
152 duration,
155 m_trigger.SetUlLength(length);
156
157 Ptr<Packet> packet = Create<Packet>();
158 packet->AddHeader(m_trigger);
159
161 m_triggerHdr.SetAddr1(Mac48Address::GetBroadcast());
165
166 auto item = Create<WifiMpdu>(packet, m_triggerHdr);
167
169 // set the TXVECTOR used to send the Trigger Frame
172
173 if (!m_heFem->TryAddMpdu(item, m_txParams, m_availableTime) ||
175 m_txParams.m_protection->protectionTime + m_txParams.m_txDuration // TF tx time
176 + m_apMac->GetWifiPhy()->GetSifs() + duration +
177 m_txParams.m_acknowledgment->acknowledgmentTime >
179 {
180 NS_LOG_DEBUG("Remaining TXOP duration is not enough for BSRP TF exchange");
181 return SU_TX;
182 }
183
185 m_ulTriggerType = ulTriggerType;
186 }
187 else if (m_txFormat == UL_MU_TX)
188 {
189 // try to send a DL MU PPDU
190 m_psduMap.clear();
191 const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList();
192 NS_ABORT_MSG_IF(staList.size() != 4, "There must be 4 associated stations");
193
194 /* Initialize TX params */
197
198 for (auto& sta : staList)
199 {
200 Ptr<WifiMpdu> peeked;
201 uint8_t tid;
202
203 for (tid = 0; tid < 8; tid++)
204 {
205 peeked = m_apMac->GetQosTxop(tid)->PeekNextMpdu(SINGLE_LINK_OP_ID, tid, sta.second);
206 if (peeked)
207 {
208 break;
209 }
210 }
211
212 if (!peeked)
213 {
214 NS_LOG_DEBUG("No frame to send to " << sta.second);
215 continue;
216 }
217
219 peeked,
223 if (!mpdu)
224 {
225 NS_LOG_DEBUG("Not enough time to send frames to all the stations");
226 return SU_TX;
227 }
228
229 std::vector<Ptr<WifiMpdu>> mpduList;
230 mpduList =
231 m_heFem->GetMpduAggregator()->GetNextAmpdu(mpdu, m_txParams, m_availableTime);
232
233 if (mpduList.size() > 1)
234 {
235 m_psduMap[sta.first] = Create<WifiPsdu>(std::move(mpduList));
236 }
237 else
238 {
239 m_psduMap[sta.first] = Create<WifiPsdu>(mpdu, true);
240 }
241 }
242
243 if (m_psduMap.empty())
244 {
245 NS_LOG_DEBUG("No frame to send");
246 return SU_TX;
247 }
248
250 }
251 else
252 {
253 NS_ABORT_MSG("Cannot get here.");
254 }
255
256 NS_LOG_DEBUG("Return " << m_txFormat);
257 return m_txFormat;
258}
259
260void
262{
264 {
265 // the TX vector has been already computed
266 return;
267 }
268
269 uint16_t bw = m_apMac->GetWifiPhy()->GetChannelWidth();
270
273 m_txVector.SetGuardInterval(m_apMac->GetHeConfiguration()->GetGuardInterval().GetNanoSeconds());
274 m_txVector.SetTxPowerLevel(GetWifiRemoteStationManager()->GetDefaultTxPowerLevel());
275
276 const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList();
277 NS_ABORT_MSG_IF(staList.size() != 4, "There must be 4 associated stations");
278
279 HeRu::RuType ruType;
280 switch (bw)
281 {
282 case 20:
283 ruType = HeRu::RU_52_TONE;
285 break;
286 case 40:
287 ruType = HeRu::RU_106_TONE;
288 m_txVector.SetRuAllocation({96, 96});
289 break;
290 case 80:
291 ruType = HeRu::RU_242_TONE;
292 m_txVector.SetRuAllocation({192, 192, 192, 192});
293 break;
294 case 160:
295 ruType = HeRu::RU_484_TONE;
296 m_txVector.SetRuAllocation({200, 200, 200, 200, 200, 200, 200, 200});
297 break;
298 default:
299 NS_ABORT_MSG("Unsupported channel width");
300 }
301
302 bool primary80 = true;
303 std::size_t ruIndex = 1;
304
305 for (auto& sta : staList)
306 {
307 if (bw == 160 && ruIndex == 3)
308 {
309 ruIndex = 1;
310 primary80 = false;
311 }
312 m_txVector.SetHeMuUserInfo(sta.first,
313 {{ruType, ruIndex++, primary80}, WifiMode("HeMcs11"), 1});
314 }
315 m_txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
316}
317
320{
321 NS_LOG_FUNCTION(this);
322 return DlMuInfo{m_psduMap, std::move(m_txParams)};
323}
324
327{
328 NS_LOG_FUNCTION(this);
329 return UlMuInfo{m_trigger, m_triggerHdr, std::move(m_txParams)};
330}
331
349{
350 public:
355 {
356 uint8_t muAifsn;
357 uint16_t muCwMin;
358 uint16_t muCwMax;
359 uint8_t muTimer;
360 };
361
371 OfdmaAckSequenceTest(uint16_t width,
373 uint32_t maxAmpduSize,
374 uint16_t txopLimit,
375 uint16_t nPktsPerSta,
376 MuEdcaParameterSet muEdcaParameterSet);
377 ~OfdmaAckSequenceTest() override;
378
385 void L7Receive(std::string context, Ptr<const Packet> p, const Address& addr);
391 void TraceCw(uint32_t staIndex, uint32_t cw, uint8_t /* linkId */);
399 void Transmit(std::string context,
400 WifiConstPsduMap psduMap,
401 WifiTxVector txVector,
402 double txPowerW);
409 void CheckResults(Time sifs, Time slotTime, uint8_t aifsn);
410
411 private:
412 void DoRun() override;
413
414 static constexpr uint16_t m_muTimerRes = 8192;
415
418 {
423 };
424
425 uint16_t m_nStations;
428 std::vector<PacketSocketAddress> m_sockets;
429 uint16_t m_channelWidth;
430 std::vector<FrameInfo> m_txPsdus;
433 uint16_t m_txopLimit;
434 uint16_t m_nPktsPerSta;
437 uint16_t m_received;
438 uint16_t m_flushed;
440 std::vector<uint32_t> m_cwValues;
441};
442
445 uint32_t maxAmpduSize,
446 uint16_t txopLimit,
447 uint16_t nPktsPerSta,
448 MuEdcaParameterSet muEdcaParameterSet)
449 : TestCase("Check correct operation of DL OFDMA acknowledgment sequences"),
450 m_nStations(4),
451 m_sockets(m_nStations),
452 m_channelWidth(width),
453 m_dlMuAckType(dlType),
454 m_maxAmpduSize(maxAmpduSize),
455 m_txopLimit(txopLimit),
456 m_nPktsPerSta(nPktsPerSta),
457 m_muEdcaParameterSet(muEdcaParameterSet),
458 m_ulPktsGenerated(false),
459 m_received(0),
460 m_flushed(0),
461 m_edcaDisabledStartTime(Seconds(0)),
462 m_cwValues(std::vector<uint32_t>(m_nStations, 2)) // 2 is an invalid CW value
463{
464}
465
467{
468}
469
470void
472{
473 if (p->GetSize() >= 1400 && Simulator::Now() > Seconds(1.5))
474 {
475 m_received++;
476 }
477}
478
479void
480OfdmaAckSequenceTest::TraceCw(uint32_t staIndex, uint32_t cw, uint8_t /* linkId */)
481{
482 if (m_cwValues.at(staIndex) == 2)
483 {
484 // store the first CW used after MU exchange (the last one may be used after
485 // the MU EDCA timer expired)
486 m_cwValues[staIndex] = cw;
487 }
488}
489
490void
492 WifiConstPsduMap psduMap,
493 WifiTxVector txVector,
494 double txPowerW)
495{
496 // skip beacon frames and frames transmitted before 1.5s (association
497 // request/response, ADDBA request, ...)
498 if (!psduMap.begin()->second->GetHeader(0).IsBeacon() && Simulator::Now() >= Seconds(1.5))
499 {
500 Time txDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, WIFI_PHY_BAND_5GHZ);
501 m_txPsdus.push_back({Simulator::Now(), Simulator::Now() + txDuration, psduMap, txVector});
502
503 for (const auto& [staId, psdu] : psduMap)
504 {
505 NS_LOG_INFO("Sending "
506 << psdu->GetHeader(0).GetTypeString() << " #MPDUs " << psdu->GetNMpdus()
507 << (psdu->GetHeader(0).IsQosData()
508 ? " TID " + std::to_string(*psdu->GetTids().begin())
509 : "")
510 << " txDuration " << txDuration << " duration/ID "
511 << psdu->GetHeader(0).GetDuration() << " #TX PSDUs = " << m_txPsdus.size());
512 }
513 }
514
515 // Flush the MAC queue of the AP after sending a DL MU PPDU (no need for
516 // further transmissions)
517 if (txVector.GetPreambleType() == WIFI_PREAMBLE_HE_MU)
518 {
519 m_flushed = 0;
520 for (uint32_t i = 0; i < m_staDevices.GetN(); i++)
521 {
522 auto queue =
523 m_apDevice->GetMac()->GetQosTxop(static_cast<AcIndex>(i))->GetWifiMacQueue();
524 auto staDev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
525 Ptr<const WifiMpdu> lastInFlight = nullptr;
527
528 while ((mpdu = queue->PeekByTidAndAddress(i * 2,
529 staDev->GetMac()->GetAddress(),
530 lastInFlight)) != nullptr)
531 {
532 if (mpdu->IsInFlight())
533 {
534 lastInFlight = mpdu;
535 }
536 else
537 {
538 queue->Remove(mpdu);
539 m_flushed++;
540 }
541 }
542 }
543 }
544 else if (txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
545 psduMap.begin()->second->GetHeader(0).HasData())
546 {
547 Mac48Address sender = psduMap.begin()->second->GetAddr2();
548
549 for (uint32_t i = 0; i < m_staDevices.GetN(); i++)
550 {
551 auto dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
552
553 if (dev->GetAddress() == sender)
554 {
555 Ptr<QosTxop> qosTxop = dev->GetMac()->GetQosTxop(static_cast<AcIndex>(i));
556
558 {
559 // stations use worse access parameters, trace CW. MU AIFSN must be large
560 // enough to avoid collisions between stations trying to transmit using EDCA
561 // right after the UL MU transmission and the AP trying to send a DL MU PPDU
563 "CwTrace",
565 }
566 else
567 {
568 // there is no "protection" against collisions from stations, hence flush
569 // their MAC queues after sending an HE TB PPDU containing QoS data frames,
570 // so that the AP can send a DL MU PPDU
571 qosTxop->GetWifiMacQueue()->Flush();
572 }
573 break;
574 }
575 }
576 }
577 else if (!txVector.IsMu() && psduMap.begin()->second->GetHeader(0).IsBlockAck() &&
578 psduMap.begin()->second->GetHeader(0).GetAddr2() == m_apDevice->GetAddress() &&
580 {
581 CtrlBAckResponseHeader blockAck;
582 psduMap.begin()->second->GetPayload(0)->PeekHeader(blockAck);
583
584 if (blockAck.IsMultiSta())
585 {
586 // AP is transmitting a multi-STA BlockAck and stations have to disable EDCA,
587 // record the starting time
589 Simulator::Now() + m_txPsdus.back().endTx - m_txPsdus.back().startTx;
590 }
591 }
592 else if (!txVector.IsMu() && psduMap.begin()->second->GetHeader(0).IsTrigger() &&
594 {
595 CtrlTriggerHeader trigger;
596 psduMap.begin()->second->GetPayload(0)->PeekHeader(trigger);
597 if (trigger.IsBasic())
598 {
599 // the AP is starting the transmission of the Basic Trigger frame, so generate
600 // the configured number of packets at STAs, which are sent in HE TB PPDUs
601 for (uint16_t i = 0; i < m_nStations; i++)
602 {
603 Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
604 client->SetAttribute("PacketSize", UintegerValue(1400 + i * 100));
605 client->SetAttribute("MaxPackets", UintegerValue(m_nPktsPerSta));
606 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
607 client->SetAttribute("Priority", UintegerValue(i * 2)); // 0, 2, 4 and 6
608 client->SetRemote(m_sockets[i]);
609 m_staDevices.Get(i)->GetNode()->AddApplication(client);
610 client->SetStartTime(Seconds(0)); // start now
611 client->SetStopTime(Seconds(1.0)); // stop in a second
612 client->Initialize();
613 }
614 m_ulPktsGenerated = true;
615 }
616 }
617}
618
619void
620OfdmaAckSequenceTest::CheckResults(Time sifs, Time slotTime, uint8_t aifsn)
621{
622 CtrlTriggerHeader trigger;
623 CtrlBAckResponseHeader blockAck;
624 Time tEnd; // TX end for a frame
625 Time tStart; // TX start fot the next frame
626 Time tolerance = NanoSeconds(500); // due to propagation delay
627 Time ifs = (m_txopLimit > 0 ? sifs : sifs + aifsn * slotTime);
628 Time navEnd;
629
630 /*
631 * |--------------NAV------------------>|
632 * |------NAV------->| | |------NAV-------->|
633 * |---------| |----------| |---------| |----------| |-----------|
634 * | | |QoS Null 1| | | |QoS Data 1| | |
635 * | BSRP | |----------| | Basic | |----------| | Multi-STA |
636 * | Trigger | |QoS Null 2| | Trigger | |QoS Data 2| | Block Ack |
637 * | Frame |<SIFS>|----------|<IFS>| Frame |<SIFS>|----------|<SIFS>| |
638 * | | |QoS Null 3| | | |QoS Data 3| | |
639 * | | |----------| | | |----------| | |
640 * | | |QoS Null 4| | | |QoS Data 4| | |
641 * -----------------------------------------------------------------------------------------
642 * From: AP AP AP
643 * To: all AP all AP all
644 */
645
646 // the first packet sent after 1.5s is a BSRP Trigger Frame
647 NS_TEST_EXPECT_MSG_GT_OR_EQ(m_txPsdus.size(), 5, "Expected at least 5 transmitted packet");
648 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[0].psduMap.size() == 1 &&
649 m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger() &&
650 m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
651 true,
652 "Expected a Trigger Frame");
653 m_txPsdus[0].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(trigger);
654 NS_TEST_EXPECT_MSG_EQ(trigger.IsBsrp(), true, "Expected a BSRP Trigger Frame");
656 4,
657 "Expected one User Info field per station");
658
659 // A first STA sends a QoS Null frame in an HE TB PPDU a SIFS after the reception of the BSRP TF
660 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[1].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
661 m_txPsdus[1].psduMap.size() == 1 &&
662 m_txPsdus[1].psduMap.begin()->second->GetNMpdus() == 1),
663 true,
664 "Expected a QoS Null frame in an HE TB PPDU");
665 {
666 const WifiMacHeader& hdr = m_txPsdus[1].psduMap.begin()->second->GetHeader(0);
667 NS_TEST_EXPECT_MSG_EQ(hdr.GetType(), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
668 uint16_t staId;
669 for (staId = 0; staId < m_nStations; staId++)
670 {
671 if (DynamicCast<WifiNetDevice>(m_staDevices.Get(staId))->GetAddress() == hdr.GetAddr2())
672 {
673 break;
674 }
675 }
676 NS_TEST_EXPECT_MSG_NE(+staId, m_nStations, "Sender not found among stations");
677 uint8_t tid = staId * 2;
678 NS_TEST_EXPECT_MSG_EQ(+hdr.GetQosTid(), +tid, "Expected a TID equal to " << +tid);
679 }
680 tEnd = m_txPsdus[0].endTx;
681 navEnd = tEnd + m_txPsdus[0].psduMap[SU_STA_ID]->GetDuration();
682 tStart = m_txPsdus[1].startTx;
683 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS Null frame in HE TB PPDU sent too early");
685 tEnd + sifs + tolerance,
686 "QoS Null frame in HE TB PPDU sent too late");
687 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
688 m_txPsdus[1].endTx,
689 "Duration/ID in BSRP Trigger Frame is too short");
690
691 // A second STA sends a QoS Null frame in an HE TB PPDU a SIFS after the reception of the BSRP
692 // TF
693 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[2].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
694 m_txPsdus[2].psduMap.size() == 1 &&
695 m_txPsdus[2].psduMap.begin()->second->GetNMpdus() == 1),
696 true,
697 "Expected a QoS Null frame in an HE TB PPDU");
698 {
699 const WifiMacHeader& hdr = m_txPsdus[2].psduMap.begin()->second->GetHeader(0);
700 NS_TEST_EXPECT_MSG_EQ(hdr.GetType(), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
701 uint16_t staId;
702 for (staId = 0; staId < m_nStations; staId++)
703 {
704 if (DynamicCast<WifiNetDevice>(m_staDevices.Get(staId))->GetAddress() == hdr.GetAddr2())
705 {
706 break;
707 }
708 }
709 NS_TEST_EXPECT_MSG_NE(+staId, m_nStations, "Sender not found among stations");
710 uint8_t tid = staId * 2;
711 NS_TEST_EXPECT_MSG_EQ(+hdr.GetQosTid(), +tid, "Expected a TID equal to " << +tid);
712 }
713 tStart = m_txPsdus[2].startTx;
714 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS Null frame in HE TB PPDU sent too early");
716 tEnd + sifs + tolerance,
717 "QoS Null frame in HE TB PPDU sent too late");
718 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
719 m_txPsdus[2].endTx,
720 "Duration/ID in BSRP Trigger Frame is too short");
721
722 // A third STA sends a QoS Null frame in an HE TB PPDU a SIFS after the reception of the BSRP TF
723 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[3].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
724 m_txPsdus[3].psduMap.size() == 1 &&
725 m_txPsdus[3].psduMap.begin()->second->GetNMpdus() == 1),
726 true,
727 "Expected a QoS Null frame in an HE TB PPDU");
728 {
729 const WifiMacHeader& hdr = m_txPsdus[3].psduMap.begin()->second->GetHeader(0);
730 NS_TEST_EXPECT_MSG_EQ(hdr.GetType(), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
731 uint16_t staId;
732 for (staId = 0; staId < m_nStations; staId++)
733 {
734 if (DynamicCast<WifiNetDevice>(m_staDevices.Get(staId))->GetAddress() == hdr.GetAddr2())
735 {
736 break;
737 }
738 }
739 NS_TEST_EXPECT_MSG_NE(+staId, m_nStations, "Sender not found among stations");
740 uint8_t tid = staId * 2;
741 NS_TEST_EXPECT_MSG_EQ(+hdr.GetQosTid(), +tid, "Expected a TID equal to " << +tid);
742 }
743 tStart = m_txPsdus[3].startTx;
744 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS Null frame in HE TB PPDU sent too early");
746 tEnd + sifs + tolerance,
747 "QoS Null frame in HE TB PPDU sent too late");
748 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
749 m_txPsdus[3].endTx,
750 "Duration/ID in BSRP Trigger Frame is too short");
751
752 // A fourth STA sends a QoS Null frame in an HE TB PPDU a SIFS after the reception of the BSRP
753 // TF
754 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[4].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
755 m_txPsdus[4].psduMap.size() == 1 &&
756 m_txPsdus[4].psduMap.begin()->second->GetNMpdus() == 1),
757 true,
758 "Expected a QoS Null frame in an HE TB PPDU");
759 {
760 const WifiMacHeader& hdr = m_txPsdus[4].psduMap.begin()->second->GetHeader(0);
761 NS_TEST_EXPECT_MSG_EQ(hdr.GetType(), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
762 uint16_t staId;
763 for (staId = 0; staId < m_nStations; staId++)
764 {
765 if (DynamicCast<WifiNetDevice>(m_staDevices.Get(staId))->GetAddress() == hdr.GetAddr2())
766 {
767 break;
768 }
769 }
770 NS_TEST_EXPECT_MSG_NE(+staId, m_nStations, "Sender not found among stations");
771 uint8_t tid = staId * 2;
772 NS_TEST_EXPECT_MSG_EQ(+hdr.GetQosTid(), +tid, "Expected a TID equal to " << +tid);
773 }
774 tStart = m_txPsdus[4].startTx;
775 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS Null frame in HE TB PPDU sent too early");
777 tEnd + sifs + tolerance,
778 "QoS Null frame in HE TB PPDU sent too late");
779 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
780 m_txPsdus[4].endTx,
781 "Duration/ID in BSRP Trigger Frame is too short");
782
783 // the AP sends a Basic Trigger Frame to solicit QoS data frames
784 NS_TEST_EXPECT_MSG_GT_OR_EQ(m_txPsdus.size(), 11, "Expected at least 11 transmitted packets");
785 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[5].psduMap.size() == 1 &&
786 m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger() &&
787 m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
788 true,
789 "Expected a Trigger Frame");
790 m_txPsdus[5].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(trigger);
791 NS_TEST_EXPECT_MSG_EQ(trigger.IsBasic(), true, "Expected a Basic Trigger Frame");
793 4,
794 "Expected one User Info field per station");
795 tEnd = m_txPsdus[1].endTx;
796 tStart = m_txPsdus[5].startTx;
797 NS_TEST_EXPECT_MSG_LT(tEnd + ifs, tStart, "Basic Trigger Frame sent too early");
798 if (m_txopLimit > 0)
799 {
800 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Basic Trigger Frame sent too late");
801 }
802
803 // A first STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
804 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[6].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
805 m_txPsdus[6].psduMap.size() == 1 &&
806 m_txPsdus[6].psduMap.begin()->second->GetNMpdus() == 2 &&
807 m_txPsdus[6].psduMap.begin()->second->GetHeader(0).IsQosData() &&
808 m_txPsdus[6].psduMap.begin()->second->GetHeader(1).IsQosData()),
809 true,
810 "Expected 2 QoS data frames in an HE TB PPDU");
811 tEnd = m_txPsdus[5].endTx;
812 tStart = m_txPsdus[6].startTx;
813 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
815 tEnd + sifs + tolerance,
816 "QoS data frames in HE TB PPDU sent too late");
817
818 // A second STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic
819 // TF
820 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[7].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
821 m_txPsdus[7].psduMap.size() == 1 &&
822 m_txPsdus[7].psduMap.begin()->second->GetNMpdus() == 2 &&
823 m_txPsdus[7].psduMap.begin()->second->GetHeader(0).IsQosData() &&
824 m_txPsdus[7].psduMap.begin()->second->GetHeader(1).IsQosData()),
825 true,
826 "Expected 2 QoS data frames in an HE TB PPDU");
827 tEnd = m_txPsdus[5].endTx;
828 tStart = m_txPsdus[7].startTx;
829 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
831 tEnd + sifs + tolerance,
832 "QoS data frames in HE TB PPDU sent too late");
833
834 // A third STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
835 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[8].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
836 m_txPsdus[8].psduMap.size() == 1 &&
837 m_txPsdus[8].psduMap.begin()->second->GetNMpdus() == 2 &&
838 m_txPsdus[8].psduMap.begin()->second->GetHeader(0).IsQosData() &&
839 m_txPsdus[8].psduMap.begin()->second->GetHeader(1).IsQosData()),
840 true,
841 "Expected 2 QoS data frames in an HE TB PPDU");
842 tEnd = m_txPsdus[5].endTx;
843 tStart = m_txPsdus[8].startTx;
844 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
846 tEnd + sifs + tolerance,
847 "QoS data frames in HE TB PPDU sent too late");
848
849 // A fourth STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic
850 // TF
851 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[9].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
852 m_txPsdus[9].psduMap.size() == 1 &&
853 m_txPsdus[9].psduMap.begin()->second->GetNMpdus() == 2 &&
854 m_txPsdus[9].psduMap.begin()->second->GetHeader(0).IsQosData() &&
855 m_txPsdus[9].psduMap.begin()->second->GetHeader(1).IsQosData()),
856 true,
857 "Expected 2 QoS data frames in an HE TB PPDU");
858 tEnd = m_txPsdus[5].endTx;
859 tStart = m_txPsdus[9].startTx;
860 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
862 tEnd + sifs + tolerance,
863 "QoS data frames in HE TB PPDU sent too late");
864
865 // the AP sends a Multi-STA Block Ack
866 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[10].psduMap.size() == 1 &&
867 m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck() &&
868 m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
869 true,
870 "Expected a Block Ack");
871 m_txPsdus[10].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(blockAck);
872 NS_TEST_EXPECT_MSG_EQ(blockAck.IsMultiSta(), true, "Expected a Multi-STA Block Ack");
874 4,
875 "Expected one Per AID TID Info subfield per station");
876 for (uint8_t i = 0; i < 4; i++)
877 {
878 NS_TEST_EXPECT_MSG_EQ(blockAck.GetAckType(i), true, "Expected All-ack context");
879 NS_TEST_EXPECT_MSG_EQ(+blockAck.GetTidInfo(i), 14, "Expected All-ack context");
880 }
881 tEnd = m_txPsdus[9].endTx;
882 tStart = m_txPsdus[10].startTx;
883 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Multi-STA Block Ack sent too early");
884 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Multi-STA Block Ack sent too late");
885
886 navEnd = m_txPsdus[5].endTx + m_txPsdus[5].psduMap[SU_STA_ID]->GetDuration(); // Basic TF's NAV
887 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
888 m_txPsdus[10].endTx,
889 "Duration/ID in Basic Trigger Frame is too short");
890 navEnd = m_txPsdus[6].endTx +
891 m_txPsdus[6].psduMap.begin()->second->GetDuration(); // 1st QoS Data frame's NAV
892 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
893 m_txPsdus[10].endTx,
894 "Duration/ID in 1st QoS Data frame is too short");
895 navEnd = m_txPsdus[7].endTx +
896 m_txPsdus[7].psduMap.begin()->second->GetDuration(); // 2nd QoS Data frame's NAV
897 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
898 m_txPsdus[10].endTx,
899 "Duration/ID in 2nd QoS Data frame is too short");
900 navEnd = m_txPsdus[8].endTx +
901 m_txPsdus[8].psduMap.begin()->second->GetDuration(); // 3rd QoS Data frame's NAV
902 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
903 m_txPsdus[10].endTx,
904 "Duration/ID in 3rd QoS Data frame is too short");
905 navEnd = m_txPsdus[9].endTx +
906 m_txPsdus[9].psduMap.begin()->second->GetDuration(); // 4th QoS Data frame's NAV
907 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
908 m_txPsdus[10].endTx,
909 "Duration/ID in 4th QoS Data frame is too short");
910
911 // the AP sends a DL MU PPDU
912 NS_TEST_EXPECT_MSG_GT_OR_EQ(m_txPsdus.size(), 12, "Expected at least 12 transmitted packet");
913 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].txVector.GetPreambleType(),
915 "Expected a DL MU PPDU");
916 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].psduMap.size(),
917 4,
918 "Expected 4 PSDUs within the DL MU PPDU");
919 // the TX duration cannot exceed the maximum PPDU duration
920 NS_TEST_EXPECT_MSG_LT_OR_EQ(m_txPsdus[11].endTx - m_txPsdus[11].startTx,
921 GetPpduMaxTime(m_txPsdus[11].txVector.GetPreambleType()),
922 "TX duration cannot exceed max PPDU duration");
923 for (auto& psdu : m_txPsdus[11].psduMap)
924 {
925 NS_TEST_EXPECT_MSG_LT_OR_EQ(psdu.second->GetSize(),
927 "Max A-MPDU size exceeded");
928 }
929 tEnd = m_txPsdus[10].endTx;
930 tStart = m_txPsdus[11].startTx;
931 NS_TEST_EXPECT_MSG_LT_OR_EQ(tEnd + ifs, tStart, "DL MU PPDU sent too early");
932
933 // The Duration/ID field is the same for all the PSDUs
934 navEnd = m_txPsdus[11].endTx;
935 for (auto& psdu : m_txPsdus[11].psduMap)
936 {
937 if (navEnd == m_txPsdus[11].endTx)
938 {
939 navEnd += psdu.second->GetDuration();
940 }
941 else
942 {
943 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].endTx + psdu.second->GetDuration(),
944 navEnd,
945 "Duration/ID must be the same for all PSDUs");
946 }
947 }
949 m_txPsdus[11].endTx,
950 "Duration/ID of the DL MU PPDU cannot be zero");
951
952 std::size_t nTxPsdus = 0;
953
954 if (m_dlMuAckType == WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE)
955 {
956 /*
957 * |----------------------------------------NAV---------------------------------------------->|
958 * | |--------------------------NAV---------------------------------->| | |
959 * |-------------------NAV--------------->| | | | |----NAV---->|
960 * |------| |-----| |-----| |-----| |-----| |-----| |-----|
961 * |-----| |PSDU 1| | | | | | | | | | | |
962 * | | |
963 * |------| |Block| |Block| |Block| |Block| |Block| |Block|
964 * |Block| |PSDU 2| | Ack | | Ack | | Ack | | Ack | | Ack | |
965 * Ack | | Ack |
966 * |------|<SIFS>| |<SIFS>| Req |<SIFS>| |<SIFS>| Req |<SIFS>| |<SIFS>| Req
967 * |<SIFS>| | |PSDU 3| | | | | | | | | | |
968 * | | | |
969 * |------| | | | | | | | | | | | | |
970 * | |PSDU 4| | | | | | | | | | | | |
971 * | |
972 * ---------------------------------------------------------------------------------------------------
973 * From: AP STA 1 AP STA 2 AP STA 3 AP STA 4
974 * To: AP STA 2 AP STA 3 AP STA 4 AP
975 */
976 NS_TEST_EXPECT_MSG_GT_OR_EQ(m_txPsdus.size(), 19, "Expected at least 19 packets");
977
978 // A first STA sends a Block Ack a SIFS after the reception of the DL MU PPDU
979 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[12].psduMap.size() == 1 &&
980 m_txPsdus[12].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck()),
981 true,
982 "Expected a Block Ack");
983 tEnd = m_txPsdus[11].endTx;
984 tStart = m_txPsdus[12].startTx;
985 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "First Block Ack sent too early");
986 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "First Block Ack sent too late");
987
988 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
989 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[13].psduMap.size() == 1 &&
990 m_txPsdus[13].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAckReq()),
991 true,
992 "Expected a Block Ack Request");
993 tEnd = m_txPsdus[12].endTx;
994 tStart = m_txPsdus[13].startTx;
995 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "First Block Ack Request sent too early");
997 tEnd + sifs + tolerance,
998 "First Block Ack Request sent too late");
999
1000 // A second STA sends a Block Ack a SIFS after the reception of the Block Ack Request
1001 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[14].psduMap.size() == 1 &&
1002 m_txPsdus[14].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck()),
1003 true,
1004 "Expected a Block Ack");
1005 tEnd = m_txPsdus[13].endTx;
1006 tStart = m_txPsdus[14].startTx;
1007 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second Block Ack sent too early");
1008 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second Block Ack sent too late");
1009
1010 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
1011 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[15].psduMap.size() == 1 &&
1012 m_txPsdus[15].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAckReq()),
1013 true,
1014 "Expected a Block Ack Request");
1015 tEnd = m_txPsdus[14].endTx;
1016 tStart = m_txPsdus[15].startTx;
1017 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second Block Ack Request sent too early");
1018 NS_TEST_EXPECT_MSG_LT(tStart,
1019 tEnd + sifs + tolerance,
1020 "Second Block Ack Request sent too late");
1021
1022 // A third STA sends a Block Ack a SIFS after the reception of the Block Ack Request
1023 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[16].psduMap.size() == 1 &&
1024 m_txPsdus[16].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck()),
1025 true,
1026 "Expected a Block Ack");
1027 tEnd = m_txPsdus[15].endTx;
1028 tStart = m_txPsdus[16].startTx;
1029 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third Block Ack sent too early");
1030 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third Block Ack sent too late");
1031
1032 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
1033 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[17].psduMap.size() == 1 &&
1034 m_txPsdus[17].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAckReq()),
1035 true,
1036 "Expected a Block Ack Request");
1037 tEnd = m_txPsdus[16].endTx;
1038 tStart = m_txPsdus[17].startTx;
1039 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third Block Ack Request sent too early");
1040 NS_TEST_EXPECT_MSG_LT(tStart,
1041 tEnd + sifs + tolerance,
1042 "Third Block Ack Request sent too late");
1043
1044 // A fourth STA sends a Block Ack a SIFS after the reception of the Block Ack Request
1045 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[18].psduMap.size() == 1 &&
1046 m_txPsdus[18].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck()),
1047 true,
1048 "Expected a Block Ack");
1049 tEnd = m_txPsdus[17].endTx;
1050 tStart = m_txPsdus[18].startTx;
1051 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Fourth Block Ack sent too early");
1052 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Fourth Block Ack sent too late");
1053
1054 if (m_txopLimit > 0)
1055 {
1056 // DL MU PPDU's NAV
1057 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1058 m_txPsdus[18].endTx,
1059 "Duration/ID in the DL MU PPDU is too short");
1060 // 1st BlockAckReq's NAV
1061 navEnd = m_txPsdus[13].endTx + m_txPsdus[13].psduMap[SU_STA_ID]->GetDuration();
1062 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1063 m_txPsdus[18].endTx,
1064 "Duration/ID in the 1st BlockAckReq is too short");
1065 // 2nd BlockAckReq's NAV
1066 navEnd = m_txPsdus[15].endTx + m_txPsdus[15].psduMap[SU_STA_ID]->GetDuration();
1067 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1068 m_txPsdus[18].endTx,
1069 "Duration/ID in the 2nd BlockAckReq is too short");
1070 // 3rd BlockAckReq's NAV
1071 navEnd = m_txPsdus[17].endTx + m_txPsdus[17].psduMap[SU_STA_ID]->GetDuration();
1072 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1073 m_txPsdus[18].endTx,
1074 "Duration/ID in the 3rd BlockAckReq is too short");
1075 }
1076 nTxPsdus = 19;
1077 }
1078 else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_TF_MU_BAR)
1079 {
1080 /*
1081 * |----------------NAV--------------->|
1082 * | |--------NAV------>|
1083 * |------| |---------| |-----------|
1084 * |PSDU 1| | | |Block Ack 1|
1085 * |------| | MU-BAR | |-----------|
1086 * |PSDU 2| | Trigger | |Block Ack 2|
1087 * |------|<SIFS>| Frame |<SIFS>|-----------|
1088 * |PSDU 3| | | |Block Ack 3|
1089 * |------| | | |-----------|
1090 * |PSDU 4| | | |Block Ack 4|
1091 * --------------------------------------------------
1092 * From: AP AP
1093 * To: all AP
1094 */
1095 NS_TEST_EXPECT_MSG_GT_OR_EQ(m_txPsdus.size(), 17, "Expected at least 17 packets");
1096
1097 // the AP transmits a MU-BAR Trigger Frame an IFS after the transmission of the DL MU PPDU
1098 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[12].psduMap.size() == 1 &&
1099 m_txPsdus[12].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger()),
1100 true,
1101 "Expected a MU-BAR Trigger Frame");
1102 tEnd = m_txPsdus[11].endTx;
1103 tStart = m_txPsdus[12].startTx;
1104 NS_TEST_EXPECT_MSG_EQ(tStart, tEnd + sifs, "MU-BAR Trigger Frame sent at wrong time");
1105
1106 // A first STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU
1107 // PPDU
1108 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[13].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
1109 m_txPsdus[13].psduMap.size() == 1 &&
1110 m_txPsdus[13].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1111 true,
1112 "Expected a Block Ack");
1113 tEnd = m_txPsdus[12].endTx;
1114 tStart = m_txPsdus[13].startTx;
1115 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1116 NS_TEST_EXPECT_MSG_LT(tStart,
1117 tEnd + sifs + tolerance,
1118 "Block Ack in HE TB PPDU sent too late");
1119
1120 // A second STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU
1121 // PPDU
1122 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[14].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
1123 m_txPsdus[14].psduMap.size() == 1 &&
1124 m_txPsdus[14].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1125 true,
1126 "Expected a Block Ack");
1127 tEnd = m_txPsdus[12].endTx;
1128 tStart = m_txPsdus[14].startTx;
1129 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1130 NS_TEST_EXPECT_MSG_LT(tStart,
1131 tEnd + sifs + tolerance,
1132 "Block Ack in HE TB PPDU sent too late");
1133
1134 // A third STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU
1135 // PPDU
1136 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[15].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
1137 m_txPsdus[15].psduMap.size() == 1 &&
1138 m_txPsdus[15].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1139 true,
1140 "Expected a Block Ack");
1141 tEnd = m_txPsdus[12].endTx;
1142 tStart = m_txPsdus[15].startTx;
1143 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1144 NS_TEST_EXPECT_MSG_LT(tStart,
1145 tEnd + sifs + tolerance,
1146 "Block Ack in HE TB PPDU sent too late");
1147
1148 // A fourth STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU
1149 // PPDU
1150 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[16].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
1151 m_txPsdus[16].psduMap.size() == 1 &&
1152 m_txPsdus[16].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1153 true,
1154 "Expected a Block Ack");
1155 tEnd = m_txPsdus[12].endTx;
1156 tStart = m_txPsdus[16].startTx;
1157 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1158 NS_TEST_EXPECT_MSG_LT(tStart,
1159 tEnd + sifs + tolerance,
1160 "Block Ack in HE TB PPDU sent too late");
1161
1162 if (m_txopLimit > 0)
1163 {
1164 // DL MU PPDU's NAV
1165 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1166 m_txPsdus[13].endTx,
1167 "Duration/ID in the DL MU PPDU is too short");
1168 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1169 m_txPsdus[14].endTx,
1170 "Duration/ID in the DL MU PPDU is too short");
1171 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1172 m_txPsdus[15].endTx,
1173 "Duration/ID in the DL MU PPDU is too short");
1174 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1175 m_txPsdus[16].endTx,
1176 "Duration/ID in the DL MU PPDU is too short");
1177 }
1178 // MU-BAR Trigger Frame's NAV
1179 navEnd = m_txPsdus[12].endTx + m_txPsdus[12].psduMap[SU_STA_ID]->GetDuration();
1180 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1181 m_txPsdus[13].endTx,
1182 "Duration/ID in the MU-BAR Trigger Frame is too short");
1183 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1184 m_txPsdus[14].endTx,
1185 "Duration/ID in the MU-BAR Trigger Frame is too short");
1186 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1187 m_txPsdus[15].endTx,
1188 "Duration/ID in the MU-BAR Trigger Frame is too short");
1189 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1190 m_txPsdus[16].endTx,
1191 "Duration/ID in the MU-BAR Trigger Frame is too short");
1192
1193 nTxPsdus = 17;
1194 }
1195 else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_AGGREGATE_TF)
1196 {
1197 /*
1198 * |--------NAV------>|
1199 * |------|-----------| |-----------|
1200 * |PSDU 1|MU-BAR TF 1| |Block Ack 1|
1201 * |------------------| |-----------|
1202 * |PSDU 2|MU-BAR TF 2| |Block Ack 2|
1203 * |------------------|<SIFS>|-----------|
1204 * |PSDU 3|MU-BAR TF 3| |Block Ack 3|
1205 * |------------------| |-----------|
1206 * |PSDU 4|MU-BAR TF 4| |Block Ack 4|
1207 * --------------------------------------------------
1208 * From: AP
1209 * To: AP
1210 */
1211 NS_TEST_EXPECT_MSG_GT_OR_EQ(m_txPsdus.size(), 16, "Expected at least 16 packets");
1212
1213 // The last MPDU in each PSDU is a MU-BAR Trigger Frame
1214 for (auto& psdu : m_txPsdus[11].psduMap)
1215 {
1216 NS_TEST_EXPECT_MSG_EQ((*(--psdu.second->end()))->GetHeader().IsTrigger(),
1217 true,
1218 "Expected an aggregated MU-BAR Trigger Frame");
1219 }
1220
1221 // A first STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU
1222 // PPDU
1223 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[12].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
1224 m_txPsdus[12].psduMap.size() == 1 &&
1225 m_txPsdus[12].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1226 true,
1227 "Expected a Block Ack");
1228 tEnd = m_txPsdus[11].endTx;
1229 tStart = m_txPsdus[12].startTx;
1230 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1231 NS_TEST_EXPECT_MSG_LT(tStart,
1232 tEnd + sifs + tolerance,
1233 "Block Ack in HE TB PPDU sent too late");
1234 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1235 m_txPsdus[12].endTx,
1236 "Duration/ID in the DL MU PPDU is too short");
1237
1238 // A second STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU
1239 // PPDU
1240 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[13].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
1241 m_txPsdus[13].psduMap.size() == 1 &&
1242 m_txPsdus[13].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1243 true,
1244 "Expected a Block Ack");
1245 tEnd = m_txPsdus[11].endTx;
1246 tStart = m_txPsdus[13].startTx;
1247 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1248 NS_TEST_EXPECT_MSG_LT(tStart,
1249 tEnd + sifs + tolerance,
1250 "Block Ack in HE TB PPDU sent too late");
1251 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1252 m_txPsdus[13].endTx,
1253 "Duration/ID in the DL MU PPDU is too short");
1254
1255 // A third STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU
1256 // PPDU
1257 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[14].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
1258 m_txPsdus[14].psduMap.size() == 1 &&
1259 m_txPsdus[14].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1260 true,
1261 "Expected a Block Ack");
1262 tEnd = m_txPsdus[11].endTx;
1263 tStart = m_txPsdus[14].startTx;
1264 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1265 NS_TEST_EXPECT_MSG_LT(tStart,
1266 tEnd + sifs + tolerance,
1267 "Block Ack in HE TB PPDU sent too late");
1268 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1269 m_txPsdus[14].endTx,
1270 "Duration/ID in the DL MU PPDU is too short");
1271
1272 // A fourth STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU
1273 // PPDU
1274 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[15].txVector.GetPreambleType() == WIFI_PREAMBLE_HE_TB &&
1275 m_txPsdus[15].psduMap.size() == 1 &&
1276 m_txPsdus[15].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1277 true,
1278 "Expected a Block Ack");
1279 tEnd = m_txPsdus[11].endTx;
1280 tStart = m_txPsdus[15].startTx;
1281 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1282 NS_TEST_EXPECT_MSG_LT(tStart,
1283 tEnd + sifs + tolerance,
1284 "Block Ack in HE TB PPDU sent too late");
1285 NS_TEST_EXPECT_MSG_GT_OR_EQ(navEnd + tolerance,
1286 m_txPsdus[15].endTx,
1287 "Duration/ID in the DL MU PPDU is too short");
1288
1289 nTxPsdus = 16;
1290 }
1291
1294 "Not all DL packets have been received");
1295
1297 {
1298 // EDCA disabled, find the first PSDU transmitted by a station not in an
1299 // HE TB PPDU and check that it was not transmitted before the MU EDCA
1300 // timer expired
1301 for (std::size_t i = nTxPsdus; i < m_txPsdus.size(); ++i)
1302 {
1303 if (m_txPsdus[i].psduMap.size() == 1 &&
1304 m_txPsdus[i].psduMap.begin()->second->GetHeader(0).GetAddr2() !=
1306 !m_txPsdus[i].txVector.IsUlMu())
1307 {
1309 m_txPsdus[i].startTx.GetMicroSeconds(),
1312 "A station transmitted before the MU EDCA timer expired");
1313 break;
1314 }
1315 }
1316 }
1318 {
1319 // stations used worse access parameters after successful UL MU transmission
1320 for (const auto& cwValue : m_cwValues)
1321 {
1322 NS_TEST_EXPECT_MSG_EQ((cwValue == 2 || cwValue >= m_muEdcaParameterSet.muCwMin),
1323 true,
1324 "A station did not set the correct MU CW min");
1325 }
1326 }
1327
1328 m_txPsdus.clear();
1329}
1330
1331void
1333{
1334 uint32_t previousSeed = RngSeedManager::GetSeed();
1335 uint64_t previousRun = RngSeedManager::GetRun();
1336 Config::SetGlobal("RngSeed", UintegerValue(1));
1337 Config::SetGlobal("RngRun", UintegerValue(1));
1338 int64_t streamNumber = 20;
1339
1341 wifiApNode.Create(1);
1342
1344 wifiStaNodes.Create(m_nStations);
1345
1346 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1347 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1348 spectrumChannel->AddPropagationLossModel(lossModel);
1350 CreateObject<ConstantSpeedPropagationDelayModel>();
1351 spectrumChannel->SetPropagationDelayModel(delayModel);
1352
1354 phy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11_RADIO);
1355 phy.SetErrorRateModel("ns3::NistErrorRateModel");
1356 phy.SetChannel(spectrumChannel);
1357 switch (m_channelWidth)
1358 {
1359 case 20:
1360 phy.Set("ChannelSettings", StringValue("{36, 20, BAND_5GHZ, 0}"));
1361 break;
1362 case 40:
1363 phy.Set("ChannelSettings", StringValue("{38, 40, BAND_5GHZ, 0}"));
1364 break;
1365 case 80:
1366 phy.Set("ChannelSettings", StringValue("{42, 80, BAND_5GHZ, 0}"));
1367 break;
1368 case 160:
1369 phy.Set("ChannelSettings", StringValue("{50, 160, BAND_5GHZ, 0}"));
1370 break;
1371 default:
1372 NS_ABORT_MSG("Invalid channel bandwidth (must be 20, 40, 80 or 160)");
1373 }
1374
1375 Config::SetDefault("ns3::HeConfiguration::MuBeAifsn",
1377 Config::SetDefault("ns3::HeConfiguration::MuBeCwMin",
1379 Config::SetDefault("ns3::HeConfiguration::MuBeCwMax",
1381 Config::SetDefault("ns3::HeConfiguration::BeMuEdcaTimer",
1383
1384 Config::SetDefault("ns3::HeConfiguration::MuBkAifsn",
1386 Config::SetDefault("ns3::HeConfiguration::MuBkCwMin",
1388 Config::SetDefault("ns3::HeConfiguration::MuBkCwMax",
1390 Config::SetDefault("ns3::HeConfiguration::BkMuEdcaTimer",
1392
1393 Config::SetDefault("ns3::HeConfiguration::MuViAifsn",
1395 Config::SetDefault("ns3::HeConfiguration::MuViCwMin",
1397 Config::SetDefault("ns3::HeConfiguration::MuViCwMax",
1399 Config::SetDefault("ns3::HeConfiguration::ViMuEdcaTimer",
1401
1402 Config::SetDefault("ns3::HeConfiguration::MuVoAifsn",
1404 Config::SetDefault("ns3::HeConfiguration::MuVoCwMin",
1406 Config::SetDefault("ns3::HeConfiguration::MuVoCwMax",
1408 Config::SetDefault("ns3::HeConfiguration::VoMuEdcaTimer",
1410
1411 // increase MSDU lifetime so that it does not expire before the MU EDCA timer ends
1412 Config::SetDefault("ns3::WifiMacQueue::MaxDelay", TimeValue(Seconds(2)));
1413
1415 wifi.SetStandard(WIFI_STANDARD_80211ax);
1416 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
1417 wifi.ConfigHeOptions("MuBeAifsn",
1419 "MuBeCwMin",
1421 "MuBeCwMax",
1423 "BeMuEdcaTimer",
1425 // MU EDCA timers must be either all null or all non-null
1426 "BkMuEdcaTimer",
1428 "ViMuEdcaTimer",
1430 "VoMuEdcaTimer",
1432
1434 Ssid ssid = Ssid("ns-3-ssid");
1435 mac.SetType("ns3::StaWifiMac",
1436 "Ssid",
1437 SsidValue(ssid),
1438 "BE_MaxAmsduSize",
1439 UintegerValue(0),
1440 "BE_MaxAmpduSize",
1442 /* setting blockack threshold for sta's BE queue */
1443 "BE_BlockAckThreshold",
1444 UintegerValue(2),
1445 "BK_MaxAmsduSize",
1446 UintegerValue(0),
1447 "BK_MaxAmpduSize",
1449 /* setting blockack threshold for sta's BK queue */
1450 "BK_BlockAckThreshold",
1451 UintegerValue(2),
1452 "VI_MaxAmsduSize",
1453 UintegerValue(0),
1454 "VI_MaxAmpduSize",
1456 /* setting blockack threshold for sta's VI queue */
1457 "VI_BlockAckThreshold",
1458 UintegerValue(2),
1459 "VO_MaxAmsduSize",
1460 UintegerValue(0),
1461 "VO_MaxAmpduSize",
1463 /* setting blockack threshold for sta's VO queue */
1464 "VO_BlockAckThreshold",
1465 UintegerValue(2),
1466 "ActiveProbing",
1467 BooleanValue(false));
1468
1469 m_staDevices = wifi.Install(phy, mac, wifiStaNodes);
1470
1471 mac.SetType("ns3::ApWifiMac", "BeaconGeneration", BooleanValue(true));
1472 mac.SetMultiUserScheduler("ns3::TestMultiUserScheduler",
1473 // request channel access at 1.5s
1474 "AccessReqInterval",
1475 TimeValue(Seconds(1.5)),
1476 "DelayAccessReqUponAccess",
1477 BooleanValue(false));
1478 mac.SetAckManager("ns3::WifiDefaultAckManager",
1479 "DlMuAckSequenceType",
1481
1482 m_apDevice = DynamicCast<WifiNetDevice>(wifi.Install(phy, mac, wifiApNode).Get(0));
1483
1484 // Assign fixed streams to random variables in use
1485 streamNumber += wifi.AssignStreams(NetDeviceContainer(m_apDevice), streamNumber);
1486 streamNumber += wifi.AssignStreams(m_staDevices, streamNumber);
1487
1489 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
1490
1491 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
1492 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
1493 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
1494 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
1495 positionAlloc->Add(Vector(-1.0, -1.0, 0.0));
1496 mobility.SetPositionAllocator(positionAlloc);
1497
1498 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
1499 mobility.Install(wifiApNode);
1500 mobility.Install(wifiStaNodes);
1501
1503 for (uint32_t i = 0; i < allDevices.GetN(); i++)
1504 {
1505 auto dev = DynamicCast<WifiNetDevice>(allDevices.Get(i));
1506 // set the same TXOP limit on all ACs
1507 dev->GetMac()->GetQosTxop(AC_BE)->SetTxopLimit(MicroSeconds(m_txopLimit));
1508 dev->GetMac()->GetQosTxop(AC_BK)->SetTxopLimit(MicroSeconds(m_txopLimit));
1509 dev->GetMac()->GetQosTxop(AC_VI)->SetTxopLimit(MicroSeconds(m_txopLimit));
1510 dev->GetMac()->GetQosTxop(AC_VO)->SetTxopLimit(MicroSeconds(m_txopLimit));
1511 // set the same AIFSN on all ACs (just to be able to check inter-frame spaces)
1512 dev->GetMac()->GetQosTxop(AC_BE)->SetAifsn(3);
1513 dev->GetMac()->GetQosTxop(AC_BK)->SetAifsn(3);
1514 dev->GetMac()->GetQosTxop(AC_VI)->SetAifsn(3);
1515 dev->GetMac()->GetQosTxop(AC_VO)->SetAifsn(3);
1516 }
1517
1518 PacketSocketHelper packetSocket;
1519 packetSocket.Install(wifiApNode);
1520 packetSocket.Install(wifiStaNodes);
1521
1522 // DL Traffic
1523 for (uint16_t i = 0; i < m_nStations; i++)
1524 {
1525 PacketSocketAddress socket;
1527 socket.SetPhysicalAddress(m_staDevices.Get(i)->GetAddress());
1528 socket.SetProtocol(1);
1529
1530 // the first client application generates two packets in order
1531 // to trigger the establishment of a Block Ack agreement
1532 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient>();
1533 client1->SetAttribute("PacketSize", UintegerValue(1400));
1534 client1->SetAttribute("MaxPackets", UintegerValue(2));
1535 client1->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
1536 client1->SetAttribute("Priority", UintegerValue(i * 2)); // 0, 2, 4 and 6
1537 client1->SetRemote(socket);
1538 wifiApNode.Get(0)->AddApplication(client1);
1539 client1->SetStartTime(Seconds(1) + i * MilliSeconds(1));
1540 client1->SetStopTime(Seconds(2.0));
1541
1542 // the second client application generates the selected number of packets,
1543 // which are sent in DL MU PPDUs.
1544 Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient>();
1545 client2->SetAttribute("PacketSize", UintegerValue(1400 + i * 100));
1546 client2->SetAttribute("MaxPackets", UintegerValue(m_nPktsPerSta));
1547 client2->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
1548 client2->SetAttribute("Priority", UintegerValue(i * 2)); // 0, 2, 4 and 6
1549 client2->SetRemote(socket);
1550 wifiApNode.Get(0)->AddApplication(client2);
1551 client2->SetStartTime(Seconds(1.5003));
1552 client2->SetStopTime(Seconds(2.5));
1553
1554 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
1555 server->SetLocal(socket);
1556 wifiStaNodes.Get(i)->AddApplication(server);
1557 server->SetStartTime(Seconds(0.0));
1558 server->SetStopTime(Seconds(3.0));
1559 }
1560
1561 // UL Traffic
1562 for (uint16_t i = 0; i < m_nStations; i++)
1563 {
1564 m_sockets[i].SetSingleDevice(m_staDevices.Get(i)->GetIfIndex());
1565 m_sockets[i].SetPhysicalAddress(m_apDevice->GetAddress());
1566 m_sockets[i].SetProtocol(1);
1567
1568 // the first client application generates two packets in order
1569 // to trigger the establishment of a Block Ack agreement
1570 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient>();
1571 client1->SetAttribute("PacketSize", UintegerValue(1400));
1572 client1->SetAttribute("MaxPackets", UintegerValue(2));
1573 client1->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
1574 client1->SetAttribute("Priority", UintegerValue(i * 2)); // 0, 2, 4 and 6
1575 client1->SetRemote(m_sockets[i]);
1576 wifiStaNodes.Get(i)->AddApplication(client1);
1577 client1->SetStartTime(Seconds(1.005) + i * MilliSeconds(1));
1578 client1->SetStopTime(Seconds(2.0));
1579
1580 // packets to be included in HE TB PPDUs are generated (by Transmit()) when
1581 // the first Basic Trigger Frame is sent by the AP
1582
1583 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
1584 server->SetLocal(m_sockets[i]);
1585 wifiApNode.Get(0)->AddApplication(server);
1586 server->SetStartTime(Seconds(0.0));
1587 server->SetStopTime(Seconds(3.0));
1588 }
1589
1590 Config::Connect("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
1592 // Trace PSDUs passed to the PHY on all devices
1593 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
1595
1596 Simulator::Stop(Seconds(3));
1597 Simulator::Run();
1598
1599 CheckResults(m_apDevice->GetMac()->GetWifiPhy()->GetSifs(),
1600 m_apDevice->GetMac()->GetWifiPhy()->GetSlot(),
1601 m_apDevice->GetMac()->GetQosTxop(AC_BE)->Txop::GetAifsn());
1602
1603 Simulator::Destroy();
1604
1605 // Restore the seed and run number that were in effect before this test
1606 Config::SetGlobal("RngSeed", UintegerValue(previousSeed));
1607 Config::SetGlobal("RngRun", UintegerValue(previousRun));
1608}
1609
1617{
1618 public:
1620};
1621
1623 : TestSuite("wifi-mac-ofdma", UNIT)
1624{
1625 using MuEdcaParams = std::initializer_list<OfdmaAckSequenceTest::MuEdcaParameterSet>;
1626
1627 for (auto& muEdcaParameterSet : MuEdcaParams{{0, 0, 0, 0} /* no MU EDCA */,
1628 {0, 127, 2047, 100} /* EDCA disabled */,
1629 {10, 127, 2047, 100} /* worse parameters */})
1630 {
1632 WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE,
1633 10000,
1634 5440,
1635 15,
1636 muEdcaParameterSet),
1637 TestCase::QUICK);
1639 WifiAcknowledgment::DL_MU_AGGREGATE_TF,
1640 10000,
1641 5440,
1642 15,
1643 muEdcaParameterSet),
1644 TestCase::QUICK);
1646 WifiAcknowledgment::DL_MU_TF_MU_BAR,
1647 10000,
1648 5440,
1649 15,
1650 muEdcaParameterSet),
1651 TestCase::QUICK);
1653 WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE,
1654 10000,
1655 0,
1656 15,
1657 muEdcaParameterSet),
1658 TestCase::QUICK);
1660 WifiAcknowledgment::DL_MU_AGGREGATE_TF,
1661 10000,
1662 0,
1663 15,
1664 muEdcaParameterSet),
1665 TestCase::QUICK);
1667 WifiAcknowledgment::DL_MU_TF_MU_BAR,
1668 10000,
1669 0,
1670 15,
1671 muEdcaParameterSet),
1672 TestCase::QUICK);
1673 }
1674}
1675
#define Min(a, b)
Test OFDMA acknowledgment sequences.
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
Time m_edcaDisabledStartTime
time when disabling EDCA started
uint16_t m_flushed
number of DL packets flushed after DL MU PPDU
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when FrameExchangeManager passes PSDUs to the PHY.
OfdmaAckSequenceTest(uint16_t width, WifiAcknowledgment::Method dlType, uint32_t maxAmpduSize, uint16_t txopLimit, uint16_t nPktsPerSta, MuEdcaParameterSet muEdcaParameterSet)
Constructor.
static constexpr uint16_t m_muTimerRes
MU timer resolution in usec.
uint16_t m_received
number of packets received by the stations
void CheckResults(Time sifs, Time slotTime, uint8_t aifsn)
Check correctness of transmitted frames.
WifiAcknowledgment::Method m_dlMuAckType
DL MU ack sequence type.
bool m_ulPktsGenerated
whether UL packets for HE TB PPDUs have been generated
uint16_t m_nPktsPerSta
number of packets to send to each station
NetDeviceContainer m_staDevices
stations' devices
std::vector< PacketSocketAddress > m_sockets
packet socket addresses for STAs
uint16_t m_txopLimit
TXOP limit in microseconds.
void DoRun() override
Implementation to actually run this TestCase.
void L7Receive(std::string context, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
uint16_t m_channelWidth
PHY channel bandwidth in MHz.
uint32_t m_maxAmpduSize
maximum A-MPDU size in bytes
Ptr< WifiNetDevice > m_apDevice
AP's device.
std::vector< uint32_t > m_cwValues
CW used by stations after MU exchange.
void TraceCw(uint32_t staIndex, uint32_t cw, uint8_t)
Function to trace CW value used by the given station after the MU exchange.
uint16_t m_nStations
number of stations
MuEdcaParameterSet m_muEdcaParameterSet
MU EDCA Parameter Set.
Dummy Multi User Scheduler used to test OFDMA ack sequences.
WifiPsduMap m_psduMap
the DL MU PPDU to transmit
TxFormat m_txFormat
the format of next transmission
WifiTxVector m_txVector
the TX vector for MU PPDUs
UlMuInfo ComputeUlMuInfo() override
Prepare the information required to solicit an UL MU transmission.
TriggerFrameType m_ulTriggerType
Trigger Frame type for UL MU.
WifiTxParameters m_txParams
TX parameters.
TxFormat SelectTxFormat() override
Select the format of the next transmission.
void ComputeWifiTxVector()
Compute the TX vector to use for MU PPDUs.
static TypeId GetTypeId()
Get the type ID.
WifiMacHeader m_triggerHdr
MAC header for Trigger Frame.
CtrlTriggerHeader m_trigger
Trigger Frame to send.
DlMuInfo ComputeDlMuInfo() override
Compute the information required to perform a DL MU transmission.
wifi MAC OFDMA Test Suite
a polymophic address class
Definition: address.h:92
const std::map< uint16_t, Mac48Address > & GetStaList(uint8_t linkId=SINGLE_LINK_OP_ID) const
Get a const reference to the map of associated stations on the given link.
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAck response.
Definition: ctrl-headers.h:202
std::size_t GetNPerAidTidInfoSubfields() const
For Multi-STA Block Acks, get the number of Per AID TID Info subfields included in this Block Ack.
uint8_t GetTidInfo(std::size_t index=0) const
For Block Ack variants other than Multi-STA Block Ack, get the TID_INFO subfield of the BA Control fi...
bool GetAckType(std::size_t index) const
For Multi-STA Block Acks, get the Ack Type subfield of the Per AID TID Info subfield identified by th...
bool IsMultiSta() const
Check if the BlockAck frame variant is Multi-STA Block Ack.
Headers for Trigger frames.
Definition: ctrl-headers.h:886
bool IsBasic() const
Check if this is a Basic Trigger frame.
WifiTxVector GetHeTbTxVector(uint16_t staId) const
Get the TX vector that the station with the given STA-ID will use to send the HE TB PPDU solicited by...
uint16_t GetGuardInterval() const
Get the guard interval duration (in nanoseconds) of the solicited HE TB PPDU.
bool IsBsrp() const
Check if this is a Buffer Status Report Poll Trigger frame.
ConstIterator begin() const
Get a const iterator pointing to the first User Info field in the list.
std::size_t GetNUserInfoFields() const
Get the number of User Info fields in this Trigger Frame.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
Hold variables of type enum.
Definition: enum.h:56
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:41
an EUI-48 address
Definition: mac48-address.h:46
Helper class used to assign positions and mobility models to nodes.
MultiUserScheduler is an abstract base class defining the API that APs supporting at least VHT can us...
bool m_initialFrame
true if a TXOP is being started
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager() const
Get the station manager attached to the AP.
Ptr< ApWifiMac > m_apMac
the AP wifi MAC
Time m_availableTime
the time available for frame exchange
Ptr< HeFrameExchangeManager > m_heFem
HE Frame Exchange Manager.
uint32_t GetMaxSizeOfQosNullAmpdu(const CtrlTriggerHeader &trigger) const
Get the maximum size in bytes among the A-MPDUs containing QoS Null frames and solicited by the given...
TxFormat
Enumeration of the possible transmission formats.
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:369
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
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.
Ptr< WifiMpdu > PeekNextMpdu(uint8_t linkId, uint8_t tid=8, Mac48Address recipient=Mac48Address::GetBroadcast(), Ptr< WifiMpdu > item=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:368
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:454
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Hold variables of type string.
Definition: string.h:42
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:412
AttributeValue implementation for Time.
Definition: nstime.h:1425
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:220
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:325
Implements the IEEE 802.11 MAC header.
uint8_t GetQosTid() const
Return the Traffic ID of a QoS header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
WifiMacType GetType() const
Return the type (enum WifiMacType)
void SetDsNotFrom()
Un-set the From DS bit in the Frame Control field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
Mac48Address GetAddr2() const
Return the address in the Address 2 field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
void SetDsNotTo()
Un-set the To DS bit in the Frame Control field.
create MAC layers for a ns3::WifiNetDevice.
Ptr< HeConfiguration > GetHeConfiguration() const
Definition: wifi-mac.cc:1250
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:949
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:881
Mac48Address GetAddress() const
Definition: wifi-mac.cc:442
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:489
represent a single transmission mode
Definition: wifi-mode.h:50
Ptr< WifiMac > GetMac() const
uint32_t GetIfIndex() const override
Address GetAddress() const override
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:980
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:728
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:950
WifiTxVector GetRtsTxVector(Mac48Address address)
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
std::unique_ptr< WifiProtection > m_protection
protection method
std::unique_ptr< WifiAcknowledgment > m_acknowledgment
acknowledgment method
Time m_txDuration
TX duration of the frame.
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...
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType() const
void SetRuAllocation(const RuAllocation &ruAlloc)
Set RU Allocation of SIG-B common field.
bool IsMu() const
Return true if this TX vector is used for a multi-user transmission.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
void SetGlobal(std::string name, const AttributeValue &value)
Definition: config.cc:937
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:891
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
#define NS_TEST_EXPECT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to limit and report if not.
Definition: test.h:996
#define NS_TEST_EXPECT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report if not.
Definition: test.h:830
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
Definition: test.h:790
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
Definition: test.h:956
#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:666
#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:251
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1374
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:74
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:559
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ AC_BE
Best Effort.
Definition: qos-utils.h:76
@ AC_VO
Voice.
Definition: qos-utils.h:82
@ AC_VI
Video.
Definition: qos-utils.h:80
@ AC_BK
Background.
Definition: qos-utils.h:78
@ BASIC_TRIGGER
Definition: ctrl-headers.h:560
@ BSRP_TRIGGER
Definition: ctrl-headers.h:564
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Time GetPpduMaxTime(WifiPreamble preamble)
Get the maximum PPDU duration (see Section 10.14 of 802.11-2016) for the PHY layers defining the aPPD...
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:691
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:140
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_QOSDATA_NULL
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
STL namespace.
ssid
Definition: third.py:86
mac
Definition: third.py:85
wifi
Definition: third.py:88
wifiApNode
Definition: third.py:79
mobility
Definition: third.py:96
wifiStaNodes
Definition: third.py:77
phy
Definition: third.py:82
Information about transmitted frames.
WifiConstPsduMap psduMap
transmitted PSDU map
uint8_t muAifsn
MU AIFS (0 to disable EDCA)
uint8_t muTimer
MU EDCA Timer in units of 8192 microseconds (0 not to use MU EDCA)
Information to be provided in case of DL MU transmission.
Information to be provided in case of UL MU transmission.
Method
Available acknowledgment methods.
static WifiMacOfdmaTestSuite g_wifiMacOfdmaTestSuite
the test suite
#define SU_STA_ID
Definition: wifi-mode.h:34