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"
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"
99 TypeId(
"ns3::TestMultiUserScheduler")
101 .SetGroupName(
"Wifi")
103 .AddAttribute(
"ModulationClass",
104 "Modulation class for DL MU PPDUs and TB PPDUs.",
143 : TriggerFrameType::BASIC_TRIGGER);
152 uint32_t ampduSize = (ulTriggerType == TriggerFrameType::BSRP_TRIGGER)
158 for (
auto it = staList.begin(); it != staList.end();)
166 staList.begin()->first);
198 NS_LOG_DEBUG(
"Remaining TXOP duration is not enough for BSRP TF exchange");
211 for (
auto it = staList.cbegin(); it != staList.cend();)
215 NS_ABORT_MSG_IF(staList.size() != 4,
"There must be 4 associated stations");
221 for (
auto& sta : staList)
226 for (tid = 0; tid < 8; tid++)
248 NS_LOG_DEBUG(
"Not enough time to send frames to all the stations");
252 std::vector<Ptr<WifiMpdu>> mpduList;
254 ->GetMpduAggregator()
257 if (mpduList.size() > 1)
259 m_psduMap[sta.first] = Create<WifiPsdu>(std::move(mpduList));
263 m_psduMap[sta.first] = Create<WifiPsdu>(mpdu,
true);
308 for (
auto it = staList.cbegin(); it != staList.cend();)
312 NS_ABORT_MSG_IF(staList.size() != 4,
"There must be 4 associated stations");
337 bool primary80 =
true;
338 std::size_t ruIndex = 1;
340 for (
auto& sta : staList)
342 if (bw == 160 && ruIndex == 3)
422 uint16_t nPktsPerSta,
460 void DoRun()
override;
499 uint16_t nPktsPerSta,
502 :
TestCase(
"Check correct operation of DL OFDMA acknowledgment sequences"),
504 m_sockets(m_nStations),
505 m_channelWidth(width),
506 m_dlMuAckType(dlType),
507 m_maxAmpduSize(maxAmpduSize),
508 m_txopLimit(txopLimit),
509 m_nPktsPerSta(nPktsPerSta),
510 m_muEdcaParameterSet(muEdcaParameterSet),
511 m_scenario(scenario),
512 m_ulPktsGenerated(false),
515 m_edcaDisabledStartTime(
Seconds(0)),
520 case WifiOfdmaScenario::HE:
521 case WifiOfdmaScenario::HE_EHT:
525 case WifiOfdmaScenario::EHT:
589 for (
const auto& [staId, psdu] : psduMap)
592 << psdu->GetHeader(0).GetTypeString() <<
" #MPDUs " << psdu->GetNMpdus()
593 << (psdu->GetHeader(0).IsQosData()
594 ?
" TID " + std::to_string(*psdu->GetTids().begin())
596 << std::setprecision(10) <<
" txDuration " << txDuration <<
" duration/ID "
597 << psdu->GetHeader(0).GetDuration() <<
" #TX PSDUs = " <<
m_txPsdus.size()
598 <<
" size=" << (*psdu->begin())->GetSize() <<
"\n"
599 <<
"TXVECTOR: " << txVector <<
"\n");
616 while ((mpdu = queue->PeekByTidAndAddress(i * 2,
617 staDev->GetMac()->GetAddress(),
618 lastInFlight)) !=
nullptr)
620 if (mpdu->IsInFlight())
633 psduMap.begin()->second->GetHeader(0).HasData())
635 Mac48Address sender = psduMap.begin()->second->GetAddr2();
641 if (dev->GetAddress() == sender)
650 qosTxop->TraceConnectWithoutContext(
659 qosTxop->GetWifiMacQueue()->Flush();
665 else if (!txVector.
IsMu() && psduMap.begin()->second->GetHeader(0).IsBlockAck() &&
670 psduMap.begin()->second->GetPayload(0)->PeekHeader(blockAck);
680 else if (!txVector.
IsMu() && psduMap.begin()->second->GetHeader(0).IsTrigger() &&
684 psduMap.
begin()->second->GetPayload(0)->PeekHeader(trigger);
693 client->SetAttribute(
"PacketSize",
UintegerValue(1400 + i * 100));
699 client->SetStartTime(txDuration);
700 client->SetStopTime(
Seconds(1.0));
701 client->Initialize();
746 "Expected a Trigger Frame");
751 "Expected one User Info field per station");
754 "Expected the MU-RTS to occupy the entire channel width");
755 for (
const auto& userInfo : trigger)
759 "Unexpected RU Allocation value in MU-RTS");
768 m_txPsdus[1].psduMap.begin()->second->GetNMpdus() == 1 &&
771 "Expected a CTS frame");
774 "Expected the CTS to occupy the entire channel width");
788 m_txPsdus[2].psduMap.begin()->second->GetNMpdus() == 1 &&
791 "Expected a CTS frame");
794 "Expected the CTS to occupy the entire channel width");
808 m_txPsdus[3].psduMap.begin()->second->GetNMpdus() == 1 &&
811 "Expected a CTS frame");
814 "Expected the CTS to occupy the entire channel width");
828 m_txPsdus[4].psduMap.begin()->second->GetNMpdus() == 1 &&
831 "Expected a CTS frame");
834 "Expected the CTS to occupy the entire channel width");
850 "Expected a Trigger Frame");
855 "Expected one User Info field per station");
868 m_txPsdus[6].psduMap.begin()->second->GetNMpdus() == 1),
870 "Expected a QoS Null frame in a TB PPDU");
883 uint8_t tid = staId * 2;
890 tEnd + sifs + tolerance,
891 "QoS Null frame in HE TB PPDU sent too late");
897 "Expected null Duration/ID for QoS Null frame in HE TB PPDU");
906 m_txPsdus[7].psduMap.begin()->second->GetNMpdus() == 1),
908 "Expected a QoS Null frame in a TB PPDU");
921 uint8_t tid = staId * 2;
927 tEnd + sifs + tolerance,
928 "QoS Null frame in HE TB PPDU sent too late");
929 qosNullNavEnd =
m_txPsdus[7].endTx +
m_txPsdus[7].psduMap.begin()->second->GetDuration();
934 "Expected null Duration/ID for QoS Null frame in HE TB PPDU");
943 m_txPsdus[8].psduMap.begin()->second->GetNMpdus() == 1),
945 "Expected a QoS Null frame in an HE TB PPDU");
958 uint8_t tid = staId * 2;
964 tEnd + sifs + tolerance,
965 "QoS Null frame in HE TB PPDU sent too late");
966 qosNullNavEnd =
m_txPsdus[8].endTx +
m_txPsdus[8].psduMap.begin()->second->GetDuration();
971 "Expected null Duration/ID for QoS Null frame in HE TB PPDU");
980 m_txPsdus[9].psduMap.begin()->second->GetNMpdus() == 1),
982 "Expected a QoS Null frame in an HE TB PPDU");
995 uint8_t tid = staId * 2;
1001 tEnd + sifs + tolerance,
1002 "QoS Null frame in HE TB PPDU sent too late");
1003 qosNullNavEnd =
m_txPsdus[9].endTx +
m_txPsdus[9].psduMap.begin()->second->GetDuration();
1008 "Expected null Duration/ID for QoS Null frame in HE TB PPDU");
1034 "Expected at least 15 transmitted packet");
1040 "Expected a Trigger Frame");
1045 "Expected one User Info field per station");
1048 "Expected the MU-RTS to occupy the entire channel width");
1049 for (
const auto& userInfo : trigger)
1053 "Unexpected RU Allocation value in MU-RTS");
1064 m_txPsdus[11].psduMap.begin()->second->GetNMpdus() == 1 &&
1067 "Expected a CTS frame");
1070 "Expected the CTS to occupy the entire channel width");
1080 "Duration/ID in CTS frame is too long");
1086 m_txPsdus[12].psduMap.begin()->second->GetNMpdus() == 1 &&
1089 "Expected a CTS frame");
1092 "Expected the CTS to occupy the entire channel width");
1102 "Duration/ID in CTS frame is too long");
1108 m_txPsdus[13].psduMap.begin()->second->GetNMpdus() == 1 &&
1111 "Expected a CTS frame");
1114 "Expected the CTS to occupy the entire channel width");
1124 "Duration/ID in CTS frame is too long");
1130 m_txPsdus[14].psduMap.begin()->second->GetNMpdus() == 1 &&
1133 "Expected a CTS frame");
1136 "Expected the CTS to occupy the entire channel width");
1146 "Duration/ID in CTS frame is too long");
1164 "Expected a Trigger Frame");
1169 "Expected one User Info field per station");
1181 m_txPsdus[16].psduMap.begin()->second->GetNMpdus() == 2 &&
1182 m_txPsdus[16].psduMap.begin()->second->GetHeader(0).IsQosData() &&
1183 m_txPsdus[16].psduMap.begin()->second->GetHeader(1).IsQosData()),
1185 "Expected 2 QoS data frames in an HE TB PPDU");
1190 tEnd + sifs + tolerance,
1191 "QoS data frames in HE TB PPDU sent too late");
1200 m_txPsdus[17].psduMap.begin()->second->GetNMpdus() == 2 &&
1201 m_txPsdus[17].psduMap.begin()->second->GetHeader(0).IsQosData() &&
1202 m_txPsdus[17].psduMap.begin()->second->GetHeader(1).IsQosData()),
1204 "Expected 2 QoS data frames in an HE TB PPDU");
1208 tEnd + sifs + tolerance,
1209 "QoS data frames in HE TB PPDU sent too late");
1210 qosDataNavEnd =
m_txPsdus[17].endTx +
m_txPsdus[17].psduMap.begin()->second->GetDuration();
1218 m_txPsdus[18].psduMap.begin()->second->GetNMpdus() == 2 &&
1219 m_txPsdus[18].psduMap.begin()->second->GetHeader(0).IsQosData() &&
1220 m_txPsdus[18].psduMap.begin()->second->GetHeader(1).IsQosData()),
1222 "Expected 2 QoS data frames in an HE TB PPDU");
1226 tEnd + sifs + tolerance,
1227 "QoS data frames in HE TB PPDU sent too late");
1228 qosDataNavEnd =
m_txPsdus[18].endTx +
m_txPsdus[18].psduMap.begin()->second->GetDuration();
1236 m_txPsdus[19].psduMap.begin()->second->GetNMpdus() == 2 &&
1237 m_txPsdus[19].psduMap.begin()->second->GetHeader(0).IsQosData() &&
1238 m_txPsdus[19].psduMap.begin()->second->GetHeader(1).IsQosData()),
1240 "Expected 2 QoS data frames in an HE TB PPDU");
1244 tEnd + sifs + tolerance,
1245 "QoS data frames in HE TB PPDU sent too late");
1246 qosDataNavEnd =
m_txPsdus[19].endTx +
m_txPsdus[19].psduMap.begin()->second->GetDuration();
1256 "Expected a Block Ack");
1261 "Expected one Per AID TID Info subfield per station");
1262 for (uint8_t i = 0; i < 4; i++)
1275 "Duration/ID in Multi-STA BlockAck is too short");
1278 "Duration/ID in Multi-STA BlockAck is too long");
1287 "Expected at least 26 transmitted packet");
1293 "Expected a Trigger Frame");
1298 "Expected one User Info field per station");
1301 "Expected the MU-RTS to occupy the entire channel width");
1302 for (
const auto& userInfo : trigger)
1306 "Unexpected RU Allocation value in MU-RTS");
1318 m_txPsdus[22].psduMap.begin()->second->GetNMpdus() == 1 &&
1321 "Expected a CTS frame");
1324 "Expected the CTS to occupy the entire channel width");
1334 "Duration/ID in CTS frame is too long");
1340 m_txPsdus[23].psduMap.begin()->second->GetNMpdus() == 1 &&
1343 "Expected a CTS frame");
1346 "Expected the CTS to occupy the entire channel width");
1356 "Duration/ID in CTS frame is too long");
1362 m_txPsdus[24].psduMap.begin()->second->GetNMpdus() == 1 &&
1365 "Expected a CTS frame");
1368 "Expected the CTS to occupy the entire channel width");
1378 "Duration/ID in CTS frame is too long");
1384 m_txPsdus[25].psduMap.begin()->second->GetNMpdus() == 1 &&
1387 "Expected a CTS frame");
1390 "Expected the CTS to occupy the entire channel width");
1400 "Duration/ID in CTS frame is too long");
1416 "Expected a DL MU PPDU");
1419 "Expected 4 PSDUs within the DL MU PPDU");
1423 "TX duration cannot exceed max PPDU duration");
1424 for (
auto& psdu :
m_txPsdus[26].psduMap)
1428 "Max A-MPDU size exceeded");
1436 for (
auto& psdu :
m_txPsdus[26].psduMap)
1440 dlMuNavEnd += psdu.second->GetDuration();
1446 "Duration/ID must be the same for all PSDUs");
1453 std::size_t nTxPsdus = 0;
1485 "Expected a Block Ack");
1496 "Duration/ID in 1st BlockAck frame is too short");
1499 "Duration/ID in 1st BlockAck is too long");
1505 "Expected a Block Ack Request");
1510 tEnd + sifs + tolerance,
1511 "First Block Ack Request sent too late");
1521 "Duration/ID in BlockAckReq is too short");
1524 "Duration/ID in BlockAckReq is too long");
1531 "Expected a Block Ack");
1543 "Duration/ID in BlockAck is too long");
1550 "Duration/ID in BlockAck is too short");
1552 barNavEnd + tolerance,
1553 "Duration/ID in BlockAck is too long");
1556 "Expected null Duration/ID for BlockAck");
1563 "Expected a Block Ack Request");
1568 tEnd + sifs + tolerance,
1569 "Second Block Ack Request sent too late");
1579 "Duration/ID in BlockAckReq is too short");
1582 "Duration/ID in BlockAckReq is too long");
1589 "Expected a Block Ack");
1601 "Duration/ID in BlockAck is too long");
1608 "Duration/ID in BlockAck is too short");
1610 barNavEnd + tolerance,
1611 "Duration/ID in BlockAck is too long");
1614 "Expected null Duration/ID for BlockAck");
1621 "Expected a Block Ack Request");
1626 tEnd + sifs + tolerance,
1627 "Third Block Ack Request sent too late");
1637 "Duration/ID in BlockAckReq is too short");
1640 "Duration/ID in BlockAckReq is too long");
1647 "Expected a Block Ack");
1659 "Duration/ID in BlockAck is too long");
1666 "Duration/ID in BlockAck is too short");
1668 barNavEnd + tolerance,
1669 "Duration/ID in BlockAck is too long");
1672 "Expected null Duration/ID for BlockAck");
1702 "Expected a MU-BAR Trigger Frame");
1710 "Duration/ID in MU-BAR Trigger Frame is too short");
1713 "Duration/ID in MU-BAR Trigger Frame is too long");
1718 m_txPsdus[28].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1720 "Expected a Block Ack");
1725 tEnd + sifs + tolerance,
1726 "Block Ack in HE TB PPDU sent too late");
1735 "Expected null Duration/ID for BlockAck");
1741 m_txPsdus[29].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1743 "Expected a Block Ack");
1747 tEnd + sifs + tolerance,
1748 "Block Ack in HE TB PPDU sent too late");
1749 baNavEnd =
m_txPsdus[29].endTx +
m_txPsdus[29].psduMap.begin()->second->GetDuration();
1754 "Duration/ID in 1st BlockAck is too long");
1759 "Expected null Duration/ID for BlockAck");
1765 m_txPsdus[30].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1767 "Expected a Block Ack");
1771 tEnd + sifs + tolerance,
1772 "Block Ack in HE TB PPDU sent too late");
1773 baNavEnd =
m_txPsdus[30].endTx +
m_txPsdus[30].psduMap.begin()->second->GetDuration();
1778 "Duration/ID in 1st BlockAck is too long");
1783 "Expected null Duration/ID for BlockAck");
1789 m_txPsdus[31].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1791 "Expected a Block Ack");
1795 tEnd + sifs + tolerance,
1796 "Block Ack in HE TB PPDU sent too late");
1797 baNavEnd =
m_txPsdus[31].endTx +
m_txPsdus[31].psduMap.begin()->second->GetDuration();
1802 "Duration/ID in 1st BlockAck is too long");
1807 "Expected null Duration/ID for BlockAck");
1833 for (
auto& psdu :
m_txPsdus[26].psduMap)
1837 "Expected an aggregated MU-BAR Trigger Frame");
1843 m_txPsdus[27].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1845 "Expected a Block Ack");
1850 tEnd + sifs + tolerance,
1851 "Block Ack in HE TB PPDU sent too late");
1860 "Expected null Duration/ID for BlockAck");
1866 m_txPsdus[28].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1868 "Expected a Block Ack");
1872 tEnd + sifs + tolerance,
1873 "Block Ack in HE TB PPDU sent too late");
1874 baNavEnd =
m_txPsdus[28].endTx +
m_txPsdus[28].psduMap.begin()->second->GetDuration();
1882 "Expected null Duration/ID for BlockAck");
1888 m_txPsdus[29].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1890 "Expected a Block Ack");
1894 tEnd + sifs + tolerance,
1895 "Block Ack in HE TB PPDU sent too late");
1896 baNavEnd =
m_txPsdus[29].endTx +
m_txPsdus[29].psduMap.begin()->second->GetDuration();
1904 "Expected null Duration/ID for BlockAck");
1910 m_txPsdus[30].psduMap.begin()->second->GetHeader(0).IsBlockAck()),
1912 "Expected a Block Ack");
1916 tEnd + sifs + tolerance,
1917 "Block Ack in HE TB PPDU sent too late");
1918 baNavEnd =
m_txPsdus[30].endTx +
m_txPsdus[30].psduMap.begin()->second->GetDuration();
1926 "Expected null Duration/ID for BlockAck");
1934 "Not all DL packets have been received");
1941 for (std::size_t i = nTxPsdus; i <
m_txPsdus.size(); ++i)
1944 !
m_txPsdus[i].psduMap.begin()->second->GetHeader(0).IsCts() &&
1945 m_txPsdus[i].psduMap.begin()->second->GetHeader(0).GetAddr2() !=
1953 "A station transmitted before the MU EDCA timer expired");
1965 "A station did not set the correct MU CW min");
1979 int64_t streamNumber = 10;
1982 wifiApNode.Create(1);
1988 NodeContainer wifiStaNodes(wifiOldStaNodes, wifiNewStaNodes);
1992 spectrumChannel->AddPropagationLossModel(lossModel);
1994 CreateObject<ConstantSpeedPropagationDelayModel>();
1995 spectrumChannel->SetPropagationDelayModel(delayModel);
1999 phy.SetErrorRateModel(
"ns3::NistErrorRateModel");
2000 phy.SetChannel(spectrumChannel);
2004 phy.Set(
"ChannelSettings",
StringValue(
"{36, 20, BAND_5GHZ, 0}"));
2007 phy.Set(
"ChannelSettings",
StringValue(
"{38, 40, BAND_5GHZ, 0}"));
2010 phy.Set(
"ChannelSettings",
StringValue(
"{42, 80, BAND_5GHZ, 0}"));
2013 phy.Set(
"ChannelSettings",
StringValue(
"{50, 160, BAND_5GHZ, 0}"));
2016 NS_ABORT_MSG(
"Invalid channel bandwidth (must be 20, 40, 80 or 160)");
2062 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
2065 wifi.ConfigHeOptions(
"MuBeAifsn",
2083 mac.SetType(
"ns3::StaWifiMac",
2091 "BE_BlockAckThreshold",
2098 "BK_BlockAckThreshold",
2105 "VI_BlockAckThreshold",
2112 "VO_BlockAckThreshold",
2117 m_staDevices = wifi.Install(phy, mac, wifiOldStaNodes);
2125 wifi.Install(phy, mac, Create<Node>());
2130 mac.SetType(
"ns3::ApWifiMac",
"BeaconGeneration",
BooleanValue(
true));
2131 mac.SetMultiUserScheduler(
2132 "ns3::TestMultiUserScheduler",
2136 "AccessReqInterval",
2138 "DelayAccessReqUponAccess",
2140 mac.SetAckManager(
"ns3::WifiDefaultAckManager",
2141 "DlMuAckSequenceType",
2144 m_apDevice = DynamicCast<WifiNetDevice>(wifi.Install(phy, mac, wifiApNode).Get(0));
2148 streamNumber += wifi.AssignStreams(
m_staDevices, streamNumber);
2153 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
2154 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
2155 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
2156 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
2157 positionAlloc->Add(Vector(-1.0, -1.0, 0.0));
2158 mobility.SetPositionAllocator(positionAlloc);
2160 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
2161 mobility.Install(wifiApNode);
2162 mobility.Install(wifiStaNodes);
2167 auto dev = DynamicCast<WifiNetDevice>(allDevices.
Get(i));
2174 dev->GetMac()->GetQosTxop(
AC_BE)->SetAifsn(3);
2175 dev->GetMac()->GetQosTxop(
AC_BK)->SetAifsn(3);
2176 dev->GetMac()->GetQosTxop(
AC_VI)->SetAifsn(3);
2177 dev->GetMac()->GetQosTxop(
AC_VO)->SetAifsn(3);
2181 packetSocket.
Install(wifiApNode);
2182 packetSocket.
Install(wifiStaNodes);
2199 client1->SetRemote(socket);
2200 wifiApNode.Get(0)->AddApplication(client1);
2202 client1->SetStopTime(
Seconds(2.0));
2207 client2->SetAttribute(
"PacketSize",
UintegerValue(1400 + i * 100));
2211 client2->SetRemote(socket);
2212 wifiApNode.Get(0)->AddApplication(client2);
2213 client2->SetStartTime(
Seconds(1.5003));
2214 client2->SetStopTime(
Seconds(2.5));
2217 server->SetLocal(socket);
2218 wifiStaNodes.Get(i)->AddApplication(server);
2219 server->SetStartTime(
Seconds(0.0));
2220 server->SetStopTime(
Seconds(3.0));
2238 wifiStaNodes.Get(i)->AddApplication(client1);
2240 client1->SetStopTime(
Seconds(2.0));
2247 wifiApNode.Get(0)->AddApplication(server);
2248 server->SetStartTime(
Seconds(0.0));
2249 server->SetStopTime(
Seconds(3.0));
2252 Config::Connect(
"/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx",
2255 Config::Connect(
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
2287 using MuEdcaParams = std::initializer_list<OfdmaAckSequenceTest::MuEdcaParameterSet>;
2289 for (
auto& muEdcaParameterSet : MuEdcaParams{{0, 0, 0, 0} ,
2290 {0, 127, 2047, 100} ,
2291 {10, 127, 2047, 100} })
2293 for (
const auto scenario :
2294 {WifiOfdmaScenario::HE, WifiOfdmaScenario::HE_EHT, WifiOfdmaScenario::EHT})
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.
~OfdmaAckSequenceTest() override
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.
~TestMultiUserScheduler() override
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
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.
Hold variables of type enum.
static std::pair< uint16_t, Time > ConvertHeTbPpduDurationToLSigLength(Time ppduDuration, const WifiTxVector &txVector, WifiPhyBand band)
Compute the L-SIG length value corresponding to the given HE TB PPDU duration.
RuType
The different HE Resource Unit (RU) types.
static Mac48Address GetBroadcast()
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.
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.
Smart pointer class similar to boost::intrusive_ptr.
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...
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...
static uint64_t GetRun()
Get the current run number.
static uint32_t GetSeed()
Get the current seed value which will be used by all subsequently instantiated RandomVariableStream o...
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
static Time Now()
Return the current simulation virtual time.
static void Run()
Run the simulation.
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
AttributeValue implementation for Ssid.
Hold variables of type string.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Simulation virtual time values and global simulation resolution.
static Time Min()
Minimum representable Time Not to be confused with Min(Time,Time).
int64_t GetMicroSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
AttributeValue implementation for Time.
Ptr< WifiMacQueue > GetWifiMacQueue() const
Return the packet queue associated with this Txop.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Hold an unsigned integer type.
static WifiMode GetVhtMcs5()
Return MCS 5 from VHT MCS values.
helps to create WifiNetDevice objects
create MAC layers for a ns3::WifiNetDevice.
Ptr< HeConfiguration > GetHeConfiguration() const
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
bool GetHeSupported() const
Return whether the device supports HE.
Ptr< WifiRemoteStationManager > GetWifiRemoteStationManager(uint8_t linkId=0) const
Mac48Address GetAddress() const
Ptr< QosTxop > GetQosTxop(AcIndex ac) const
Accessor for a specified EDCA object.
Ptr< WifiMac > GetMac() const
uint32_t GetIfIndex() const override
Address GetAddress() const override
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
Time GetSlot() const
Return the slot duration for this PHY.
uint16_t GetChannelWidth() const
Time GetSifs() const
Return the Short Interframe Space (SIFS) for this PHY.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
WifiPhyBand GetPhyBand() const
Get the configured Wi-Fi band.
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 SetRuAllocation(const RuAllocation &ruAlloc, uint8_t p20Index)
Set RU_ALLOCATION field.
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
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
Ptr< const AttributeAccessor > MakeEnumAccessor(T1 a1)
void SetGlobal(std::string name, const AttributeValue &value)
void SetDefault(std::string name, const AttributeValue &value)
void Connect(std::string path, const CallbackBase &cb)
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#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.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
#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.
#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.
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
#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.
WifiOfdmaScenario
The scenarios.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Time Seconds(double value)
Construct a Time in the indicated unit.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
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 ...
TriggerFrameType
The different Trigger frame types.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_MOD_CLASS_EHT
EHT (Clause 36)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
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...
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...
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
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.
Information about transmitted frames.
Time startTx
start TX time
WifiTxVector txVector
TXVECTOR.
WifiConstPsduMap psduMap
transmitted PSDU map
uint8_t muAifsn
MU AIFS (0 to disable EDCA)
uint16_t muCwMin
MU CW min.
uint8_t muTimer
MU EDCA Timer in units of 8192 microseconds (0 not to use MU EDCA)
uint16_t muCwMax
MU CW max.
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