21#include "ns3/dsss-phy.h"
22#include "ns3/eht-phy.h"
23#include "ns3/erp-ofdm-phy.h"
26#include "ns3/packet.h"
27#include "ns3/simulator.h"
29#include "ns3/wifi-psdu.h"
30#include "ns3/yans-wifi-phy.h"
49 void DoRun()
override;
67 uint16_t channelWidth,
68 uint16_t guardInterval,
87 uint16_t channelWidth,
88 uint16_t guardInterval,
106 std::list<HeMuUserInfo> userInfos,
107 uint16_t channelWidth,
108 uint16_t guardInterval,
127 std::list<uint16_t> staIds,
144 uint16_t channelWidth,
145 uint16_t guardInterval,
157 std::list<WifiPhyBand> testedBands;
171 for (
auto& testedBand : testedBands)
179 Time calculatedDuration =
phy->GetPayloadDuration(size, txVector, testedBand);
180 if (calculatedDuration != knownDuration)
182 std::cerr <<
"size=" << size <<
" band=" << testedBand <<
" mode=" << payloadMode
183 <<
" channelWidth=" << channelWidth <<
" guardInterval=" << guardInterval
184 <<
" datarate=" << payloadMode.
GetDataRate(channelWidth, guardInterval, 1)
185 <<
" known=" << knownDuration <<
" calculated=" << calculatedDuration
196 uint16_t channelWidth,
197 uint16_t guardInterval,
209 std::list<WifiPhyBand> testedBands;
223 for (
auto& testedBand : testedBands)
231 Time calculatedDuration =
phy->CalculateTxDuration(size, txVector, testedBand);
232 Time calculatedDurationUsingList =
237 if (calculatedDuration != knownDuration ||
238 calculatedDuration != calculatedDurationUsingList)
240 std::cerr <<
"size=" << size <<
" band=" << testedBand <<
" mode=" << payloadMode
241 <<
" channelWidth=" << +channelWidth <<
" guardInterval=" << guardInterval
242 <<
" datarate=" << payloadMode.
GetDataRate(channelWidth, guardInterval, 1)
243 <<
" preamble=" << preamble <<
" known=" << knownDuration
244 <<
" calculated=" << calculatedDuration
245 <<
" calculatedUsingList=" << calculatedDurationUsingList << std::endl;
254 std::list<HeMuUserInfo> userInfos,
255 uint16_t channelWidth,
256 uint16_t guardInterval,
260 NS_ASSERT(sizes.size() == userInfos.size() && sizes.size() > 1);
262 channelWidth < std::accumulate(
263 std::begin(userInfos),
267 return prevBw + HeRu::GetBandwidth(info.
ru.
GetRuType());
269 "Cannot accommodate all the RUs in the provided band");
277 std::list<uint16_t> staIds;
280 for (
const auto& userInfo : userInfos)
283 staIds.push_back(staId++);
289 std::list<WifiPhyBand> testedBands{
294 for (
auto& testedBand : testedBands)
303 auto iterStaId = staIds.begin();
304 for (
auto& size : sizes)
306 Time ppduDurationForSta =
307 phy->CalculateTxDuration(size, txVector, testedBand, *iterStaId);
308 if (ppduDurationForSta > calculatedDuration)
310 calculatedDuration = ppduDurationForSta;
316 Time calculatedDurationUsingList =
318 if (calculatedDuration != knownDuration ||
319 calculatedDuration != calculatedDurationUsingList)
321 std::cerr <<
"size=" << longuestSize <<
" band=" << testedBand <<
" staId=" << staId
322 <<
" nss=" << +txVector.
GetNss(staId) <<
" mode=" << txVector.
GetMode(staId)
323 <<
" channelWidth=" << channelWidth <<
" guardInterval=" << guardInterval
328 <<
" known=" << knownDuration <<
" calculated=" << calculatedDuration
329 <<
" calculatedUsingList=" << calculatedDurationUsingList << std::endl;
338 std::list<uint16_t> staIds,
342 NS_ASSERT(sizes.size() == staIds.size());
344 auto itStaId = staIds.begin();
347 for (
auto& size : sizes)
350 psduMap[*itStaId++] =
353 return WifiPhy::CalculateTxDuration(psduMap, txVector, band);
364 DsssPhy::GetDsssRate11Mbps(),
370 DsssPhy::GetDsssRate11Mbps(),
376 DsssPhy::GetDsssRate11Mbps(),
382 DsssPhy::GetDsssRate11Mbps(),
396 DsssPhy::GetDsssRate11Mbps(),
402 DsssPhy::GetDsssRate11Mbps(),
408 DsssPhy::GetDsssRate11Mbps(),
414 DsssPhy::GetDsssRate11Mbps(),
420 DsssPhy::GetDsssRate11Mbps(),
426 DsssPhy::GetDsssRate11Mbps(),
432 DsssPhy::GetDsssRate11Mbps(),
438 DsssPhy::GetDsssRate11Mbps(),
444 DsssPhy::GetDsssRate5_5Mbps(),
450 DsssPhy::GetDsssRate5_5Mbps(),
456 DsssPhy::GetDsssRate5_5Mbps(),
462 DsssPhy::GetDsssRate5_5Mbps(),
468 DsssPhy::GetDsssRate5_5Mbps(),
474 DsssPhy::GetDsssRate5_5Mbps(),
480 DsssPhy::GetDsssRate5_5Mbps(),
486 DsssPhy::GetDsssRate5_5Mbps(),
492 DsssPhy::GetDsssRate2Mbps(),
498 DsssPhy::GetDsssRate2Mbps(),
504 DsssPhy::GetDsssRate2Mbps(),
510 DsssPhy::GetDsssRate2Mbps(),
516 DsssPhy::GetDsssRate2Mbps(),
522 DsssPhy::GetDsssRate2Mbps(),
528 DsssPhy::GetDsssRate2Mbps(),
534 DsssPhy::GetDsssRate2Mbps(),
540 DsssPhy::GetDsssRate1Mbps(),
546 DsssPhy::GetDsssRate1Mbps(),
552 DsssPhy::GetDsssRate1Mbps(),
558 DsssPhy::GetDsssRate1Mbps(),
564 DsssPhy::GetDsssRate1Mbps(),
570 DsssPhy::GetDsssRate1Mbps(),
576 DsssPhy::GetDsssRate1Mbps(),
582 DsssPhy::GetDsssRate1Mbps(),
590 DsssPhy::GetDsssRate1Mbps(),
599 DsssPhy::GetDsssRate11Mbps(),
605 DsssPhy::GetDsssRate11Mbps(),
611 DsssPhy::GetDsssRate11Mbps(),
623 OfdmPhy::GetOfdmRate54Mbps(),
629 OfdmPhy::GetOfdmRate54Mbps(),
635 OfdmPhy::GetOfdmRate54Mbps(),
646 ErpOfdmPhy::GetErpOfdmRate54Mbps(),
652 ErpOfdmPhy::GetErpOfdmRate54Mbps(),
658 ErpOfdmPhy::GetErpOfdmRate54Mbps(),
715 VhtPhy::GetVhtMcs8(),
721 VhtPhy::GetVhtMcs8(),
727 VhtPhy::GetVhtMcs8(),
733 VhtPhy::GetVhtMcs8(),
739 VhtPhy::GetVhtMcs8(),
745 VhtPhy::GetVhtMcs8(),
751 VhtPhy::GetVhtMcs9(),
757 VhtPhy::GetVhtMcs9(),
763 VhtPhy::GetVhtMcs9(),
769 VhtPhy::GetVhtMcs9(),
775 VhtPhy::GetVhtMcs9(),
781 VhtPhy::GetVhtMcs9(),
787 VhtPhy::GetVhtMcs0(),
793 VhtPhy::GetVhtMcs0(),
799 VhtPhy::GetVhtMcs0(),
805 VhtPhy::GetVhtMcs0(),
811 VhtPhy::GetVhtMcs0(),
817 VhtPhy::GetVhtMcs0(),
823 VhtPhy::GetVhtMcs9(),
829 VhtPhy::GetVhtMcs9(),
835 VhtPhy::GetVhtMcs9(),
841 VhtPhy::GetVhtMcs9(),
847 VhtPhy::GetVhtMcs9(),
853 VhtPhy::GetVhtMcs9(),
859 VhtPhy::GetVhtMcs8(),
865 VhtPhy::GetVhtMcs8(),
871 VhtPhy::GetVhtMcs8(),
877 VhtPhy::GetVhtMcs8(),
883 VhtPhy::GetVhtMcs8(),
889 VhtPhy::GetVhtMcs8(),
1052 HePhy::GetHeMcs11(),
1058 HePhy::GetHeMcs11(),
1064 HePhy::GetHeMcs11(),
1070 HePhy::GetHeMcs11(),
1076 HePhy::GetHeMcs11(),
1082 HePhy::GetHeMcs11(),
1088 HePhy::GetHeMcs11(),
1094 HePhy::GetHeMcs11(),
1100 HePhy::GetHeMcs11(),
1106 HePhy::GetHeMcs11(),
1112 HePhy::GetHeMcs11(),
1118 HePhy::GetHeMcs11(),
1124 HePhy::GetHeMcs11(),
1130 HePhy::GetHeMcs11(),
1136 HePhy::GetHeMcs11(),
1142 HePhy::GetHeMcs11(),
1148 HePhy::GetHeMcs11(),
1154 HePhy::GetHeMcs11(),
1160 HePhy::GetHeMcs11(),
1166 HePhy::GetHeMcs11(),
1172 HePhy::GetHeMcs11(),
1178 HePhy::GetHeMcs11(),
1184 HePhy::GetHeMcs11(),
1190 HePhy::GetHeMcs11(),
1196 HePhy::GetHeMcs11(),
1204 HePhy::GetHeMcs11(),
1212 HePhy::GetHeMcs11(),
1220 HePhy::GetHeMcs11(),
1226 HePhy::GetHeMcs11(),
1238 std::list<uint32_t>{1536, 1536},
1239 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1,
true}, HePhy::GetHeMcs0(), 1},
1240 {{HeRu::RU_242_TONE, 2,
true}, HePhy::GetHeMcs0(), 1}},
1247 std::list<uint32_t>{1536, 1536},
1248 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1,
true}, HePhy::GetHeMcs1(), 1},
1249 {{HeRu::RU_242_TONE, 2,
true}, HePhy::GetHeMcs0(), 1}},
1255 std::list<uint32_t>{1536, 76},
1256 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1,
true}, HePhy::GetHeMcs0(), 1},
1257 {{HeRu::RU_242_TONE, 2,
true}, HePhy::GetHeMcs0(), 1}},
1269 std::list<uint32_t>{1536, 1536},
1270 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1,
true}, EhtPhy::GetEhtMcs0(), 1},
1271 {{HeRu::RU_242_TONE, 2,
true}, EhtPhy::GetEhtMcs0(), 1}},
1277 std::list<uint32_t>{1536, 1536},
1278 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1,
true}, EhtPhy::GetEhtMcs1(), 1},
1279 {{HeRu::RU_242_TONE, 2,
true}, EhtPhy::GetEhtMcs0(), 1}},
1285 std::list<uint32_t>{1536, 76},
1286 std::list<HeMuUserInfo>{{{HeRu::RU_242_TONE, 1,
true}, EhtPhy::GetEhtMcs0(), 1},
1287 {{HeRu::RU_242_TONE, 2,
true}, EhtPhy::GetEhtMcs0(), 1}},
1295 Simulator::Destroy();
1309 void DoRun()
override;
1324 :
TestCase(
"Check HE-SIG-B duration computation")
1341 std::list<uint16_t> staIds;
1343 for (
const auto& userInfo : userInfos)
1346 staIds.push_back(staId++);
1357 std::list<HeMuUserInfo> userInfos;
1358 userInfos.push_back({{HeRu::RU_106_TONE, 1,
true}, HePhy::GetHeMcs11(), 1});
1359 userInfos.push_back({{HeRu::RU_106_TONE, 2,
true}, HePhy::GetHeMcs10(), 4});
1364 VhtPhy::GetVhtMcs5(),
1365 "HE-SIG-B should be sent at MCS 5");
1369 "Both users should be on HE-SIG-B content channel 1");
1372 "Both users should be on HE-SIG-B content channel 2");
1375 "HE-SIG-B should only last one OFDM symbol");
1378 userInfos.push_back({{HeRu::RU_52_TONE, 5,
true}, HePhy::GetHeMcs4(), 1});
1379 userInfos.push_back({{HeRu::RU_52_TONE, 6,
true}, HePhy::GetHeMcs6(), 2});
1380 userInfos.push_back({{HeRu::RU_52_TONE, 7,
true}, HePhy::GetHeMcs5(), 3});
1381 userInfos.push_back({{HeRu::RU_52_TONE, 8,
true}, HePhy::GetHeMcs6(), 2});
1386 VhtPhy::GetVhtMcs4(),
1387 "HE-SIG-B should be sent at MCS 4");
1391 "Two users should be on HE-SIG-B content channel 1");
1394 "Four users should be on HE-SIG-B content channel 2");
1397 "HE-SIG-B should only last one OFDM symbol");
1400 userInfos.push_back({{HeRu::RU_26_TONE, 14,
true}, HePhy::GetHeMcs3(), 1});
1405 VhtPhy::GetVhtMcs3(),
1406 "HE-SIG-B should be sent at MCS 3");
1410 "Two users should be on HE-SIG-B content channel 1");
1413 "Five users should be on HE-SIG-B content channel 2");
1416 "HE-SIG-B should last two OFDM symbols");
1419 userInfos.push_back({{HeRu::RU_242_TONE, 3,
true}, HePhy::GetHeMcs1(), 1});
1420 userInfos.push_back({{HeRu::RU_242_TONE, 4,
true}, HePhy::GetHeMcs4(), 1});
1425 VhtPhy::GetVhtMcs1(),
1426 "HE-SIG-B should be sent at MCS 1");
1430 "Three users should be on HE-SIG-B content channel 1");
1433 "Six users should be on HE-SIG-B content channel 2");
1436 "HE-SIG-B should last four OFDM symbols");
1439 userInfos.push_back({{HeRu::RU_996_TONE, 1,
false}, HePhy::GetHeMcs1(), 1});
1444 VhtPhy::GetVhtMcs1(),
1445 "HE-SIG-B should be sent at MCS 1");
1449 "Four users should be on HE-SIG-B content channel 1");
1452 "Seven users should be on HE-SIG-B content channel 2");
1455 "HE-SIG-B should last five OFDM symbols");
1469 void DoRun()
override;
1484 :
TestCase(
"PHY header sections consistency")
1497 "The expected map size (" << expected.size() <<
") was not obtained ("
1498 << obtained.size() <<
")");
1500 auto itObtained = obtained.begin();
1501 auto itExpected = expected.begin();
1502 for (; itObtained != obtained.end() || itExpected != expected.end();)
1505 auto window = itObtained->second.first;
1506 auto mode = itObtained->second.second;
1509 auto windowRef = itExpected->second.first;
1510 auto modeRef = itExpected->second.second;
1514 "The expected PPDU field (" << fieldRef <<
") was not obtained ("
1518 "The expected start time (" << windowRef.first
1519 <<
") was not obtained (" <<
window.first
1523 "The expected stop time (" << windowRef.second
1524 <<
") was not obtained (" <<
window.second
1528 "The expected mode (" << modeRef <<
") was not obtained (" << mode
1546 phyEntity = Create<DsssPhy>();
1547 txVector.
SetMode(DsssPhy::GetDsssRate1Mbps());
1552 nonHtMode = DsssPhy::GetDsssRate1Mbps();
1563 txVector.
SetMode(DsssPhy::GetDsssRate11Mbps());
1564 nonHtMode = DsssPhy::GetDsssRate2Mbps();
1576 std::map<OfdmPhyVariant, std::size_t> variants{
1581 for (
auto variant : variants)
1583 phyEntity = Create<OfdmPhy>(variant.first);
1584 std::size_t ratio = variant.second;
1585 uint16_t bw = 20 / ratio;
1587 txVector.
SetMode(OfdmPhy::GetOfdmRate(12000000 / ratio, bw));
1588 nonHtMode = OfdmPhy::GetOfdmRate(6000000 / ratio, bw);
1590 {{ppduStart, ppduStart +
MicroSeconds(16 * ratio)}, nonHtMode}},
1599 phyEntity = Create<ErpOfdmPhy>();
1601 txVector.
SetMode(ErpOfdmPhy::GetErpOfdmRate(54000000));
1602 nonHtMode = ErpOfdmPhy::GetErpOfdmRate6Mbps();
1610 phyEntity = Create<HtPhy>(4);
1612 txVector.
SetMode(HtPhy::GetHtMcs6());
1613 nonHtMode = OfdmPhy::GetOfdmRate6Mbps();
1644 phyEntity = Create<VhtPhy>();
1647 txVector.
SetMode(VhtPhy::GetVhtMcs7());
1649 WifiMode sigBMode = VhtPhy::GetVhtMcs0();
1686 phyEntity = Create<HePhy>();
1690 txVector.
SetMode(HePhy::GetHeMcs9());
1691 std::map<uint16_t, HeMuUserInfo> userInfoMap = {
1692 {1, {{HeRu::RU_106_TONE, 1,
true}, HePhy::GetHeMcs4(), 2}},
1693 {2, {{HeRu::RU_106_TONE, 1,
true}, HePhy::GetHeMcs9(), 1}}};
1694 sigAMode = HePhy::GetVhtMcs0();
1695 sigBMode = HePhy::GetVhtMcs4();
1757 phyEntity = Create<EhtPhy>();
1761 txVector.
SetMode(EhtPhy::GetEhtMcs9());
1762 userInfoMap = {{1, {{HeRu::RU_106_TONE, 1,
true}, EhtPhy::GetEhtMcs4(), 2}},
1763 {2, {{HeRu::RU_106_TONE, 1,
true}, EhtPhy::GetEhtMcs9(), 1}}};
1764 WifiMode uSigMode = EhtPhy::GetVhtMcs0();
1765 WifiMode ehtSigMode = EhtPhy::GetVhtMcs4();
1811 :
TestSuite(
"wifi-devices-tx-duration", UNIT)
static WifiTxVector BuildTxVector(uint16_t bw, std::list< HeMuUserInfo > userInfos)
Build a TXVECTOR for HE MU with the given bandwith and user informations.
void DoRun() override
Implementation to actually run this TestCase.
~HeSigBDurationTest() override
~TxDurationTest() override
static Time CalculateTxDurationUsingList(std::list< uint32_t > sizes, std::list< uint16_t > staIds, WifiTxVector txVector, WifiPhyBand band)
Calculate the overall Tx duration returned by WifiPhy for list of sizes.
static bool CheckMuTxDuration(std::list< uint32_t > sizes, std::list< HeMuUserInfo > userInfos, uint16_t channelWidth, uint16_t guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the overall Tx duration returned by WifiPhy for a MU PPDU corresponds to a known value.
bool CheckTxDuration(uint32_t size, WifiMode payloadMode, uint16_t channelWidth, uint16_t guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the overall tx duration returned by InterferenceHelper corresponds to a known value.
bool CheckPayloadDuration(uint32_t size, WifiMode payloadMode, uint16_t channelWidth, uint16_t guardInterval, WifiPreamble preamble, Time knownDuration)
Check if the payload tx duration returned by InterferenceHelper corresponds to a known value.
void DoRun() override
Implementation to actually run this TestCase.
RuType GetRuType() const
Get the RU type.
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Simulation virtual time values and global simulation resolution.
represent a single transmission mode
WifiModulationClass GetModulationClass() const
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetStbc(bool stbc)
Sets if STBC is being used.
void SetNess(uint8_t ness)
Sets the Ness number.
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
WifiMode GetMode(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the selected payload transmission mode.
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
void SetRuAllocation(const RuAllocation &ruAlloc)
Set RU Allocation of SIG-B common field.
uint8_t GetNss(uint16_t staId=SU_STA_ID) const
If this TX vector is associated with an SU PPDU, return the number of spatial streams.
void SetSigBMode(const WifiMode &mode)
Set the MCS used for SIG-B.
std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel() const
Get the number of RUs per HE-SIG-B content channel.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
void SetNss(uint8_t nss)
Sets the number of Nss.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
#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_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_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
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.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
WifiPhyBand
Identifies the PHY band.
WifiPpduField
The type of PPDU field (grouped for convenience)
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ WIFI_MOD_CLASS_OFDM
OFDM (Clause 17)
@ WIFI_MOD_CLASS_VHT
VHT (Clause 22)
@ WIFI_MOD_CLASS_HE
HE (Clause 27)
@ WIFI_PPDU_FIELD_SIG_B
SIG-B field.
@ WIFI_PPDU_FIELD_TRAINING
STF + LTF fields (excluding those in preamble for HT-GF)
@ WIFI_PPDU_FIELD_NON_HT_HEADER
PHY header field for DSSS or ERP, short PHY header field for HR/DSSS or ERP, field not present for HT...
@ WIFI_PPDU_FIELD_EHT_SIG
EHT-SIG field.
@ WIFI_PPDU_FIELD_HT_SIG
HT-SIG field.
@ WIFI_PPDU_FIELD_PREAMBLE
SYNC + SFD fields for DSSS or ERP, shortSYNC + shortSFD fields for HR/DSSS or ERP,...
@ WIFI_PPDU_FIELD_U_SIG
U-SIG field.
@ WIFI_PPDU_FIELD_SIG_A
SIG-A field.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
HE MU specific user transmission parameters.
HeRu::RuSpec ru
RU specification.
static TxDurationTestSuite g_txDurationTestSuite
the test suite