9#include "ns3/ap-wifi-mac.h"
10#include "ns3/boolean.h"
11#include "ns3/constant-position-mobility-model.h"
12#include "ns3/ctrl-headers.h"
13#include "ns3/demangle.h"
14#include "ns3/double.h"
15#include "ns3/eht-configuration.h"
16#include "ns3/eht-phy.h"
17#include "ns3/he-configuration.h"
18#include "ns3/he-ppdu.h"
19#include "ns3/interference-helper.h"
21#include "ns3/mobility-helper.h"
22#include "ns3/multi-model-spectrum-channel.h"
23#include "ns3/nist-error-rate-model.h"
25#include "ns3/non-communicating-net-device.h"
26#include "ns3/pointer.h"
27#include "ns3/rng-seed-manager.h"
28#include "ns3/simulator.h"
29#include "ns3/spectrum-wifi-helper.h"
30#include "ns3/spectrum-wifi-phy.h"
31#include "ns3/sta-wifi-mac.h"
32#include "ns3/string.h"
34#include "ns3/threshold-preamble-detection-model.h"
36#include "ns3/waveform-generator.h"
37#include "ns3/wifi-mac-header.h"
38#include "ns3/wifi-net-device.h"
39#include "ns3/wifi-phy-listener.h"
40#include "ns3/wifi-psdu.h"
41#include "ns3/wifi-spectrum-phy-interface.h"
42#include "ns3/wifi-spectrum-signal-parameters.h"
43#include "ns3/wifi-spectrum-value-helper.h"
44#include "ns3/wifi-utils.h"
65template <
typename PhyEntityType>
108template <
typename PhyEntityType>
115template <
typename PhyEntityType>
124 return PhyEntityType::GetStaId(ppdu);
127template <
typename PhyEntityType>
131 PhyEntityType::m_globalPpduUid = uid;
134template <
typename PhyEntityType>
141 NS_ASSERT(channelWidth <= PhyEntityType::m_wifiPhy->GetChannelWidth());
143 auto ru = txVector.
GetRu(staId);
144 const auto nonOfdmaWidth = PhyEntityType::GetNonOfdmaWidth(ru);
155 PhyEntityType::m_wifiPhy->GetOperatingChannel().GetPrimaryChannelIndex(
MHz_u{20})),
157 const auto indices = PhyEntityType::ConvertRuSubcarriers(
159 PhyEntityType::GetGuardBandwidth(PhyEntityType::m_wifiPhy->GetChannelWidth()),
160 PhyEntityType::m_wifiPhy->GetOperatingChannel().GetFrequencies(),
161 PhyEntityType::m_wifiPhy->GetChannelWidth(),
162 PhyEntityType::m_wifiPhy->GetSubcarrierSpacing(),
164 {groupPreamble.front().first, groupPreamble.back().second},
165 PhyEntityType::m_wifiPhy->GetOperatingChannel().GetPrimaryChannelIndex(channelWidth)});
167 for (
const auto& indicesPerSegment : indices)
169 nonOfdmaBand.
indices.emplace_back(indicesPerSegment);
170 nonOfdmaBand.frequencies.emplace_back(
171 PhyEntityType::m_wifiPhy->ConvertIndicesToFrequencies(indicesPerSegment));
179template <
typename LatestPhyEntityType>
258template <
typename LatestPhyEntityType>
263 TypeId(std::string(
"ns3::OfdmaSpectrumWifiPhy") +
264 Demangle(
typeid(LatestPhyEntityType).name()))
266 .SetGroupName(
"Wifi")
267 .AddTraceSource(
"TxPpduUid",
268 "UID of the PPDU to be transmitted",
271 "ns3::OfdmaSpectrumWifiPhy<LatestPhyEntityType>::TxPpduUidCallback");
275template <
typename LatestPhyEntityType>
283template <
typename LatestPhyEntityType>
289 m_phyEntities[modClass] = m_ofdmaTestPhy;
293template <
typename LatestPhyEntityType>
297 m_ofdmaTestPhy =
nullptr;
301template <
typename LatestPhyEntityType>
305 m_ofdmaTestPhy->SetGlobalPpduUid(uid);
306 m_previouslyRxPpduUid = uid;
309template <
typename LatestPhyEntityType>
313 m_previouslyRxPpduUid = uid;
316template <
typename LatestPhyEntityType>
320 m_phyTxPpduUidTrace(ppdu->GetUid());
324template <
typename LatestPhyEntityType>
325std::map<std::pair<uint64_t, WifiPreamble>,
Ptr<Event>>&
328 return m_currentPreambleEvents;
331template <
typename LatestPhyEntityType>
335 return m_currentEvent;
338template <
typename LatestPhyEntityType>
343 return m_interference->GetEnergyDuration(energy, band);
346template <
typename LatestPhyEntityType>
359template <
typename LatestPhyEntityType>
371 void DoRun()
override;
383 const std::vector<bool>& statusPerMpdu);
394 const std::vector<bool>& statusPerMpdu);
405 const std::vector<bool>& statusPerMpdu);
461 void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2);
517template <
typename LatestPhyEntityType>
520 ((
Demangle(typeid(LatestPhyEntityType).name()).find(
"He") !=
std::string::npos)
523 m_modClass{(
Demangle(typeid(LatestPhyEntityType).name()).find(
"He") !=
std::string::npos)
530template <
typename LatestPhyEntityType>
534 m_countRxSuccessSta1 = 0;
535 m_countRxSuccessSta2 = 0;
536 m_countRxSuccessSta3 = 0;
537 m_countRxFailureSta1 = 0;
538 m_countRxFailureSta2 = 0;
539 m_countRxFailureSta3 = 0;
540 m_countRxBytesSta1 = 0;
541 m_countRxBytesSta2 = 0;
542 m_countRxBytesSta3 = 0;
545template <
typename LatestPhyEntityType>
564 txVector.SetEhtPpduType(0);
566 auto ruType{RuType::RU_TYPE_MAX};
567 if (m_channelWidth ==
MHz_u{20})
569 ruType = RuType::RU_106_TONE;
571 txVector.SetRuAllocation({ruAllocPer20}, 0);
573 else if (m_channelWidth ==
MHz_u{40})
575 ruType = RuType::RU_242_TONE;
577 txVector.SetRuAllocation({ruAllocPer20, ruAllocPer20}, 0);
579 else if (m_channelWidth ==
MHz_u{80})
581 ruType = RuType::RU_484_TONE;
584 txVector.SetRuAllocation({ruAllocUser, ruAllocNoUser, ruAllocNoUser, ruAllocUser}, 0);
586 else if (m_channelWidth ==
MHz_u{160})
588 ruType = RuType::RU_996_TONE;
591 txVector.SetRuAllocation({ruAllocUser,
601 else if (m_channelWidth ==
MHz_u{320})
604 ruType = RuType::RU_2x996_TONE;
605 txVector.SetRuAllocation({88, 30, 88, 30, 88, 30, 88, 30, 30, 88, 30, 88, 30, 88, 30, 88},
610 NS_ASSERT_MSG(
false,
"Unsupported channel width: " << m_channelWidth);
618 txVector.SetRu(ru1, rxStaId1);
621 txVector.SetNss(1, rxStaId1);
623 std::size_t ru2Index = (m_channelWidth >
MHz_u{80}) ? 1 : 2;
628 txVector.SetRu(ru2, rxStaId2);
631 txVector.SetNss(1, rxStaId2);
640 psdus.insert(std::make_pair(rxStaId1, psdu1));
649 psdus.insert(std::make_pair(rxStaId2, psdu2));
651 m_phyAp->Send(psdus, txVector);
654template <
typename LatestPhyEntityType>
660 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
661 m_phyInterferer->SetPeriod(duration);
662 m_phyInterferer->Start();
668template <
typename LatestPhyEntityType>
672 m_phyInterferer->Stop();
675template <
typename LatestPhyEntityType>
681 const std::vector<bool>& )
684 m_countRxSuccessSta1++;
685 m_countRxBytesSta1 += (psdu->GetSize() - 30);
688template <
typename LatestPhyEntityType>
694 const std::vector<bool>& )
697 m_countRxSuccessSta2++;
698 m_countRxBytesSta2 += (psdu->GetSize() - 30);
701template <
typename LatestPhyEntityType>
707 const std::vector<bool>& )
710 m_countRxSuccessSta3++;
711 m_countRxBytesSta3 += (psdu->GetSize() - 30);
714template <
typename LatestPhyEntityType>
719 m_countRxFailureSta1++;
722template <
typename LatestPhyEntityType>
727 m_countRxFailureSta2++;
730template <
typename LatestPhyEntityType>
735 m_countRxFailureSta3++;
738template <
typename LatestPhyEntityType>
746 "The number of successfully received packets by STA 1 is not correct!");
749 "The number of unsuccessfully received packets by STA 1 is not correct!");
752 "The number of bytes received by STA 1 is not correct!");
755template <
typename LatestPhyEntityType>
763 "The number of successfully received packets by STA 2 is not correct!");
766 "The number of unsuccessfully received packets by STA 2 is not correct!");
769 "The number of bytes received by STA 2 is not correct!");
772template <
typename LatestPhyEntityType>
780 "The number of successfully received packets by STA 3 is not correct!");
783 "The number of unsuccessfully received packets by STA 3 is not correct!");
786 "The number of bytes received by STA 3 is not correct!");
789template <
typename LatestPhyEntityType>
803template <
typename LatestPhyEntityType>
811 phy->GetAttribute(
"State", ptr);
813 currentState = state->GetState();
817 "PHY State " << currentState <<
" does not match expected state "
821template <
typename LatestPhyEntityType>
825 const auto standard =
830 lossModel->SetFrequency(
MHzToHz(m_frequency));
831 spectrumChannel->AddPropagationLossModel(lossModel);
834 spectrumChannel->SetPropagationDelayModel(delayModel);
840 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
842 m_phyAp->SetErrorRateModel(apErrorModel);
843 m_phyAp->SetDevice(apDev);
844 m_phyAp->AddChannel(spectrumChannel);
845 m_phyAp->ConfigureStandard(standard);
847 m_phyAp->SetMobility(apMobility);
848 apDev->SetPhy(m_phyAp);
849 apNode->AggregateObject(apMobility);
850 apNode->AddDevice(apDev);
851 apDev->SetStandard(standard);
861 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
863 m_phySta1->SetErrorRateModel(sta1ErrorModel);
864 m_phySta1->SetDevice(sta1Dev);
865 m_phySta1->AddChannel(spectrumChannel);
866 m_phySta1->ConfigureStandard(standard);
867 m_phySta1->SetReceiveOkCallback(
869 m_phySta1->SetReceiveErrorCallback(
872 m_phySta1->SetMobility(sta1Mobility);
873 sta1Dev->SetPhy(m_phySta1);
874 sta1Node->AggregateObject(sta1Mobility);
875 sta1Node->AddDevice(sta1Dev);
876 sta1Dev->SetStandard(standard);
886 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
888 m_phySta2->SetErrorRateModel(sta2ErrorModel);
889 m_phySta2->SetDevice(sta2Dev);
890 m_phySta2->AddChannel(spectrumChannel);
891 m_phySta2->ConfigureStandard(standard);
892 m_phySta2->SetReceiveOkCallback(
894 m_phySta2->SetReceiveErrorCallback(
897 m_phySta2->SetMobility(sta2Mobility);
898 sta2Dev->SetPhy(m_phySta2);
899 sta2Node->AggregateObject(sta2Mobility);
900 sta2Node->AddDevice(sta2Dev);
901 sta2Dev->SetStandard(standard);
911 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
913 m_phySta3->SetErrorRateModel(sta3ErrorModel);
914 m_phySta3->SetDevice(sta3Dev);
915 m_phySta3->AddChannel(spectrumChannel);
916 m_phySta3->ConfigureStandard(standard);
918 m_phySta3->SetReceiveOkCallback(
920 m_phySta3->SetReceiveErrorCallback(
923 m_phySta3->SetMobility(sta3Mobility);
924 sta3Dev->SetPhy(m_phySta3);
925 sta3Node->AggregateObject(sta3Mobility);
926 sta3Node->AddDevice(sta3Dev);
927 sta3Dev->SetStandard(standard);
936 m_phyInterferer->SetDevice(interfererDev);
937 m_phyInterferer->SetChannel(spectrumChannel);
938 m_phyInterferer->SetDutyCycle(1);
939 interfererNode->AddDevice(interfererDev);
942template <
typename LatestPhyEntityType>
948 m_phySta1->Dispose();
950 m_phySta2->Dispose();
952 m_phySta3->Dispose();
954 m_phyInterferer->Dispose();
955 m_phyInterferer =
nullptr;
958template <
typename LatestPhyEntityType>
964 int64_t streamNumber = 0;
965 m_phyAp->AssignStreams(streamNumber);
966 m_phySta1->AssignStreams(streamNumber);
967 m_phySta2->AssignStreams(streamNumber);
968 m_phySta3->AssignStreams(streamNumber);
977 const auto operatingChannel{
979 m_phyAp->SetOperatingChannel(operatingChannel);
980 m_phySta1->SetOperatingChannel(operatingChannel);
981 m_phySta2->SetOperatingChannel(operatingChannel);
982 m_phySta3->SetOperatingChannel(operatingChannel);
1014 WifiPhyState::CCA_BUSY);
1019 WifiPhyState::IDLE);
1024 WifiPhyState::IDLE);
1029 WifiPhyState::IDLE);
1078 WifiPhyState::CCA_BUSY);
1088 WifiPhyState::IDLE);
1093 WifiPhyState::IDLE);
1098 WifiPhyState::IDLE);
1135 bandInfo.
fc =
MHzToHz(m_frequency - (m_channelWidth / 4));
1136 bandInfo.
fl = bandInfo.
fc -
MHzToHz(m_channelWidth / 4);
1137 bandInfo.
fh = bandInfo.
fc +
MHzToHz(m_channelWidth / 4);
1139 bands.push_back(bandInfo);
1143 Watt_u interferencePower{0.1};
1144 *interferencePsdRu1 = interferencePower / (
MHzToHz(m_channelWidth / 2) * 20);
1169 WifiPhyState::CCA_BUSY);
1174 WifiPhyState::CCA_BUSY);
1179 WifiPhyState::CCA_BUSY);
1184 WifiPhyState::CCA_BUSY);
1221 bandInfo.
fc =
MHzToHz(m_frequency + (m_channelWidth / 4));
1222 bandInfo.
fl = bandInfo.
fc -
MHzToHz(m_channelWidth / 4);
1223 bandInfo.
fh = bandInfo.
fc +
MHzToHz(m_channelWidth / 4);
1225 bands.push_back(bandInfo);
1229 *interferencePsdRu2 = interferencePower / (
MHzToHz(m_channelWidth / 2) * 20);
1254 WifiPhyState::CCA_BUSY);
1259 (m_channelWidth >=
MHz_u{40}) ? WifiPhyState::IDLE
1260 : WifiPhyState::CCA_BUSY);
1265 (m_channelWidth >=
MHz_u{40}) ? WifiPhyState::IDLE
1266 : WifiPhyState::CCA_BUSY);
1271 (m_channelWidth >=
MHz_u{40}) ? WifiPhyState::IDLE
1272 : WifiPhyState::CCA_BUSY);
1310 bandInfo.
fl = bandInfo.
fc -
MHzToHz(m_channelWidth / 2);
1311 bandInfo.
fh = bandInfo.
fc +
MHzToHz(m_channelWidth / 2);
1313 bands.push_back(bandInfo);
1317 *interferencePsdAll = interferencePower / (
MHzToHz(m_channelWidth) * 20);
1342 WifiPhyState::CCA_BUSY);
1347 WifiPhyState::CCA_BUSY);
1352 WifiPhyState::CCA_BUSY);
1357 WifiPhyState::CCA_BUSY);
1390template <
typename LatestPhyEntityType>
1394 m_frequency =
MHz_u{5955};
1395 m_channelWidth =
MHz_u{20};
1399 m_frequency =
MHz_u{5965};
1400 m_channelWidth =
MHz_u{40};
1404 m_frequency =
MHz_u{5985};
1405 m_channelWidth =
MHz_u{80};
1409 m_frequency =
MHz_u{6025};
1410 m_channelWidth =
MHz_u{160};
1416 m_frequency =
MHz_u{6105};
1417 m_channelWidth =
MHz_u{320};
1439 void DoRun()
override;
1451 const std::vector<bool>& statusPerMpdu);
1463 const std::vector<bool>& statusPerMpdu);
1511 const std::vector<bool>& puncturedSubchannels);
1567 :
TestCase(
"DL-OFDMA PHY puncturing test"),
1568 m_countRxSuccessSta1(0),
1569 m_countRxSuccessSta2(0),
1570 m_countRxFailureSta1(0),
1571 m_countRxFailureSta2(0),
1572 m_countRxBytesSta1(0),
1573 m_countRxBytesSta2(0),
1574 m_frequency(
MHz_u{5210}),
1575 m_channelWidth(
MHz_u{80}),
1576 m_indexSubchannel(0),
1596 const std::vector<bool>& puncturedSubchannels)
1611 RuType ruType = puncturedSubchannels.empty()
1612 ? RuType::RU_484_TONE
1613 : (puncturedSubchannels.at(1) ? RuType::RU_242_TONE : RuType::RU_484_TONE);
1615 txVector.SetRu(ru1, rxStaId1);
1617 txVector.SetNss(1, rxStaId1);
1619 ruType = puncturedSubchannels.empty()
1620 ? RuType::RU_484_TONE
1621 : (puncturedSubchannels.at(1) ? RuType::RU_484_TONE : RuType::RU_242_TONE);
1623 ruType == RuType::RU_484_TONE ? 2 : (puncturedSubchannels.at(3) ? 3 : 4),
1625 txVector.SetRu(ru2, rxStaId2);
1627 txVector.SetNss(1, rxStaId2);
1630 if (puncturedSubchannels.empty())
1632 ruAlloc.push_back(200);
1633 ruAlloc.push_back(114);
1634 ruAlloc.push_back(114);
1635 ruAlloc.push_back(200);
1639 ruAlloc.push_back(puncturedSubchannels.at(1) ? 192 : 200);
1640 ruAlloc.push_back(puncturedSubchannels.at(1) ? 113 : 114);
1641 ruAlloc.push_back(puncturedSubchannels.at(2) ? 113
1642 : (puncturedSubchannels.at(3) ? 192 : 114));
1643 ruAlloc.push_back(puncturedSubchannels.at(2) ? 192
1644 : (puncturedSubchannels.at(3) ? 113 : 200));
1647 txVector.SetRuAllocation(ruAlloc, 0);
1657 psdus.insert(std::make_pair(rxStaId1, psdu1));
1666 psdus.insert(std::make_pair(rxStaId2, psdu2));
1668 if (!puncturedSubchannels.empty())
1670 txVector.SetInactiveSubchannels(puncturedSubchannels);
1673 m_phyAp->Send(psdus, txVector);
1697 const std::vector<bool>& )
1708 const std::vector<bool>& )
1736 "The number of successfully received packets by STA 1 is not correct!");
1739 "The number of unsuccessfully received packets by STA 1 is not correct!");
1742 "The number of bytes received by STA 1 is not correct!");
1752 "The number of successfully received packets by STA 2 is not correct!");
1755 "The number of unsuccessfully received packets by STA 2 is not correct!");
1758 "The number of bytes received by STA 2 is not correct!");
1776 phy->GetAttribute(
"State", ptr);
1778 currentState = state->GetState();
1782 "PHY State " << currentState <<
" does not match expected state "
1792 spectrumChannel->AddPropagationLossModel(lossModel);
1795 spectrumChannel->SetPropagationDelayModel(delayModel);
1801 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
1803 m_phyAp->SetErrorRateModel(apErrorModel);
1805 m_phyAp->AddChannel(spectrumChannel);
1808 m_phyAp->SetMobility(apMobility);
1810 apNode->AggregateObject(apMobility);
1811 apNode->AddDevice(apDev);
1818 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
1820 m_phySta1->SetErrorRateModel(sta1ErrorModel);
1830 sta1Node->AggregateObject(sta1Mobility);
1831 sta1Node->AddDevice(sta1Dev);
1838 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
1840 m_phySta2->SetErrorRateModel(sta2ErrorModel);
1850 sta2Node->AggregateObject(sta2Mobility);
1851 sta2Node->AddDevice(sta2Dev);
1860 interfererNode->AddDevice(interfererDev);
1881 int64_t streamNumber = 0;
1882 m_phyAp->AssignStreams(streamNumber);
1909 bands.push_back(bandInfo);
1913 Watt_u interferencePower{0.1};
1914 *interferencePsd = interferencePower / 10e6;
1929 std::vector<bool>{});
1947 WifiPhyState::IDLE);
1952 WifiPhyState::IDLE);
1994 std::vector<bool> puncturedSubchannels;
1996 for (std::size_t i = 0; i < num20MhzSubchannels; ++i)
2000 puncturedSubchannels.push_back(
true);
2004 puncturedSubchannels.push_back(
false);
2012 puncturedSubchannels);
2030 WifiPhyState::IDLE);
2035 WifiPhyState::IDLE);
2062 for (
auto index : {1, 2, 3})
2085 void DoRun()
override;
2126 void CheckUid(uint16_t staId, uint64_t expectedUid);
2138 :
TestCase(
"UL-OFDMA PPDU UID attribution test"),
2139 m_ppduUidAp(UINT64_MAX),
2140 m_ppduUidSta1(UINT64_MAX),
2141 m_ppduUidSta2(UINT64_MAX)
2155 spectrumChannel->AddPropagationLossModel(lossModel);
2158 spectrumChannel->SetPropagationDelayModel(delayModel);
2164 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
2166 m_phyAp->SetErrorRateModel(apErrorModel);
2167 m_phyAp->AddChannel(spectrumChannel);
2178 m_phyAp->TraceConnectWithoutContext(
"TxPpduUid",
2181 m_phyAp->SetMobility(apMobility);
2183 apNode->AggregateObject(apMobility);
2184 apNode->AddDevice(apDev);
2192 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
2194 m_phySta1->SetErrorRateModel(sta1ErrorModel);
2200 m_phySta1->TraceConnectWithoutContext(
"TxPpduUid",
2205 sta1Node->AggregateObject(sta1Mobility);
2206 sta1Node->AddDevice(sta1Dev);
2212 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
2214 m_phySta2->SetErrorRateModel(sta2ErrorModel);
2220 m_phySta2->TraceConnectWithoutContext(
"TxPpduUid",
2225 sta2Node->AggregateObject(sta2Mobility);
2226 sta2Node->AddDevice(sta2Dev);
2264 "UID " << uid <<
" does not match expected one " << expectedUid <<
" for "
2311 uint16_t rxStaId1 = 1;
2313 txVector.SetRu(ru1, rxStaId1);
2315 txVector.SetNss(1, rxStaId1);
2317 uint16_t rxStaId2 = 2;
2319 txVector.SetRu(ru2, rxStaId2);
2321 txVector.SetNss(1, rxStaId2);
2323 txVector.SetRuAllocation({96}, 0);
2332 psdus.insert(std::make_pair(rxStaId1, psdu1));
2341 psdus.insert(std::make_pair(rxStaId2, psdu2));
2343 m_phyAp->Send(psdus, txVector);
2365 uint16_t rxStaId1 = 1;
2367 txVector1.SetRu(ru1, rxStaId1);
2369 txVector1.SetNss(1, rxStaId1);
2370 trigVector.SetRu(ru1, rxStaId1);
2372 trigVector.SetNss(1, rxStaId1);
2381 psdus1.insert(std::make_pair(rxStaId1, psdu1));
2383 uint16_t rxStaId2 = 2;
2385 txVector2.SetRu(ru2, rxStaId2);
2387 txVector2.SetNss(1, rxStaId2);
2388 trigVector.SetRu(ru2, rxStaId2);
2390 trigVector.SetNss(1, rxStaId2);
2399 psdus2.insert(std::make_pair(rxStaId2, psdu2));
2401 const auto txDuration1 =
2406 const auto txDuration2 =
2411 const auto txDuration = std::max(txDuration1, txDuration2);
2413 txVector1.SetLength(
2416 txVector2.SetLength(
2420 auto phyAp =
m_phyAp->GetPhyEntity();
2421 phyAp->SetTrigVector(trigVector, txDuration);
2449 psdus.insert(std::make_pair(
SU_STA_ID, psdu));
2454 m_phyAp->Send(psdus, txVector);
2472 int64_t streamNumber = 0;
2473 m_phyAp->AssignStreams(streamNumber);
2522 void DoRun()
override;
2533 void RxHeTbPpdu(uint64_t uid, uint16_t staId,
Watt_u txPower,
size_t payloadSize);
2582 :
TestCase(
"UL-OFDMA multiple RX events test"),
2583 m_totalBytesDropped(0),
2584 m_trigVector(
HePhy::GetHeMcs7(),
2621 auto events =
m_phy->GetCurrentPreambleEvents();
2623 for (
const auto& uid : uids)
2626 auto it = events.find(pair);
2627 bool found = (it != events.end());
2630 "HE TB PPDU with UID " << uid <<
" has not been received!");
2638 expectedBytesDropped,
2639 "The number of dropped bytes is not correct!");
2661 txVector.SetRu(ru, staId);
2663 txVector.SetNss(1, staId);
2674 psdus.insert(std::make_pair(staId, psdu));
2678 m_phy->GetPhyBand(),
2682 m_phy->GetOperatingChannel(),
2688 const auto nonOfdmaDuration =
m_phy->GetPhyEntity()->CalculateNonHeDurationForHeTb(txVector);
2689 const auto centerFrequency =
2690 m_phy->GetPhyEntity()->GetCenterFrequenciesForNonHePart(ppdu, staId).front();
2692 auto channelWidth = ruWidth <
MHz_u{20} ?
MHz_u{20} : ruWidth;
2697 m_phy->GetGuardBandwidth(channelWidth));
2699 rxParams->psd = rxPsd;
2700 rxParams->txPhy =
nullptr;
2701 rxParams->duration = nonOfdmaDuration;
2702 rxParams->ppdu = ppdu;
2705 std::tie(length, ppduDuration) =
2707 txVector.SetLength(length);
2711 ppdu->ResetTxVector();
2712 m_phy->StartRx(rxParams,
nullptr);
2717 const auto band =
m_phy->GetPhyEntity()->GetRuBandForRx(txVector, staId);
2725 rxParamsOfdma->psd = rxPsd;
2726 rxParamsOfdma->txPhy =
nullptr;
2727 rxParamsOfdma->duration = ppduDuration - nonOfdmaDuration;
2728 rxParamsOfdma->ppdu = ppduOfdma;
2747 m_phy->StartRx(rxParamsOfdma,
nullptr);
2763 mac->SetAttribute(
"BeaconGeneration",
BooleanValue(
false));
2765 m_phy->SetInterferenceHelper(interferenceHelper);
2766 m_phy->SetErrorRateModel(error);
2767 m_phy->AddChannel(spectrumChannel);
2773 m_phy->TraceConnectWithoutContext(
"PhyRxDrop",
2775 m_phy->SetDevice(dev);
2778 preambleDetectionModel->SetAttribute(
"Threshold",
DoubleValue(4));
2779 preambleDetectionModel->SetAttribute(
"MinimumRssi",
DoubleValue(-82));
2780 m_phy->SetPreambleDetectionModel(preambleDetectionModel);
2782 heConfiguration->m_maxTbPpduDelay =
NanoSeconds(400);
2783 dev->SetHeConfiguration(heConfiguration);
2785 node->AddDevice(dev);
2800 int64_t streamNumber = 0;
2801 m_phy->AssignStreams(streamNumber);
2807 std::vector<uint64_t> uids{0};
2835 std::vector<uint64_t> uids{1, 2};
2879 std::vector<uint64_t> uids{3, 4};
2923 std::vector<uint64_t> uids{5, 6};
2958 std::vector<uint64_t>{uids[0]});
2971 std::vector<uint64_t> uids{7, 8};
3006 std::vector<uint64_t>{uids[0]});
3019 std::vector<uint64_t> uids{9};
3097 const std::vector<Time>& )
override
3193template <
typename LatestPhyEntityType>
3213 void DoRun()
override;
3241 std::size_t payloadSize,
3253 void SendSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor);
3355 Time expectedLastNotification,
3356 bool expectedSuccess);
3373 const std::vector<bool>& statusPerMpdu);
3410 bool scheduleTxSta1 =
true,
3412 WifiPhyState expectedStateBeforeEnd = WifiPhyState::RX,
3425 Watt_u rxPowerNonOfdmaRu1,
3426 Watt_u rxPowerNonOfdmaRu2,
3443 std::shared_ptr<OfdmaTestPhyListener>
3460template <
typename LatestPhyEntityType>
3462 :
TestCase{
std::string(
"UL-OFDMA PHY test for ") +
3463 ((
Demangle(typeid(LatestPhyEntityType).name()).find(
"He") !=
std::string::npos)
3466 m_modClass{(
Demangle(typeid(LatestPhyEntityType).name()).find(
"He") !=
std::string::npos)
3473template <
typename LatestPhyEntityType>
3476 std::size_t payloadSize,
3502 std::ostringstream addr;
3503 addr <<
"00:00:00:00:00:0" << txStaId;
3507 psdus.insert(std::make_pair(
SU_STA_ID, psdu));
3514 else if (txStaId == 2)
3518 else if (txStaId == 3)
3522 else if (txStaId == 0)
3526 phy->SetPpduUid(uid);
3527 phy->Send(psdus, txVector);
3530template <
typename LatestPhyEntityType>
3534 uint8_t bssColor)
const
3551 txVector.SetEhtPpduType(0);
3553 auto ruType{RuType::RU_TYPE_MAX};
3554 if (m_channelWidth ==
MHz_u{20})
3556 ruType = RuType::RU_106_TONE;
3558 else if (m_channelWidth ==
MHz_u{40})
3560 ruType = RuType::RU_242_TONE;
3562 else if (m_channelWidth ==
MHz_u{80})
3564 ruType = RuType::RU_484_TONE;
3566 else if (m_channelWidth ==
MHz_u{160})
3568 ruType = RuType::RU_996_TONE;
3570 else if (m_channelWidth ==
MHz_u{320})
3572 ruType = RuType::RU_2x996_TONE;
3576 NS_ASSERT_MSG(
false,
"Unsupported channel width: " << m_channelWidth);
3579 auto primary80MHzOrLow80MHz{
true};
3580 auto primary160MHz{
true};
3581 if (m_channelWidth >
MHz_u{80})
3590 const auto& [p160, p80OrLow80] =
3592 primary160MHz = p160;
3593 primary80MHzOrLow80MHz = p80OrLow80;
3601 txVector.SetRu(ru, txStaId);
3604 txVector.SetNss(1, txStaId);
3608template <
typename LatestPhyEntityType>
3613 auto channelWidth = m_channelWidth;
3634 RuType ruType = RuType::RU_106_TONE;
3635 if (channelWidth ==
MHz_u{20})
3637 ruType = RuType::RU_106_TONE;
3639 else if (channelWidth ==
MHz_u{40})
3641 ruType = RuType::RU_242_TONE;
3643 else if (channelWidth ==
MHz_u{80})
3645 ruType = RuType::RU_484_TONE;
3647 else if (channelWidth ==
MHz_u{160})
3649 ruType = RuType::RU_996_TONE;
3651 else if (channelWidth ==
MHz_u{320})
3653 ruType = RuType::RU_2x996_TONE;
3657 NS_ASSERT_MSG(
false,
"Unsupported channel width: " << channelWidth);
3660 uint16_t aid1 = (error == AID ? 3 : 1);
3661 uint16_t aid2 = (error == AID ? 4 : 2);
3666 txVector.
SetRu(ru1, aid1);
3669 txVector.
SetNss(1, aid1);
3673 (channelWidth ==
MHz_u{160} ? 1ULL : 2ULL),
3674 (channelWidth !=
MHz_u{160})})
3676 (channelWidth ==
MHz_u{320} ? 1ULL : 2ULL),
3677 (channelWidth !=
MHz_u{320}),
3679 txVector.
SetRu(ru2, aid2);
3682 txVector.
SetNss(1, aid2);
3685 std::tie(length, m_expectedPpduDuration) =
3688 m_phyAp->GetPhyBand());
3689 if (error == UL_LENGTH)
3694 auto phyAp = m_phyAp->GetPhyEntity();
3695 phyAp->SetTrigVector(txVector, m_expectedPpduDuration);
3698template <
typename LatestPhyEntityType>
3702 std::size_t payloadSize,
3707 NS_LOG_FUNCTION(
this << txStaId << index << payloadSize << uid << +bssColor << (incrementUid));
3715 auto txVector = GetTxVectorForTbPpdu(txStaId, index, bssColor);
3721 std::ostringstream addr;
3722 addr <<
"00:00:00:00:00:0" << txStaId;
3726 psdus.insert(std::make_pair(txStaId, psdu));
3733 else if (txStaId == 2)
3737 else if (txStaId == 3)
3750 phy->SetPpduUid(uid);
3751 phy->Send(psdus, txVector);
3754template <
typename LatestPhyEntityType>
3761 m_phyInterferer->SetTxPowerSpectralDensity(interferencePsd);
3762 m_phyInterferer->SetPeriod(duration);
3763 m_phyInterferer->Start();
3769template <
typename LatestPhyEntityType>
3773 m_phyInterferer->Stop();
3776template <
typename LatestPhyEntityType>
3782 const std::vector<bool>& )
3784 NS_LOG_FUNCTION(
this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
3785 if (psdu->GetAddr2() ==
Mac48Address(
"00:00:00:00:00:01"))
3787 m_countRxSuccessFromSta1++;
3788 m_countRxBytesFromSta1 += (psdu->GetSize() - 30);
3790 else if (psdu->GetAddr2() ==
Mac48Address(
"00:00:00:00:00:02"))
3792 m_countRxSuccessFromSta2++;
3793 m_countRxBytesFromSta2 += (psdu->GetSize() - 30);
3797template <
typename LatestPhyEntityType>
3802 if (psdu->GetAddr2() ==
Mac48Address(
"00:00:00:00:00:01"))
3804 m_countRxFailureFromSta1++;
3806 else if (psdu->GetAddr2() ==
Mac48Address(
"00:00:00:00:00:02"))
3808 m_countRxFailureFromSta2++;
3812template <
typename LatestPhyEntityType>
3820 "The number of successfully received packets from STA 1 is not correct!");
3822 m_countRxFailureFromSta1,
3824 "The number of unsuccessfully received packets from STA 1 is not correct!");
3827 "The number of bytes received from STA 1 is not correct!");
3830template <
typename LatestPhyEntityType>
3838 "The number of successfully received packets from STA 2 is not correct!");
3840 m_countRxFailureFromSta2,
3842 "The number of unsuccessfully received packets from STA 2 is not correct!");
3845 "The number of bytes received from STA 2 is not correct!");
3848template <
typename LatestPhyEntityType>
3855 auto event = phy->GetCurrentEvent();
3857 auto rxPower =
event->GetRxPower(band);
3863 "RX power " << rxPower <<
" over (" << band
3864 <<
") does not match expected power " << expectedRxPower
3868template <
typename LatestPhyEntityType>
3882 if (expectedRxPower >
Watt_u{0.0})
3885 phy->GetEnergyDuration(expectedRxPower - step, band).IsStrictlyPositive(),
3887 "At least " << expectedRxPower <<
" W expected for OFDMA part over (" << band <<
") at "
3890 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3892 "At most " << expectedRxPower <<
" W expected for OFDMA part over (" << band <<
") at "
3898 phy->GetEnergyDuration(expectedRxPower + step, band).IsStrictlyPositive(),
3900 "At most " << expectedRxPower <<
" W expected for OFDMA part over (" << band <<
") at "
3905template <
typename LatestPhyEntityType>
3911 "m_currentEvent for AP was not cleared");
3914 "m_currentEvent for STA 1 was not cleared");
3917 "m_currentEvent for STA 2 was not cleared");
3920template <
typename LatestPhyEntityType>
3934template <
typename LatestPhyEntityType>
3942 phy->GetAttribute(
"State", ptr);
3944 currentState = state->GetState();
3948 "PHY State " << currentState <<
" does not match expected state "
3952template <
typename LatestPhyEntityType>
3955 Time expectedLastNotification)
3958 expectedNotifications,
3959 "Number of RX start notifications "
3960 << m_apPhyStateListener->GetNumRxStartNotifications()
3961 <<
" does not match expected count " << expectedNotifications
3964 expectedLastNotification,
3965 "Last time RX start notification has been received "
3966 << m_apPhyStateListener->GetLastRxStartNotification()
3967 <<
" does not match expected time " << expectedLastNotification
3971template <
typename LatestPhyEntityType>
3974 Time expectedLastNotification,
3975 bool expectedSuccess)
3978 expectedNotifications,
3979 "Number of RX end notifications "
3980 << m_apPhyStateListener->GetNumRxEndNotifications()
3981 <<
" does not match expected count " << expectedNotifications
3984 expectedLastNotification,
3985 "Last time RX end notification has been received "
3986 << m_apPhyStateListener->GetLastRxEndNotification()
3987 <<
" does not match expected time " << expectedLastNotification
3991 "Last time RX end notification indicated a "
3992 << (m_apPhyStateListener->IsLastRxSuccess() ?
"success" :
"failure")
3993 <<
" but expected a " << (expectedSuccess ?
"success" :
"failure")
3997template <
typename LatestPhyEntityType>
4001 m_countRxSuccessFromSta1 = 0;
4002 m_countRxSuccessFromSta2 = 0;
4003 m_countRxFailureFromSta1 = 0;
4004 m_countRxFailureFromSta2 = 0;
4005 m_countRxBytesFromSta1 = 0;
4006 m_countRxBytesFromSta2 = 0;
4007 m_phySta1->SetPpduUid(0);
4008 m_phySta1->SetTriggerFrameUid(0);
4009 m_phySta2->SetTriggerFrameUid(0);
4010 SetBssColor(m_phyAp, 0);
4011 m_apPhyStateListener->Reset();
4014template <
typename LatestPhyEntityType>
4020 heConfiguration->m_bssColor = bssColor;
4023template <
typename LatestPhyEntityType>
4029 phy->SetAttribute(
"PowerDensityLimit",
DoubleValue(psdLimit));
4032template <
typename LatestPhyEntityType>
4036 const auto standard =
4041 lossModel->SetFrequency(m_frequency);
4042 spectrumChannel->AddPropagationLossModel(lossModel);
4045 spectrumChannel->SetPropagationDelayModel(delayModel);
4049 preambleDetectionModel->SetAttribute(
4053 preambleDetectionModel->SetAttribute(
"Threshold",
DoubleValue(-100));
4057 apDev->SetStandard(standard);
4061 apMac->SetAttribute(
"BeaconGeneration",
BooleanValue(
false));
4062 apDev->SetMac(apMac);
4065 apDev->SetHeConfiguration(heConfiguration);
4071 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
4073 m_phyAp->SetErrorRateModel(apErrorModel);
4074 m_phyAp->SetDevice(apDev);
4075 m_phyAp->AddChannel(spectrumChannel);
4076 m_phyAp->ConfigureStandard(standard);
4077 m_phyAp->SetReceiveOkCallback(
4079 m_phyAp->SetReceiveErrorCallback(
4081 m_phyAp->SetPreambleDetectionModel(preambleDetectionModel);
4083 m_phyAp->SetMobility(apMobility);
4084 m_apPhyStateListener = std::make_unique<OfdmaTestPhyListener>();
4085 m_phyAp->RegisterListener(m_apPhyStateListener);
4086 apDev->SetPhy(m_phyAp);
4087 apMac->SetWifiPhys({m_phyAp});
4088 apNode->AggregateObject(apMobility);
4089 apNode->AddDevice(apDev);
4093 sta1Dev->SetStandard(standard);
4101 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
4103 m_phySta1->SetErrorRateModel(sta1ErrorModel);
4104 m_phySta1->SetDevice(sta1Dev);
4105 m_phySta1->AddChannel(spectrumChannel);
4106 m_phySta1->ConfigureStandard(standard);
4107 m_phySta1->SetPreambleDetectionModel(preambleDetectionModel);
4109 m_phySta1->SetMobility(sta1Mobility);
4110 sta1Dev->SetPhy(m_phySta1);
4111 sta1Node->AggregateObject(sta1Mobility);
4112 sta1Node->AddDevice(sta1Dev);
4116 sta2Dev->SetStandard(standard);
4124 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
4126 m_phySta2->SetErrorRateModel(sta2ErrorModel);
4127 m_phySta2->SetDevice(sta2Dev);
4128 m_phySta2->AddChannel(spectrumChannel);
4129 m_phySta2->ConfigureStandard(standard);
4130 m_phySta2->SetPreambleDetectionModel(preambleDetectionModel);
4132 m_phySta2->SetMobility(sta2Mobility);
4133 sta2Dev->SetPhy(m_phySta2);
4134 sta2Node->AggregateObject(sta2Mobility);
4135 sta2Node->AddDevice(sta2Dev);
4139 sta3Dev->SetStandard(standard);
4147 m_phySta3->SetInterferenceHelper(sta3InterferenceHelper);
4149 m_phySta3->SetErrorRateModel(sta3ErrorModel);
4150 m_phySta3->SetDevice(sta3Dev);
4151 m_phySta3->AddChannel(spectrumChannel);
4152 m_phySta3->ConfigureStandard(standard);
4153 m_phySta3->SetPreambleDetectionModel(preambleDetectionModel);
4155 m_phySta3->SetMobility(sta3Mobility);
4156 sta3Dev->SetPhy(m_phySta3);
4157 sta3Node->AggregateObject(sta3Mobility);
4158 sta3Node->AddDevice(sta3Dev);
4163 m_phyInterferer->SetDevice(interfererDev);
4164 m_phyInterferer->SetChannel(spectrumChannel);
4165 m_phyInterferer->SetDutyCycle(1);
4166 interfererNode->AddDevice(interfererDev);
4169 std::list<Ptr<WifiPhy>> phys{m_phyAp, m_phySta1, m_phySta2, m_phySta3};
4170 for (
auto& phy : phys)
4173 phy->SetAttribute(
"TxPowerStart",
DoubleValue(16.0));
4174 phy->SetAttribute(
"TxPowerEnd",
DoubleValue(16.0));
4175 phy->SetAttribute(
"PowerDensityLimit",
DoubleValue(100.0));
4178 phy->SetAttribute(
"TxMaskInnerBandMinimumRejection",
DoubleValue(-100.0));
4179 phy->SetAttribute(
"TxMaskOuterBandMinimumRejection",
DoubleValue(-100.0));
4180 phy->SetAttribute(
"TxMaskOuterBandMaximumRejection",
DoubleValue(-100.0));
4184template <
typename LatestPhyEntityType>
4190 m_phySta1->Dispose();
4191 m_phySta1 =
nullptr;
4192 m_phySta2->Dispose();
4193 m_phySta2 =
nullptr;
4194 m_phySta3->Dispose();
4195 m_phySta3 =
nullptr;
4196 m_phyInterferer->Dispose();
4197 m_phyInterferer =
nullptr;
4200template <
typename LatestPhyEntityType>
4207template <
typename LatestPhyEntityType>
4218 bool scheduleTxSta1,
4219 Time ulTimeDifference,
4223 static uint64_t uid = 0;
4249 m_apPhyStateListener.get());
4277 expectedStateBeforeEnd);
4282 expectedStateAtEnd);
4285 if (expectedSuccessFromSta1 + expectedFailuresFromSta1 + expectedSuccessFromSta2 +
4286 expectedFailuresFromSta2 >
4290 const bool isSuccess = (expectedSuccessFromSta1 > 0) || (expectedSuccessFromSta2 > 0);
4297 const Time expectedPayloadEnd = delay + m_expectedPpduDuration + ulTimeDifference;
4320 expectedSuccessFromSta1,
4321 expectedFailuresFromSta1,
4322 expectedBytesFromSta1);
4327 expectedSuccessFromSta2,
4328 expectedFailuresFromSta2,
4329 expectedBytesFromSta2);
4339template <
typename LatestPhyEntityType>
4343 Watt_u rxPowerNonOfdmaRu1,
4344 Watt_u rxPowerNonOfdmaRu2,
4349 const auto txVectorSta1 = GetTxVectorForTbPpdu(1, 1, 0);
4350 const auto txVectorSta2 = GetTxVectorForTbPpdu(2, 2, 0);
4352 const auto nonOfdmaDuration = phyEntity->CalculateNonHeDurationForHeTb(txVectorSta2);
4353 NS_ASSERT(nonOfdmaDuration == phyEntity->CalculateNonHeDurationForHeTb(txVectorSta1));
4355 std::vector<Watt_u> rxPowerNonOfdma{rxPowerNonOfdmaRu1, rxPowerNonOfdmaRu2};
4356 std::vector<WifiSpectrumBandInfo> nonOfdmaBand{phyEntity->GetNonOfdmaBand(txVectorSta1, 1),
4357 phyEntity->GetNonOfdmaBand(txVectorSta2, 2)};
4358 std::vector<Watt_u> rxPowerOfdma{rxPowerOfdmaRu1, rxPowerOfdmaRu2};
4359 std::vector<WifiSpectrumBandInfo> ofdmaBand{phyEntity->GetRuBandForRx(txVectorSta1, 1),
4360 phyEntity->GetRuBandForRx(txVectorSta2, 2)};
4362 for (uint8_t i = 0; i < 2; ++i)
4369 delay + detectionDuration +
4375 rxPowerNonOfdma[i]);
4381 rxPowerNonOfdma[i]);
4405 delay + detectionDuration +
4411 rxPowerNonOfdma[i]);
4417 rxPowerNonOfdma[i]);
4435 if (rxPowerOfdmaRu1 !=
Watt_u{0.0})
4442 const auto rxPowerNonOfdmaSta1Only =
4443 (m_channelWidth >=
MHz_u{40})
4444 ? rxPowerNonOfdma[0]
4445 : rxPowerNonOfdma[0] / 2;
4448 delay + detectionDuration +
4454 rxPowerNonOfdmaSta1Only);
4460 rxPowerNonOfdmaSta1Only);
4479template <
typename LatestPhyEntityType>
4483 NS_LOG_DEBUG(
"Run UL OFDMA PHY transmission test for " << m_channelWidth <<
" MHz");
4487 int64_t streamNumber = 0;
4488 m_phyAp->AssignStreams(streamNumber);
4489 m_phySta1->AssignStreams(streamNumber);
4490 m_phySta2->AssignStreams(streamNumber);
4491 m_phySta3->AssignStreams(streamNumber);
4493 const auto standard =
4502 const auto operatingChannel{
4504 m_phyAp->SetOperatingChannel(operatingChannel);
4505 m_phySta1->SetOperatingChannel(operatingChannel);
4506 m_phySta2->SetOperatingChannel(operatingChannel);
4507 m_phySta3->SetOperatingChannel(operatingChannel);
4526 "Reception of solicited HE TB PPDUs");
4545 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals");
4564 "Dropping of unsolicited HE TB PPDUs");
4576 WifiPhyState::CCA_BUSY);
4584 "Dropping of HE TB PPDUs with channel width differing from TRIGVECTOR");
4596 WifiPhyState::CCA_BUSY,
4605 "Dropping of HE TB PPDUs with UL Length differing from TRIGVECTOR");
4617 WifiPhyState::CCA_BUSY,
4626 "Dropping of HE TB PPDUs with AIDs differing from TRIGVECTOR");
4638 WifiPhyState::CCA_BUSY,
4649 "Reception of solicited HE TB PPDUs with interference on RU 1 during PSDU reception");
4652 bandInfo.
fc =
MHzToHz(m_frequency - (m_channelWidth / 4));
4653 bandInfo.
fl = bandInfo.
fc -
MHzToHz(m_channelWidth / 4);
4654 bandInfo.
fh = bandInfo.
fc +
MHzToHz(m_channelWidth / 4);
4656 bands.push_back(bandInfo);
4660 Watt_u interferencePower{0.1};
4661 *interferencePsdRu1 = interferencePower / (
MHzToHz(m_channelWidth / 2) * 20);
4671 WifiPhyState::CCA_BUSY,
4688 "Reception of solicited HE TB PPDUs with interference on RU 2 during PSDU reception");
4690 bandInfo.
fc =
MHzToHz(m_frequency + (m_channelWidth / 4));
4691 bandInfo.
fl = bandInfo.
fc -
MHzToHz(m_channelWidth / 4);
4692 bandInfo.
fh = bandInfo.
fc +
MHzToHz(m_channelWidth / 4);
4694 bands.push_back(bandInfo);
4698 *interferencePsdRu2 = interferencePower / (
MHzToHz(m_channelWidth / 2) * 20);
4707 (m_channelWidth >=
MHz_u{40})
4708 ? WifiPhyState::IDLE
4709 : WifiPhyState::CCA_BUSY,
4726 "Reception of solicited HE TB PPDUs with interference on the full band "
4727 "during PSDU reception");
4730 bandInfo.
fl = bandInfo.
fc -
MHzToHz(m_channelWidth / 2);
4731 bandInfo.
fh = bandInfo.
fc +
MHzToHz(m_channelWidth / 2);
4733 bands.push_back(bandInfo);
4737 *interferencePsdAll = interferencePower / (
MHzToHz(m_channelWidth) * 20);
4747 WifiPhyState::CCA_BUSY,
4765 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4766 "1 during PSDU reception");
4781 if (m_channelWidth >
MHz_u{20})
4799 WifiPhyState::CCA_BUSY,
4817 "Reception of solicited HE TB PPDUs with another HE TB PPDU arriving on RU "
4818 "2 during PSDU reception");
4830 if (m_channelWidth >
MHz_u{20})
4848 (m_channelWidth >=
MHz_u{40})
4849 ? WifiPhyState::IDLE
4850 : WifiPhyState::CCA_BUSY,
4868 "Reception of solicited HE TB PPDUs with an HE SU PPDU arriving during the 400 ns window");
4895 "Reception of solicited HE TB PPDU only on RU 2");
4902 (m_channelWidth >=
MHz_u{40})
4903 ? WifiPhyState::IDLE
4904 : WifiPhyState::CCA_BUSY);
4925 "Measure power for reception of HE TB PPDU only on RU 2");
4928 SchedulePowerMeasurementChecks(delay,
4929 (m_channelWidth >=
MHz_u{40}) ?
Watt_u{0.0} : rxPower,
4954 "Measure power for reception of HE TB PPDU only on RU 2 with PSD limitation");
4963 rxPower = (m_channelWidth >
MHz_u{40})
4967 auto rxPowerOfdma = rxPower;
4968 if (m_channelWidth <=
MHz_u{40})
4971 (m_channelWidth ==
MHz_u{20})
4975 SchedulePowerMeasurementChecks(delay,
4976 (m_channelWidth >=
MHz_u{40}) ?
Watt_u{0.0} : rxPower,
5006 "Measure power for reception of HE TB PPDU on both RUs");
5009 const auto rxPowerNonOfdma =
5010 (m_channelWidth >=
MHz_u{40})
5013 SchedulePowerMeasurementChecks(delay, rxPowerNonOfdma, rxPowerNonOfdma, rxPower, rxPower);
5031 "Reception of an HE TB PPDU from another BSS");
5065 "Reception of solicited HE TB PPDUs with delay (< 400ns) between the two signals and "
5066 "reception of an HE TB PPDU from another BSS between the ends of the two HE TB PPDUs");
5083 WifiPhyState::CCA_BUSY,
5097template <
typename LatestPhyEntityType>
5101 m_frequency =
MHz_u{5955};
5102 m_channelWidth =
MHz_u{20};
5106 m_frequency =
MHz_u{5965};
5107 m_channelWidth =
MHz_u{40};
5111 m_frequency =
MHz_u{5985};
5112 m_channelWidth =
MHz_u{80};
5116 m_frequency =
MHz_u{6025};
5117 m_channelWidth =
MHz_u{160};
5123 m_frequency =
MHz_u{6105};
5124 m_channelWidth =
MHz_u{320};
5147 void DoRun()
override;
5156 void SendTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize,
Time txDuration);
5229 const std::vector<bool>& statusPerMpdu);
5252 :
TestCase(
"PHY padding exclusion test"),
5253 m_countRxSuccessFromSta1(0),
5254 m_countRxSuccessFromSta2(0),
5255 m_countRxFailureFromSta1(0),
5256 m_countRxFailureFromSta2(0),
5257 m_countRxBytesFromSta1(0),
5258 m_countRxBytesFromSta2(0)
5265 std::size_t payloadSize,
5283 txVector.SetRu(ru, txStaId);
5285 txVector.SetNss(1, txStaId);
5292 std::ostringstream addr;
5293 addr <<
"00:00:00:00:00:0" << txStaId;
5297 psdus.insert(std::make_pair(txStaId, psdu));
5304 else if (txStaId == 2)
5313 phy->Send(psdus, txVector);
5339 const std::vector<bool>& )
5341 NS_LOG_FUNCTION(
this << *psdu << psdu->GetAddr2() << rxSignalInfo << txVector);
5342 if (psdu->GetAddr2() ==
Mac48Address(
"00:00:00:00:00:01"))
5347 else if (psdu->GetAddr2() ==
Mac48Address(
"00:00:00:00:00:02"))
5358 if (psdu->GetAddr2() ==
Mac48Address(
"00:00:00:00:00:01"))
5362 else if (psdu->GetAddr2() ==
Mac48Address(
"00:00:00:00:00:02"))
5375 "The number of successfully received packets from STA 1 is not correct!");
5379 "The number of unsuccessfully received packets from STA 1 is not correct!");
5382 "The number of bytes received from STA 1 is not correct!");
5392 "The number of successfully received packets from STA 2 is not correct!");
5396 "The number of unsuccessfully received packets from STA 2 is not correct!");
5399 "The number of bytes received from STA 2 is not correct!");
5407 "m_currentEvent for AP was not cleared");
5410 "m_currentEvent for STA 1 was not cleared");
5413 "m_currentEvent for STA 2 was not cleared");
5429 WifiPhyState currentState = phy->GetState()->GetState();
5433 "PHY State " << currentState <<
" does not match expected state "
5456 int64_t streamNumber = 0;
5461 spectrumChannel->AddPropagationLossModel(lossModel);
5464 spectrumChannel->SetPropagationDelayModel(delayModel);
5471 apMac->SetAttribute(
"BeaconGeneration",
BooleanValue(
false));
5472 apDev->SetMac(apMac);
5475 apDev->SetHeConfiguration(heConfiguration);
5477 m_phyAp->SetInterferenceHelper(apInterferenceHelper);
5479 m_phyAp->SetErrorRateModel(apErrorModel);
5481 m_phyAp->AddChannel(spectrumChannel);
5483 m_phyAp->AssignStreams(streamNumber);
5496 m_phyAp->SetMobility(apMobility);
5500 apMac->SetWifiPhys({
m_phyAp});
5501 apNode->AggregateObject(apMobility);
5502 apNode->AddDevice(apDev);
5508 m_phySta1->SetInterferenceHelper(sta1InterferenceHelper);
5510 m_phySta1->SetErrorRateModel(sta1ErrorModel);
5522 sta1Node->AggregateObject(sta1Mobility);
5523 sta1Node->AddDevice(sta1Dev);
5529 m_phySta2->SetInterferenceHelper(sta2InterferenceHelper);
5531 m_phySta2->SetErrorRateModel(sta2ErrorModel);
5543 sta2Node->AggregateObject(sta2Mobility);
5544 sta2Node->AddDevice(sta2Dev);
5552 interfererNode->AddDevice(interfererDev);
5582 trigVector.SetRu(
HeRu::RuSpec(RuType::RU_106_TONE, 1,
false), 1);
5584 trigVector.SetNss(1, 1);
5585 trigVector.SetRu(
HeRu::RuSpec(RuType::RU_106_TONE, 2,
false), 2);
5587 trigVector.SetNss(1, 2);
5589 std::tie(length, ppduDuration) =
5591 trigVector.SetLength(length);
5593 hePhyAp->SetTrigVector(trigVector, ppduDuration);
5600 Time ppduWithPaddingDuration =
5601 expectedPpduDuration + 10 *
NanoSeconds(12800 + 1600 );
5612 ppduWithPaddingDuration);
5619 ppduWithPaddingDuration);
5625 ppduWithPaddingDuration);
5637 WifiPhyState::IDLE);
5655 ppduWithPaddingDuration);
5662 ppduWithPaddingDuration);
5668 ppduWithPaddingDuration);
5676 bands.push_back(bandInfo);
5680 Watt_u interferencePower{0.1};
5700 WifiPhyState::CCA_BUSY);
5732 void DoRun()
override;
5739 void SendMuBar(std::vector<uint16_t> staIds);
5755 void RunOne(
bool setupBa);
5775 const std::vector<bool>& statusPerMpdu);
5800 :
TestCase(
"UL-OFDMA power control test"),
5802 m_txPowerAp(
dBm_u{0}),
5803 m_txPowerStart(
dBm_u{0}),
5804 m_txPowerEnd(
dBm_u{0}),
5806 m_requestedRssiSta1(
dBm_u{0}),
5807 m_requestedRssiSta2(
dBm_u{0}),
5808 m_rssiSta1(
dBm_u{0}),
5809 m_rssiSta2(
dBm_u{0}),
5827 m_apDev->Send(pkt, destination, 0);
5833 NS_ASSERT(!staIds.empty() && staIds.size() <= 2);
5837 muBar.
SetType(TriggerFrameType::MU_BAR_TRIGGER);
5845 RuType ru = (staIds.size() == 1) ? RuType::RU_242_TONE : RuType::RU_106_TONE;
5846 std::size_t index = 1;
5847 int8_t ulTargetRssi = -40;
5848 for (
const auto& staId : staIds)
5861 else if (staId == 2)
5901 bar->AddHeader(muBar);
5904 if (staIds.size() == 1)
5907 if (staIds.front() == aidSta1)
5930 auto nav =
m_apDev->GetPhy()->GetSifs();
5931 const auto staId = staIds.front();
5936 psdu->SetDuration(nav);
5937 psdus.insert(std::make_pair(
SU_STA_ID, psdu));
5939 m_phyAp->Send(psdus, txVector);
5946 const std::vector<bool>& )
5949 const auto rssi = rxSignalInfo.
rssi;
5951 const auto& hdr = psdu->GetHeader(0);
5953 if (hdr.GetAddr2() ==
m_sta1Dev->GetAddress())
5959 "The obtained RSSI from STA 1 at AP is different from the expected one ("
5960 << rssi <<
" vs " <<
m_rssiSta1 <<
", with tolerance of " <<
m_tol <<
")");
5962 else if (psdu->GetAddr2() ==
m_sta2Dev->GetAddress())
5968 "The obtained RSSI from STA 2 at AP is different from the expected one ("
5969 << rssi <<
" vs " <<
m_rssiSta2 <<
", with tolerance of " <<
m_tol <<
")");
5981 m_phyAp->SetReceiveOkCallback(
5994 spectrumChannel->AddPropagationLossModel(lossModel);
5996 spectrumChannel->SetPropagationDelayModel(delayModel);
6001 spectrumPhy.
Set(
"ChannelSettings",
StringValue(
"{0, 0, BAND_5GHZ, 0}"));
6005 wifi.SetRemoteStationManager(
"ns3::ConstantRateWifiManager",
6012 mac.SetType(
"ns3::StaWifiMac");
6013 auto staDevs = wifi.Install(spectrumPhy, mac, staNodes);
6023 mac.SetType(
"ns3::ApWifiMac",
6037 mobility.SetMobilityModel(
"ns3::ConstantPositionMobilityModel");
6039 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
6040 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
6042 Vector(2.0, 0.0, 0.0));
6043 mobility.SetPositionAllocator(positionAlloc);
6045 mobility.Install(apNode);
6046 mobility.Install(staNodes);
6048 lossModel->SetDefaultLoss(50.0);
6073 int64_t streamNumber = 0;
6078 m_phyAp->AssignStreams(streamNumber);
6079 phySta1->AssignStreams(streamNumber);
6080 phySta2->AssignStreams(streamNumber);
6094 Time relativeStart{};
6113 apMac->SetAttribute(
"BeaconGeneration",
BooleanValue(
false));
6122 std::vector<uint16_t> staIds{1};
6128 std::vector<uint16_t> staIds{2};
6137 std::vector<uint16_t> staIds{1, 2};
SpectrumWifiPhy used for testing OFDMA.
Ptr< Event > GetCurrentEvent()
void SetTriggerFrameUid(uint64_t uid)
Since we assume trigger frame was previously received from AP, this is used to set its UID.
TracedCallback< uint64_t > m_phyTxPpduUidTrace
Callback providing UID of the PPDU that is about to be transmitted.
Ptr< LatestPhyEntityType > GetPhyEntity() const
static TypeId GetTypeId()
Get the type ID.
Ptr< OfdmaTestPhy< LatestPhyEntityType > > m_ofdmaTestPhy
Pointer to latest PHY entity instance used for OFDMA test.
std::map< std::pair< uint64_t, WifiPreamble >, Ptr< Event > > & GetCurrentPreambleEvents()
void DoDispose() override
Destructor implementation.
Time GetEnergyDuration(Watt_u energy, WifiSpectrumBandInfo band)
Wrapper to InterferenceHelper method.
void SetPpduUid(uint64_t uid)
Set the global PPDU UID counter.
void(* TxPpduUidCallback)(uint64_t uid)
TracedCallback signature for UID of transmitted PPDU.
void DoInitialize() override
Initialize() implementation.
OfdmaSpectrumWifiPhy(uint16_t staId)
Constructor.
void StartTx(Ptr< const WifiPpdu > ppdu) override
PHY entity slightly modified so as to return a given STA-ID in case of DL MU for OfdmaSpectrumWifiPhy...
void SetGlobalPpduUid(uint64_t uid)
Set the global PPDU UID counter.
uint16_t m_staId
ID of the STA to which this PHY belongs to.
uint16_t GetStaId(const Ptr< const WifiPpdu > ppdu) const override
Return the STA ID that has been assigned to the station this PHY belongs to.
WifiSpectrumBandInfo GetNonOfdmaBand(const WifiTxVector &txVector, uint16_t staId) const
Get the band used to transmit the non-OFDMA part of an HE TB PPDU.
OfdmaTestPhy(uint16_t staId)
Constructor.
PHY listener for OFDMA tests.
OfdmaTestPhyListener()=default
bool m_lastRxSuccess
flag whether last RX has been successful
void NotifyRxStart(Time duration) override
Time GetLastRxStartNotification() const
Return the time at which the last RX start notification has been received.
void NotifySwitchingStart(Time duration) override
void NotifyWakeup() override
Notify listeners that we woke up.
uint32_t m_notifyRxStart
count number of RX start notifications
void Reset()
Reset function.
Time m_lastRxEnd
last time a RX end notification has been received
Time m_lastRxStart
last time a RX start notification has been received
Time GetLastRxEndNotification() const
Return the time at which the last RX end notification has been received.
void NotifyCcaBusyStart(Time duration, WifiChannelListType channelType, const std::vector< Time > &) override
uint32_t m_notifyRxEnd
count number of RX end notifications
bool IsLastRxSuccess() const
Return whether last RX has been successful.
void NotifySleep() override
Notify listeners that we went to sleep.
uint32_t GetNumRxEndNotifications() const
Return the number of RX end notifications that has been received since the last reset.
void NotifyRxEndOk() override
We have received the last bit of a packet for which NotifyRxStart was invoked first and,...
void NotifyTxStart(Time duration, dBm_u txPower) override
uint32_t GetNumRxStartNotifications() const
Return the number of RX start notifications that has been received since the last reset.
void NotifyRxEndError(const WifiTxVector &txVector) override
void NotifyOff() override
Notify listeners that we went to switch off.
void NotifyOn() override
Notify listeners that we went to switch on.
DL-OFDMA PHY puncturing test.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void DoRun() override
Implementation to actually run this TestCase.
TestDlOfdmaPhyPuncturing()
Time m_expectedPpduDuration20Mhz
expected duration to send MU PPDU on 20 MHz RU
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
void ResetResults()
Reset the results.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
void RunOne()
Run one function.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy< HePhy > > phy, WifiPhyState expectedState)
Check the PHY state now.
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2, const std::vector< bool > &puncturedSubchannels)
Send MU-PPDU function.
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 2.
Time m_expectedPpduDuration40Mhz
expected duration to send MU PPDU on 40 MHz RU
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
MHz_u m_frequency
frequency
MHz_u m_channelWidth
channel width
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phySta2
PHY of STA 2.
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phySta1
PHY of STA 1.
void StopInterference()
Stop interference function.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 1.
uint8_t m_indexSubchannel
Index of the subchannel (starting from 0) that should contain an interference and be punctured during...
uint32_t m_countRxSuccessSta1
count RX success for STA 1
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy< HePhy > > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > m_phySta1
PHY of STA 1.
uint32_t m_countRxSuccessSta3
count RX success for STA 3
uint32_t m_countRxBytesSta3
count RX bytes for STA 3
void DoRun() override
Implementation to actually run this TestCase.
Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > m_phySta3
PHY of STA 3.
void StopInterference()
Stop interference function.
void CheckResultsSta1(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 1.
void RxFailureSta3(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 3.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void RxFailureSta2(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 2.
void RunOne()
Run one function.
uint32_t m_countRxFailureSta3
count RX failure for STA 3
uint32_t m_countRxBytesSta2
count RX bytes for STA 2
TestDlOfdmaPhyTransmission()
Constructor.
void ResetResults()
Reset the results.
Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > m_phySta2
PHY of STA 2.
void RxSuccessSta3(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 3.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > phy, WifiPhyState expectedState)
Schedule now to check the PHY state.
MHz_u m_frequency
frequency
uint32_t m_countRxBytesSta1
count RX bytes for STA 1
void CheckResultsSta2(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 2.
void RxSuccessSta1(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 1.
Time m_expectedPpduDuration
expected duration to send MU PPDU
void RxFailureSta1(Ptr< const WifiPsdu > psdu)
Receive failure function for STA 1.
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
MHz_u m_channelWidth
channel width
void CheckResultsSta3(uint32_t expectedRxSuccess, uint32_t expectedRxFailure, uint32_t expectedRxBytes)
Check the results for STA 3.
uint32_t m_countRxFailureSta1
count RX failure for STA 1
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > phy, WifiPhyState expectedState)
Check the PHY state now.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxSuccessSta2
count RX success for STA 2
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
WifiModulationClass m_modClass
the modulation class to consider for the test
uint32_t m_countRxFailureSta2
count RX failure for STA 2
void RxSuccessSta2(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function for STA 2.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendMuPpdu(uint16_t rxStaId1, uint16_t rxStaId2)
Send MU-PPDU function.
uint32_t m_countRxSuccessSta1
count RX success for STA 1
UL-OFDMA multiple RX events test.
WifiTxVector m_trigVector
TRIGVECTOR.
void RxHeTbPpdu(uint64_t uid, uint16_t staId, Watt_u txPower, size_t payloadSize)
Receive HE TB PPDU function.
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phy
Phy.
void Reset()
Reset function.
~TestMultipleHeTbPreambles() override
void RxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void CheckHeTbPreambles(size_t nEvents, std::vector< uint64_t > uids)
Check the received HE TB preambles.
TestMultipleHeTbPreambles()
uint64_t m_totalBytesDropped
total number of dropped bytes
void CheckBytesDropped(size_t expectedBytesDropped)
Check the number of bytes dropped.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
void RxDropped(Ptr< const Packet > p, WifiPhyRxfailureReason reason)
RX dropped function.
void DoRxHeTbPpduOfdmaPart(Ptr< WifiSpectrumSignalParameters > rxParamsOfdma)
Receive OFDMA part of HE TB PPDU function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
PHY padding exclusion test.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy< HePhy > > phy, WifiPhyState expectedState)
Check the PHY state.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
TestPhyPaddingExclusion()
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
~TestPhyPaddingExclusion() override
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
void DoRun() override
Implementation to actually run this TestCase.
void SendTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, Time txDuration)
Send HE TB PPDU function.
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phySta1
PHY of STA 1.
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phySta2
PHY of STA 2.
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function.
void SetTrigVector(Time ppduDuration)
Set TRIGVECTOR for HE TB PPDU.
void Reset()
Reset function.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
void StopInterference()
Stop interference function.
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phyAp
PHY of AP.
void RunOne()
Run one function.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy< HePhy > > phy, WifiPhyState expectedState)
Check the PHY state.
void SetPsdLimit(Ptr< WifiPhy > phy, dBm_per_MHz_u psdLimit)
Set the PSD limit.
void StopInterference()
Stop interference function.
Time m_expectedPpduDuration
expected duration to send MU PPDU
Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > m_phySta2
PHY of STA 2.
void RxSuccess(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive success function.
void RunOne()
Run one function.
void DoCheckPhyState(Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > phy, WifiPhyState expectedState)
Check the PHY state.
void CheckApRxEnd(uint32_t expectedNotifications, Time expectedLastNotification, bool expectedSuccess)
Check the the number of RX end notifications at the AP as well as the last time a RX end has been not...
uint32_t m_countRxSuccessFromSta1
count RX success from STA 1
uint32_t m_countRxFailureFromSta2
count RX failure from STA 2
uint32_t m_countRxSuccessFromSta2
count RX success from STA 2
uint32_t m_countRxBytesFromSta1
count RX bytes from STA 1
WifiTxVector GetTxVectorForTbPpdu(uint16_t txStaId, std::size_t index, uint8_t bssColor) const
Get TXVECTOR for HE PPDU.
Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > m_phySta3
PHY of STA 3.
Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > m_phySta1
PHY of STA 1.
void SchedulePowerMeasurementChecks(Time delay, Watt_u rxPowerNonOfdmaRu1, Watt_u rxPowerNonOfdmaRu2, Watt_u rxPowerOfdmaRu1, Watt_u rxPowerOfdmaRu2)
Schedule power measurement related checks.
void SendTbPpdu(uint16_t txStaId, std::size_t index, std::size_t payloadSize, uint64_t uid, uint8_t bssColor, bool incrementUid)
Send HE TB PPDU function.
void CheckPhyState(Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > phy, WifiPhyState expectedState)
Check the PHY state.
TrigVectorInfo
Erroneous info included in a TRIGVECTOR.
void CheckNonOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > phy, WifiSpectrumBandInfo band, Watt_u expectedRxPower)
Check the received power for the non-OFDMA of the HE TB PPDUs over the given band.
void Reset()
Reset function.
void CheckOfdmaRxPower(Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > phy, WifiSpectrumBandInfo band, Watt_u expectedRxPower)
Check the received power for the OFDMA part of the HE TB PPDUs over the given band.
WifiModulationClass m_modClass
the modulation class to consider for the test
void CheckRxFromSta1(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA1.
uint32_t m_countRxFailureFromSta1
count RX failure from STA 1
TestUlOfdmaPhyTransmission()
void RxFailure(Ptr< const WifiPsdu > psdu)
Receive failure function.
void CheckApRxStart(uint32_t expectedNotifications, Time expectedLastNotification)
Check the the number of RX start notifications at the AP as well as the last time a RX start has been...
void DoRun() override
Implementation to actually run this TestCase.
void LogScenario(std::string log) const
Log scenario description.
void ScheduleTest(Time delay, bool solicited, WifiPhyState expectedStateAtEnd, uint32_t expectedSuccessFromSta1, uint32_t expectedFailuresFromSta1, uint32_t expectedBytesFromSta1, uint32_t expectedSuccessFromSta2, uint32_t expectedFailuresFromSta2, uint32_t expectedBytesFromSta2, bool scheduleTxSta1=true, Time ulTimeDifference=Seconds(0), WifiPhyState expectedStateBeforeEnd=WifiPhyState::RX, TrigVectorInfo error=NONE)
Schedule test to perform.
void CheckRxFromSta2(uint32_t expectedSuccess, uint32_t expectedFailures, uint32_t expectedBytes)
Check the received PSDUs from STA2.
MHz_u m_frequency
frequency
Ptr< OfdmaSpectrumWifiPhy< LatestPhyEntityType > > m_phyAp
PHY of AP.
MHz_u m_channelWidth
channel width
void VerifyEventsCleared()
Verify all events are cleared at end of TX or RX.
void SendSuPpdu(uint16_t txStaId, std::size_t payloadSize, uint64_t uid, uint8_t bssColor)
Send HE SU PPDU function.
std::shared_ptr< OfdmaTestPhyListener > m_apPhyStateListener
listener for AP PHY state transitions
void GenerateInterference(Ptr< SpectrumValue > interferencePsd, Time duration)
Generate interference function.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint32_t m_countRxBytesFromSta2
count RX bytes from STA 2
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
void SetBssColor(Ptr< WifiPhy > phy, uint8_t bssColor)
Set the BSS color.
Ptr< WaveformGenerator > m_phyInterferer
PHY of interferer.
void SetTrigVector(uint8_t bssColor, TrigVectorInfo error)
Set TRIGVECTOR for HE TB PPDU.
UL-OFDMA power control test.
dBm_u m_requestedRssiSta2
requested RSSI from STA 2 at AP for HE TB PPDUs
void DoRun() override
Implementation to actually run this TestCase.
Ptr< WifiNetDevice > m_sta2Dev
network device of STA 2
dBm_u m_rssiSta2
expected RSSI from STA 2 at AP for HE TB PPDUs
dBm_u m_txPowerEnd
maximum transmission power for STAs
dBm_u m_txPowerStart
minimum transmission power for STAs
void SetupBa(Address destination)
Send a QoS Data packet to the destination station in order to set up a block Ack session (so that the...
Ptr< WifiNetDevice > m_sta1Dev
network device of STA 1
dBm_u m_rssiSta1
expected RSSI from STA 1 at AP for HE TB PPDUs
Ptr< WifiNetDevice > m_apDev
network device of AP
dBm_u m_requestedRssiSta1
requested RSSI from STA 1 at AP for HE TB PPDUs
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
uint8_t m_bssColor
BSS color.
void ReplaceReceiveOkCallbackOfAp()
Replace the AP's callback on its PHY's ReceiveOkCallback by the ReceiveOkCallbackAtAp method.
dBm_u m_txPowerAp
transmit power of AP
uint8_t m_txPowerLevels
number of transmission power levels for STAs
dB_u m_tol
tolerance between received and expected RSSIs
TestUlOfdmaPowerControl()
void RunOne(bool setupBa)
Run one simulation with an optional BA session set up phase.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
Ptr< SpectrumWifiPhy > m_phyAp
PHY of AP.
void ReceiveOkCallbackAtAp(Ptr< const WifiPsdu > psdu, RxSignalInfo rxSignalInfo, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Receive OK callback function at AP.
~TestUlOfdmaPowerControl() override
void SendMuBar(std::vector< uint16_t > staIds)
Send a MU BAR through the AP to the STAs listed in the provided vector.
UL-OFDMA PPDU UID attribution test.
~TestUlOfdmaPpduUid() override
void TxPpduSta1(uint64_t uid)
Transmitted PPDU information function for STA 1.
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phyAp
PHY of AP.
void ResetPpduUid()
Reset the global PPDU UID counter in WifiPhy.
void CheckUid(uint16_t staId, uint64_t expectedUid)
Check the UID of the transmitted PPDU.
void TxPpduAp(uint64_t uid)
Transmitted PPDU information function for AP.
void TxPpduSta2(uint64_t uid)
Transmitted PPDU information function for STA 2.
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phySta1
PHY of STA 1.
uint64_t m_ppduUidAp
UID of PPDU transmitted by AP.
uint64_t m_ppduUidSta1
UID of PPDU transmitted by STA1.
uint64_t m_ppduUidSta2
UID of PPDU transmitted by STA2.
void DoRun() override
Implementation to actually run this TestCase.
void DoTeardown() override
Implementation to do any local setup required for this TestCase.
Ptr< OfdmaSpectrumWifiPhy< HePhy > > m_phySta2
PHY of STA 2.
void SendMuPpdu()
Send MU-PPDU toward both STAs.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void SendTbPpdu()
Send TB-PPDU from both STAs.
void SendSuPpdu(uint16_t txStaId)
Send SU-PPDU function.
wifi PHY OFDMA Test Suite
a polymophic address class
AttributeValue implementation for Boolean.
User Info field of Trigger frames.
void SetAid12(uint16_t aid)
Set the AID12 subfield, which carries the 12 LSBs of the AID of the station for which this User Info ...
void SetUlFecCodingType(bool ldpc)
Set the UL FEC Coding Type subfield, which indicates whether BCC or LDPC is used.
void SetUlMcs(uint8_t mcs)
Set the UL MCS subfield, which indicates the MCS of the solicited HE TB PPDU.
void SetMuBarTriggerDepUserInfo(const CtrlBAckRequestHeader &bar)
Set the Trigger Dependent User Info subfield for the MU-BAR variant of Trigger frames,...
void SetUlDcm(bool dcm)
Set the UL DCM subfield, which indicates whether or not DCM is used.
void SetSsAllocation(uint8_t startingSs, uint8_t nSs)
Set the SS Allocation subfield, which is present when the AID12 subfield is neither 0 nor 2045.
void SetUlTargetRssi(int8_t dBm)
Set the UL Target RSSI subfield to indicate the expected receive signal power in dBm.
void SetRuAllocation(WifiRu::RuSpec ru)
Set the RU Allocation subfield according to the specified RU.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
static WifiMode GetEhtMcs7()
Return MCS 7 from EHT MCS values.
static WifiMode GetEhtMcs9()
Return MCS 9 from EHT MCS values.
static std::pair< bool, bool > GetPrimaryFlags(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
Get the primary flags of a given RU transmitted in a PPDU.
static std::size_t GetIndexIn80MHzSegment(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the index of a given RU transmitted in a PPDU within its 80 MHz segment.
static WifiMode GetHeMcs9()
Return MCS 9 from HE MCS values.
static WifiMode GetHeMcs7()
Return MCS 7 from HE MCS values.
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.
@ PSD_HE_PORTION
HE portion of an HE PPDU.
@ PSD_NON_HE_PORTION
Non-HE portion of an HE PPDU.
static std::size_t GetIndexIn80MHzSegment(MHz_u bw, RuType ruType, std::size_t phyIndex)
Get the index of a given RU transmitted in a PPDU within its 80 MHz segment.
static bool GetPrimary80MHzFlag(MHz_u bw, RuType ruType, std::size_t phyIndex, uint8_t p20Index)
Get the primary 80 MHz flag of a given RU transmitted in a PPDU.
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
AttributeValue implementation for Pointer.
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
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 EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
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.
void SetChannel(const Ptr< SpectrumChannel > channel)
void DoInitialize() override
Initialize() implementation.
void DoDispose() override
Destructor implementation.
void StartTx(Ptr< const WifiPpdu > ppdu) override
Hold variables of type string.
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Simulation virtual time values and global simulation resolution.
AttributeValue implementation for Time.
Forward calls to a chain of Callback.
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
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
create MAC layers for a ns3::WifiNetDevice.
void Set(std::string name, const AttributeValue &v)
void SetErrorRateModel(std::string type, Args &&... args)
Helper function used to set the error rate model.
std::tuple< uint8_t, MHz_u, WifiPhyBand, uint8_t > ChannelTuple
Tuple identifying a segment of an operating channel.
static Time GetPreambleDetectionDuration()
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
void Reset()
Reset data upon end of TX or RX.
receive notifications about PHY events.
static ConstIterator FindFirst(uint8_t number, MHz_u frequency, MHz_u width, WifiStandard standard, WifiPhyBand band, ConstIterator start=m_frequencyChannels.begin())
Find the first frequency segment matching the specified parameters.
This objects implements the PHY state machine of the Wifi device.
std::variant< HeRu::RuSpec, EhtRu::RuSpec > RuSpec
variant of the RU specification
static RuSpec FindOverlappingRu(MHz_u bw, RuSpec referenceRu, RuType searchedRuType)
Find the RU allocation of the given RU type overlapping the given reference RU allocation.
static MHz_u GetBandwidth(RuType ruType)
Get the approximate bandwidth occupied by a RU.
static RuType GetRuType(RuSpec ru)
Get the type of a given RU.
static SubcarrierGroup GetSubcarrierGroup(MHz_u bw, RuType ruType, std::size_t phyIndex, WifiModulationClass mc)
Get the subcarrier group of the RU having the given PHY index among all the RUs of the given type (nu...
static std::size_t GetPhyIndex(RuSpec ru, MHz_u bw, uint8_t p20Index)
Get the RU PHY index.
static Ptr< SpectrumValue > CreateHeMuOfdmTxPowerSpectralDensity(const std::vector< MHz_u > ¢erFrequencies, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, const std::vector< WifiSpectrumBandIndices > &ru)
Create a transmit power spectral density corresponding to the OFDMA part of HE TB PPDUs for a given R...
static Ptr< SpectrumValue > CreateHeOfdmTxPowerSpectralDensity(MHz_u centerFrequency, MHz_u channelWidth, Watt_u txPower, MHz_u guardBandwidth, dBr_u minInnerBand=dBr_u{-20}, dBr_u minOuterband=dBr_u{-28}, dBr_u lowestPoint=dBr_u{-40}, const std::vector< bool > &puncturedSubchannels={})
Create a transmit power spectral density corresponding to OFDM High Efficiency (HE/EHT) (802....
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
void SetRu(WifiRu::RuSpec ru, uint16_t staId)
Set the RU specification for the STA-ID.
WifiPreamble GetPreambleType() const
const HeMuUserInfoMap & GetHeMuUserInfoMap() const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID.
WifiModulationClass GetModulationClass() const
Get the modulation class specified by this TXVECTOR.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
MHz_u GetChannelWidth() const
WifiRu::RuSpec GetRu(uint16_t staId) const
Get the RU specification for the STA-ID.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination 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(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.
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
#define NS_TEST_ASSERT_MSG_EQ_TOL(actual, limit, tol, msg)
Test that actual and expected (limit) values are equal to plus or minus some tolerance and report and...
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.
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
WifiPhyBand
Identifies the PHY band.
WifiModulationClass
This enumeration defines the modulation classes per (Table 10-6 "Modulation classes"; IEEE 802....
WifiChannelListType
Enumeration of the possible channel-list parameter elements defined in Table 8-5 of IEEE 802....
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ 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.
WifiPhyState
The state of the PHY layer.
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...
std::string Demangle(const std::string &mangled)
std::vector< BandInfo > Bands
Container of BandInfo.
RuType
The different Resource Unit (RU) types.
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
std::size_t Count20MHzSubchannels(MHz_u channelWidth)
Return the number of 20 MHz subchannels covering the channel width.
MHz_u GetMaximumChannelWidth(WifiModulationClass modulation)
Get the maximum channel width allowed for the given modulation class.
Watt_u DbmToW(dBm_u val)
Convert from dBm to Watts.
uint32_t GetBlockAckSize(BlockAckType type)
Return the total BlockAck size (including FCS trailer).
WifiModulationClass GetModulationClassForStandard(WifiStandard standard)
Return the modulation class corresponding to a given standard.
Hz_u MHzToHz(MHz_u val)
Convert from MHz to Hz.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
std::vector< uint16_t > RuAllocation
9 bits RU_ALLOCATION per 20 MHz
static const MHz_u CHANNEL_WIDTH
The building block of a SpectrumModel.
double fc
center frequency
double fl
lower limit of subband
double fh
upper limit of subband
RxSignalInfo structure containing info on the received signal.
WifiSpectrumBandInfo structure containing info about a spectrum band.
std::vector< WifiSpectrumBandIndices > indices
the start and stop indices for each segment of the band
static const MHz_u DEFAULT_FREQUENCY
static WifiPhyOfdmaTestSuite wifiPhyOfdmaTestSuite
the test suite
static const uint8_t DEFAULT_CHANNEL_NUMBER
static const WifiPhyBand DEFAULT_WIFI_BAND
static const MHz_u DEFAULT_CHANNEL_WIDTH
static const MHz_u DEFAULT_GUARD_WIDTH