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
43#include <iomanip>
44
45using namespace ns3;
46
47NS_LOG_COMPONENT_DEFINE("WifiMacOfdmaTestSuite");
48
62{
63 public:
68 static TypeId GetTypeId();
70 ~TestMultiUserScheduler() override;
71
72 private:
73 // Implementation of pure virtual methods of MultiUserScheduler class
74 TxFormat SelectTxFormat() override;
75 DlMuInfo ComputeDlMuInfo() override;
76 UlMuInfo ComputeUlMuInfo() override;
77
82
91};
92
94
97{
98 static TypeId tid =
99 TypeId("ns3::TestMultiUserScheduler")
101 .SetGroupName("Wifi")
102 .AddConstructor<TestMultiUserScheduler>()
103 .AddAttribute("ModulationClass",
104 "Modulation class for DL MU PPDUs and TB PPDUs.",
108 return tid;
109}
110
112 : m_txFormat(SU_TX),
113 m_ulTriggerType(TriggerFrameType::BSRP_TRIGGER)
114{
115 NS_LOG_FUNCTION(this);
116}
117
119{
121}
122
125{
126 NS_LOG_FUNCTION(this);
127
128 // Do not use OFDMA if a BA agreement has not been established with all the stations
129 if (Simulator::Now() < Seconds(1.5))
130 {
131 NS_LOG_DEBUG("Return SU_TX");
132 return SU_TX;
133 }
134
136
137 if (m_txFormat == SU_TX || m_txFormat == DL_MU_TX ||
138 (m_txFormat == UL_MU_TX && m_ulTriggerType == TriggerFrameType::BSRP_TRIGGER))
139 {
140 // try to send a Trigger Frame
141 TriggerFrameType ulTriggerType =
142 (m_txFormat == SU_TX || m_txFormat == DL_MU_TX ? TriggerFrameType::BSRP_TRIGGER
143 : TriggerFrameType::BASIC_TRIGGER);
144
145 WifiTxVector txVector = m_txVector;
148 m_trigger = CtrlTriggerHeader(ulTriggerType, txVector);
149
151
152 uint32_t ampduSize = (ulTriggerType == TriggerFrameType::BSRP_TRIGGER)
154 : 3500; // allows aggregation of 2 MPDUs in TB PPDUs
155
156 Time duration =
157 WifiPhy::CalculateTxDuration(ampduSize,
158 txVector,
160 m_apMac->GetStaList(SINGLE_LINK_OP_ID).begin()->first);
161
162 uint16_t length;
163 std::tie(length, duration) = HePhy::ConvertHeTbPpduDurationToLSigLength(
164 duration,
167 m_trigger.SetUlLength(length);
168
169 Ptr<Packet> packet = Create<Packet>();
170 packet->AddHeader(m_trigger);
171
173 m_triggerHdr.SetAddr1(Mac48Address::GetBroadcast());
177
178 auto item = Create<WifiMpdu>(packet, m_triggerHdr);
179
181 // set the TXVECTOR used to send the Trigger Frame
184
185 if (!GetHeFem(SINGLE_LINK_OP_ID)->TryAddMpdu(item, m_txParams, m_availableTime) ||
187 m_txParams.m_protection->protectionTime + m_txParams.m_txDuration // TF tx time
188 + m_apMac->GetWifiPhy()->GetSifs() + duration +
189 m_txParams.m_acknowledgment->acknowledgmentTime >
191 {
192 NS_LOG_DEBUG("Remaining TXOP duration is not enough for BSRP TF exchange");
193 return SU_TX;
194 }
195
197 m_ulTriggerType = ulTriggerType;
198 }
199 else if (m_txFormat == UL_MU_TX)
200 {
201 // try to send a DL MU PPDU
202 m_psduMap.clear();
203 const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList(SINGLE_LINK_OP_ID);
204 NS_ABORT_MSG_IF(staList.size() != 4, "There must be 4 associated stations");
205
206 /* Initialize TX params */
209
210 for (auto& sta : staList)
211 {
212 Ptr<WifiMpdu> peeked;
213 uint8_t tid;
214
215 for (tid = 0; tid < 8; tid++)
216 {
217 peeked = m_apMac->GetQosTxop(tid)->PeekNextMpdu(SINGLE_LINK_OP_ID, tid, sta.second);
218 if (peeked)
219 {
220 break;
221 }
222 }
223
224 if (!peeked)
225 {
226 NS_LOG_DEBUG("No frame to send to " << sta.second);
227 continue;
228 }
229
231 peeked,
235 if (!mpdu)
236 {
237 NS_LOG_DEBUG("Not enough time to send frames to all the stations");
238 return SU_TX;
239 }
240
241 std::vector<Ptr<WifiMpdu>> mpduList;
242 mpduList = GetHeFem(SINGLE_LINK_OP_ID)
243 ->GetMpduAggregator()
244 ->GetNextAmpdu(mpdu, m_txParams, m_availableTime);
245
246 if (mpduList.size() > 1)
247 {
248 m_psduMap[sta.first] = Create<WifiPsdu>(std::move(mpduList));
249 }
250 else
251 {
252 m_psduMap[sta.first] = Create<WifiPsdu>(mpdu, true);
253 }
254 }
255
256 if (m_psduMap.empty())
257 {
258 NS_LOG_DEBUG("No frame to send");
259 return SU_TX;
260 }
261
263 }
264 else
265 {
266 NS_ABORT_MSG("Cannot get here.");
267 }
268
269 NS_LOG_DEBUG("Return " << m_txFormat);
270 return m_txFormat;
271}
272
273void
275{
276 if (m_txVector.IsDlMu())
277 {
278 // the TX vector has been already computed
279 return;
280 }
281
282 uint16_t bw = m_apMac->GetWifiPhy()->GetChannelWidth();
283
287 {
289 }
291 m_txVector.SetGuardInterval(m_apMac->GetHeConfiguration()->GetGuardInterval().GetNanoSeconds());
293 GetWifiRemoteStationManager(SINGLE_LINK_OP_ID)->GetDefaultTxPowerLevel());
294
295 const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList(SINGLE_LINK_OP_ID);
296 NS_ABORT_MSG_IF(staList.size() != 4, "There must be 4 associated stations");
297
298 HeRu::RuType ruType;
299 switch (bw)
300 {
301 case 20:
302 ruType = HeRu::RU_52_TONE;
304 break;
305 case 40:
306 ruType = HeRu::RU_106_TONE;
307 m_txVector.SetRuAllocation({96, 96});
308 break;
309 case 80:
310 ruType = HeRu::RU_242_TONE;
311 m_txVector.SetRuAllocation({192, 192, 192, 192});
312 break;
313 case 160:
314 ruType = HeRu::RU_484_TONE;
315 m_txVector.SetRuAllocation({200, 200, 200, 200, 200, 200, 200, 200});
316 break;
317 default:
318 NS_ABORT_MSG("Unsupported channel width");
319 }
320
321 bool primary80 = true;
322 std::size_t ruIndex = 1;
323
324 for (auto& sta : staList)
325 {
326 if (bw == 160 && ruIndex == 3)
327 {
328 ruIndex = 1;
329 primary80 = false;
330 }
331 m_txVector.SetHeMuUserInfo(sta.first, {{ruType, ruIndex++, primary80}, 11, 1});
332 }
333 m_txVector.SetSigBMode(VhtPhy::GetVhtMcs5());
334}
335
338{
339 NS_LOG_FUNCTION(this);
340 return DlMuInfo{m_psduMap, std::move(m_txParams)};
341}
342
345{
346 NS_LOG_FUNCTION(this);
347 return UlMuInfo{m_trigger, m_triggerHdr, std::move(m_txParams)};
348}
349
355enum class WifiOfdmaScenario : uint8_t
356{
357 HE = 0, // HE AP and HE non-AP STAs
358 HE_EHT, // EHT AP, some EHT non-AP STAs and some non-EHT HE non-AP STAs
359 EHT // EHT AP and EHT non-AP STAs
360};
361
379{
380 public:
385 {
386 uint8_t muAifsn;
387 uint16_t muCwMin;
388 uint16_t muCwMax;
389 uint8_t muTimer;
390 };
391
402 OfdmaAckSequenceTest(uint16_t width,
404 uint32_t maxAmpduSize,
405 uint16_t txopLimit,
406 uint16_t nPktsPerSta,
407 MuEdcaParameterSet muEdcaParameterSet,
408 WifiOfdmaScenario scenario);
409 ~OfdmaAckSequenceTest() override;
410
417 void L7Receive(std::string context, Ptr<const Packet> p, const Address& addr);
423 void TraceCw(uint32_t staIndex, uint32_t cw, uint8_t /* linkId */);
431 void Transmit(std::string context,
432 WifiConstPsduMap psduMap,
433 WifiTxVector txVector,
434 double txPowerW);
441 void CheckResults(Time sifs, Time slotTime, uint8_t aifsn);
442
443 private:
444 void DoRun() override;
445
446 static constexpr uint16_t m_muTimerRes = 8192;
447
450 {
455 };
456
457 uint16_t m_nStations;
460 std::vector<PacketSocketAddress> m_sockets;
461 uint16_t m_channelWidth;
463 std::vector<FrameInfo> m_txPsdus;
466 uint16_t m_txopLimit;
467 uint16_t m_nPktsPerSta;
473 uint16_t m_received;
474 uint16_t m_flushed;
476 std::vector<uint32_t> m_cwValues;
477};
478
481 uint32_t maxAmpduSize,
482 uint16_t txopLimit,
483 uint16_t nPktsPerSta,
484 MuEdcaParameterSet muEdcaParameterSet,
485 WifiOfdmaScenario scenario)
486 : TestCase("Check correct operation of DL OFDMA acknowledgment sequences"),
487 m_nStations(4),
488 m_sockets(m_nStations),
489 m_channelWidth(width),
490 m_dlMuAckType(dlType),
491 m_maxAmpduSize(maxAmpduSize),
492 m_txopLimit(txopLimit),
493 m_nPktsPerSta(nPktsPerSta),
494 m_muEdcaParameterSet(muEdcaParameterSet),
495 m_scenario(scenario),
496 m_ulPktsGenerated(false),
497 m_received(0),
498 m_flushed(0),
499 m_edcaDisabledStartTime(Seconds(0)),
500 m_cwValues(std::vector<uint32_t>(m_nStations, 2)) // 2 is an invalid CW value
501{
502 switch (m_scenario)
503 {
508 break;
512 break;
513 }
514
515 switch (m_channelWidth)
516 {
517 case 20:
518 m_muRtsRuAllocation = 61; // p20 index is 0
519 break;
520 case 40:
521 m_muRtsRuAllocation = 65; // p20 index is 0
522 break;
523 case 80:
525 break;
526 case 160:
528 break;
529 default:
530 NS_ABORT_MSG("Unhandled channel width (" << m_channelWidth << " MHz)");
531 }
532}
533
535{
536}
537
538void
540{
541 if (p->GetSize() >= 1400 && Simulator::Now() > Seconds(1.5))
542 {
543 m_received++;
544 }
545}
546
547void
548OfdmaAckSequenceTest::TraceCw(uint32_t staIndex, uint32_t cw, uint8_t /* linkId */)
549{
550 if (m_cwValues.at(staIndex) == 2)
551 {
552 // store the first CW used after MU exchange (the last one may be used after
553 // the MU EDCA timer expired)
554 m_cwValues[staIndex] = cw;
555 }
556}
557
558void
560 WifiConstPsduMap psduMap,
561 WifiTxVector txVector,
562 double txPowerW)
563{
564 // skip beacon frames and frames transmitted before 1.5s (association
565 // request/response, ADDBA request, ...)
566 if (!psduMap.begin()->second->GetHeader(0).IsBeacon() && Simulator::Now() >= Seconds(1.5))
567 {
568 Time txDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, WIFI_PHY_BAND_5GHZ);
569 m_txPsdus.push_back({Simulator::Now(), Simulator::Now() + txDuration, psduMap, txVector});
570
571 for (const auto& [staId, psdu] : psduMap)
572 {
573 NS_LOG_INFO("Sending "
574 << psdu->GetHeader(0).GetTypeString() << " #MPDUs " << psdu->GetNMpdus()
575 << (psdu->GetHeader(0).IsQosData()
576 ? " TID " + std::to_string(*psdu->GetTids().begin())
577 : "")
578 << std::setprecision(10) << " txDuration " << txDuration << " duration/ID "
579 << psdu->GetHeader(0).GetDuration() << " #TX PSDUs = " << m_txPsdus.size()
580 << " size=" << (*psdu->begin())->GetSize() << "\n"
581 << "TXVECTOR: " << txVector << "\n");
582 }
583 }
584
585 // Flush the MAC queue of the AP after sending a DL MU PPDU (no need for
586 // further transmissions)
587 if (txVector.GetPreambleType() == m_dlMuPreamble)
588 {
589 m_flushed = 0;
590 for (uint32_t i = 0; i < m_staDevices.GetN(); i++)
591 {
592 auto queue =
593 m_apDevice->GetMac()->GetQosTxop(static_cast<AcIndex>(i))->GetWifiMacQueue();
594 auto staDev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
595 Ptr<const WifiMpdu> lastInFlight = nullptr;
597
598 while ((mpdu = queue->PeekByTidAndAddress(i * 2,
599 staDev->GetMac()->GetAddress(),
600 lastInFlight)) != nullptr)
601 {
602 if (mpdu->IsInFlight())
603 {
604 lastInFlight = mpdu;
605 }
606 else
607 {
608 queue->Remove(mpdu);
609 m_flushed++;
610 }
611 }
612 }
613 }
614 else if (txVector.GetPreambleType() == m_tbPreamble &&
615 psduMap.begin()->second->GetHeader(0).HasData())
616 {
617 Mac48Address sender = psduMap.begin()->second->GetAddr2();
618
619 for (uint32_t i = 0; i < m_staDevices.GetN(); i++)
620 {
621 auto dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
622
623 if (dev->GetAddress() == sender)
624 {
625 Ptr<QosTxop> qosTxop = dev->GetMac()->GetQosTxop(static_cast<AcIndex>(i));
626
628 {
629 // stations use worse access parameters, trace CW. MU AIFSN must be large
630 // enough to avoid collisions between stations trying to transmit using EDCA
631 // right after the UL MU transmission and the AP trying to send a DL MU PPDU
633 "CwTrace",
635 }
636 else
637 {
638 // there is no "protection" against collisions from stations, hence flush
639 // their MAC queues after sending an HE TB PPDU containing QoS data frames,
640 // so that the AP can send a DL MU PPDU
641 qosTxop->GetWifiMacQueue()->Flush();
642 }
643 break;
644 }
645 }
646 }
647 else if (!txVector.IsMu() && psduMap.begin()->second->GetHeader(0).IsBlockAck() &&
648 psduMap.begin()->second->GetHeader(0).GetAddr2() == m_apDevice->GetAddress() &&
650 {
651 CtrlBAckResponseHeader blockAck;
652 psduMap.begin()->second->GetPayload(0)->PeekHeader(blockAck);
653
654 if (blockAck.IsMultiSta())
655 {
656 // AP is transmitting a multi-STA BlockAck and stations have to disable EDCA,
657 // record the starting time
659 Simulator::Now() + m_txPsdus.back().endTx - m_txPsdus.back().startTx;
660 }
661 }
662 else if (!txVector.IsMu() && psduMap.begin()->second->GetHeader(0).IsTrigger() &&
664 {
665 CtrlTriggerHeader trigger;
666 psduMap.begin()->second->GetPayload(0)->PeekHeader(trigger);
667 if (trigger.IsBasic())
668 {
669 // the AP is starting the transmission of the Basic Trigger frame, so generate
670 // the configured number of packets at STAs, which are sent in HE TB PPDUs
671 Time txDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, WIFI_PHY_BAND_5GHZ);
672 for (uint16_t i = 0; i < m_nStations; i++)
673 {
674 Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
675 client->SetAttribute("PacketSize", UintegerValue(1400 + i * 100));
676 client->SetAttribute("MaxPackets", UintegerValue(m_nPktsPerSta));
677 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
678 client->SetAttribute("Priority", UintegerValue(i * 2)); // 0, 2, 4 and 6
679 client->SetRemote(m_sockets[i]);
680 m_staDevices.Get(i)->GetNode()->AddApplication(client);
681 client->SetStartTime(txDuration); // start when TX ends
682 client->SetStopTime(Seconds(1.0)); // stop in a second
683 client->Initialize();
684 }
685 m_ulPktsGenerated = true;
686 }
687 }
688}
689
690void
691OfdmaAckSequenceTest::CheckResults(Time sifs, Time slotTime, uint8_t aifsn)
692{
693 CtrlTriggerHeader trigger;
694 CtrlBAckResponseHeader blockAck;
695 Time tEnd; // TX end for a frame
696 Time tStart; // TX start for the next frame
697 Time tolerance = NanoSeconds(500); // due to propagation delay
698 Time ifs = (m_txopLimit > 0 ? sifs : sifs + aifsn * slotTime);
699 Time navEnd;
700
701 /*
702 * |-------------NAV----------->| |-----------------NAV------------------->|
703 * |---------NAV------>| |--------------NAV------------->|
704 * |---NAV-->| |--------NAV-------->|
705 * ┌───┐ ┌───┐ ┌────┐ ┌────┐ ┌───┐ ┌───┐ ┌─────┐ ┌────┐ ┌─────┐
706 * │ │ │ │ │ │ │QoS │ │ │ │ │ │ │ │QoS │ │ │
707 * │ │ │ │ │ │ │Null│ │ │ │ │ │ │ │Data│ │ │
708 * │ │ │ │ │ │ ├────┤ │ │ │ │ │ │ ├────┤ │ │
709 * │ │ │ │ │ │ │QoS │ │ │ │ │ │ │ │QoS │ │Multi│
710 * │MU-│ │CTS│ │BSRP│ │Null│ │MU-│ │CTS│ │Basic│ │Data│ │-STA │
711 * │RTS│SIFS│ │SIFS│ TF │SIFS├────┤<IFS>│RTS│SIFS│ │SIFS│ TF │SIFS├────┤SIFS│Block│
712 * │TF │ │x4 │ │ │ │QoS │ │TF │ │x4 │ │ │ │QoS │ │ Ack │
713 * │ │ │ │ │ │ │Null│ │ │ │ │ │ │ │Data│ │ │
714 * │ │ │ │ │ │ ├────┤ │ │ │ │ │ │ ├────┤ │ │
715 * │ │ │ │ │ │ │QoS │ │ │ │ │ │ │ │QoS │ │ │
716 * │ │ │ │ │ │ │Null│ │ │ │ │ │ │ │Data│ │ │
717 * ───┴───┴────┴───┴────┴────┴────┴────┴─────┴───┴────┴───┴────┴─────┴────┴────┴────┴─────┴──
718 * From: AP all AP all AP all AP all AP
719 * To: all AP all AP all AP all AP all
720 */
721
722 // the first packet sent after 1.5s is an MU-RTS Trigger Frame
723 NS_TEST_ASSERT_MSG_GT_OR_EQ(m_txPsdus.size(), 5, "Expected at least 5 transmitted packet");
724 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[0].psduMap.size() == 1 &&
725 m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger() &&
726 m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
727 true,
728 "Expected a Trigger Frame");
729 m_txPsdus[0].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(trigger);
730 NS_TEST_EXPECT_MSG_EQ(trigger.IsMuRts(), true, "Expected an MU-RTS Trigger Frame");
732 4,
733 "Expected one User Info field per station");
734 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[0].txVector.GetChannelWidth(),
736 "Expected the MU-RTS to occupy the entire channel width");
737 for (const auto& userInfo : trigger)
738 {
739 NS_TEST_EXPECT_MSG_EQ(+userInfo.GetMuRtsRuAllocation(),
741 "Unexpected RU Allocation value in MU-RTS");
742 }
743 tEnd = m_txPsdus[0].endTx;
744 navEnd = tEnd + m_txPsdus[0].psduMap[SU_STA_ID]->GetDuration();
745
746 // A first STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
748 (m_txPsdus[1].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
749 m_txPsdus[1].psduMap.size() == 1 &&
750 m_txPsdus[1].psduMap.begin()->second->GetNMpdus() == 1 &&
751 m_txPsdus[1].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
752 true,
753 "Expected a CTS frame");
754 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[1].txVector.GetChannelWidth(),
756 "Expected the CTS to occupy the entire channel width");
757
758 tStart = m_txPsdus[1].startTx;
759 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
760 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
761 Time ctsNavEnd = m_txPsdus[1].endTx + m_txPsdus[1].psduMap[SU_STA_ID]->GetDuration();
762 // navEnd <= ctsNavEnd < navEnd + tolerance
763 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
764 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
765
766 // A second STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
768 (m_txPsdus[2].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
769 m_txPsdus[2].psduMap.size() == 1 &&
770 m_txPsdus[2].psduMap.begin()->second->GetNMpdus() == 1 &&
771 m_txPsdus[2].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
772 true,
773 "Expected a CTS frame");
774 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[2].txVector.GetChannelWidth(),
776 "Expected the CTS to occupy the entire channel width");
777
778 tStart = m_txPsdus[2].startTx;
779 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
780 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
781 ctsNavEnd = m_txPsdus[2].endTx + m_txPsdus[2].psduMap[SU_STA_ID]->GetDuration();
782 // navEnd <= ctsNavEnd < navEnd + tolerance
783 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
784 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
785
786 // A third STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
788 (m_txPsdus[3].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
789 m_txPsdus[3].psduMap.size() == 1 &&
790 m_txPsdus[3].psduMap.begin()->second->GetNMpdus() == 1 &&
791 m_txPsdus[3].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
792 true,
793 "Expected a CTS frame");
794 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[3].txVector.GetChannelWidth(),
796 "Expected the CTS to occupy the entire channel width");
797
798 tStart = m_txPsdus[3].startTx;
799 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
800 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
801 ctsNavEnd = m_txPsdus[3].endTx + m_txPsdus[3].psduMap[SU_STA_ID]->GetDuration();
802 // navEnd <= ctsNavEnd < navEnd + tolerance
803 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
804 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
805
806 // A fourth STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
808 (m_txPsdus[4].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
809 m_txPsdus[4].psduMap.size() == 1 &&
810 m_txPsdus[4].psduMap.begin()->second->GetNMpdus() == 1 &&
811 m_txPsdus[4].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
812 true,
813 "Expected a CTS frame");
814 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].txVector.GetChannelWidth(),
816 "Expected the CTS to occupy the entire channel width");
817
818 tStart = m_txPsdus[4].startTx;
819 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
820 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
821 ctsNavEnd = m_txPsdus[4].endTx + m_txPsdus[4].psduMap[SU_STA_ID]->GetDuration();
822 // navEnd <= ctsNavEnd < navEnd + tolerance
823 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
824 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
825
826 // the AP sends a BSRP Trigger Frame
827 NS_TEST_ASSERT_MSG_GT_OR_EQ(m_txPsdus.size(), 10, "Expected at least 10 transmitted packet");
828 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[5].psduMap.size() == 1 &&
829 m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger() &&
830 m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
831 true,
832 "Expected a Trigger Frame");
833 m_txPsdus[5].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(trigger);
834 NS_TEST_EXPECT_MSG_EQ(trigger.IsBsrp(), true, "Expected a BSRP Trigger Frame");
836 4,
837 "Expected one User Info field per station");
838 tEnd = m_txPsdus[4].endTx;
839 tStart = m_txPsdus[5].startTx;
840 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "BSRP Trigger Frame sent too early");
841 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "BSRP Trigger Frame sent too late");
842 Time bsrpNavEnd = m_txPsdus[5].endTx + m_txPsdus[5].psduMap[SU_STA_ID]->GetDuration();
843 // navEnd <= bsrpNavEnd < navEnd + tolerance
844 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, bsrpNavEnd, "Duration/ID in BSRP TF is too short");
845 NS_TEST_EXPECT_MSG_LT(bsrpNavEnd, navEnd + tolerance, "Duration/ID in BSRP TF is too long");
846
847 // A first STA sends a QoS Null frame in a TB PPDU a SIFS after the reception of the BSRP TF
848 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[6].txVector.GetPreambleType() == m_tbPreamble &&
849 m_txPsdus[6].psduMap.size() == 1 &&
850 m_txPsdus[6].psduMap.begin()->second->GetNMpdus() == 1),
851 true,
852 "Expected a QoS Null frame in a TB PPDU");
853 {
854 const WifiMacHeader& hdr = m_txPsdus[6].psduMap.begin()->second->GetHeader(0);
855 NS_TEST_EXPECT_MSG_EQ(hdr.GetType(), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
856 uint16_t staId;
857 for (staId = 0; staId < m_nStations; staId++)
858 {
859 if (DynamicCast<WifiNetDevice>(m_staDevices.Get(staId))->GetAddress() == hdr.GetAddr2())
860 {
861 break;
862 }
863 }
864 NS_TEST_EXPECT_MSG_NE(+staId, m_nStations, "Sender not found among stations");
865 uint8_t tid = staId * 2;
866 NS_TEST_EXPECT_MSG_EQ(+hdr.GetQosTid(), +tid, "Expected a TID equal to " << +tid);
867 }
868 tEnd = m_txPsdus[5].endTx;
869 tStart = m_txPsdus[6].startTx;
870 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS Null frame in HE TB PPDU sent too early");
872 tEnd + sifs + tolerance,
873 "QoS Null frame in HE TB PPDU sent too late");
874 Time qosNullNavEnd = m_txPsdus[6].endTx + m_txPsdus[6].psduMap.begin()->second->GetDuration();
875 if (m_txopLimit == 0)
876 {
877 NS_TEST_EXPECT_MSG_EQ(qosNullNavEnd,
878 m_txPsdus[6].endTx,
879 "Expected null Duration/ID for QoS Null frame in HE TB PPDU");
880 }
881 // navEnd <= qosNullNavEnd < navEnd + tolerance
882 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, qosNullNavEnd, "Duration/ID in QoS Null is too short");
883 NS_TEST_EXPECT_MSG_LT(qosNullNavEnd, navEnd + tolerance, "Duration/ID in QoS Null is too long");
884
885 // A second STA sends a QoS Null frame in a TB PPDU a SIFS after the reception of the BSRP TF
886 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[7].txVector.GetPreambleType() == m_tbPreamble &&
887 m_txPsdus[7].psduMap.size() == 1 &&
888 m_txPsdus[7].psduMap.begin()->second->GetNMpdus() == 1),
889 true,
890 "Expected a QoS Null frame in a TB PPDU");
891 {
892 const WifiMacHeader& hdr = m_txPsdus[7].psduMap.begin()->second->GetHeader(0);
893 NS_TEST_EXPECT_MSG_EQ(hdr.GetType(), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
894 uint16_t staId;
895 for (staId = 0; staId < m_nStations; staId++)
896 {
897 if (DynamicCast<WifiNetDevice>(m_staDevices.Get(staId))->GetAddress() == hdr.GetAddr2())
898 {
899 break;
900 }
901 }
902 NS_TEST_EXPECT_MSG_NE(+staId, m_nStations, "Sender not found among stations");
903 uint8_t tid = staId * 2;
904 NS_TEST_EXPECT_MSG_EQ(+hdr.GetQosTid(), +tid, "Expected a TID equal to " << +tid);
905 }
906 tStart = m_txPsdus[7].startTx;
907 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS Null frame in HE TB PPDU sent too early");
909 tEnd + sifs + tolerance,
910 "QoS Null frame in HE TB PPDU sent too late");
911 qosNullNavEnd = m_txPsdus[7].endTx + m_txPsdus[7].psduMap.begin()->second->GetDuration();
912 if (m_txopLimit == 0)
913 {
914 NS_TEST_EXPECT_MSG_EQ(qosNullNavEnd,
915 m_txPsdus[7].endTx,
916 "Expected null Duration/ID for QoS Null frame in HE TB PPDU");
917 }
918 // navEnd <= qosNullNavEnd < navEnd + tolerance
919 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, qosNullNavEnd, "Duration/ID in QoS Null is too short");
920 NS_TEST_EXPECT_MSG_LT(qosNullNavEnd, navEnd + tolerance, "Duration/ID in QoS Null is too long");
921
922 // A third STA sends a QoS Null frame in a TB PPDU a SIFS after the reception of the BSRP TF
923 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[8].txVector.GetPreambleType() == m_tbPreamble &&
924 m_txPsdus[8].psduMap.size() == 1 &&
925 m_txPsdus[8].psduMap.begin()->second->GetNMpdus() == 1),
926 true,
927 "Expected a QoS Null frame in an HE TB PPDU");
928 {
929 const WifiMacHeader& hdr = m_txPsdus[8].psduMap.begin()->second->GetHeader(0);
930 NS_TEST_EXPECT_MSG_EQ(hdr.GetType(), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
931 uint16_t staId;
932 for (staId = 0; staId < m_nStations; staId++)
933 {
934 if (DynamicCast<WifiNetDevice>(m_staDevices.Get(staId))->GetAddress() == hdr.GetAddr2())
935 {
936 break;
937 }
938 }
939 NS_TEST_EXPECT_MSG_NE(+staId, m_nStations, "Sender not found among stations");
940 uint8_t tid = staId * 2;
941 NS_TEST_EXPECT_MSG_EQ(+hdr.GetQosTid(), +tid, "Expected a TID equal to " << +tid);
942 }
943 tStart = m_txPsdus[8].startTx;
944 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS Null frame in HE TB PPDU sent too early");
946 tEnd + sifs + tolerance,
947 "QoS Null frame in HE TB PPDU sent too late");
948 qosNullNavEnd = m_txPsdus[8].endTx + m_txPsdus[8].psduMap.begin()->second->GetDuration();
949 if (m_txopLimit == 0)
950 {
951 NS_TEST_EXPECT_MSG_EQ(qosNullNavEnd,
952 m_txPsdus[8].endTx,
953 "Expected null Duration/ID for QoS Null frame in HE TB PPDU");
954 }
955 // navEnd <= qosNullNavEnd < navEnd + tolerance
956 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, qosNullNavEnd, "Duration/ID in QoS Null is too short");
957 NS_TEST_EXPECT_MSG_LT(qosNullNavEnd, navEnd + tolerance, "Duration/ID in QoS Null is too long");
958
959 // A fourth STA sends a QoS Null frame in a TB PPDU a SIFS after the reception of the BSRP TF
960 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[9].txVector.GetPreambleType() == m_tbPreamble &&
961 m_txPsdus[9].psduMap.size() == 1 &&
962 m_txPsdus[9].psduMap.begin()->second->GetNMpdus() == 1),
963 true,
964 "Expected a QoS Null frame in an HE TB PPDU");
965 {
966 const WifiMacHeader& hdr = m_txPsdus[9].psduMap.begin()->second->GetHeader(0);
967 NS_TEST_EXPECT_MSG_EQ(hdr.GetType(), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
968 uint16_t staId;
969 for (staId = 0; staId < m_nStations; staId++)
970 {
971 if (DynamicCast<WifiNetDevice>(m_staDevices.Get(staId))->GetAddress() == hdr.GetAddr2())
972 {
973 break;
974 }
975 }
976 NS_TEST_EXPECT_MSG_NE(+staId, m_nStations, "Sender not found among stations");
977 uint8_t tid = staId * 2;
978 NS_TEST_EXPECT_MSG_EQ(+hdr.GetQosTid(), +tid, "Expected a TID equal to " << +tid);
979 }
980 tStart = m_txPsdus[9].startTx;
981 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS Null frame in HE TB PPDU sent too early");
983 tEnd + sifs + tolerance,
984 "QoS Null frame in HE TB PPDU sent too late");
985 qosNullNavEnd = m_txPsdus[9].endTx + m_txPsdus[9].psduMap.begin()->second->GetDuration();
986 if (m_txopLimit == 0)
987 {
988 NS_TEST_EXPECT_MSG_EQ(qosNullNavEnd,
989 m_txPsdus[9].endTx,
990 "Expected null Duration/ID for QoS Null frame in HE TB PPDU");
991 }
992 // navEnd <= qosNullNavEnd < navEnd + tolerance
993 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, qosNullNavEnd, "Duration/ID in QoS Null is too short");
994 NS_TEST_EXPECT_MSG_LT(qosNullNavEnd, navEnd + tolerance, "Duration/ID in QoS Null is too long");
995
996 // the AP sends another MU-RTS Trigger Frame to protect the Basic TF
997 NS_TEST_ASSERT_MSG_GT_OR_EQ(m_txPsdus.size(), 15, "Expected at least 15 transmitted packet");
998 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[10].psduMap.size() == 1 &&
999 m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger() &&
1000 m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
1001 true,
1002 "Expected a Trigger Frame");
1003 m_txPsdus[10].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(trigger);
1004 NS_TEST_EXPECT_MSG_EQ(trigger.IsMuRts(), true, "Expected an MU-RTS Trigger Frame");
1006 4,
1007 "Expected one User Info field per station");
1008 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].txVector.GetChannelWidth(),
1010 "Expected the MU-RTS to occupy the entire channel width");
1011 for (const auto& userInfo : trigger)
1012 {
1013 NS_TEST_EXPECT_MSG_EQ(+userInfo.GetMuRtsRuAllocation(),
1015 "Unexpected RU Allocation value in MU-RTS");
1016 }
1017 tEnd = m_txPsdus[9].endTx;
1018 tStart = m_txPsdus[10].startTx;
1019 NS_TEST_EXPECT_MSG_LT(tEnd + ifs, tStart, "Basic Trigger Frame sent too early");
1020 if (m_txopLimit > 0)
1021 {
1022 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Basic Trigger Frame sent too late");
1023 // Duration/ID still protects until the end of the TXOP
1024 auto muRtsNavEnd = m_txPsdus[10].endTx + m_txPsdus[10].psduMap[SU_STA_ID]->GetDuration();
1025 // navEnd <= muRtsNavEnd < navEnd + tolerance
1026 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, muRtsNavEnd, "Duration/ID in MU-RTS is too short");
1027 NS_TEST_EXPECT_MSG_LT(muRtsNavEnd, navEnd + tolerance, "Duration/ID in MU-RTS is too long");
1028 }
1029
1030 // NAV end is now set by the Duration/ID of the second MU-RTS TF
1031 tEnd = m_txPsdus[10].endTx;
1032 navEnd = tEnd + m_txPsdus[10].psduMap[SU_STA_ID]->GetDuration();
1033
1034 // A first STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
1036 (m_txPsdus[11].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
1037 m_txPsdus[11].psduMap.size() == 1 &&
1038 m_txPsdus[11].psduMap.begin()->second->GetNMpdus() == 1 &&
1039 m_txPsdus[11].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
1040 true,
1041 "Expected a CTS frame");
1042 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].txVector.GetChannelWidth(),
1044 "Expected the CTS to occupy the entire channel width");
1045
1046 tStart = m_txPsdus[11].startTx;
1047 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
1048 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
1049 ctsNavEnd = m_txPsdus[11].endTx + m_txPsdus[11].psduMap[SU_STA_ID]->GetDuration();
1050 // navEnd <= ctsNavEnd < navEnd + tolerance
1051 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
1052 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
1053
1054 // A second STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
1056 (m_txPsdus[12].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
1057 m_txPsdus[12].psduMap.size() == 1 &&
1058 m_txPsdus[12].psduMap.begin()->second->GetNMpdus() == 1 &&
1059 m_txPsdus[12].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
1060 true,
1061 "Expected a CTS frame");
1062 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[12].txVector.GetChannelWidth(),
1064 "Expected the CTS to occupy the entire channel width");
1065
1066 tStart = m_txPsdus[12].startTx;
1067 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
1068 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
1069 ctsNavEnd = m_txPsdus[12].endTx + m_txPsdus[12].psduMap[SU_STA_ID]->GetDuration();
1070 // navEnd <= ctsNavEnd < navEnd + tolerance
1071 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
1072 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
1073
1074 // A third STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
1076 (m_txPsdus[13].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
1077 m_txPsdus[13].psduMap.size() == 1 &&
1078 m_txPsdus[13].psduMap.begin()->second->GetNMpdus() == 1 &&
1079 m_txPsdus[13].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
1080 true,
1081 "Expected a CTS frame");
1082 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].txVector.GetChannelWidth(),
1084 "Expected the CTS to occupy the entire channel width");
1085
1086 tStart = m_txPsdus[13].startTx;
1087 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
1088 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
1089 ctsNavEnd = m_txPsdus[13].endTx + m_txPsdus[13].psduMap[SU_STA_ID]->GetDuration();
1090 // navEnd <= ctsNavEnd < navEnd + tolerance
1091 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
1092 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
1093
1094 // A fourth STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
1096 (m_txPsdus[14].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
1097 m_txPsdus[14].psduMap.size() == 1 &&
1098 m_txPsdus[14].psduMap.begin()->second->GetNMpdus() == 1 &&
1099 m_txPsdus[14].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
1100 true,
1101 "Expected a CTS frame");
1102 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[14].txVector.GetChannelWidth(),
1104 "Expected the CTS to occupy the entire channel width");
1105
1106 tStart = m_txPsdus[14].startTx;
1107 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
1108 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
1109 ctsNavEnd = m_txPsdus[14].endTx + m_txPsdus[14].psduMap[SU_STA_ID]->GetDuration();
1110 // navEnd <= ctsNavEnd < navEnd + tolerance
1111 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
1112 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
1113
1114 // the AP sends a Basic Trigger Frame to solicit QoS data frames
1115 NS_TEST_ASSERT_MSG_GT_OR_EQ(m_txPsdus.size(), 21, "Expected at least 21 transmitted packets");
1116 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[15].psduMap.size() == 1 &&
1117 m_txPsdus[15].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger() &&
1118 m_txPsdus[15].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
1119 true,
1120 "Expected a Trigger Frame");
1121 m_txPsdus[15].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(trigger);
1122 NS_TEST_EXPECT_MSG_EQ(trigger.IsBasic(), true, "Expected a Basic Trigger Frame");
1124 4,
1125 "Expected one User Info field per station");
1126 tEnd = m_txPsdus[14].endTx;
1127 tStart = m_txPsdus[15].startTx;
1128 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Basic Trigger Frame sent too early");
1129 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Basic Trigger Frame sent too late");
1130 Time basicNavEnd = m_txPsdus[15].endTx + m_txPsdus[15].psduMap[SU_STA_ID]->GetDuration();
1131 // navEnd <= basicNavEnd < navEnd + tolerance
1132 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, basicNavEnd, "Duration/ID in Basic TF is too short");
1133 NS_TEST_EXPECT_MSG_LT(basicNavEnd, navEnd + tolerance, "Duration/ID in Basic TF is too long");
1134
1135 // A first STA sends QoS data frames in a TB PPDU a SIFS after the reception of the Basic TF
1136 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[16].txVector.GetPreambleType() == m_tbPreamble &&
1137 m_txPsdus[16].psduMap.size() == 1 &&
1138 m_txPsdus[16].psduMap.begin()->second->GetNMpdus() == 2 &&
1139 m_txPsdus[16].psduMap.begin()->second->GetHeader(0).IsQosData() &&
1140 m_txPsdus[16].psduMap.begin()->second->GetHeader(1).IsQosData()),
1141 true,
1142 "Expected 2 QoS data frames in an HE TB PPDU");
1143 tEnd = m_txPsdus[15].endTx;
1144 tStart = m_txPsdus[16].startTx;
1145 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
1146 NS_TEST_EXPECT_MSG_LT(tStart,
1147 tEnd + sifs + tolerance,
1148 "QoS data frames in HE TB PPDU sent too late");
1149 Time qosDataNavEnd = m_txPsdus[16].endTx + m_txPsdus[16].psduMap.begin()->second->GetDuration();
1150 // navEnd <= qosDataNavEnd < navEnd + tolerance
1151 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, qosDataNavEnd, "Duration/ID in QoS Data is too short");
1152 NS_TEST_EXPECT_MSG_LT(qosDataNavEnd, navEnd + tolerance, "Duration/ID in QoS Data is too long");
1153
1154 // A second STA sends QoS data frames in a TB PPDU a SIFS after the reception of the Basic TF
1155 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[17].txVector.GetPreambleType() == m_tbPreamble &&
1156 m_txPsdus[17].psduMap.size() == 1 &&
1157 m_txPsdus[17].psduMap.begin()->second->GetNMpdus() == 2 &&
1158 m_txPsdus[17].psduMap.begin()->second->GetHeader(0).IsQosData() &&
1159 m_txPsdus[17].psduMap.begin()->second->GetHeader(1).IsQosData()),
1160 true,
1161 "Expected 2 QoS data frames in an HE TB PPDU");
1162 tStart = m_txPsdus[17].startTx;
1163 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
1164 NS_TEST_EXPECT_MSG_LT(tStart,
1165 tEnd + sifs + tolerance,
1166 "QoS data frames in HE TB PPDU sent too late");
1167 qosDataNavEnd = m_txPsdus[17].endTx + m_txPsdus[17].psduMap.begin()->second->GetDuration();
1168 // navEnd <= qosDataNavEnd < navEnd + tolerance
1169 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, qosDataNavEnd, "Duration/ID in QoS Data is too short");
1170 NS_TEST_EXPECT_MSG_LT(qosDataNavEnd, navEnd + tolerance, "Duration/ID in QoS Data is too long");
1171
1172 // A third STA sends QoS data frames in a TB PPDU a SIFS after the reception of the Basic TF
1173 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[18].txVector.GetPreambleType() == m_tbPreamble &&
1174 m_txPsdus[18].psduMap.size() == 1 &&
1175 m_txPsdus[18].psduMap.begin()->second->GetNMpdus() == 2 &&
1176 m_txPsdus[18].psduMap.begin()->second->GetHeader(0).IsQosData() &&
1177 m_txPsdus[18].psduMap.begin()->second->GetHeader(1).IsQosData()),
1178 true,
1179 "Expected 2 QoS data frames in an HE TB PPDU");
1180 tStart = m_txPsdus[18].startTx;
1181 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
1182 NS_TEST_EXPECT_MSG_LT(tStart,
1183 tEnd + sifs + tolerance,
1184 "QoS data frames in HE TB PPDU sent too late");
1185 qosDataNavEnd = m_txPsdus[18].endTx + m_txPsdus[18].psduMap.begin()->second->GetDuration();
1186 // navEnd <= qosDataNavEnd < navEnd + tolerance
1187 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, qosDataNavEnd, "Duration/ID in QoS Data is too short");
1188 NS_TEST_EXPECT_MSG_LT(qosDataNavEnd, navEnd + tolerance, "Duration/ID in QoS Data is too long");
1189
1190 // A fourth STA sends QoS data frames in a TB PPDU a SIFS after the reception of the Basic TF
1191 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[19].txVector.GetPreambleType() == m_tbPreamble &&
1192 m_txPsdus[19].psduMap.size() == 1 &&
1193 m_txPsdus[19].psduMap.begin()->second->GetNMpdus() == 2 &&
1194 m_txPsdus[19].psduMap.begin()->second->GetHeader(0).IsQosData() &&
1195 m_txPsdus[19].psduMap.begin()->second->GetHeader(1).IsQosData()),
1196 true,
1197 "Expected 2 QoS data frames in an HE TB PPDU");
1198 tStart = m_txPsdus[19].startTx;
1199 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
1200 NS_TEST_EXPECT_MSG_LT(tStart,
1201 tEnd + sifs + tolerance,
1202 "QoS data frames in HE TB PPDU sent too late");
1203 qosDataNavEnd = m_txPsdus[19].endTx + m_txPsdus[19].psduMap.begin()->second->GetDuration();
1204 // navEnd <= qosDataNavEnd < navEnd + tolerance
1205 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, qosDataNavEnd, "Duration/ID in QoS Data is too short");
1206 NS_TEST_EXPECT_MSG_LT(qosDataNavEnd, navEnd + tolerance, "Duration/ID in QoS Data is too long");
1207
1208 // the AP sends a Multi-STA Block Ack
1209 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[20].psduMap.size() == 1 &&
1210 m_txPsdus[20].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck() &&
1211 m_txPsdus[20].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
1212 true,
1213 "Expected a Block Ack");
1214 m_txPsdus[20].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(blockAck);
1215 NS_TEST_EXPECT_MSG_EQ(blockAck.IsMultiSta(), true, "Expected a Multi-STA Block Ack");
1217 4,
1218 "Expected one Per AID TID Info subfield per station");
1219 for (uint8_t i = 0; i < 4; i++)
1220 {
1221 NS_TEST_EXPECT_MSG_EQ(blockAck.GetAckType(i), true, "Expected All-ack context");
1222 NS_TEST_EXPECT_MSG_EQ(+blockAck.GetTidInfo(i), 14, "Expected All-ack context");
1223 }
1224 tEnd = m_txPsdus[19].endTx;
1225 tStart = m_txPsdus[20].startTx;
1226 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Multi-STA Block Ack sent too early");
1227 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Multi-STA Block Ack sent too late");
1228 auto multiStaBaNavEnd = m_txPsdus[20].endTx + m_txPsdus[20].psduMap[SU_STA_ID]->GetDuration();
1229 // navEnd <= multiStaBaNavEnd < navEnd + tolerance
1231 multiStaBaNavEnd,
1232 "Duration/ID in Multi-STA BlockAck is too short");
1233 NS_TEST_EXPECT_MSG_LT(multiStaBaNavEnd,
1234 navEnd + tolerance,
1235 "Duration/ID in Multi-STA BlockAck is too long");
1236
1237 // the AP sends an MU-RTS Trigger Frame to protect the DL MU PPDU
1238 NS_TEST_ASSERT_MSG_GT_OR_EQ(m_txPsdus.size(), 26, "Expected at least 26 transmitted packet");
1239 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[21].psduMap.size() == 1 &&
1240 m_txPsdus[21].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger() &&
1241 m_txPsdus[21].psduMap[SU_STA_ID]->GetHeader(0).GetAddr1().IsBroadcast()),
1242 true,
1243 "Expected a Trigger Frame");
1244 m_txPsdus[21].psduMap[SU_STA_ID]->GetPayload(0)->PeekHeader(trigger);
1245 NS_TEST_EXPECT_MSG_EQ(trigger.IsMuRts(), true, "Expected an MU-RTS Trigger Frame");
1247 4,
1248 "Expected one User Info field per station");
1249 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[21].txVector.GetChannelWidth(),
1251 "Expected the MU-RTS to occupy the entire channel width");
1252 for (const auto& userInfo : trigger)
1253 {
1254 NS_TEST_EXPECT_MSG_EQ(+userInfo.GetMuRtsRuAllocation(),
1256 "Unexpected RU Allocation value in MU-RTS");
1257 }
1258 tEnd = m_txPsdus[20].endTx;
1259 tStart = m_txPsdus[21].startTx;
1260 NS_TEST_EXPECT_MSG_LT_OR_EQ(tEnd + ifs, tStart, "MU-RTS Trigger Frame sent too early");
1261 tEnd = m_txPsdus[21].endTx;
1262 navEnd = tEnd + m_txPsdus[21].psduMap[SU_STA_ID]->GetDuration();
1263
1264 // A first STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
1266 (m_txPsdus[22].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
1267 m_txPsdus[22].psduMap.size() == 1 &&
1268 m_txPsdus[22].psduMap.begin()->second->GetNMpdus() == 1 &&
1269 m_txPsdus[22].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
1270 true,
1271 "Expected a CTS frame");
1272 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[22].txVector.GetChannelWidth(),
1274 "Expected the CTS to occupy the entire channel width");
1275
1276 tStart = m_txPsdus[22].startTx;
1277 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
1278 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
1279 ctsNavEnd = m_txPsdus[22].endTx + m_txPsdus[22].psduMap[SU_STA_ID]->GetDuration();
1280 // navEnd <= ctsNavEnd < navEnd + tolerance
1281 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
1282 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
1283
1284 // A second STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
1286 (m_txPsdus[23].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
1287 m_txPsdus[23].psduMap.size() == 1 &&
1288 m_txPsdus[23].psduMap.begin()->second->GetNMpdus() == 1 &&
1289 m_txPsdus[23].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
1290 true,
1291 "Expected a CTS frame");
1292 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[23].txVector.GetChannelWidth(),
1294 "Expected the CTS to occupy the entire channel width");
1295
1296 tStart = m_txPsdus[23].startTx;
1297 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
1298 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
1299 ctsNavEnd = m_txPsdus[23].endTx + m_txPsdus[23].psduMap[SU_STA_ID]->GetDuration();
1300 // navEnd <= ctsNavEnd < navEnd + tolerance
1301 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
1302 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
1303
1304 // A third STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
1306 (m_txPsdus[24].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
1307 m_txPsdus[24].psduMap.size() == 1 &&
1308 m_txPsdus[24].psduMap.begin()->second->GetNMpdus() == 1 &&
1309 m_txPsdus[24].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
1310 true,
1311 "Expected a CTS frame");
1312 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[24].txVector.GetChannelWidth(),
1314 "Expected the CTS to occupy the entire channel width");
1315
1316 tStart = m_txPsdus[24].startTx;
1317 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
1318 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
1319 ctsNavEnd = m_txPsdus[24].endTx + m_txPsdus[24].psduMap[SU_STA_ID]->GetDuration();
1320 // navEnd <= ctsNavEnd < navEnd + tolerance
1321 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
1322 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
1323
1324 // A fourth STA sends a CTS frame a SIFS after the reception of the MU-RTS TF
1326 (m_txPsdus[25].txVector.GetPreambleType() != WIFI_PREAMBLE_HE_TB &&
1327 m_txPsdus[25].psduMap.size() == 1 &&
1328 m_txPsdus[25].psduMap.begin()->second->GetNMpdus() == 1 &&
1329 m_txPsdus[25].psduMap.begin()->second->GetHeader(0).GetType() == WIFI_MAC_CTL_CTS),
1330 true,
1331 "Expected a CTS frame");
1332 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[25].txVector.GetChannelWidth(),
1334 "Expected the CTS to occupy the entire channel width");
1335
1336 tStart = m_txPsdus[25].startTx;
1337 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CTS frame sent too early");
1338 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CTS frame sent too late");
1339 ctsNavEnd = m_txPsdus[25].endTx + m_txPsdus[25].psduMap[SU_STA_ID]->GetDuration();
1340 // navEnd <= ctsNavEnd < navEnd + tolerance
1341 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, ctsNavEnd, "Duration/ID in CTS frame is too short");
1342 NS_TEST_EXPECT_MSG_LT(ctsNavEnd, navEnd + tolerance, "Duration/ID in CTS frame is too long");
1343
1344 // the AP sends a DL MU PPDU
1345 NS_TEST_ASSERT_MSG_GT_OR_EQ(m_txPsdus.size(), 27, "Expected at least 27 transmitted packet");
1346 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[26].txVector.GetPreambleType(),
1348 "Expected a DL MU PPDU");
1349 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[26].psduMap.size(),
1350 4,
1351 "Expected 4 PSDUs within the DL MU PPDU");
1352 // the TX duration cannot exceed the maximum PPDU duration
1353 NS_TEST_EXPECT_MSG_LT_OR_EQ(m_txPsdus[26].endTx - m_txPsdus[26].startTx,
1354 GetPpduMaxTime(m_txPsdus[26].txVector.GetPreambleType()),
1355 "TX duration cannot exceed max PPDU duration");
1356 for (auto& psdu : m_txPsdus[26].psduMap)
1357 {
1358 NS_TEST_EXPECT_MSG_LT_OR_EQ(psdu.second->GetSize(),
1360 "Max A-MPDU size exceeded");
1361 }
1362 tEnd = m_txPsdus[25].endTx;
1363 tStart = m_txPsdus[26].startTx;
1364 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "DL MU PPDU sent too early");
1365 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "DL MU PPDU sent too late");
1366
1367 // The Duration/ID field is the same for all the PSDUs
1368 auto dlMuNavEnd = m_txPsdus[26].endTx;
1369 for (auto& psdu : m_txPsdus[26].psduMap)
1370 {
1371 if (dlMuNavEnd == m_txPsdus[26].endTx)
1372 {
1373 dlMuNavEnd += psdu.second->GetDuration();
1374 }
1375 else
1376 {
1377 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[26].endTx + psdu.second->GetDuration(),
1378 dlMuNavEnd,
1379 "Duration/ID must be the same for all PSDUs");
1380 }
1381 }
1382 // navEnd <= dlMuNavEnd < navEnd + tolerance
1383 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, dlMuNavEnd, "Duration/ID in DL MU PPDU is too short");
1384 NS_TEST_EXPECT_MSG_LT(dlMuNavEnd, navEnd + tolerance, "Duration/ID in DL MU PPDU is too long");
1385
1386 std::size_t nTxPsdus = 0;
1387
1388 if (m_dlMuAckType == WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE)
1389 {
1390 /*
1391 * |-----------------------------------------NAV-------------------------------->|
1392 * |----------------------------------NAV------------------------------>|
1393 * |-----------------------------NAV------------------------->|
1394 * |-------------------------NAV--------------------->|
1395 * |--NAV->| |--NAV->| |--NAV->|
1396 * ┌───┐ ┌───┐ ┌────┐ ┌──┐ ┌───┐ ┌──┐ ┌───┐ ┌──┐ ┌───┐ ┌──┐
1397 * │ │ │ │ │PSDU│ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1398 * │ │ │ │ │ 1 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1399 * │ │ │ │ ├────┤ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1400 * │ │ │ │ │PSDU│ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1401 * │MU-│ │CTS│ │ 2 │ │BA│ │BAR│ │BA│ │BAR│ │BA│ │BAR│ │BA│
1402 * │RTS│SIFS│ │SIFS├────┤SIFS│ │SIFS│ │SIFS│ │SIFS│ │SIFS│ │SIFS│ │SIFS│ │
1403 * │TF │ │x4 │ │PSDU│ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1404 * │ │ │ │ │ 3 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1405 * │ │ │ │ ├────┤ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1406 * │ │ │ │ │PSDU│ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1407 * │ │ │ │ │ 4 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │
1408 * ───┴───┴────┴───┴────┴────┴────┴──┴────┴───┴────┴──┴────┴───┴────┴──┴────┴───┴────┴──┴──
1409 * From: AP all AP STA 1 AP STA 2 AP STA 3 AP STA 4
1410 * To: all AP all AP STA 2 AP STA 3 AP STA 4 AP
1411 */
1412 NS_TEST_EXPECT_MSG_GT_OR_EQ(m_txPsdus.size(), 34, "Expected at least 34 packets");
1413
1414 // A first STA sends a Block Ack a SIFS after the reception of the DL MU PPDU
1415 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[27].psduMap.size() == 1 &&
1416 m_txPsdus[27].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck()),
1417 true,
1418 "Expected a Block Ack");
1419 tEnd = m_txPsdus[26].endTx;
1420 tStart = m_txPsdus[27].startTx;
1421 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "First Block Ack sent too early");
1422 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "First Block Ack sent too late");
1423 Time baNavEnd = m_txPsdus[27].endTx + m_txPsdus[27].psduMap[SU_STA_ID]->GetDuration();
1424 // The NAV of the first BlockAck, being a response to a QoS Data frame, matches the NAV
1425 // set by the MU-RTS TF.
1426 // navEnd <= baNavEnd < navEnd + tolerance
1428 baNavEnd,
1429 "Duration/ID in 1st BlockAck frame is too short");
1430 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1431 navEnd + tolerance,
1432 "Duration/ID in 1st BlockAck is too long");
1433
1434 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
1435 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[28].psduMap.size() == 1 &&
1436 m_txPsdus[28].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAckReq()),
1437 true,
1438 "Expected a Block Ack Request");
1439 tEnd = m_txPsdus[27].endTx;
1440 tStart = m_txPsdus[28].startTx;
1441 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "First Block Ack Request sent too early");
1442 NS_TEST_EXPECT_MSG_LT(tStart,
1443 tEnd + sifs + tolerance,
1444 "First Block Ack Request sent too late");
1445 // under single protection setting (TXOP limit equal to zero), the NAV of the BlockAckReq
1446 // only covers the following BlockAck response; under multiple protection setting, the
1447 // NAV of the BlockAckReq matches the NAV set by the MU-RTS TF
1448 Time barNavEnd = m_txPsdus[28].endTx + m_txPsdus[28].psduMap[SU_STA_ID]->GetDuration();
1449 if (m_txopLimit > 0)
1450 {
1451 // navEnd <= barNavEnd < navEnd + tolerance
1453 barNavEnd,
1454 "Duration/ID in BlockAckReq is too short");
1455 NS_TEST_EXPECT_MSG_LT(barNavEnd,
1456 navEnd + tolerance,
1457 "Duration/ID in BlockAckReq is too long");
1458 }
1459
1460 // A second STA sends a Block Ack a SIFS after the reception of the Block Ack Request
1461 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[29].psduMap.size() == 1 &&
1462 m_txPsdus[29].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck()),
1463 true,
1464 "Expected a Block Ack");
1465 tEnd = m_txPsdus[28].endTx;
1466 tStart = m_txPsdus[29].startTx;
1467 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second Block Ack sent too early");
1468 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second Block Ack sent too late");
1469 baNavEnd = m_txPsdus[29].endTx + m_txPsdus[29].psduMap[SU_STA_ID]->GetDuration();
1470 if (m_txopLimit > 0)
1471 {
1472 // navEnd <= baNavEnd < navEnd + tolerance
1473 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck is too short");
1474 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1475 navEnd + tolerance,
1476 "Duration/ID in BlockAck is too long");
1477 }
1478 else
1479 {
1480 // barNavEnd <= baNavEnd < barNavEnd + tolerance
1482 baNavEnd,
1483 "Duration/ID in BlockAck is too short");
1484 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1485 barNavEnd + tolerance,
1486 "Duration/ID in BlockAck is too long");
1487 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1488 m_txPsdus[29].endTx,
1489 "Expected null Duration/ID for BlockAck");
1490 }
1491
1492 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
1493 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[30].psduMap.size() == 1 &&
1494 m_txPsdus[30].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAckReq()),
1495 true,
1496 "Expected a Block Ack Request");
1497 tEnd = m_txPsdus[29].endTx;
1498 tStart = m_txPsdus[30].startTx;
1499 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second Block Ack Request sent too early");
1500 NS_TEST_EXPECT_MSG_LT(tStart,
1501 tEnd + sifs + tolerance,
1502 "Second Block Ack Request sent too late");
1503 // under single protection setting (TXOP limit equal to zero), the NAV of the BlockAckReq
1504 // only covers the following BlockAck response; under multiple protection setting, the
1505 // NAV of the BlockAckReq matches the NAV set by the MU-RTS TF
1506 barNavEnd = m_txPsdus[30].endTx + m_txPsdus[30].psduMap[SU_STA_ID]->GetDuration();
1507 if (m_txopLimit > 0)
1508 {
1509 // navEnd <= barNavEnd < navEnd + tolerance
1511 barNavEnd,
1512 "Duration/ID in BlockAckReq is too short");
1513 NS_TEST_EXPECT_MSG_LT(barNavEnd,
1514 navEnd + tolerance,
1515 "Duration/ID in BlockAckReq is too long");
1516 }
1517
1518 // A third STA sends a Block Ack a SIFS after the reception of the Block Ack Request
1519 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[31].psduMap.size() == 1 &&
1520 m_txPsdus[31].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck()),
1521 true,
1522 "Expected a Block Ack");
1523 tEnd = m_txPsdus[30].endTx;
1524 tStart = m_txPsdus[31].startTx;
1525 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third Block Ack sent too early");
1526 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third Block Ack sent too late");
1527 baNavEnd = m_txPsdus[31].endTx + m_txPsdus[31].psduMap[SU_STA_ID]->GetDuration();
1528 if (m_txopLimit > 0)
1529 {
1530 // navEnd <= baNavEnd < navEnd + tolerance
1531 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck is too short");
1532 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1533 navEnd + tolerance,
1534 "Duration/ID in BlockAck is too long");
1535 }
1536 else
1537 {
1538 // barNavEnd <= baNavEnd < barNavEnd + tolerance
1540 baNavEnd,
1541 "Duration/ID in BlockAck is too short");
1542 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1543 barNavEnd + tolerance,
1544 "Duration/ID in BlockAck is too long");
1545 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1546 m_txPsdus[31].endTx,
1547 "Expected null Duration/ID for BlockAck");
1548 }
1549
1550 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
1551 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[32].psduMap.size() == 1 &&
1552 m_txPsdus[32].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAckReq()),
1553 true,
1554 "Expected a Block Ack Request");
1555 tEnd = m_txPsdus[31].endTx;
1556 tStart = m_txPsdus[32].startTx;
1557 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third Block Ack Request sent too early");
1558 NS_TEST_EXPECT_MSG_LT(tStart,
1559 tEnd + sifs + tolerance,
1560 "Third Block Ack Request sent too late");
1561 // under single protection setting (TXOP limit equal to zero), the NAV of the BlockAckReq
1562 // only covers the following BlockAck response; under multiple protection setting, the
1563 // NAV of the BlockAckReq matches the NAV set by the MU-RTS TF
1564 barNavEnd = m_txPsdus[32].endTx + m_txPsdus[32].psduMap[SU_STA_ID]->GetDuration();
1565 if (m_txopLimit > 0)
1566 {
1567 // navEnd <= barNavEnd < navEnd + tolerance
1569 barNavEnd,
1570 "Duration/ID in BlockAckReq is too short");
1571 NS_TEST_EXPECT_MSG_LT(barNavEnd,
1572 navEnd + tolerance,
1573 "Duration/ID in BlockAckReq is too long");
1574 }
1575
1576 // A fourth STA sends a Block Ack a SIFS after the reception of the Block Ack Request
1577 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[33].psduMap.size() == 1 &&
1578 m_txPsdus[33].psduMap[SU_STA_ID]->GetHeader(0).IsBlockAck()),
1579 true,
1580 "Expected a Block Ack");
1581 tEnd = m_txPsdus[32].endTx;
1582 tStart = m_txPsdus[33].startTx;
1583 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Fourth Block Ack sent too early");
1584 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Fourth Block Ack sent too late");
1585 baNavEnd = m_txPsdus[33].endTx + m_txPsdus[33].psduMap[SU_STA_ID]->GetDuration();
1586 if (m_txopLimit > 0)
1587 {
1588 // navEnd <= baNavEnd < navEnd + tolerance
1589 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck is too short");
1590 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1591 navEnd + tolerance,
1592 "Duration/ID in BlockAck is too long");
1593 }
1594 else
1595 {
1596 // barNavEnd <= baNavEnd < barNavEnd + tolerance
1598 baNavEnd,
1599 "Duration/ID in BlockAck is too short");
1600 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1601 barNavEnd + tolerance,
1602 "Duration/ID in BlockAck is too long");
1603 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1604 m_txPsdus[33].endTx,
1605 "Expected null Duration/ID for BlockAck");
1606 }
1607
1608 nTxPsdus = 34;
1609 }
1610 else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_TF_MU_BAR)
1611 {
1612 /*
1613 * |---------------------NAV------------------------>|
1614 * |-------------------NAV----------------->|
1615 * |---------------NAV--------->|
1616 * |------NAV----->|
1617 * ┌───┐ ┌───┐ ┌──────┐ ┌───────┐ ┌──────────┐
1618 * │ │ │ │ │PSDU 1│ │ │ │BlockAck 1│
1619 * │ │ │ │ ├──────┤ │MU-BAR │ ├──────────┤
1620 * │MU-│ │CTS│ │PSDU 2│ │Trigger│ │BlockAck 2│
1621 * │RTS│SIFS│ │SIFS├──────┤SIFS│ Frame │SIFS├──────────┤
1622 * │TF │ │x4 │ │PSDU 3│ │ │ │BlockAck 3│
1623 * │ │ │ │ ├──────┤ │ │ ├──────────┤
1624 * │ │ │ │ │PSDU 4│ │ │ │BlockAck 4│
1625 * -----┴───┴────┴───┴────┴──────┴────┴───────┴────┴──────────┴───
1626 * From: AP all AP AP all
1627 * To: all AP all all AP
1628 */
1629 NS_TEST_EXPECT_MSG_GT_OR_EQ(m_txPsdus.size(), 32, "Expected at least 32 packets");
1630
1631 // the AP transmits a MU-BAR Trigger Frame a SIFS after the transmission of the DL MU PPDU
1632 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[27].psduMap.size() == 1 &&
1633 m_txPsdus[27].psduMap[SU_STA_ID]->GetHeader(0).IsTrigger()),
1634 true,
1635 "Expected a MU-BAR Trigger Frame");
1636 tEnd = m_txPsdus[26].endTx;
1637 tStart = m_txPsdus[27].startTx;
1638 NS_TEST_EXPECT_MSG_EQ(tStart, tEnd + sifs, "MU-BAR Trigger Frame sent at wrong time");
1639 auto muBarNavEnd = m_txPsdus[27].endTx + m_txPsdus[27].psduMap[SU_STA_ID]->GetDuration();
1640 // navEnd <= muBarNavEnd < navEnd + tolerance
1642 muBarNavEnd,
1643 "Duration/ID in MU-BAR Trigger Frame is too short");
1644 NS_TEST_EXPECT_MSG_LT(muBarNavEnd,
1645 navEnd + tolerance,
1646 "Duration/ID in MU-BAR Trigger Frame is too long");
1647
1648 // A first STA sends a Block Ack in a TB PPDU a SIFS after the reception of the MU-BAR
1649 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[28].txVector.GetPreambleType() == m_tbPreamble &&
1650 m_txPsdus[28].psduMap.size() == 1 &&
1651 m_txPsdus[28].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1652 true,
1653 "Expected a Block Ack");
1654 tEnd = m_txPsdus[27].endTx;
1655 tStart = m_txPsdus[28].startTx;
1656 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1657 NS_TEST_EXPECT_MSG_LT(tStart,
1658 tEnd + sifs + tolerance,
1659 "Block Ack in HE TB PPDU sent too late");
1660 Time baNavEnd = m_txPsdus[28].endTx + m_txPsdus[28].psduMap.begin()->second->GetDuration();
1661 // navEnd <= baNavEnd < navEnd + tolerance
1662 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck frame is too short");
1663 NS_TEST_EXPECT_MSG_LT(baNavEnd, navEnd + tolerance, "Duration/ID in BlockAck is too long");
1664 if (m_txopLimit == 0)
1665 {
1666 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1667 m_txPsdus[28].endTx,
1668 "Expected null Duration/ID for BlockAck");
1669 }
1670
1671 // A second STA sends a Block Ack in a TB PPDU a SIFS after the reception of the MU-BAR
1672 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[29].txVector.GetPreambleType() == m_tbPreamble &&
1673 m_txPsdus[29].psduMap.size() == 1 &&
1674 m_txPsdus[29].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1675 true,
1676 "Expected a Block Ack");
1677 tStart = m_txPsdus[29].startTx;
1678 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1679 NS_TEST_EXPECT_MSG_LT(tStart,
1680 tEnd + sifs + tolerance,
1681 "Block Ack in HE TB PPDU sent too late");
1682 baNavEnd = m_txPsdus[29].endTx + m_txPsdus[29].psduMap.begin()->second->GetDuration();
1683 // navEnd <= baNavEnd < navEnd + tolerance
1684 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck frame is too short");
1685 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1686 navEnd + tolerance,
1687 "Duration/ID in 1st BlockAck is too long");
1688 if (m_txopLimit == 0)
1689 {
1690 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1691 m_txPsdus[29].endTx,
1692 "Expected null Duration/ID for BlockAck");
1693 }
1694
1695 // A third STA sends a Block Ack in a TB PPDU a SIFS after the reception of the MU-BAR
1696 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[30].txVector.GetPreambleType() == m_tbPreamble &&
1697 m_txPsdus[30].psduMap.size() == 1 &&
1698 m_txPsdus[30].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1699 true,
1700 "Expected a Block Ack");
1701 tStart = m_txPsdus[30].startTx;
1702 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1703 NS_TEST_EXPECT_MSG_LT(tStart,
1704 tEnd + sifs + tolerance,
1705 "Block Ack in HE TB PPDU sent too late");
1706 baNavEnd = m_txPsdus[30].endTx + m_txPsdus[30].psduMap.begin()->second->GetDuration();
1707 // navEnd <= baNavEnd < navEnd + tolerance
1708 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck frame is too short");
1709 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1710 navEnd + tolerance,
1711 "Duration/ID in 1st BlockAck is too long");
1712 if (m_txopLimit == 0)
1713 {
1714 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1715 m_txPsdus[30].endTx,
1716 "Expected null Duration/ID for BlockAck");
1717 }
1718
1719 // A fourth STA sends a Block Ack in a TB PPDU a SIFS after the reception of the MU-BAR
1720 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[31].txVector.GetPreambleType() == m_tbPreamble &&
1721 m_txPsdus[31].psduMap.size() == 1 &&
1722 m_txPsdus[31].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1723 true,
1724 "Expected a Block Ack");
1725 tStart = m_txPsdus[31].startTx;
1726 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1727 NS_TEST_EXPECT_MSG_LT(tStart,
1728 tEnd + sifs + tolerance,
1729 "Block Ack in HE TB PPDU sent too late");
1730 baNavEnd = m_txPsdus[31].endTx + m_txPsdus[31].psduMap.begin()->second->GetDuration();
1731 // navEnd <= baNavEnd < navEnd + tolerance
1732 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck frame is too short");
1733 NS_TEST_EXPECT_MSG_LT(baNavEnd,
1734 navEnd + tolerance,
1735 "Duration/ID in 1st BlockAck is too long");
1736 if (m_txopLimit == 0)
1737 {
1738 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1739 m_txPsdus[31].endTx,
1740 "Expected null Duration/ID for BlockAck");
1741 }
1742
1743 nTxPsdus = 32;
1744 }
1745 else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_AGGREGATE_TF)
1746 {
1747 /*
1748 * |---------------------NAV----------------------->|
1749 * |-------------------NAV---------------->|
1750 * |------NAV----->|
1751 * ┌───┐ ┌───┐ ┌──────┬───────────┐ ┌──────────┐
1752 * │ │ │ │ │PSDU 1│MU-BAR TF 1│ │BlockAck 1│
1753 * │ │ │ │ ├──────┼───────────┤ ├──────────┤
1754 * │MU-│ │CTS│ │PSDU 2│MU-BAR TF 2│ │BlockAck 2│
1755 * │RTS│SIFS│ │SIFS├──────┼───────────┤SIFS├──────────┤
1756 * │TF │ │x4 │ │PSDU 3│MU-BAR TF 3│ │BlockAck 3│
1757 * │ │ │ │ ├──────┼───────────┤ ├──────────┤
1758 * │ │ │ │ │PSDU 4│MU-BAR TF 4│ │BlockAck 4│
1759 * -----┴───┴────┴───┴────┴──────┴───────────┴────┴──────────┴───
1760 * From: AP all AP all
1761 * To: all AP all AP
1762 */
1763 NS_TEST_ASSERT_MSG_GT_OR_EQ(m_txPsdus.size(), 31, "Expected at least 31 packets");
1764
1765 // The last MPDU in each PSDU is a MU-BAR Trigger Frame
1766 for (auto& psdu : m_txPsdus[26].psduMap)
1767 {
1768 NS_TEST_EXPECT_MSG_EQ((*std::prev(psdu.second->end()))->GetHeader().IsTrigger(),
1769 true,
1770 "Expected an aggregated MU-BAR Trigger Frame");
1771 }
1772
1773 // A first STA sends a Block Ack in a TB PPDU a SIFS after the reception of the DL MU PPDU
1774 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[27].txVector.GetPreambleType() == m_tbPreamble &&
1775 m_txPsdus[27].psduMap.size() == 1 &&
1776 m_txPsdus[27].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1777 true,
1778 "Expected a Block Ack");
1779 tEnd = m_txPsdus[26].endTx;
1780 tStart = m_txPsdus[27].startTx;
1781 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1782 NS_TEST_EXPECT_MSG_LT(tStart,
1783 tEnd + sifs + tolerance,
1784 "Block Ack in HE TB PPDU sent too late");
1785 Time baNavEnd = m_txPsdus[27].endTx + m_txPsdus[27].psduMap.begin()->second->GetDuration();
1786 // navEnd <= baNavEnd < navEnd + tolerance
1787 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck frame is too short");
1788 NS_TEST_EXPECT_MSG_LT(baNavEnd, navEnd + tolerance, "Duration/ID in BlockAck is too long");
1789 if (m_txopLimit == 0)
1790 {
1791 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1792 m_txPsdus[27].endTx,
1793 "Expected null Duration/ID for BlockAck");
1794 }
1795
1796 // A second STA sends a Block Ack in a TB PPDU a SIFS after the reception of the DL MU PPDU
1797 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[28].txVector.GetPreambleType() == m_tbPreamble &&
1798 m_txPsdus[28].psduMap.size() == 1 &&
1799 m_txPsdus[28].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1800 true,
1801 "Expected a Block Ack");
1802 tStart = m_txPsdus[28].startTx;
1803 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1804 NS_TEST_EXPECT_MSG_LT(tStart,
1805 tEnd + sifs + tolerance,
1806 "Block Ack in HE TB PPDU sent too late");
1807 baNavEnd = m_txPsdus[28].endTx + m_txPsdus[28].psduMap.begin()->second->GetDuration();
1808 // navEnd <= baNavEnd < navEnd + tolerance
1809 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck frame is too short");
1810 NS_TEST_EXPECT_MSG_LT(baNavEnd, navEnd + tolerance, "Duration/ID in BlockAck is too long");
1811 if (m_txopLimit == 0)
1812 {
1813 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1814 m_txPsdus[28].endTx,
1815 "Expected null Duration/ID for BlockAck");
1816 }
1817
1818 // A third STA sends a Block Ack in a TB PPDU a SIFS after the reception of the DL MU PPDU
1819 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[29].txVector.GetPreambleType() == m_tbPreamble &&
1820 m_txPsdus[29].psduMap.size() == 1 &&
1821 m_txPsdus[29].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1822 true,
1823 "Expected a Block Ack");
1824 tStart = m_txPsdus[29].startTx;
1825 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1826 NS_TEST_EXPECT_MSG_LT(tStart,
1827 tEnd + sifs + tolerance,
1828 "Block Ack in HE TB PPDU sent too late");
1829 baNavEnd = m_txPsdus[29].endTx + m_txPsdus[29].psduMap.begin()->second->GetDuration();
1830 // navEnd <= baNavEnd < navEnd + tolerance
1831 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck frame is too short");
1832 NS_TEST_EXPECT_MSG_LT(baNavEnd, navEnd + tolerance, "Duration/ID in BlockAck is too long");
1833 if (m_txopLimit == 0)
1834 {
1835 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1836 m_txPsdus[29].endTx,
1837 "Expected null Duration/ID for BlockAck");
1838 }
1839
1840 // A fourth STA sends a Block Ack in a TB PPDU a SIFS after the reception of the DL MU PPDU
1841 NS_TEST_EXPECT_MSG_EQ((m_txPsdus[30].txVector.GetPreambleType() == m_tbPreamble &&
1842 m_txPsdus[30].psduMap.size() == 1 &&
1843 m_txPsdus[30].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1844 true,
1845 "Expected a Block Ack");
1846 tStart = m_txPsdus[30].startTx;
1847 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1848 NS_TEST_EXPECT_MSG_LT(tStart,
1849 tEnd + sifs + tolerance,
1850 "Block Ack in HE TB PPDU sent too late");
1851 baNavEnd = m_txPsdus[30].endTx + m_txPsdus[30].psduMap.begin()->second->GetDuration();
1852 // navEnd <= baNavEnd < navEnd + tolerance
1853 NS_TEST_EXPECT_MSG_LT_OR_EQ(navEnd, baNavEnd, "Duration/ID in BlockAck frame is too short");
1854 NS_TEST_EXPECT_MSG_LT(baNavEnd, navEnd + tolerance, "Duration/ID in BlockAck is too long");
1855 if (m_txopLimit == 0)
1856 {
1857 NS_TEST_EXPECT_MSG_EQ(baNavEnd,
1858 m_txPsdus[30].endTx,
1859 "Expected null Duration/ID for BlockAck");
1860 }
1861
1862 nTxPsdus = 31;
1863 }
1864
1867 "Not all DL packets have been received");
1868
1870 {
1871 // EDCA disabled, find the first PSDU transmitted by a station not in an
1872 // HE TB PPDU and check that it was not transmitted before the MU EDCA
1873 // timer expired
1874 for (std::size_t i = nTxPsdus; i < m_txPsdus.size(); ++i)
1875 {
1876 if (m_txPsdus[i].psduMap.size() == 1 &&
1877 !m_txPsdus[i].psduMap.begin()->second->GetHeader(0).IsCts() &&
1878 m_txPsdus[i].psduMap.begin()->second->GetHeader(0).GetAddr2() !=
1880 !m_txPsdus[i].txVector.IsUlMu())
1881 {
1883 m_txPsdus[i].startTx.GetMicroSeconds(),
1886 "A station transmitted before the MU EDCA timer expired");
1887 break;
1888 }
1889 }
1890 }
1892 {
1893 // stations used worse access parameters after successful UL MU transmission
1894 for (const auto& cwValue : m_cwValues)
1895 {
1896 NS_TEST_EXPECT_MSG_EQ((cwValue == 2 || cwValue >= m_muEdcaParameterSet.muCwMin),
1897 true,
1898 "A station did not set the correct MU CW min");
1899 }
1900 }
1901
1902 m_txPsdus.clear();
1903}
1904
1905void
1907{
1908 uint32_t previousSeed = RngSeedManager::GetSeed();
1909 uint64_t previousRun = RngSeedManager::GetRun();
1910 Config::SetGlobal("RngSeed", UintegerValue(1));
1911 Config::SetGlobal("RngRun", UintegerValue(1));
1912 int64_t streamNumber = 10;
1913
1915 wifiApNode.Create(1);
1916
1917 NodeContainer wifiOldStaNodes;
1918 NodeContainer wifiNewStaNodes;
1919 wifiOldStaNodes.Create(m_nStations / 2);
1920 wifiNewStaNodes.Create(m_nStations - m_nStations / 2);
1921 NodeContainer wifiStaNodes(wifiOldStaNodes, wifiNewStaNodes);
1922
1923 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
1924 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
1925 spectrumChannel->AddPropagationLossModel(lossModel);
1927 CreateObject<ConstantSpeedPropagationDelayModel>();
1928 spectrumChannel->SetPropagationDelayModel(delayModel);
1929
1931 phy.SetPcapDataLinkType(WifiPhyHelper::DLT_IEEE802_11_RADIO);
1932 phy.SetErrorRateModel("ns3::NistErrorRateModel");
1933 phy.SetChannel(spectrumChannel);
1934 switch (m_channelWidth)
1935 {
1936 case 20:
1937 phy.Set("ChannelSettings", StringValue("{36, 20, BAND_5GHZ, 0}"));
1938 break;
1939 case 40:
1940 phy.Set("ChannelSettings", StringValue("{38, 40, BAND_5GHZ, 0}"));
1941 break;
1942 case 80:
1943 phy.Set("ChannelSettings", StringValue("{42, 80, BAND_5GHZ, 0}"));
1944 break;
1945 case 160:
1946 phy.Set("ChannelSettings", StringValue("{50, 160, BAND_5GHZ, 0}"));
1947 break;
1948 default:
1949 NS_ABORT_MSG("Invalid channel bandwidth (must be 20, 40, 80 or 160)");
1950 }
1951
1952 Config::SetDefault("ns3::WifiDefaultProtectionManager::EnableMuRts", BooleanValue(true));
1953 Config::SetDefault("ns3::HeConfiguration::MuBeAifsn",
1955 Config::SetDefault("ns3::HeConfiguration::MuBeCwMin",
1957 Config::SetDefault("ns3::HeConfiguration::MuBeCwMax",
1959 Config::SetDefault("ns3::HeConfiguration::BeMuEdcaTimer",
1961
1962 Config::SetDefault("ns3::HeConfiguration::MuBkAifsn",
1964 Config::SetDefault("ns3::HeConfiguration::MuBkCwMin",
1966 Config::SetDefault("ns3::HeConfiguration::MuBkCwMax",
1968 Config::SetDefault("ns3::HeConfiguration::BkMuEdcaTimer",
1970
1971 Config::SetDefault("ns3::HeConfiguration::MuViAifsn",
1973 Config::SetDefault("ns3::HeConfiguration::MuViCwMin",
1975 Config::SetDefault("ns3::HeConfiguration::MuViCwMax",
1977 Config::SetDefault("ns3::HeConfiguration::ViMuEdcaTimer",
1979
1980 Config::SetDefault("ns3::HeConfiguration::MuVoAifsn",
1982 Config::SetDefault("ns3::HeConfiguration::MuVoCwMin",
1984 Config::SetDefault("ns3::HeConfiguration::MuVoCwMax",
1986 Config::SetDefault("ns3::HeConfiguration::VoMuEdcaTimer",
1988
1989 // increase MSDU lifetime so that it does not expire before the MU EDCA timer ends
1990 Config::SetDefault("ns3::WifiMacQueue::MaxDelay", TimeValue(Seconds(2)));
1991
1995 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
1996 "DataMode",
1997 StringValue("HeMcs11"));
1998 wifi.ConfigHeOptions("MuBeAifsn",
2000 "MuBeCwMin",
2002 "MuBeCwMax",
2004 "BeMuEdcaTimer",
2006 // MU EDCA timers must be either all null or all non-null
2007 "BkMuEdcaTimer",
2009 "ViMuEdcaTimer",
2011 "VoMuEdcaTimer",
2013
2015 Ssid ssid = Ssid("ns-3-ssid");
2016 mac.SetType("ns3::StaWifiMac",
2017 "Ssid",
2018 SsidValue(ssid),
2019 "BE_MaxAmsduSize",
2020 UintegerValue(0),
2021 "BE_MaxAmpduSize",
2023 /* setting blockack threshold for sta's BE queue */
2024 "BE_BlockAckThreshold",
2025 UintegerValue(2),
2026 "BK_MaxAmsduSize",
2027 UintegerValue(0),
2028 "BK_MaxAmpduSize",
2030 /* setting blockack threshold for sta's BK queue */
2031 "BK_BlockAckThreshold",
2032 UintegerValue(2),
2033 "VI_MaxAmsduSize",
2034 UintegerValue(0),
2035 "VI_MaxAmpduSize",
2037 /* setting blockack threshold for sta's VI queue */
2038 "VI_BlockAckThreshold",
2039 UintegerValue(2),
2040 "VO_MaxAmsduSize",
2041 UintegerValue(0),
2042 "VO_MaxAmpduSize",
2044 /* setting blockack threshold for sta's VO queue */
2045 "VO_BlockAckThreshold",
2046 UintegerValue(2),
2047 "ActiveProbing",
2048 BooleanValue(false));
2049
2050 m_staDevices = wifi.Install(phy, mac, wifiOldStaNodes);
2051
2054 m_staDevices = NetDeviceContainer(m_staDevices, wifi.Install(phy, mac, wifiNewStaNodes));
2055
2056 mac.SetType("ns3::ApWifiMac", "BeaconGeneration", BooleanValue(true));
2057 mac.SetMultiUserScheduler(
2058 "ns3::TestMultiUserScheduler",
2059 "ModulationClass",
2061 // request channel access at 1.5s
2062 "AccessReqInterval",
2063 TimeValue(Seconds(1.5)),
2064 "DelayAccessReqUponAccess",
2065 BooleanValue(false));
2066 mac.SetAckManager("ns3::WifiDefaultAckManager",
2067 "DlMuAckSequenceType",
2069
2070 m_apDevice = DynamicCast<WifiNetDevice>(wifi.Install(phy, mac, wifiApNode).Get(0));
2071
2072 // Assign fixed streams to random variables in use
2073 streamNumber += wifi.AssignStreams(NetDeviceContainer(m_apDevice), streamNumber);
2074 streamNumber += wifi.AssignStreams(m_staDevices, streamNumber);
2075
2077 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
2078
2079 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
2080 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
2081 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
2082 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
2083 positionAlloc->Add(Vector(-1.0, -1.0, 0.0));
2084 mobility.SetPositionAllocator(positionAlloc);
2085
2086 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
2087 mobility.Install(wifiApNode);
2088 mobility.Install(wifiStaNodes);
2089
2091 for (uint32_t i = 0; i < allDevices.GetN(); i++)
2092 {
2093 auto dev = DynamicCast<WifiNetDevice>(allDevices.Get(i));
2094 // set the same TXOP limit on all ACs
2095 dev->GetMac()->GetQosTxop(AC_BE)->SetTxopLimit(MicroSeconds(m_txopLimit));
2096 dev->GetMac()->GetQosTxop(AC_BK)->SetTxopLimit(MicroSeconds(m_txopLimit));
2097 dev->GetMac()->GetQosTxop(AC_VI)->SetTxopLimit(MicroSeconds(m_txopLimit));
2098 dev->GetMac()->GetQosTxop(AC_VO)->SetTxopLimit(MicroSeconds(m_txopLimit));
2099 // set the same AIFSN on all ACs (just to be able to check inter-frame spaces)
2100 dev->GetMac()->GetQosTxop(AC_BE)->SetAifsn(3);
2101 dev->GetMac()->GetQosTxop(AC_BK)->SetAifsn(3);
2102 dev->GetMac()->GetQosTxop(AC_VI)->SetAifsn(3);
2103 dev->GetMac()->GetQosTxop(AC_VO)->SetAifsn(3);
2104 }
2105
2106 PacketSocketHelper packetSocket;
2107 packetSocket.Install(wifiApNode);
2108 packetSocket.Install(wifiStaNodes);
2109
2110 // DL Traffic
2111 for (uint16_t i = 0; i < m_nStations; i++)
2112 {
2113 PacketSocketAddress socket;
2115 socket.SetPhysicalAddress(m_staDevices.Get(i)->GetAddress());
2116 socket.SetProtocol(1);
2117
2118 // the first client application generates two packets in order
2119 // to trigger the establishment of a Block Ack agreement
2120 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient>();
2121 client1->SetAttribute("PacketSize", UintegerValue(1400));
2122 client1->SetAttribute("MaxPackets", UintegerValue(2));
2123 client1->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
2124 client1->SetAttribute("Priority", UintegerValue(i * 2)); // 0, 2, 4 and 6
2125 client1->SetRemote(socket);
2126 wifiApNode.Get(0)->AddApplication(client1);
2127 client1->SetStartTime(Seconds(1) + i * MilliSeconds(1));
2128 client1->SetStopTime(Seconds(2.0));
2129
2130 // the second client application generates the selected number of packets,
2131 // which are sent in DL MU PPDUs.
2132 Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient>();
2133 client2->SetAttribute("PacketSize", UintegerValue(1400 + i * 100));
2134 client2->SetAttribute("MaxPackets", UintegerValue(m_nPktsPerSta));
2135 client2->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
2136 client2->SetAttribute("Priority", UintegerValue(i * 2)); // 0, 2, 4 and 6
2137 client2->SetRemote(socket);
2138 wifiApNode.Get(0)->AddApplication(client2);
2139 client2->SetStartTime(Seconds(1.5003));
2140 client2->SetStopTime(Seconds(2.5));
2141
2142 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
2143 server->SetLocal(socket);
2144 wifiStaNodes.Get(i)->AddApplication(server);
2145 server->SetStartTime(Seconds(0.0));
2146 server->SetStopTime(Seconds(3.0));
2147 }
2148
2149 // UL Traffic
2150 for (uint16_t i = 0; i < m_nStations; i++)
2151 {
2152 m_sockets[i].SetSingleDevice(m_staDevices.Get(i)->GetIfIndex());
2153 m_sockets[i].SetPhysicalAddress(m_apDevice->GetAddress());
2154 m_sockets[i].SetProtocol(1);
2155
2156 // the first client application generates two packets in order
2157 // to trigger the establishment of a Block Ack agreement
2158 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient>();
2159 client1->SetAttribute("PacketSize", UintegerValue(1400));
2160 client1->SetAttribute("MaxPackets", UintegerValue(2));
2161 client1->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
2162 client1->SetAttribute("Priority", UintegerValue(i * 2)); // 0, 2, 4 and 6
2163 client1->SetRemote(m_sockets[i]);
2164 wifiStaNodes.Get(i)->AddApplication(client1);
2165 client1->SetStartTime(Seconds(1.005) + i * MilliSeconds(1));
2166 client1->SetStopTime(Seconds(2.0));
2167
2168 // packets to be included in HE TB PPDUs are generated (by Transmit()) when
2169 // the first Basic Trigger Frame is sent by the AP
2170
2171 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
2172 server->SetLocal(m_sockets[i]);
2173 wifiApNode.Get(0)->AddApplication(server);
2174 server->SetStartTime(Seconds(0.0));
2175 server->SetStopTime(Seconds(3.0));
2176 }
2177
2178 Config::Connect("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
2180 // Trace PSDUs passed to the PHY on all devices
2181 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
2183
2184 Simulator::Stop(Seconds(3));
2185 Simulator::Run();
2186
2189 m_apDevice->GetMac()->GetQosTxop(AC_BE)->Txop::GetAifsn());
2190
2191 Simulator::Destroy();
2192
2193 // Restore the seed and run number that were in effect before this test
2194 Config::SetGlobal("RngSeed", UintegerValue(previousSeed));
2195 Config::SetGlobal("RngRun", UintegerValue(previousRun));
2196}
2197
2205{
2206 public:
2208};
2209
2211 : TestSuite("wifi-mac-ofdma", UNIT)
2212{
2213 using MuEdcaParams = std::initializer_list<OfdmaAckSequenceTest::MuEdcaParameterSet>;
2214
2215 for (auto& muEdcaParameterSet : MuEdcaParams{{0, 0, 0, 0} /* no MU EDCA */,
2216 {0, 127, 2047, 100} /* EDCA disabled */,
2217 {10, 127, 2047, 100} /* worse parameters */})
2218 {
2219 for (const auto scenario :
2221 {
2223 WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE,
2224 10000,
2225 5504,
2226 15,
2227 muEdcaParameterSet,
2228 scenario),
2229 TestCase::QUICK);
2231 WifiAcknowledgment::DL_MU_AGGREGATE_TF,
2232 10000,
2233 5504,
2234 15,
2235 muEdcaParameterSet,
2236 scenario),
2237 TestCase::QUICK);
2239 WifiAcknowledgment::DL_MU_TF_MU_BAR,
2240 10000,
2241 5504,
2242 15,
2243 muEdcaParameterSet,
2244 scenario),
2245 TestCase::QUICK);
2247 WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE,
2248 10000,
2249 0,
2250 15,
2251 muEdcaParameterSet,
2252 scenario),
2253 TestCase::QUICK);
2255 WifiAcknowledgment::DL_MU_AGGREGATE_TF,
2256 10000,
2257 0,
2258 15,
2259 muEdcaParameterSet,
2260 scenario),
2261 TestCase::QUICK);
2263 WifiAcknowledgment::DL_MU_TF_MU_BAR,
2264 10000,
2265 0,
2266 15,
2267 muEdcaParameterSet,
2268 scenario),
2269 TestCase::QUICK);
2270 }
2271 }
2272}
2273
#define Min(a, b)
Test OFDMA acknowledgment sequences.
OfdmaAckSequenceTest(uint16_t width, WifiAcknowledgment::Method dlType, uint32_t maxAmpduSize, uint16_t txopLimit, uint16_t nPktsPerSta, MuEdcaParameterSet muEdcaParameterSet, WifiOfdmaScenario scenario)
Constructor.
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
uint8_t m_muRtsRuAllocation
B7-B1 of RU Allocation subfield of MU-RTS.
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when FrameExchangeManager passes PSDUs to the PHY.
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.
WifiOfdmaScenario m_scenario
OFDMA scenario to test.
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.
WifiPreamble m_tbPreamble
expected preamble type for TB PPDUs
uint16_t m_nStations
number of stations
MuEdcaParameterSet m_muEdcaParameterSet
MU EDCA Parameter Set.
WifiPreamble m_dlMuPreamble
expected preamble type for DL MU PPDUs
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
WifiModulationClass m_modClass
modulation class for DL MU PPDUs and TB PPDUs
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:100
const std::map< uint16_t, Mac48Address > & GetStaList(uint8_t linkId) 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:203
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:945
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...
bool IsMuRts() const
Check if this is a MU-RTS Trigger frame.
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< ApWifiMac > m_apMac
the AP wifi MAC
Time m_availableTime
the time available for frame exchange
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId) const
Get the station manager attached to the AP on the given link.
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...
Ptr< HeFrameExchangeManager > GetHeFem(uint8_t linkId) const
Get the HE Frame Exchange Manager attached to the AP on the given link.
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.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:311
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:862
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< 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:359
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:474
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:56
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:1423
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:59
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:324
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:1353
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:954
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Definition: wifi-mac.cc:886
Mac48Address GetAddress() const
Definition: wifi-mac.cc:443
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Definition: wifi-mac.cc:490
Ptr< WifiMac > GetMac() const
uint32_t GetIfIndex() const override
Address GetAddress() const override
Time GetSlot() const
Return the slot duration for this PHY.
Definition: wifi-phy.cc:786
uint16_t GetChannelWidth() const
Definition: wifi-phy.cc:1026
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
Definition: wifi-phy.cc:774
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
Definition: wifi-phy.cc:996
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 SetEhtPpduType(uint8_t type)
Set the EHT_PPDU_TYPE parameter.
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
bool IsDlMu() const
void SetRuAllocation(const RuAllocation &ruAlloc)
Set RU Allocation of SIG-B common field.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
Definition: enum.h:205
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:46
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_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
#define NS_TEST_ASSERT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to a limit and report and abort if not.
Definition: test.h:915
WifiOfdmaScenario
The scenarios.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
AcIndex
This enumeration defines the Access Categories as an enumeration with values corresponding to the AC ...
Definition: qos-utils.h:72
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:560
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_EHT_TB
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_EHT_MU
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ AC_BE
Best Effort.
Definition: qos-utils.h:74
@ AC_VO
Voice.
Definition: qos-utils.h:80
@ AC_VI
Video.
Definition: qos-utils.h:78
@ AC_BK
Background.
Definition: qos-utils.h:76
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:707
bool IsEht(WifiPreamble preamble)
Return true if a preamble corresponds to an EHT transmission.
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_CTL_CTS
@ WIFI_MAC_QOSDATA_NULL
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
Ptr< const AttributeChecker > MakeEnumChecker(int v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:163
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.
uint32_t prev
static WifiMacOfdmaTestSuite g_wifiMacOfdmaTestSuite
the test suite
#define SU_STA_ID
Definition: wifi-mode.h:34