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)
Simulation virtual time values and global simulation resolution.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetChannelWidth(uint16_t channelWidth)
Sets the selected channelWidth (in MHz)
static TxDurationTestSuite g_txDurationTestSuite
the test suite
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
void SetStbc(bool stbc)
Sets if STBC is being used.
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
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.
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
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.
std::map< WifiPpduField, PhyHeaderChunkInfo > PhyHeaderSections
A map of PhyHeaderChunkInfo elements per PPDU field.
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...
SYNC + SFD fields for DSSS or ERP, shortSYNC + shortSFD fields for HR/DSSS or ERP, HT-GF-STF + HT-GF-LTF1 fields for HT-GF, L-STF + L-LTF fields otherwise.
WifiPreamble
The type of preamble to be used by an IEEE 802.11 transmission.
virtual ~TxDurationTest()
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...
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
void SetGuardInterval(uint16_t guardInterval)
Sets the guard interval duration (in nanoseconds)
virtual ~HeSigBDurationTest()
WifiPpduField
The type of PPDU field (grouped for convenience)
void DoRun(void) override
Implementation to actually run this TestCase.
std::pair< std::size_t, std::size_t > GetNumRusPerHeSigBContentChannel(void) const
Get the number of RUs per HE-SIG-B content channel.
WifiModulationClass GetModulationClass() const
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
void SetNss(uint8_t nss)
Sets the number of Nss.
void DoRun(void) override
Implementation to actually run this TestCase.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void SetPreambleType(WifiPreamble preamble)
Sets the preamble type.
RuType GetRuType(void) const
Get the RU type.
HeRu::RuSpec ru
RU specification.
void SetMode(WifiMode mode)
Sets the selected payload transmission mode.
WifiPhyBand
Identifies the PHY band.
static WifiTxVector BuildTxVector(uint16_t bw, std::list< HeMuUserInfo > userInfos)
Build a TXVECTOR for HE MU with the given bandwith and user informations.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Time Seconds(double value)
Construct a Time in the indicated unit.
PhyHeaderSections GetPhyHeaderSections(const WifiTxVector &txVector, Time ppduStart) const
Return a map of PHY header chunk information per PPDU field.
STF + LTF fields (excluding those in preamble for HT-GF)
void SetNess(uint8_t ness)
Sets the Ness number.
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...
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
PHY header field for DSSS or ERP, short PHY header field for HR/DSSS or ERP, field not present for HT...
HE MU specific user transmission parameters.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
uint64_t GetDataRate(uint16_t channelWidth, uint16_t guardInterval, uint8_t nss) const
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...