A Discrete-Event Network Simulator
API
wifi-mac-ofdma-test.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Stefano Avallone <stavallo@unina.it>
19 */
20
21#include "ns3/test.h"
22#include "ns3/string.h"
23#include "ns3/qos-utils.h"
24#include "ns3/packet.h"
25#include "ns3/wifi-net-device.h"
26#include "ns3/wifi-mac-header.h"
27#include "ns3/he-frame-exchange-manager.h"
28#include "ns3/wifi-acknowledgment.h"
29#include "ns3/wifi-protection.h"
30#include "ns3/he-configuration.h"
31#include "ns3/mobility-helper.h"
32#include "ns3/spectrum-wifi-helper.h"
33#include "ns3/multi-model-spectrum-channel.h"
34#include "ns3/packet-socket-server.h"
35#include "ns3/packet-socket-client.h"
36#include "ns3/packet-socket-helper.h"
37#include "ns3/config.h"
38#include "ns3/pointer.h"
39#include "ns3/rng-seed-manager.h"
40#include "ns3/wifi-psdu.h"
41#include "ns3/multi-user-scheduler.h"
42#include "ns3/he-phy.h"
43
44using namespace ns3;
45
46NS_LOG_COMPONENT_DEFINE ("WifiMacOfdmaTestSuite");
47
61{
62public:
67 static TypeId GetTypeId (void);
69 virtual ~TestMultiUserScheduler ();
70
71private:
72 // Implementation of pure virtual methods of MultiUserScheduler class
73 TxFormat SelectTxFormat (void) override;
74 DlMuInfo ComputeDlMuInfo (void) override;
75 UlMuInfo ComputeUlMuInfo (void) override;
76
80 void ComputeWifiTxVector (void);
81
89};
90
91
93
96{
97 static TypeId tid = TypeId ("ns3::TestMultiUserScheduler")
99 .SetGroupName ("Wifi")
100 .AddConstructor<TestMultiUserScheduler> ()
101 ;
102 return tid;
103}
104
106 : m_txFormat (SU_TX),
107 m_ulTriggerType (TriggerFrameType::BSRP_TRIGGER)
108{
109 NS_LOG_FUNCTION (this);
110}
111
113{
115}
116
119{
120 NS_LOG_FUNCTION (this);
121
122 // Do not use OFDMA if a BA agreement has not been established with all the stations
123 if (Simulator::Now () < Seconds (1.5))
124 {
125 NS_LOG_DEBUG ("Return SU_TX");
126 return SU_TX;
127 }
128
130
133 {
134 // try to send a Trigger Frame
135 TriggerFrameType ulTriggerType = (m_txFormat == SU_TX || m_txFormat == DL_MU_TX
138
139 m_trigger = CtrlTriggerHeader (ulTriggerType, m_txVector);
140
141 WifiTxVector txVector = m_txVector;
143
144 uint32_t ampduSize = (ulTriggerType == TriggerFrameType::BSRP_TRIGGER ? m_sizeOf8QosNull : 3500);
145
146 Time duration = WifiPhy::CalculateTxDuration (ampduSize, txVector,
147 m_apMac->GetWifiPhy ()->GetPhyBand (),
148 m_apMac->GetStaList ().begin ()->first);
149
150 uint16_t length;
151 std::tie (length, duration) = HePhy::ConvertHeTbPpduDurationToLSigLength (duration,
152 m_trigger.GetHeTbTxVector (m_trigger.begin ()->GetAid12 ()),
153 m_apMac->GetWifiPhy ()->GetPhyBand ());
154 m_trigger.SetUlLength (length);
155
156 Ptr<Packet> packet = Create<Packet> ();
157 packet->AddHeader (m_trigger);
158
160 m_triggerHdr.SetAddr1 (Mac48Address::GetBroadcast ());
161 m_triggerHdr.SetAddr2 (m_apMac->GetAddress ());
164
165 auto item = Create<WifiMacQueueItem> (packet, m_triggerHdr);
166
167 m_txParams.Clear ();
168 // set the TXVECTOR used to send the Trigger Frame
169 m_txParams.m_txVector = m_apMac->GetWifiRemoteStationManager ()->GetRtsTxVector (m_triggerHdr.GetAddr1 ());
170
171 if (!m_heFem->TryAddMpdu (item, m_txParams, m_availableTime)
172 || (m_availableTime != Time::Min ()
173 && m_txParams.m_protection->protectionTime
174 + m_txParams.m_txDuration // TF tx time
175 + m_apMac->GetWifiPhy ()->GetSifs ()
176 + duration
177 + m_txParams.m_acknowledgment->acknowledgmentTime
178 > m_availableTime ))
179 {
180 NS_LOG_DEBUG ("Remaining TXOP duration is not enough for BSRP TF exchange");
181 return SU_TX;
182 }
183
185 m_ulTriggerType = ulTriggerType;
186 }
187 else if (m_txFormat == UL_MU_TX)
188 {
189 // try to send a DL MU PPDU
190 m_psduMap.clear ();
191 const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList ();
192 NS_ABORT_MSG_IF (staList.size () != 4, "There must be 4 associated stations");
193
194 /* Initialize TX params */
195 m_txParams.Clear ();
197
198 for (auto& sta : staList)
199 {
200 Ptr<const WifiMacQueueItem> peeked = m_apMac->GetQosTxop (AC_BE)->PeekNextMpdu (0, sta.second);
201
202 if (peeked == 0)
203 {
204 NS_LOG_DEBUG ("No frame to send");
205 return SU_TX;
206 }
207
208 Ptr<WifiMacQueueItem> mpdu = m_apMac->GetQosTxop (AC_BE)->GetNextMpdu (peeked, m_txParams,
211 if (mpdu == 0)
212 {
213 NS_LOG_DEBUG ("Not enough time to send frames to all the stations");
214 return SU_TX;
215 }
216
217 std::vector<Ptr<WifiMacQueueItem>> mpduList;
218 mpduList = m_heFem->GetMpduAggregator ()->GetNextAmpdu (mpdu, m_txParams, m_availableTime);
219
220 if (mpduList.size () > 1)
221 {
222 m_psduMap[sta.first] = Create<WifiPsdu> (std::move (mpduList));
223 }
224 else
225 {
226 m_psduMap[sta.first] = Create<WifiPsdu> (mpdu, true);
227 }
228 }
229
231 }
232 else
233 {
234 NS_ABORT_MSG ("Cannot get here.");
235 }
236
237 NS_LOG_DEBUG ("Return " << m_txFormat);
238 return m_txFormat;
239}
240
241void
243{
245 {
246 // the TX vector has been already computed
247 return;
248 }
249
250 uint16_t bw = m_apMac->GetWifiPhy ()->GetChannelWidth ();
251
254 m_txVector.SetGuardInterval (m_apMac->GetHeConfiguration ()->GetGuardInterval ().GetNanoSeconds ());
255 m_txVector.SetTxPowerLevel (GetWifiRemoteStationManager ()->GetDefaultTxPowerLevel ());
256
257 const std::map<uint16_t, Mac48Address>& staList = m_apMac->GetStaList ();
258 NS_ABORT_MSG_IF (staList.size () != 4, "There must be 4 associated stations");
259
260 HeRu::RuType ruType;
261 switch (bw)
262 {
263 case 20:
264 ruType = HeRu::RU_52_TONE;
265 break;
266 case 40:
267 ruType = HeRu::RU_106_TONE;
268 break;
269 case 80:
270 ruType = HeRu::RU_242_TONE;
271 break;
272 case 160:
273 ruType = HeRu::RU_484_TONE;
274 break;
275 default:
276 NS_ABORT_MSG ("Unsupported channel width");
277 }
278
279 bool primary80 = true;
280 std::size_t ruIndex = 1;
281
282 for (auto& sta : staList)
283 {
284 if (bw == 160 && ruIndex == 3)
285 {
286 ruIndex = 1;
287 primary80 = false;
288 }
289 m_txVector.SetHeMuUserInfo (sta.first,
290 {{ruType, ruIndex++, primary80}, WifiMode ("HeMcs11"), 1});
291 }
292}
293
296{
297 NS_LOG_FUNCTION (this);
298 return DlMuInfo {m_psduMap, std::move (m_txParams)};
299}
300
303{
304 NS_LOG_FUNCTION (this);
305 return UlMuInfo {m_trigger, m_triggerHdr, std::move (m_txParams)};
306}
307
308
325{
326public:
331 {
332 uint8_t muAifsn;
333 uint16_t muCwMin;
334 uint16_t muCwMax;
335 uint8_t muTimer;
336 };
337
347 OfdmaAckSequenceTest (uint16_t width, WifiAcknowledgment::Method dlType, uint32_t maxAmpduSize,
348 uint16_t txopLimit, uint16_t nPktsPerSta,
349 MuEdcaParameterSet muEdcaParameterSet);
350 virtual ~OfdmaAckSequenceTest ();
351
358 void L7Receive (std::string context, Ptr<const Packet> p, const Address &addr);
365 void TraceCw (uint32_t staIndex, uint32_t oldCw, uint32_t cw);
373 void Transmit (std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW);
380 void CheckResults (Time sifs, Time slotTime, uint8_t aifsn);
381
382private:
383 void DoRun (void) override;
384
387 {
392 };
393
394 uint16_t m_nStations;
397 uint16_t m_channelWidth;
398 std::vector<FrameInfo> m_txPsdus;
401 uint16_t m_txopLimit;
402 uint16_t m_nPktsPerSta;
404 uint16_t m_received;
405 uint16_t m_flushed;
407 std::vector<uint32_t> m_cwValues;
408};
409
411 uint32_t maxAmpduSize, uint16_t txopLimit,
412 uint16_t nPktsPerSta,
413 MuEdcaParameterSet muEdcaParameterSet)
414 : TestCase ("Check correct operation of DL OFDMA acknowledgment sequences"),
415 m_nStations (4),
416 m_channelWidth (width),
417 m_dlMuAckType (dlType),
418 m_maxAmpduSize (maxAmpduSize),
419 m_txopLimit (txopLimit),
420 m_nPktsPerSta (nPktsPerSta),
421 m_muEdcaParameterSet (muEdcaParameterSet),
422 m_received (0),
423 m_flushed (0),
424 m_edcaDisabledStartTime (Seconds (0)),
425 m_cwValues (std::vector<uint32_t> (m_nStations, 2)) // 2 is an invalid CW value
426{
427}
428
430{
431}
432
433void
434OfdmaAckSequenceTest::L7Receive (std::string context, Ptr<const Packet> p, const Address &addr)
435{
436 if (p->GetSize () >= 1400 && Simulator::Now () > Seconds (1.5))
437 {
438 m_received++;
439 }
440}
441
442void
444{
445 if (m_cwValues.at (staIndex) == 2)
446 {
447 // store the first CW used after MU exchange (the last one may be used after
448 // the MU EDCA timer expired)
449 m_cwValues[staIndex] = cw;
450 }
451}
452
453void
454OfdmaAckSequenceTest::Transmit (std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
455{
456 // skip beacon frames and frames transmitted before 1.5s (association
457 // request/response, ADDBA request, ...)
458 if (!psduMap.begin ()->second->GetHeader (0).IsBeacon ()
459 && Simulator::Now () > Seconds (1.5))
460 {
461 Time txDuration = WifiPhy::CalculateTxDuration (psduMap, txVector, WIFI_PHY_BAND_5GHZ);
462 m_txPsdus.push_back ({Simulator::Now (),
463 Simulator::Now () + txDuration,
464 psduMap, txVector});
465
466 for (const auto& psduPair : psduMap)
467 {
468 NS_LOG_INFO ("Sending " << psduPair.second->GetHeader (0).GetTypeString ()
469 << " #MPDUs " << psduPair.second->GetNMpdus ()
470 << " txDuration " << txDuration
471 << " duration/ID " << psduPair.second->GetHeader (0).GetDuration ()
472 << " #TX PSDUs = " << m_txPsdus.size ());
473 }
474 }
475
476 // Flush the MAC queue of the AP after sending a DL MU PPDU (no need for
477 // further transmissions)
478 if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_MU)
479 {
480 auto dev = DynamicCast<WifiNetDevice> (m_apDevice);
481 Ptr<WifiMacQueue> queue = dev->GetMac ()->GetQosTxop (AC_BE)->GetWifiMacQueue ();
482 m_flushed = 0;
483 for (auto it = queue->begin (); it != queue->end (); )
484 {
485 auto tmp = it++;
486 if (!(*tmp)->IsInFlight ())
487 {
488 queue->Remove (*tmp, false);
489 m_flushed++;
490 }
491 }
492 }
493 else if (txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
494 && psduMap.begin ()->second->GetHeader (0).HasData ())
495 {
496 Mac48Address sender = psduMap.begin ()->second->GetAddr2 ();
497
498 for (uint32_t i = 0; i < m_staDevices.GetN (); i++)
499 {
500 auto dev = DynamicCast<WifiNetDevice> (m_staDevices.Get (i));
501
502 if (dev->GetAddress () == sender)
503 {
504 Ptr<QosTxop> qosTxop = dev->GetMac ()->GetQosTxop (AC_BE);
505
507 {
508 // stations use worse access parameters, trace CW. MU AIFSN must be large
509 // enough to avoid collisions between stations trying to transmit using EDCA
510 // right after the UL MU transmission and the AP trying to send a DL MU PPDU
511 qosTxop->TraceConnectWithoutContext ("CwTrace",
513 this).Bind (i));
514 }
515 else
516 {
517 // there is no "protection" against collisions from stations, hence flush
518 // their MAC queues after sending an HE TB PPDU containing QoS data frames,
519 // so that the AP can send a DL MU PPDU
520 qosTxop->GetWifiMacQueue ()->Flush ();
521 }
522 break;
523 }
524 }
525 }
526 else if (!txVector.IsMu () && psduMap.begin ()->second->GetHeader (0).IsBlockAck ()
527 && psduMap.begin ()->second->GetHeader (0).GetAddr2 () == m_apDevice->GetAddress ()
529 {
530 CtrlBAckResponseHeader blockAck;
531 psduMap.begin ()->second->GetPayload (0)->PeekHeader (blockAck);
532
533 if (blockAck.IsMultiSta ())
534 {
535 // AP is transmitting a multi-STA BlockAck and stations have to disable EDCA,
536 // record the starting time
537 m_edcaDisabledStartTime = Simulator::Now () + m_txPsdus.back ().endTx - m_txPsdus.back ().startTx;
538 }
539 }
540}
541
542void
543OfdmaAckSequenceTest::CheckResults (Time sifs, Time slotTime, uint8_t aifsn)
544{
545 CtrlTriggerHeader trigger;
546 CtrlBAckResponseHeader blockAck;
547 Time tEnd, // TX end for a frame
548 tStart, // TX start fot the next frame
549 tolerance = NanoSeconds (500), // due to propagation delay
550 ifs = (m_txopLimit > 0 ? sifs : sifs + aifsn * slotTime),
551 navEnd;
552
553 /*
554 * |--------------NAV------------------>|
555 * |------NAV------->| | |------NAV-------->|
556 * |---------| |----------| |---------| |----------| |-----------|
557 * | | |QoS Null 1| | | |QoS Data 1| | |
558 * | BSRP | |----------| | Basic | |----------| | Multi-STA |
559 * | Trigger | |QoS Null 2| | Trigger | |QoS Data 2| | Block Ack |
560 * | Frame |<SIFS>|----------|<IFS>| Frame |<SIFS>|----------|<SIFS>| |
561 * | | |QoS Null 3| | | |QoS Data 3| | |
562 * | | |----------| | | |----------| | |
563 * | | |QoS Null 4| | | |QoS Data 4| | |
564 * -----------------------------------------------------------------------------------------
565 * From: AP AP AP
566 * To: all AP all AP all
567 */
568
569 // the first packet sent after 1.5s is a BSRP Trigger Frame
570 NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 5, "Expected at least 5 transmitted packet");
571 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[0].psduMap.size () == 1
572 && m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()
573 && m_txPsdus[0].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
574 true, "Expected a Trigger Frame");
575 m_txPsdus[0].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (trigger);
576 NS_TEST_EXPECT_MSG_EQ (trigger.IsBsrp (), true, "Expected a BSRP Trigger Frame");
577 NS_TEST_EXPECT_MSG_EQ (trigger.GetNUserInfoFields (), 4, "Expected one User Info field per station");
578
579 // A first STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
580 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[1].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
581 && m_txPsdus[1].psduMap.size () == 1
582 && m_txPsdus[1].psduMap.begin ()->second->GetNMpdus () == 8),
583 true, "Expected 8 QoS Null frames in an HE TB PPDU");
584 for (uint8_t i = 0; i < 8; i++)
585 {
586 const WifiMacHeader& hdr = m_txPsdus[1].psduMap.begin ()->second->GetHeader (i);
587 NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
588 uint8_t tid = hdr.GetQosTid ();
589 if (tid == 0)
590 {
591 NS_TEST_EXPECT_MSG_GT (+hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
592 }
593 else
594 {
595 NS_TEST_EXPECT_MSG_EQ (+hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
596 }
597 }
598 tEnd = m_txPsdus[0].endTx;
599 navEnd = tEnd + m_txPsdus[0].psduMap[SU_STA_ID]->GetDuration ();
600 tStart = m_txPsdus[1].startTx;
601 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
602 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
603 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[1].endTx, "Duration/ID in BSRP Trigger Frame is too short");
604
605 // A second STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
606 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[2].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
607 && m_txPsdus[2].psduMap.size () == 1
608 && m_txPsdus[2].psduMap.begin ()->second->GetNMpdus () == 8),
609 true, "Expected 8 QoS Null frames in an HE TB PPDU");
610 for (uint8_t i = 0; i < 8; i++)
611 {
612 const WifiMacHeader& hdr = m_txPsdus[2].psduMap.begin ()->second->GetHeader (i);
613 NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
614 uint8_t tid = hdr.GetQosTid ();
615 if (tid == 0)
616 {
617 NS_TEST_EXPECT_MSG_GT (+hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
618 }
619 else
620 {
621 NS_TEST_EXPECT_MSG_EQ (+hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
622 }
623 }
624 tStart = m_txPsdus[2].startTx;
625 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
626 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
627 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[2].endTx, "Duration/ID in BSRP Trigger Frame is too short");
628
629 // A third STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
630 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[3].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
631 && m_txPsdus[3].psduMap.size () == 1
632 && m_txPsdus[3].psduMap.begin ()->second->GetNMpdus () == 8),
633 true, "Expected 8 QoS Null frames in an HE TB PPDU");
634 for (uint8_t i = 0; i < 8; i++)
635 {
636 const WifiMacHeader& hdr = m_txPsdus[3].psduMap.begin ()->second->GetHeader (i);
637 NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
638 uint8_t tid = hdr.GetQosTid ();
639 if (tid == 0)
640 {
641 NS_TEST_EXPECT_MSG_GT (+hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
642 }
643 else
644 {
645 NS_TEST_EXPECT_MSG_EQ (+hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
646 }
647 }
648 tStart = m_txPsdus[3].startTx;
649 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
650 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
651 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[3].endTx, "Duration/ID in BSRP Trigger Frame is too short");
652
653 // A fourth STA sends 8 QoS Null frames in an HE TB PPDU a SIFS after the reception of the BSRP TF
654 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[4].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
655 && m_txPsdus[4].psduMap.size () == 1
656 && m_txPsdus[4].psduMap.begin ()->second->GetNMpdus () == 8),
657 true, "Expected 8 QoS Null frames in an HE TB PPDU");
658 for (uint8_t i = 0; i < 8; i++)
659 {
660 const WifiMacHeader& hdr = m_txPsdus[4].psduMap.begin ()->second->GetHeader (i);
661 NS_TEST_EXPECT_MSG_EQ (hdr.GetType (), WIFI_MAC_QOSDATA_NULL, "Expected a QoS Null frame");
662 uint8_t tid = hdr.GetQosTid ();
663 if (tid == 0)
664 {
665 NS_TEST_EXPECT_MSG_GT (+hdr.GetQosQueueSize (), 0, "Expected a non null queue size for TID " << +tid);
666 }
667 else
668 {
669 NS_TEST_EXPECT_MSG_EQ (+hdr.GetQosQueueSize (), 0, "Expected a null queue size for TID " << +tid);
670 }
671 }
672 tStart = m_txPsdus[4].startTx;
673 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS Null frames in HE TB PPDU sent too early");
674 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS Null frames in HE TB PPDU sent too late");
675 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[4].endTx, "Duration/ID in BSRP Trigger Frame is too short");
676
677 // the AP sends a Basic Trigger Frame to solicit QoS data frames
678 NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 11, "Expected at least 11 transmitted packet");
679 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[5].psduMap.size () == 1
680 && m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()
681 && m_txPsdus[5].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
682 true, "Expected a Trigger Frame");
683 m_txPsdus[5].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (trigger);
684 NS_TEST_EXPECT_MSG_EQ (trigger.IsBasic (), true, "Expected a Basic Trigger Frame");
685 NS_TEST_EXPECT_MSG_EQ (trigger.GetNUserInfoFields (), 4, "Expected one User Info field per station");
686 tEnd = m_txPsdus[1].endTx;
687 tStart = m_txPsdus[5].startTx;
688 NS_TEST_EXPECT_MSG_LT (tEnd + ifs, tStart, "Basic Trigger Frame sent too early");
689 if (m_txopLimit > 0)
690 {
691 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Basic Trigger Frame sent too late");
692 }
693
694 // A first STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
695 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[6].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
696 && m_txPsdus[6].psduMap.size () == 1
697 && m_txPsdus[6].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
698 true, "Expected QoS data frames in an HE TB PPDU");
699 tEnd = m_txPsdus[5].endTx;
700 tStart = m_txPsdus[6].startTx;
701 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
702 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
703
704 // A second STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
705 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[7].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
706 && m_txPsdus[7].psduMap.size () == 1
707 && m_txPsdus[7].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
708 true, "Expected QoS data frames in an HE TB PPDU");
709 tEnd = m_txPsdus[5].endTx;
710 tStart = m_txPsdus[7].startTx;
711 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
712 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
713
714 // A third STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
715 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[8].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
716 && m_txPsdus[8].psduMap.size () == 1
717 && m_txPsdus[8].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
718 true, "Expected QoS data frames in an HE TB PPDU");
719 tEnd = m_txPsdus[5].endTx;
720 tStart = m_txPsdus[8].startTx;
721 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
722 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
723
724 // A fourth STA sends QoS data frames in an HE TB PPDU a SIFS after the reception of the Basic TF
725 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[9].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
726 && m_txPsdus[9].psduMap.size () == 1
727 && m_txPsdus[9].psduMap.begin ()->second->GetHeader (0).IsQosData ()),
728 true, "Expected QoS data frames in an HE TB PPDU");
729 tEnd = m_txPsdus[5].endTx;
730 tStart = m_txPsdus[9].startTx;
731 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "QoS data frames in HE TB PPDU sent too early");
732 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "QoS data frames in HE TB PPDU sent too late");
733
734 // the AP sends a Multi-STA Block Ack
735 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[10].psduMap.size () == 1
736 && m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()
737 && m_txPsdus[10].psduMap[SU_STA_ID]->GetHeader (0).GetAddr1 ().IsBroadcast ()),
738 true, "Expected a Block Ack");
739 m_txPsdus[10].psduMap[SU_STA_ID]->GetPayload (0)->PeekHeader (blockAck);
740 NS_TEST_EXPECT_MSG_EQ (blockAck.IsMultiSta (), true, "Expected a Multi-STA Block Ack");
742 "Expected one Per AID TID Info subfield per station");
743 for (uint8_t i = 0; i < 4; i++)
744 {
745 NS_TEST_EXPECT_MSG_EQ (blockAck.GetAckType (i), true, "Expected All-ack context");
746 NS_TEST_EXPECT_MSG_EQ (+blockAck.GetTidInfo (i), 14, "Expected All-ack context");
747 }
748 tEnd = m_txPsdus[9].endTx;
749 tStart = m_txPsdus[10].startTx;
750 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Multi-STA Block Ack sent too early");
751 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Multi-STA Block Ack sent too late");
752
753 navEnd = m_txPsdus[5].endTx + m_txPsdus[5].psduMap[SU_STA_ID]->GetDuration (); // Basic TF's NAV
754 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in Basic Trigger Frame is too short");
755 navEnd = m_txPsdus[6].endTx + m_txPsdus[6].psduMap.begin ()->second->GetDuration (); // 1st QoS Data frame's NAV
756 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 1st QoS Data frame is too short");
757 navEnd = m_txPsdus[7].endTx + m_txPsdus[7].psduMap.begin ()->second->GetDuration (); // 2nd QoS Data frame's NAV
758 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 2nd QoS Data frame is too short");
759 navEnd = m_txPsdus[8].endTx + m_txPsdus[8].psduMap.begin ()->second->GetDuration (); // 3rd QoS Data frame's NAV
760 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 3rd QoS Data frame is too short");
761 navEnd = m_txPsdus[9].endTx + m_txPsdus[9].psduMap.begin ()->second->GetDuration (); // 4th QoS Data frame's NAV
762 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[10].endTx, "Duration/ID in 4th QoS Data frame is too short");
763
764 // the AP sends a DL MU PPDU
765 NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 12, "Expected at least 12 transmitted packet");
766 NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].txVector.GetPreambleType (), WIFI_PREAMBLE_HE_MU,
767 "Expected a DL MU PPDU");
768 NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].psduMap.size (), 4, "Expected 4 PSDUs within the DL MU PPDU");
769 // the TX duration cannot exceed the maximum PPDU duration
770 NS_TEST_EXPECT_MSG_LT_OR_EQ (m_txPsdus[11].endTx - m_txPsdus[11].startTx,
771 GetPpduMaxTime (m_txPsdus[11].txVector.GetPreambleType ()),
772 "TX duration cannot exceed max PPDU duration");
773 for (auto& psdu : m_txPsdus[11].psduMap)
774 {
775 NS_TEST_EXPECT_MSG_LT_OR_EQ (psdu.second->GetSize (), m_maxAmpduSize, "Max A-MPDU size exceeded");
776 }
777 tEnd = m_txPsdus[10].endTx;
778 tStart = m_txPsdus[11].startTx;
779 NS_TEST_EXPECT_MSG_LT_OR_EQ (tEnd + ifs, tStart, "DL MU PPDU sent too early");
780
781 // The Duration/ID field is the same for all the PSDUs
782 navEnd = m_txPsdus[11].endTx;
783 for (auto& psdu : m_txPsdus[11].psduMap)
784 {
785 if (navEnd == m_txPsdus[11].endTx)
786 {
787 navEnd += psdu.second->GetDuration ();
788 }
789 else
790 {
791 NS_TEST_EXPECT_MSG_EQ (m_txPsdus[11].endTx + psdu.second->GetDuration (), navEnd,
792 "Duration/ID must be the same for all PSDUs");
793 }
794 }
795 NS_TEST_EXPECT_MSG_GT (navEnd, m_txPsdus[11].endTx, "Duration/ID of the DL MU PPDU cannot be zero");
796
797 std::size_t nTxPsdus = 0;
798
799 if (m_dlMuAckType == WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE)
800 {
801 /*
802 * |----------------------------------------NAV---------------------------------------------->|
803 * | |--------------------------NAV---------------------------------->|
804 * | | |-------------------NAV--------------->|
805 * | | | |----NAV---->|
806 * |------| |-----| |-----| |-----| |-----| |-----| |-----| |-----|
807 * |PSDU 1| | | | | | | | | | | | | | |
808 * |------| |Block| |Block| |Block| |Block| |Block| |Block| |Block|
809 * |PSDU 2| | Ack | | Ack | | Ack | | Ack | | Ack | | Ack | | Ack |
810 * |------|<SIFS>| |<SIFS>| Req |<SIFS>| |<SIFS>| Req |<SIFS>| |<SIFS>| Req |<SIFS>| |
811 * |PSDU 3| | | | | | | | | | | | | | |
812 * |------| | | | | | | | | | | | | | |
813 * |PSDU 4| | | | | | | | | | | | | | |
814 * ---------------------------------------------------------------------------------------------------
815 * From: AP STA 1 AP STA 2 AP STA 3 AP STA 4
816 * To: AP STA 2 AP STA 3 AP STA 4 AP
817 */
818 NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 19, "Expected at least 19 packets");
819
820 // A first STA sends a Block Ack a SIFS after the reception of the DL MU PPDU
821 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].psduMap.size () == 1
822 && m_txPsdus[12].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
823 true, "Expected a Block Ack");
824 tEnd = m_txPsdus[11].endTx;
825 tStart = m_txPsdus[12].startTx;
826 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "First Block Ack sent too early");
827 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "First Block Ack sent too late");
828
829 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
830 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].psduMap.size () == 1
831 && m_txPsdus[13].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
832 true, "Expected a Block Ack Request");
833 tEnd = m_txPsdus[12].endTx;
834 tStart = m_txPsdus[13].startTx;
835 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "First Block Ack Request sent too early");
836 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "First Block Ack Request sent too late");
837
838 // A second STA sends a Block Ack a SIFS after the reception of the Block Ack Request
839 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].psduMap.size () == 1
840 && m_txPsdus[14].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
841 true, "Expected a Block Ack");
842 tEnd = m_txPsdus[13].endTx;
843 tStart = m_txPsdus[14].startTx;
844 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Second Block Ack sent too early");
845 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Second Block Ack sent too late");
846
847 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
848 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].psduMap.size () == 1
849 && m_txPsdus[15].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
850 true, "Expected a Block Ack Request");
851 tEnd = m_txPsdus[14].endTx;
852 tStart = m_txPsdus[15].startTx;
853 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Second Block Ack Request sent too early");
854 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Second Block Ack Request sent too late");
855
856 // A third STA sends a Block Ack a SIFS after the reception of the Block Ack Request
857 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[16].psduMap.size () == 1
858 && m_txPsdus[16].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
859 true, "Expected a Block Ack");
860 tEnd = m_txPsdus[15].endTx;
861 tStart = m_txPsdus[16].startTx;
862 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Third Block Ack sent too early");
863 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Third Block Ack sent too late");
864
865 // the AP transmits a Block Ack Request an IFS after the reception of the Block Ack
866 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[17].psduMap.size () == 1
867 && m_txPsdus[17].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAckReq ()),
868 true, "Expected a Block Ack Request");
869 tEnd = m_txPsdus[16].endTx;
870 tStart = m_txPsdus[17].startTx;
871 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Third Block Ack Request sent too early");
872 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Third Block Ack Request sent too late");
873
874 // A fourth STA sends a Block Ack a SIFS after the reception of the Block Ack Request
875 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[18].psduMap.size () == 1
876 && m_txPsdus[18].psduMap[SU_STA_ID]->GetHeader (0).IsBlockAck ()),
877 true, "Expected a Block Ack");
878 tEnd = m_txPsdus[17].endTx;
879 tStart = m_txPsdus[18].startTx;
880 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Fourth Block Ack sent too early");
881 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Fourth Block Ack sent too late");
882
883 if (m_txopLimit > 0)
884 {
885 // DL MU PPDU's NAV
886 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the DL MU PPDU is too short");
887 // 1st BlockAckReq's NAV
888 navEnd = m_txPsdus[13].endTx + m_txPsdus[13].psduMap[SU_STA_ID]->GetDuration ();
889 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 1st BlockAckReq is too short");
890 // 2nd BlockAckReq's NAV
891 navEnd = m_txPsdus[15].endTx + m_txPsdus[15].psduMap[SU_STA_ID]->GetDuration ();
892 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 2nd BlockAckReq is too short");
893 // 3rd BlockAckReq's NAV
894 navEnd = m_txPsdus[17].endTx + m_txPsdus[17].psduMap[SU_STA_ID]->GetDuration ();
895 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[18].endTx, "Duration/ID in the 3rd BlockAckReq is too short");
896 }
897 nTxPsdus = 19;
898 }
899 else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_TF_MU_BAR)
900 {
901 /*
902 * |----------------NAV--------------->|
903 * | |--------NAV------>|
904 * |------| |---------| |-----------|
905 * |PSDU 1| | | |Block Ack 1|
906 * |------| | MU-BAR | |-----------|
907 * |PSDU 2| | Trigger | |Block Ack 2|
908 * |------|<SIFS>| Frame |<SIFS>|-----------|
909 * |PSDU 3| | | |Block Ack 3|
910 * |------| | | |-----------|
911 * |PSDU 4| | | |Block Ack 4|
912 * --------------------------------------------------
913 * From: AP AP
914 * To: all AP
915 */
916 NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 17, "Expected at least 17 packets");
917
918 // the AP transmits a MU-BAR Trigger Frame an IFS after the transmission of the DL MU PPDU
919 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].psduMap.size () == 1
920 && m_txPsdus[12].psduMap[SU_STA_ID]->GetHeader (0).IsTrigger ()),
921 true, "Expected a MU-BAR Trigger Frame");
922 tEnd = m_txPsdus[11].endTx;
923 tStart = m_txPsdus[12].startTx;
924 NS_TEST_EXPECT_MSG_EQ (tStart, tEnd + sifs, "MU-BAR Trigger Frame sent at wrong time");
925
926 // A first STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
927 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
928 && m_txPsdus[13].psduMap.size () == 1
929 && m_txPsdus[13].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
930 true, "Expected a Block Ack");
931 tEnd = m_txPsdus[12].endTx;
932 tStart = m_txPsdus[13].startTx;
933 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
934 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
935
936 // A second STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
937 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
938 && m_txPsdus[14].psduMap.size () == 1
939 && m_txPsdus[14].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
940 true, "Expected a Block Ack");
941 tEnd = m_txPsdus[12].endTx;
942 tStart = m_txPsdus[14].startTx;
943 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
944 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
945
946 // A third STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
947 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
948 && m_txPsdus[15].psduMap.size () == 1
949 && m_txPsdus[15].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
950 true, "Expected a Block Ack");
951 tEnd = m_txPsdus[12].endTx;
952 tStart = m_txPsdus[15].startTx;
953 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
954 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
955
956 // A fourth STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
957 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[16].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
958 && m_txPsdus[16].psduMap.size () == 1
959 && m_txPsdus[16].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
960 true, "Expected a Block Ack");
961 tEnd = m_txPsdus[12].endTx;
962 tStart = m_txPsdus[16].startTx;
963 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
964 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
965
966 if (m_txopLimit > 0)
967 {
968 // DL MU PPDU's NAV
969 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the DL MU PPDU is too short");
970 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the DL MU PPDU is too short");
971 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the DL MU PPDU is too short");
972 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[16].endTx, "Duration/ID in the DL MU PPDU is too short");
973 }
974 // MU-BAR Trigger Frame's NAV
975 navEnd = m_txPsdus[12].endTx + m_txPsdus[12].psduMap[SU_STA_ID]->GetDuration ();
976 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
977 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
978 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
979 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[16].endTx, "Duration/ID in the MU-BAR Trigger Frame is too short");
980
981 nTxPsdus = 17;
982 }
983 else if (m_dlMuAckType == WifiAcknowledgment::DL_MU_AGGREGATE_TF)
984 {
985 /*
986 * |--------NAV------>|
987 * |------|-----------| |-----------|
988 * |PSDU 1|MU-BAR TF 1| |Block Ack 1|
989 * |------------------| |-----------|
990 * |PSDU 2|MU-BAR TF 2| |Block Ack 2|
991 * |------------------|<SIFS>|-----------|
992 * |PSDU 3|MU-BAR TF 3| |Block Ack 3|
993 * |------------------| |-----------|
994 * |PSDU 4|MU-BAR TF 4| |Block Ack 4|
995 * --------------------------------------------------
996 * From: AP
997 * To: AP
998 */
999 NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus.size (), 16, "Expected at least 16 packets");
1000
1001 // The last MPDU in each PSDU is a MU-BAR Trigger Frame
1002 for (auto& psdu : m_txPsdus[11].psduMap)
1003 {
1004 NS_TEST_EXPECT_MSG_EQ ((*(--psdu.second->end ()))->GetHeader ().IsTrigger (), true,
1005 "Expected an aggregated MU-BAR Trigger Frame");
1006 }
1007
1008 // A first STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1009 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[12].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1010 && m_txPsdus[12].psduMap.size () == 1
1011 && m_txPsdus[12].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1012 true, "Expected a Block Ack");
1013 tEnd = m_txPsdus[11].endTx;
1014 tStart = m_txPsdus[12].startTx;
1015 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1016 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1017 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[12].endTx, "Duration/ID in the DL MU PPDU is too short");
1018
1019 // A second STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1020 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[13].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1021 && m_txPsdus[13].psduMap.size () == 1
1022 && m_txPsdus[13].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1023 true, "Expected a Block Ack");
1024 tEnd = m_txPsdus[11].endTx;
1025 tStart = m_txPsdus[13].startTx;
1026 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1027 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1028 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[13].endTx, "Duration/ID in the DL MU PPDU is too short");
1029
1030 // A third STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1031 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[14].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1032 && m_txPsdus[14].psduMap.size () == 1
1033 && m_txPsdus[14].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1034 true, "Expected a Block Ack");
1035 tEnd = m_txPsdus[11].endTx;
1036 tStart = m_txPsdus[14].startTx;
1037 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1038 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1039 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[14].endTx, "Duration/ID in the DL MU PPDU is too short");
1040
1041 // A fourth STA sends a Block Ack in an HE TB PPDU a SIFS after the reception of the DL MU PPDU
1042 NS_TEST_EXPECT_MSG_EQ ((m_txPsdus[15].txVector.GetPreambleType () == WIFI_PREAMBLE_HE_TB
1043 && m_txPsdus[15].psduMap.size () == 1
1044 && m_txPsdus[15].psduMap.begin ()->second->GetHeader (0).IsBlockAck ()),
1045 true, "Expected a Block Ack");
1046 tEnd = m_txPsdus[11].endTx;
1047 tStart = m_txPsdus[15].startTx;
1048 NS_TEST_EXPECT_MSG_LT (tEnd + sifs, tStart, "Block Ack in HE TB PPDU sent too early");
1049 NS_TEST_EXPECT_MSG_LT (tStart, tEnd + sifs + tolerance, "Block Ack in HE TB PPDU sent too late");
1050 NS_TEST_EXPECT_MSG_GT_OR_EQ (navEnd + tolerance, m_txPsdus[15].endTx, "Duration/ID in the DL MU PPDU is too short");
1051
1052 nTxPsdus = 16;
1053 }
1054
1056 "Not all DL packets have been received");
1057
1059 {
1060 // EDCA disabled, find the first PSDU transmitted by a station not in an
1061 // HE TB PPDU and check that it was not transmitted before the MU EDCA
1062 // timer expired
1063 for (std::size_t i = nTxPsdus; i < m_txPsdus.size (); ++i)
1064 {
1065 if (m_txPsdus[i].psduMap.size () == 1
1066 && m_txPsdus[i].psduMap.begin ()->second->GetHeader (0).GetAddr2 () != m_apDevice->GetAddress ()
1067 && !m_txPsdus[i].txVector.IsUlMu ())
1068 {
1069 NS_TEST_EXPECT_MSG_GT_OR_EQ (m_txPsdus[i].startTx.GetMicroSeconds (),
1072 "A station transmitted before the MU EDCA timer expired");
1073 break;
1074 }
1075 }
1076 }
1078 {
1079 // stations used worse access parameters after successful UL MU transmission
1080 for (const auto& cwValue : m_cwValues)
1081 {
1082 NS_TEST_EXPECT_MSG_EQ ((cwValue == 2 || cwValue >= m_muEdcaParameterSet.muCwMin),
1083 true, "A station did not set the correct MU CW min");
1084 }
1085 }
1086
1087 m_txPsdus.clear ();
1088}
1089
1090void
1092{
1093 RngSeedManager::SetSeed (1);
1094 RngSeedManager::SetRun (1);
1095 int64_t streamNumber = 20;
1096
1098 wifiApNode.Create (1);
1099
1101 wifiStaNodes.Create (m_nStations);
1102
1103 Ptr<MultiModelSpectrumChannel> spectrumChannel = CreateObject<MultiModelSpectrumChannel> ();
1104 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel> ();
1105 spectrumChannel->AddPropagationLossModel (lossModel);
1106 Ptr<ConstantSpeedPropagationDelayModel> delayModel = CreateObject<ConstantSpeedPropagationDelayModel> ();
1107 spectrumChannel->SetPropagationDelayModel (delayModel);
1108
1110 phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO);
1111 phy.SetErrorRateModel ("ns3::NistErrorRateModel");
1112 phy.SetChannel (spectrumChannel);
1113 switch (m_channelWidth)
1114 {
1115 case 20:
1116 phy.Set ("ChannelSettings", StringValue ("{36, 20, BAND_5GHZ, 0}"));
1117 break;
1118 case 40:
1119 phy.Set ("ChannelSettings", StringValue ("{38, 40, BAND_5GHZ, 0}"));
1120 break;
1121 case 80:
1122 phy.Set ("ChannelSettings", StringValue ("{42, 80, BAND_5GHZ, 0}"));
1123 break;
1124 case 160:
1125 phy.Set ("ChannelSettings", StringValue ("{50, 160, BAND_5GHZ, 0}"));
1126 break;
1127 default:
1128 NS_ABORT_MSG ("Invalid channel bandwidth (must be 20, 40, 80 or 160)");
1129 }
1130
1131 Config::SetDefault ("ns3::HeConfiguration::MuBeAifsn",
1133 Config::SetDefault ("ns3::HeConfiguration::MuBeCwMin",
1135 Config::SetDefault ("ns3::HeConfiguration::MuBeCwMax",
1137 Config::SetDefault ("ns3::HeConfiguration::BeMuEdcaTimer",
1139 // MU EDCA timers must be either all null or all non-null
1140 Config::SetDefault ("ns3::HeConfiguration::BkMuEdcaTimer",
1142 Config::SetDefault ("ns3::HeConfiguration::ViMuEdcaTimer",
1144 Config::SetDefault ("ns3::HeConfiguration::VoMuEdcaTimer",
1146
1147 // increase MSDU lifetime so that it does not expire before the MU EDCA timer ends
1148 Config::SetDefault ("ns3::WifiMacQueue::MaxDelay", TimeValue (Seconds (2)));
1149
1151 wifi.SetStandard (WIFI_STANDARD_80211ax);
1152 wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
1153
1155 Ssid ssid = Ssid ("ns-3-ssid");
1156 mac.SetType ("ns3::StaWifiMac",
1157 "BE_MaxAmsduSize", UintegerValue (0),
1158 "BE_MaxAmpduSize", UintegerValue (0),
1159 "Ssid", SsidValue (ssid),
1160 /* setting blockack threshold for sta's BE queue */
1161 "BE_BlockAckThreshold", UintegerValue (2),
1162 "ActiveProbing", BooleanValue (false));
1163
1164 m_staDevices = wifi.Install (phy, mac, wifiStaNodes);
1165
1166 mac.SetType ("ns3::ApWifiMac",
1167 "BE_MaxAmsduSize", UintegerValue (0),
1168 "BE_MaxAmpduSize", UintegerValue (0),
1169 "Ssid", SsidValue (ssid),
1170 "BeaconGeneration", BooleanValue (true));
1171 mac.SetMultiUserScheduler ("ns3::TestMultiUserScheduler");
1172 mac.SetAckManager ("ns3::WifiDefaultAckManager", "DlMuAckSequenceType", EnumValue (m_dlMuAckType));
1173
1174 m_apDevice = wifi.Install (phy, mac, wifiApNode).Get (0);
1175
1176 // Assign fixed streams to random variables in use
1177 streamNumber += wifi.AssignStreams (NetDeviceContainer (m_apDevice), streamNumber);
1178 streamNumber += wifi.AssignStreams (m_staDevices, streamNumber);
1179
1181 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
1182
1183 positionAlloc->Add (Vector (0.0, 0.0, 0.0));
1184 positionAlloc->Add (Vector (1.0, 0.0, 0.0));
1185 positionAlloc->Add (Vector (0.0, 1.0, 0.0));
1186 positionAlloc->Add (Vector (-1.0, 0.0, 0.0));
1187 positionAlloc->Add (Vector (-1.0, -1.0, 0.0));
1188 mobility.SetPositionAllocator (positionAlloc);
1189
1190 mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
1191 mobility.Install (wifiApNode);
1192 mobility.Install (wifiStaNodes);
1193
1195
1196 // Set maximum A-MPDU size
1197 for (uint32_t i = 0; i < m_staDevices.GetN (); i++)
1198 {
1199 dev = DynamicCast<WifiNetDevice> (m_staDevices.Get (i));
1200 dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (m_maxAmpduSize));
1201 }
1202 dev = DynamicCast<WifiNetDevice> (m_apDevice);
1203 dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (m_maxAmpduSize));
1204
1205 PointerValue ptr;
1206 dev->GetMac ()->GetAttribute ("BE_Txop", ptr);
1207 Ptr<QosTxop> apBeQosTxop = ptr.Get<QosTxop> ();
1208 // set the TXOP limit on BE AC
1209 apBeQosTxop->SetTxopLimit (MicroSeconds (m_txopLimit));
1210
1211 PacketSocketHelper packetSocket;
1212 packetSocket.Install (wifiApNode);
1213 packetSocket.Install (wifiStaNodes);
1214
1215 // DL Traffic
1216 for (uint16_t i = 0; i < m_nStations; i++)
1217 {
1218 PacketSocketAddress socket;
1221 socket.SetProtocol (1);
1222
1223 // the first client application generates two packets in order
1224 // to trigger the establishment of a Block Ack agreement
1225 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
1226 client1->SetAttribute ("PacketSize", UintegerValue (1400));
1227 client1->SetAttribute ("MaxPackets", UintegerValue (2));
1228 client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1229 client1->SetRemote (socket);
1230 wifiApNode.Get (0)->AddApplication (client1);
1231 client1->SetStartTime (Seconds (1) + i * MilliSeconds (1));
1232 client1->SetStopTime (Seconds (2.0));
1233
1234 // the second client application generates the selected number of packets,
1235 // which are sent in DL MU PPDUs.
1236 Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
1237 client2->SetAttribute ("PacketSize", UintegerValue (1400 + i * 100));
1238 client2->SetAttribute ("MaxPackets", UintegerValue (m_nPktsPerSta));
1239 client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1240 client2->SetRemote (socket);
1241 wifiApNode.Get (0)->AddApplication (client2);
1242 client2->SetStartTime (Seconds (1.5));
1243 client2->SetStopTime (Seconds (2.5));
1244
1245 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
1246 server->SetLocal (socket);
1247 wifiStaNodes.Get (i)->AddApplication (server);
1248 server->SetStartTime (Seconds (0.0));
1249 server->SetStopTime (Seconds (3.0));
1250 }
1251
1252 // UL Traffic
1253 for (uint16_t i = 0; i < m_nStations; i++)
1254 {
1255 PacketSocketAddress socket;
1256 socket.SetSingleDevice (m_staDevices.Get (i)->GetIfIndex ());
1258 socket.SetProtocol (1);
1259
1260 // the first client application generates two packets in order
1261 // to trigger the establishment of a Block Ack agreement
1262 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient> ();
1263 client1->SetAttribute ("PacketSize", UintegerValue (1400));
1264 client1->SetAttribute ("MaxPackets", UintegerValue (2));
1265 client1->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1266 client1->SetRemote (socket);
1267 wifiStaNodes.Get (i)->AddApplication (client1);
1268 client1->SetStartTime (Seconds (1.005) + i * MilliSeconds (1));
1269 client1->SetStopTime (Seconds (2.0));
1270
1271 // the second client application generates the selected number of packets,
1272 // which are sent in HE TB PPDUs.
1273 Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient> ();
1274 client2->SetAttribute ("PacketSize", UintegerValue (1400 + i * 100));
1275 client2->SetAttribute ("MaxPackets", UintegerValue (m_nPktsPerSta));
1276 client2->SetAttribute ("Interval", TimeValue (MicroSeconds (0)));
1277 client2->SetRemote (socket);
1278 wifiStaNodes.Get (i)->AddApplication (client2);
1279 client2->SetStartTime (Seconds (1.50011)); // start before sending QoS Null frames
1280 client2->SetStopTime (Seconds (2.5));
1281
1282 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer> ();
1283 server->SetLocal (socket);
1284 wifiApNode.Get (0)->AddApplication (server);
1285 server->SetStartTime (Seconds (0.0));
1286 server->SetStopTime (Seconds (3.0));
1287 }
1288
1289 Config::Connect ("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
1291 // Trace PSDUs passed to the PHY on all devices
1292 Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
1294
1295 Simulator::Stop (Seconds (3));
1296 Simulator::Run ();
1297
1298 CheckResults (dev->GetMac ()->GetWifiPhy ()->GetSifs (), dev->GetMac ()->GetWifiPhy ()->GetSlot (),
1299 apBeQosTxop->GetAifsn ());
1300
1301 Simulator::Destroy ();
1302}
1303
1304
1312{
1313public:
1315};
1316
1318 : TestSuite ("wifi-mac-ofdma", UNIT)
1319{
1320 using MuEdcaParams = std::initializer_list<OfdmaAckSequenceTest::MuEdcaParameterSet>;
1321
1322 for (auto& muEdcaParameterSet : MuEdcaParams {{0, 0, 0, 0} /* no MU EDCA */,
1323 {0, 127, 2047, 100} /* EDCA disabled */,
1324 {10, 127, 2047, 100} /* worse parameters */})
1325 {
1326 AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1327 AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_AGGREGATE_TF, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1328 AddTestCase (new OfdmaAckSequenceTest (20, WifiAcknowledgment::DL_MU_TF_MU_BAR, 10000, 5440, 15, muEdcaParameterSet), TestCase::QUICK);
1329 AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_BAR_BA_SEQUENCE, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1330 AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_AGGREGATE_TF, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1331 AddTestCase (new OfdmaAckSequenceTest (40, WifiAcknowledgment::DL_MU_TF_MU_BAR, 10000, 0, 15, muEdcaParameterSet), TestCase::QUICK);
1332 }
1333}
1334
#define Min(a, b)
Test OFDMA acknowledgment sequences.
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
Time m_edcaDisabledStartTime
time when disabling EDCA started
uint16_t m_flushed
number of DL packets flushed after DL MU PPDU
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when FrameExchangeManager passes PSDUs to the PHY.
OfdmaAckSequenceTest(uint16_t width, WifiAcknowledgment::Method dlType, uint32_t maxAmpduSize, uint16_t txopLimit, uint16_t nPktsPerSta, MuEdcaParameterSet muEdcaParameterSet)
Constructor.
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.
Ptr< NetDevice > m_apDevice
AP's device.
uint16_t m_nPktsPerSta
number of packets to send to each station
NetDeviceContainer m_staDevices
stations' devices
uint16_t m_txopLimit
TXOP limit in microseconds.
void L7Receive(std::string context, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
uint16_t m_channelWidth
PHY channel bandwidth in MHz.
uint32_t m_maxAmpduSize
maximum A-MPDU size in bytes
std::vector< uint32_t > m_cwValues
CW used by stations after MU exchange.
void DoRun(void) override
Implementation to actually run this TestCase.
void TraceCw(uint32_t staIndex, uint32_t oldCw, uint32_t cw)
Function to trace CW value used by the given station after the MU exchange.
uint16_t m_nStations
number of stations
MuEdcaParameterSet m_muEdcaParameterSet
MU EDCA Parameter Set.
Dummy Multi User Scheduler used to test OFDMA ack sequences.
TxFormat SelectTxFormat(void) override
Select the format of the next transmission.
WifiPsduMap m_psduMap
the DL MU PPDU to transmit
TxFormat m_txFormat
the format of next transmission
WifiTxVector m_txVector
the TX vector for MU PPDUs
UlMuInfo ComputeUlMuInfo(void) override
Prepare the information required to solicit an UL MU transmission.
static TypeId GetTypeId(void)
Get the type ID.
TriggerFrameType m_ulTriggerType
Trigger Frame type for UL MU.
WifiTxParameters m_txParams
TX parameters.
DlMuInfo ComputeDlMuInfo(void) override
Compute the information required to perform a DL MU transmission.
void ComputeWifiTxVector(void)
Compute the TX vector to use for MU PPDUs.
WifiMacHeader m_triggerHdr
MAC header for Trigger Frame.
CtrlTriggerHeader m_trigger
Trigger Frame to send.
wifi MAC OFDMA Test Suite
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Headers for BlockAck response.
Definition: ctrl-headers.h:202
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...
std::size_t GetNPerAidTidInfoSubfields(void) const
For Multi-STA Block Acks, get the number of Per AID TID Info subfields included in this Block Ack.
bool IsMultiSta(void) const
Check if the BlockAck frame variant is Multi-STA Block Ack.
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...
Headers for Trigger frames.
Definition: ctrl-headers.h:886
ConstIterator begin(void) const
Get a const iterator pointing to the first User Info field in the list.
bool IsBsrp(void) const
Check if this is a Buffer Status Report Poll 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...
std::size_t GetNUserInfoFields(void) const
Get the number of User Info fields in this Trigger Frame.
bool IsBasic(void) const
Check if this is a Basic Trigger frame.
void SetUlLength(uint16_t len)
Set the UL Length subfield of the Common Info field.
uint16_t GetGuardInterval(void) const
Get the guard interval duration (in nanoseconds) of the solicited HE TB PPDU.
Hold variables of type enum.
Definition: enum.h:55
RuType
The different HE Resource Unit (RU) types.
Definition: he-ru.h:42
an EUI-48 address
Definition: mac48-address.h:44
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< HeFrameExchangeManager > m_heFem
HE Frame Exchange Manager.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(void) const
Get the station manager attached to the AP.
uint32_t m_sizeOf8QosNull
size in bytes of 8 QoS Null frames
TxFormat
Enumeration of the possible transmission formats.
holds a vector of ns3::NetDevice pointers
uint32_t GetN(void) 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.
virtual Address GetAddress(void) const =0
virtual uint32_t GetIfIndex(void) const =0
keep track of a set of node pointers.
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:364
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
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.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get(void) const
Definition: pointer.h:201
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:72
uint8_t GetAifsn(void) const override
Return the number of slots that make up an AIFS according to the EDCA Parameter Set or the MU EDCA Pa...
Definition: qos-txop.cc:233
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:41
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
int64_t GetMicroSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:387
AttributeValue implementation for Time.
Definition: nstime.h:1308
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
Definition: txop.cc:154
void SetTxopLimit(Time txopLimit)
Set the TXOP limit.
Definition: txop.cc:254
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
helps to create WifiNetDevice objects
Definition: wifi-helper.h:323
Implements the IEEE 802.11 MAC header.
void SetDsNotFrom(void)
Un-set the From DS bit in the Frame Control field.
uint8_t GetQosTid(void) const
Return the Traffic ID of a QoS header.
uint8_t GetQosQueueSize(void) const
Get the Queue Size subfield in the QoS control field.
void SetAddr1(Mac48Address address)
Fill the Address 1 field with the given address.
void SetDsNotTo(void)
Un-set the To DS bit in the Frame Control field.
Mac48Address GetAddr1(void) const
Return the address in the Address 1 field.
void SetAddr2(Mac48Address address)
Fill the Address 2 field with the given address.
WifiMacType GetType(void) const
Return the type (enum WifiMacType)
create MAC layers for a ns3::WifiNetDevice.
represent a single transmission mode
Definition: wifi-mode.h:48
Ptr< WifiMac > GetMac(void) const
This class stores the TX parameters (TX vector, protection mechanism, acknowledgment mechanism,...
void Clear(void)
Reset the TX parameters.
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.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetTxPowerLevel(uint8_t powerlevel)
Sets the selected transmission power level.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
WifiPreamble GetPreambleType(void) const
bool IsMu(void) const
Return true if this TX vector is used for a multi-user transmission.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:849
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
#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:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#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:281
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
#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:935
#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:785
#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:748
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
Definition: test.h:899
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:240
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1268
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
TriggerFrameType
The different Trigger frame types.
Definition: ctrl-headers.h:561
@ WIFI_STANDARD_80211ax
@ WIFI_PREAMBLE_HE_TB
@ WIFI_PREAMBLE_HE_MU
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
@ AC_BE
Best Effort.
Definition: qos-utils.h:73
@ BASIC_TRIGGER
Definition: ctrl-headers.h:562
@ BSRP_TRIGGER
Definition: ctrl-headers.h:566
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.
@ WIFI_MAC_CTL_TRIGGER
@ WIFI_MAC_QOSDATA_NULL
std::unordered_map< uint16_t, Ptr< WifiPsdu > > WifiPsduMap
Map of PSDUs indexed by STA-ID.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
STL namespace.
ssid
Definition: third.py:97
mac
Definition: third.py:96
wifi
Definition: third.py:99
wifiApNode
Definition: third.py:90
mobility
Definition: third.py:107
wifiStaNodes
Definition: third.py:88
phy
Definition: third.py:93
Information about transmitted frames.
WifiConstPsduMap psduMap
transmitted PSDU map
uint8_t muAifsn
MU AIFS (0 to disable EDCA)
uint8_t muTimer
MU EDCA Timer in units of 8192 microseconds (0 not to use MU EDCA)
Information to be provided in case of DL MU transmission.
Information to be provided in case of UL MU transmission.
Method
Available acknowledgment methods.
static WifiMacOfdmaTestSuite g_wifiMacOfdmaTestSuite
the test suite
#define SU_STA_ID
Definition: wifi-mode.h:32