23 #include "ns3/simulator.h"
25 #include "ns3/yans-wifi-phy.h"
26 #include "ns3/he-ru.h"
27 #include "ns3/wifi-psdu.h"
28 #include "ns3/packet.h"
29 #include "ns3/dsss-phy.h"
30 #include "ns3/erp-ofdm-phy.h"
31 #include "ns3/he-phy.h"
49 void DoRun (
void)
override;
66 bool CheckPayloadDuration (uint32_t size,
WifiMode payloadMode, uint16_t channelWidth, uint16_t guardInterval,
WifiPreamble preamble,
Time knownDuration);
81 bool CheckTxDuration (uint32_t size,
WifiMode payloadMode, uint16_t channelWidth, uint16_t guardInterval,
WifiPreamble preamble,
Time knownDuration);
95 static bool CheckHeMuTxDuration (std::list<uint32_t> sizes, std::list<HeMuUserInfo> userInfos,
96 uint16_t channelWidth, uint16_t guardInterval,
113 static Time CalculateTxDurationUsingList (std::list<uint32_t> sizes, std::list<uint16_t> staIds,
130 txVector.
SetMode (payloadMode);
146 Time calculatedDuration =
phy->GetPayloadDuration (size, txVector, band);
147 if (calculatedDuration != knownDuration)
149 std::cerr <<
"size=" << size
150 <<
" mode=" << payloadMode
151 <<
" channelWidth=" << channelWidth
152 <<
" guardInterval=" << guardInterval
153 <<
" datarate=" << payloadMode.
GetDataRate (channelWidth, guardInterval, 1)
154 <<
" known=" << knownDuration
155 <<
" calculated=" << calculatedDuration
163 calculatedDuration =
phy->GetPayloadDuration (size, txVector, band);
165 if (calculatedDuration != knownDuration)
167 std::cerr <<
"size=" << size
168 <<
" mode=" << payloadMode
169 <<
" channelWidth=" << channelWidth
170 <<
" guardInterval=" << guardInterval
171 <<
" datarate=" << payloadMode.
GetDataRate (channelWidth, guardInterval, 1)
172 <<
" known=" << knownDuration
173 <<
" calculated=" << calculatedDuration
185 txVector.
SetMode (payloadMode);
201 Time calculatedDuration =
phy->CalculateTxDuration (size, txVector, band);
204 if (calculatedDuration != knownDuration || calculatedDuration != calculatedDurationUsingList)
206 std::cerr <<
"size=" << size
207 <<
" mode=" << payloadMode
208 <<
" channelWidth=" << +channelWidth
209 <<
" guardInterval=" << guardInterval
210 <<
" datarate=" << payloadMode.
GetDataRate (channelWidth, guardInterval, 1)
211 <<
" preamble=" << preamble
212 <<
" known=" << knownDuration
213 <<
" calculated=" << calculatedDuration
214 <<
" calculatedUsingList=" << calculatedDurationUsingList
222 calculatedDuration =
phy->CalculateTxDuration (size, txVector, band);
226 if (calculatedDuration != knownDuration || calculatedDuration != calculatedDurationUsingList)
228 std::cerr <<
"size=" << size
229 <<
" mode=" << payloadMode
230 <<
" channelWidth=" << channelWidth
231 <<
" guardInterval=" << guardInterval
232 <<
" datarate=" << payloadMode.
GetDataRate (channelWidth, guardInterval, 1)
233 <<
" preamble=" << preamble
234 <<
" known=" << knownDuration
235 <<
" calculated=" << calculatedDuration
236 <<
" calculatedUsingList=" << calculatedDurationUsingList
246 uint16_t channelWidth, uint16_t guardInterval,
249 NS_ASSERT (sizes.size () == userInfos.size () && sizes.size () > 1);
250 NS_ABORT_MSG_IF (channelWidth < std::accumulate (std::begin (userInfos), std::end (userInfos), 0,
252 {
return prevBw + HeRu::GetBandwidth (info.
ru.
GetRuType ()); }),
253 "Cannot accommodate all the RUs in the provided band");
260 std::list<uint16_t> staIds;
262 for (
const auto & userInfo : userInfos)
265 staIds.push_back (staId++);
269 for (
auto & testedBand : testedBands)
276 uint32_t longuestSize = 0;
277 auto iterStaId = staIds.begin ();
278 for (
auto & size : sizes)
280 Time ppduDurationForSta =
phy->CalculateTxDuration (size, txVector, testedBand, *iterStaId);
281 if (ppduDurationForSta > calculatedDuration)
283 calculatedDuration = ppduDurationForSta;
290 if (calculatedDuration != knownDuration || calculatedDuration != calculatedDurationUsingList)
292 std::cerr <<
"size=" << longuestSize
293 <<
" band=" << testedBand
294 <<
" staId=" << staId
295 <<
" nss=" << +txVector.
GetNss (staId)
296 <<
" mode=" << txVector.
GetMode (staId)
297 <<
" channelWidth=" << channelWidth
298 <<
" guardInterval=" << guardInterval
300 <<
" known=" << knownDuration
301 <<
" calculated=" << calculatedDuration
302 <<
" calculatedUsingList=" << calculatedDurationUsingList
314 NS_ASSERT (sizes.size () == staIds.size ());
316 auto itStaId = staIds.begin ();
319 for (
auto & size : sizes)
322 psduMap[*itStaId++] = Create<WifiPsdu> (Create<Packet> (size - hdr.
GetSerializedSize () - 4), hdr);
324 return WifiPhy::CalculateTxDuration (psduMap, txVector, band);
543 std::list<HeMuUserInfo> { {{HeRu::RU_242_TONE, 1,
true}, HePhy::GetHeMcs0 (), 1},
544 {{HeRu::RU_242_TONE, 2,
true}, HePhy::GetHeMcs0 (), 1} },
548 std::list<HeMuUserInfo> { {{HeRu::RU_242_TONE, 1,
true}, HePhy::GetHeMcs1 (), 1},
549 {{HeRu::RU_242_TONE, 2,
true}, HePhy::GetHeMcs0 (), 1} },
553 std::list<HeMuUserInfo> { {{HeRu::RU_242_TONE, 1,
true}, HePhy::GetHeMcs0 (), 1},
554 {{HeRu::RU_242_TONE, 2,
true}, HePhy::GetHeMcs0 (), 1} },
559 Simulator::Destroy ();
573 void DoRun (
void)
override;
588 :
TestCase (
"Check HE-SIG-B duration computation")
605 std::list<uint16_t> staIds;
607 for (
const auto & userInfo : userInfos)
610 staIds.push_back (staId++);
621 std::list<HeMuUserInfo> userInfos;
622 userInfos.push_back ({{HeRu::RU_106_TONE, 1,
true}, HePhy::GetHeMcs11 (), 1});
623 userInfos.push_back ({{HeRu::RU_106_TONE, 2,
true}, HePhy::GetHeMcs10 (), 4});
627 NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.first, 2,
"Both users should be on HE-SIG-B content channel 1");
628 NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 0,
"Both users should be on HE-SIG-B content channel 2");
632 userInfos.push_back ({{HeRu::RU_52_TONE, 5,
true}, HePhy::GetHeMcs4 (), 1});
633 userInfos.push_back ({{HeRu::RU_52_TONE, 6,
true}, HePhy::GetHeMcs6 (), 2});
634 userInfos.push_back ({{HeRu::RU_52_TONE, 7,
true}, HePhy::GetHeMcs5 (), 3});
635 userInfos.push_back ({{HeRu::RU_52_TONE, 8,
true}, HePhy::GetHeMcs6 (), 2});
640 NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 4,
"Four users should be on HE-SIG-B content channel 2");
644 userInfos.push_back ({{HeRu::RU_26_TONE, 13,
true}, HePhy::GetHeMcs3 (), 1});
649 NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 5,
"Five users should be on HE-SIG-B content channel 2");
653 userInfos.push_back ({{HeRu::RU_242_TONE, 3,
true}, HePhy::GetHeMcs1 (), 1});
654 userInfos.push_back ({{HeRu::RU_242_TONE, 4,
true}, HePhy::GetHeMcs4 (), 1});
658 NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.first, 3,
"Three users should be on HE-SIG-B content channel 1");
659 NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 6,
"Six users should be on HE-SIG-B content channel 2");
663 userInfos.push_back ({{HeRu::RU_996_TONE, 1,
false}, HePhy::GetHeMcs1 (), 1});
667 NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.first, 4,
"Four users should be on HE-SIG-B content channel 1");
668 NS_TEST_EXPECT_MSG_EQ (numUsersPerCc.second, 7,
"Seven users should be on HE-SIG-B content channel 2");
683 void DoRun (
void)
override;
699 :
TestCase (
"PHY header sections consistency")
711 NS_TEST_EXPECT_MSG_EQ (obtained.size (), expected.size (),
"The expected map size (" << expected.size () <<
") was not obtained (" << obtained.size () <<
")");
713 auto itObtained = obtained.begin ();
714 auto itExpected = expected.begin ();
715 for (;itObtained != obtained.end () || itExpected != expected.end ();)
718 auto window = itObtained->second.first;
719 auto mode = itObtained->second.second;
722 auto windowRef = itExpected->second.first;
723 auto modeRef = itExpected->second.second;
725 NS_TEST_EXPECT_MSG_EQ (field, fieldRef,
"The expected PPDU field (" << fieldRef <<
") was not obtained (" << field <<
")");
728 NS_TEST_EXPECT_MSG_EQ (mode, modeRef,
"The expected mode (" << modeRef <<
") was not obtained (" << mode <<
")");
746 phyEntity = Create<DsssPhy> ();
747 txVector.
SetMode (DsssPhy::GetDsssRate1Mbps ());
752 nonHtMode = DsssPhy::GetDsssRate1Mbps ();
766 txVector.
SetMode (DsssPhy::GetDsssRate11Mbps ());
767 nonHtMode = DsssPhy::GetDsssRate2Mbps ();
783 std::map<OfdmPhyVariant, std::size_t> variants {
788 for (
auto variant : variants)
790 phyEntity = Create<OfdmPhy> (variant.first);
791 std::size_t ratio = variant.second;
792 uint16_t bw = 20 / ratio;
794 txVector.
SetMode (OfdmPhy::GetOfdmRate (12000000 / ratio, bw));
795 nonHtMode = OfdmPhy::GetOfdmRate (6000000 / ratio, bw);
808 phyEntity = Create<ErpOfdmPhy> ();
810 txVector.
SetMode (ErpOfdmPhy::GetErpOfdmRate (54000000));
811 nonHtMode = ErpOfdmPhy::GetErpOfdmRate6Mbps ();
823 phyEntity = Create<HtPhy> (4);
825 txVector.
SetMode (HtPhy::GetHtMcs6 ());
826 nonHtMode = OfdmPhy::GetOfdmRate6Mbps ();
860 phyEntity = Create<VhtPhy> ();
863 txVector.
SetMode (VhtPhy::GetVhtMcs7 ());
865 WifiMode sigBMode = VhtPhy::GetVhtMcs0 ();
907 phyEntity = Create<HePhy> ();
910 txVector.
SetMode (HePhy::GetHeMcs9 ());
911 std::map<uint16_t, HeMuUserInfo> userInfoMap = { { 1, { {HeRu::RU_106_TONE, 1,
true}, HePhy::GetHeMcs4 (), 2 } },
912 { 2, { {HeRu::RU_106_TONE, 1,
true}, HePhy::GetHeMcs9 (), 1 } } };
913 sigAMode = HePhy::GetVhtMcs0 ();
914 sigBMode = HePhy::GetVhtMcs4 ();
983 :
TestSuite (
"wifi-devices-tx-duration", UNIT)
void DoRun(void) override
Implementation to actually run this TestCase.
static WifiTxVector BuildTxVector(uint16_t bw, std::list< HeMuUserInfo > userInfos)
Build a TXVECTOR for HE MU with the given bandwith and user informations.
virtual ~HeSigBDurationTest()
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.
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.
virtual ~TxDurationTest()
static bool CheckHeMuTxDuration(std::list< uint32_t > sizes, std::list< HeMuUserInfo > userInfos, uint16_t channelWidth, uint16_t guardInterval, Time knownDuration)
Check if the overall Tx duration returned by WifiPhy for a HE MU PPDU corresponds to a known value.
void DoRun(void) override
Implementation to actually run this TestCase.
RuType GetRuType(void) 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.
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.
std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel(void) 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_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_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_HT
HT (Clause 19)
@ 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_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_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