22 #include "ns3/wifi-net-device.h" 23 #include "ns3/mobility-helper.h" 24 #include "ns3/spectrum-wifi-helper.h" 25 #include "ns3/multi-model-spectrum-channel.h" 26 #include "ns3/config.h" 27 #include "ns3/rng-seed-manager.h" 28 #include "ns3/wifi-psdu.h" 29 #include "ns3/ap-wifi-mac.h" 30 #include "ns3/sta-wifi-mac.h" 31 #include "ns3/he-phy.h" 32 #include "ns3/he-configuration.h" 33 #include "ns3/ctrl-headers.h" 87 void SendDlSuPpdu (uint8_t bss, uint16_t txChannelWidth);
97 void SendDlMuPpdu (uint8_t bss, uint16_t txChannelWidth,
HeRu::RuType ruType, std::size_t nRus);
108 void SendHeTbPpdu (uint8_t bss, uint16_t txChannelWidth,
HeRu::RuType ruType, std::size_t nRus);
118 void DoSendHeTbPpdu (uint8_t bss, uint16_t txChannelWidth,
HeRu::RuType ruType, std::size_t nRus);
130 WifiTxVector txVector, std::vector<bool> perMpduStatus);
141 WifiTxVector txVector, std::vector<bool> perMpduStatus);
145 void CheckAssociation (
void);
156 void CheckReceivedSuPpdus (std::set<uint8_t> txBss, uint16_t txChannelWidth);
170 void CheckReceivedMuPpdus (std::set<uint8_t> txBss, uint16_t txChannelWidth,
HeRu::RuType ruType,
171 std::size_t nRus,
bool isDlMu);
181 void CheckReceivedTriggerFrames (std::set<uint8_t> txBss, uint16_t txChannelWidth);
184 void DoSetup (
void)
override;
185 void DoRun (
void)
override;
204 :
TestCase (
"Check correct transmissions for various primary channel settings"),
205 m_channelWidth (channelWidth),
206 m_useDistinctBssColors (useDistinctBssColors)
217 for (
const auto& psduPair : psduMap)
219 std::stringstream ss;
223 ss <<
" STA-ID " << psduPair.first;
225 ss <<
" " << psduPair.second->GetHeader (0).GetTypeString ()
226 <<
" seq " << psduPair.second->GetHeader (0).GetSequenceNumber ()
227 <<
" from " << psduPair.second->GetAddr2 ()
228 <<
" to " << psduPair.second->GetAddr1 ();
237 std::vector<bool> perMpduStatus)
245 NS_LOG_INFO (
"RECEIVED BY BSS=" << +bss <<
" STA=" << +station <<
" " << *psdu);
248 << +station <<
"] received a frame twice");
251 auto dev = DynamicCast<WifiNetDevice> (
m_staDevices[bss].Get (station));
256 << +station <<
"] processed a frame twice");
274 uint8_t station = staId - 1;
275 NS_LOG_INFO (
"RECEIVED FROM BSS=" << +bss <<
" STA=" << +station
279 <<
" received a frame from station " << +station <<
" twice");
285 <<
" received a frame from station " << +station <<
" twice");
294 RngSeedManager::SetSeed (1);
295 RngSeedManager::SetRun (40);
296 int64_t streamNumber = 100;
342 phy.SetChannel (spectrumChannel);
347 wifi.SetRemoteStationManager (
"ns3::ConstantRateWifiManager");
350 mac.SetType (
"ns3::StaWifiMac",
355 for (uint8_t bss = 0; bss <
m_nBss; bss++)
362 for (uint8_t bss = 0; bss <
m_nBss; bss++)
366 mac.SetType (
"ns3::ApWifiMac",
367 "Ssid",
SsidValue (
Ssid (
"wifi-ssid-" + std::to_string (bss))),
376 for (uint8_t bss = 0; bss <
m_nBss; bss++)
384 for (uint8_t bss = 0; bss <
m_nBss; bss++)
387 dev->GetHeConfiguration ()->SetBssColor (bss + 1);
394 positionAlloc->
Add (Vector (0.0, 0.0, 0.0));
395 mobility.SetPositionAllocator (positionAlloc);
397 mobility.SetMobilityModel (
"ns3::ConstantPositionMobilityModel");
399 for (uint8_t bss = 0; bss <
m_nBss; bss++)
412 hdr.SetAddr1 (Mac48Address::GetBroadcast ());
414 hdr.SetSequenceNumber (1);
422 20,
false,
false,
false);
426 apDev->GetMac ()->GetWifiPhy ()->GetPhyBand ());
438 for (uint8_t bss = 0; bss <
m_nBss; bss++)
440 dev = DynamicCast<WifiNetDevice> (
m_staDevices[bss].Get (i));
441 Simulator::Schedule (i *
MicroSeconds (102400), &WifiMac::SetSsid,
442 dev->
GetMac (),
Ssid (
"wifi-ssid-" + std::to_string (bss)));
448 for (uint8_t bss = 0; bss <
m_nBss; bss++)
451 auto mac = DynamicCast<ApWifiMac> (dev->
GetMac ());
463 for (uint8_t bss = 0; bss <
m_nBss; bss++)
467 auto dev = DynamicCast<WifiNetDevice> (
m_staDevices[bss].Get (i));
468 Simulator::Schedule (
m_time, &WifiPhy::SetReceiveOkCallback, dev->
GetPhy (),
473 Simulator::Schedule (
m_time, &WifiPhy::SetReceiveOkCallback, dev->
GetPhy (),
551 for (uint16_t txChannelWidth = 20, nRounds = 2, nApsPerRound =
m_channelWidth / 20 / 2;
553 txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
555 nRounds = std::min<uint16_t> (nRounds,
m_nBss);
556 nApsPerRound = std::max<uint16_t> (nApsPerRound, 1);
558 for (uint16_t round = 0; round < nRounds; round++)
560 std::set<uint8_t> txBss;
562 for (uint16_t i = 0; i < nApsPerRound; i++)
564 uint16_t ap = round + i * nRounds;
571 this, txBss, txChannelWidth);
581 for (uint16_t txChannelWidth = 20, nRounds = 2, nApsPerRound =
m_channelWidth / 20 / 2;
583 txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
585 nRounds = std::min<uint16_t> (nRounds,
m_nBss);
586 nApsPerRound = std::max<uint16_t> (nApsPerRound, 1);
588 for (uint16_t round = 0; round < nRounds; round++)
590 for (
unsigned int type = 0; type < 7; type++)
593 std::size_t nRus = HeRu::GetNRus (txChannelWidth, ruType);
594 std::set<uint8_t> txBss;
597 for (uint16_t i = 0; i < nApsPerRound; i++)
599 uint16_t ap = round + i * nRounds;
602 ap, txChannelWidth, ruType, nRus);
606 this, txBss, txChannelWidth, ruType, nRus,
true);
618 for (uint16_t txChannelWidth = 20, nRounds = 2, nApsPerRound =
m_channelWidth / 20 / 2;
620 txChannelWidth *= 2, nRounds *= 2, nApsPerRound /= 2)
622 nRounds = std::min<uint16_t> (nRounds,
m_nBss);
623 nApsPerRound = std::max<uint16_t> (nApsPerRound, 1);
625 for (uint16_t round = 0; round < nRounds; round++)
627 for (
unsigned int type = 0; type < 7; type++)
630 std::size_t nRus = HeRu::GetNRus (txChannelWidth, ruType);
631 std::set<uint8_t> txBss;
634 for (uint16_t i = 0; i < nApsPerRound; i++)
636 uint16_t ap = round + i * nRounds;
639 ap, txChannelWidth, ruType, nRus);
644 this, txBss, txChannelWidth);
646 this, txBss, txChannelWidth, ruType, nRus,
false);
654 Config::Connect (
"/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
660 Simulator::Destroy ();
666 NS_LOG_INFO (
"*** BSS " << +bss <<
" transmits on primary " << txChannelWidth <<
" MHz channel");
669 auto staDev = DynamicCast<WifiNetDevice> (
m_staDevices[bss].Get (0));
671 uint8_t bssColor = apDev->GetHeConfiguration ()->GetBssColor ();
672 WifiTxVector txVector =
WifiTxVector (HePhy::GetHeMcs8 (), 0,
WIFI_PREAMBLE_HE_SU, 800, 1, 1, 0, txChannelWidth,
false,
false,
false, bssColor);
676 hdr.
SetAddr1 (staDev->GetMac ()->GetAddress ());
677 hdr.
SetAddr2 (apDev->GetMac ()->GetAddress ());
678 hdr.
SetAddr3 (apDev->GetMac ()->GetBssid ());
680 Ptr<WifiPsdu> psdu = Create<WifiPsdu> (Create<Packet> (1000), hdr);
687 NS_LOG_INFO (
"*** BSS " << +bss <<
" transmits on primary " << txChannelWidth
688 <<
" MHz channel a DL MU PPDU " <<
"addressed to " << nRus
689 <<
" stations (RU type: " << ruType <<
")");
692 uint8_t bssColor = apDev->GetHeConfiguration ()->GetBssColor ();
694 WifiTxVector txVector =
WifiTxVector (HePhy::GetHeMcs8 (), 0,
WIFI_PREAMBLE_HE_MU, 800, 1, 1, 0, txChannelWidth,
false,
false,
false, bssColor);
698 hdr.
SetAddr2 (apDev->GetMac ()->GetAddress ());
699 hdr.
SetAddr3 (apDev->GetMac ()->GetBssid ());
704 for (std::size_t i = 1; i <= nRus; i++)
706 std::size_t index = (txChannelWidth == 160 && i > nRus / 2 ? i - nRus / 2 : i);
707 bool primary80 = (txChannelWidth == 160 && i > nRus / 2 ? false :
true);
709 auto staDev = DynamicCast<WifiNetDevice> (
m_staDevices[bss].Get (i - 1));
710 uint16_t staId = DynamicCast<StaWifiMac> (staDev->GetMac ())->GetAssociationId ();
711 txVector.
SetHeMuUserInfo (staId, {{ruType, index, primary80}, HePhy::GetHeMcs8 (), 1});
712 hdr.
SetAddr1 (staDev->GetMac ()->GetAddress ());
713 psduMap[staId] = Create<const WifiPsdu> (Create<Packet> (1000), hdr);
715 apDev->GetPhy ()->Send (psduMap, txVector);
721 NS_LOG_INFO (
"*** BSS " << +bss <<
" transmits a Basic Trigger Frame");
732 bss, txChannelWidth, ruType, nRus);
739 uint8_t bssColor = apDev->GetHeConfiguration ()->GetBssColor ();
744 hdr.
SetAddr1 (apDev->GetMac ()->GetAddress ());
745 hdr.
SetAddr3 (apDev->GetMac ()->GetBssid ());
751 for (std::size_t i = 1; i <= nRus; i++)
753 NS_LOG_INFO (
"*** BSS " << +bss <<
" STA " << i - 1 <<
" transmits on primary " 754 << txChannelWidth <<
" MHz channel an HE TB PPDU (RU type: " << ruType <<
")");
756 std::size_t index = (txChannelWidth == 160 && i > nRus / 2 ? i - nRus / 2 : i);
757 bool primary80 = (txChannelWidth == 160 && i > nRus / 2 ? false :
true);
759 auto staDev = DynamicCast<WifiNetDevice> (
m_staDevices[bss].Get (i - 1));
760 uint16_t staId = DynamicCast<StaWifiMac> (staDev->GetMac ())->GetAssociationId ();
762 WifiTxVector txVector (HePhy::GetHeMcs8 (), 0,
WIFI_PREAMBLE_HE_TB, 3200, 1, 1, 0, txChannelWidth,
false,
false,
false, bssColor);
763 txVector.
SetHeMuUserInfo (staId, {{ruType, index, primary80}, HePhy::GetHeMcs8 (), 1});
765 hdr.
SetAddr2 (staDev->GetMac ()->GetAddress ());
771 duration = WifiPhy::CalculateTxDuration (psdu->
GetSize (), txVector,
772 staDev->GetMac ()->GetWifiPhy ()->GetPhyBand (), staId);
773 length = HePhy::ConvertHeTbPpduDurationToLSigLength (duration,
774 staDev->GetMac ()->GetWifiPhy ()->GetPhyBand ());
785 for (uint8_t bss = 0; bss <
m_nBss; bss++)
788 auto mac = DynamicCast<ApWifiMac> (dev->GetMac ());
790 "Not all the stations completed association");
797 for (uint8_t bss = 0; bss <
m_nBss; bss++)
799 if (txBss.find (bss) != txBss.end ())
806 <<
"] did not receive the SU frame on primary" << txChannelWidth <<
" channel");
810 <<
" did not process the SU frame on primary" << txChannelWidth <<
" channel");
814 <<
"] processed the SU frame on primary" << txChannelWidth <<
" channel");
823 || std::none_of (txBss.begin (), txBss.end (),
824 [&](
const uint8_t& txAp)
826 auto txApPhy = DynamicCast<WifiNetDevice> (
m_apDevices.
Get (txAp))->GetPhy ();
827 auto thisApPhy = DynamicCast<WifiNetDevice> (
m_apDevices.
Get (bss))->GetPhy ();
828 return txApPhy->GetOperatingChannel ().GetPrimaryChannelIndex (txChannelWidth)
829 == thisApPhy->GetOperatingChannel ().GetPrimaryChannelIndex (txChannelWidth);
835 <<
"] received the SU frame on primary" << txChannelWidth <<
" channel");
844 <<
"] did not receive the SU frame on primary" << txChannelWidth <<
" channel");
846 <<
"] processed the SU frame on primary" << txChannelWidth <<
" channel");
860 for (uint8_t bss = 0; bss <
m_nBss; bss++)
862 if (txBss.find (bss) != txBss.end ())
865 for (uint8_t sta = 0; sta < nRus; sta++)
868 (isDlMu ?
"A DL MU PPDU transmitted to" :
"An HE TB PPDU transmitted by")
869 <<
" station [" << +bss <<
"][" << +sta <<
"] on primary" 870 << txChannelWidth <<
" channel, RU type " << ruType
871 <<
" was not received");
876 (isDlMu ?
"A DL MU PPDU" :
"An HE TB PPDU")
877 <<
" transmitted on primary" << txChannelWidth
878 <<
" channel, RU type " << ruType <<
" was received " 879 << (isDlMu ?
"by" :
"from") <<
" station [" << +bss <<
"][" 883 for (uint8_t sta = 0; sta < nRus; sta++)
886 (isDlMu ?
"A DL MU PPDU transmitted to" :
"An HE TB PPDU transmitted by")
887 <<
" station [" << +bss <<
"][" << +sta <<
"] on primary" 888 << txChannelWidth <<
" channel, RU type " << ruType
889 <<
" was not processed");
894 (isDlMu ?
"A DL MU PPDU" :
"An HE TB PPDU")
895 <<
" transmitted on primary" << txChannelWidth
896 <<
" channel, RU type " << ruType <<
" was received " 897 << (isDlMu ?
"by" :
"from") <<
" station [" << +bss <<
"][" 898 << +sta <<
"] and processed");
907 || std::none_of (txBss.begin (), txBss.end (),
908 [&](
const uint8_t& txAp)
910 auto txApPhy = DynamicCast<WifiNetDevice> (
m_apDevices.
Get (txAp))->GetPhy ();
911 auto thisApPhy = DynamicCast<WifiNetDevice> (
m_apDevices.
Get (bss))->GetPhy ();
912 return txApPhy->GetOperatingChannel ().GetPrimaryChannelIndex (txChannelWidth)
913 == thisApPhy->GetOperatingChannel ().GetPrimaryChannelIndex (txChannelWidth);
919 (isDlMu ?
"A DL MU PPDU" :
"An HE TB PPDU")
920 <<
" transmitted on primary" << txChannelWidth
921 <<
" channel, RU type " << ruType <<
" was received " 922 << (isDlMu ?
"by" :
"from") <<
" station [" << +bss <<
"][" 929 for (uint8_t sta = 0; sta < nRus; sta++)
932 (isDlMu ?
"A DL MU PPDU transmitted to" :
"An HE TB PPDU transmitted by")
933 <<
" station [" << +bss <<
"][" << +sta <<
"] on primary" 934 << txChannelWidth <<
" channel, RU type " << ruType
935 <<
" was not received");
940 (isDlMu ?
"A DL MU PPDU" :
"An HE TB PPDU")
941 <<
" transmitted on primary" << txChannelWidth
942 <<
" channel, RU type " << ruType <<
" was received " 943 << (isDlMu ?
"by" :
"from") <<
" station [" << +bss <<
"][" 950 (isDlMu ?
"A DL MU PPDU" :
"An HE TB PPDU")
951 <<
" transmitted on primary" << txChannelWidth
952 <<
" channel, RU type " << ruType <<
" was received " 953 << (isDlMu ?
"by" :
"from") <<
" station [" << +bss <<
"][" 954 << +sta <<
"] and processed");
967 for (uint8_t bss = 0; bss <
m_nBss; bss++)
969 if (txBss.find (bss) != txBss.end ())
976 <<
"] did not receive the Trigger Frame soliciting a transmission on primary" 977 << txChannelWidth <<
" channel");
979 <<
"] did not process the Trigger Frame soliciting a transmission on primary" 980 << txChannelWidth <<
" channel");
990 <<
"] received the Trigger Frame soliciting a transmission on primary" 991 << txChannelWidth <<
" channel");
1014 :
TestSuite (
"wifi-primary-channels", UNIT)
Time m_triggerTxDuration
TX duration for Basic Trigger Frame.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
Simulation virtual time values and global simulation resolution.
Time m_time
the time when the current action is executed
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
AttributeValue implementation for Boolean.
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void CheckReceivedMuPpdus(std::set< uint8_t > txBss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus, bool isDlMu)
Check that (i) all stations/APs belonging to the given BSSes received the DL/UL MU PPDUs transmitted ...
void CheckReceivedSuPpdus(std::set< uint8_t > txBss, uint16_t txChannelWidth)
Check that (i) all stations belonging to the given BSSes received the SU PPDUs transmitted over the g...
void DoRun(void) override
Implementation to actually run this TestCase.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
void SendDlMuPpdu(uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the AP of the given BSS transmit a MU PPDU using the given transmission channel width and RU typ...
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
std::vector< NetDeviceContainer > m_staDevices
containers for stations' NetDevices
void AddPropagationLossModel(Ptr< PropagationLossModel > loss)
Add the single-frequency propagation loss model to be used.
helps to create WifiNetDevice objects
uint8_t m_nStationsPerBss
number of stations per AP
void SendDlSuPpdu(uint8_t bss, uint16_t txChannelWidth)
Have the AP of the given BSS transmit a SU PPDU using the given transmission channel width...
uint32_t GetSize(void) const
Return the size of the PSDU in bytes.
std::vector< std::bitset< 74 > > m_received
whether the last packet transmitted to/from each of the (up to 74 per BSS) stations was received ...
RxSignalInfo structure containing info on the received signal.
bool IsZero(void) const
Exactly equivalent to t == 0.
AttributeValue implementation for Time.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
uint16_t m_channelWidth
operating channel width in MHz
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
void CheckAssociation(void)
Check that all stations associated with an AP.
void SendHeTbPpdu(uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the AP of the given BSS transmit a Basic Trigger Frame.
Hold an unsigned integer type.
uint8_t m_nBss
number of BSSes
holds a vector of ns3::NetDevice pointers
void DoSendHeTbPpdu(uint8_t bss, uint16_t txChannelWidth, HeRu::RuType ruType, std::size_t nRus)
Have the STAs of the given BSS transmit an HE TB PPDU using the given transmission channel width and ...
void Connect(std::string path, const CallbackBase &cb)
void SetHeMuUserInfo(uint16_t staId, HeMuUserInfo userInfo)
Set the HE MU user-specific transmission information for the given STA-ID.
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
static WifiPrimaryChannelsTestSuite g_wifiPrimaryChannelsTestSuite
the test suite
Ptr< WifiPhy > GetPhy(void) const
Ptr< WifiPsdu > m_trigger
Basic Trigger Frame.
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::vector< std::bitset< 74 > > m_processed
whether the last packet transmitted to/from each of the (up to 74 per BSS) stations was processed ...
keep track of a set of node pointers.
wifi primary channels test suite
RuType
The different HE Resource Unit (RU) types.
create MAC layers for a ns3::WifiNetDevice.
The IEEE 802.11 SSID Information Element.
Helper class used to assign positions and mobility models to nodes.
virtual ~WifiPrimaryChannelsTest()
Ptr< WifiMac > GetMac(void) const
WifiPrimaryChannelsTestSuite()
NetDeviceContainer m_apDevices
container for AP's NetDevice
bool IsUlMu(void) const
Return true if this TX vector is used for an uplink multi-user transmission.
void SetPropagationDelayModel(Ptr< PropagationDelayModel > delay)
Set the propagation delay model to be used.
Time Seconds(double value)
Construct a Time in the indicated unit.
AttributeValue implementation for Ssid.
bool m_useDistinctBssColors
true to set distinct BSS colors to BSSes
void Add(Vector v)
Add a position to the list of positions.
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when PHY receives a PSDU to transmit.
void CheckReceivedTriggerFrames(std::set< uint8_t > txBss, uint16_t txChannelWidth)
Check that (i) all stations belonging to the given BSSes received the transmitted Trigger Frame; and ...
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
WifiTxVector m_triggerTxVector
TX vector for Basic Trigger Frame.
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
void SetLength(uint16_t length)
Set the LENGTH field of the L-SIG.
const HeMuUserInfoMap & GetHeMuUserInfoMap(void) const
Get a const reference to the map HE MU user-specific transmission information indexed by STA-ID...
void ReceiveDl(uint8_t bss, uint8_t station, Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > perMpduStatus)
Callback invoked when a station receives a DL PPDU.
void ReceiveUl(uint8_t bss, Ptr< WifiPsdu > psdu, RxSignalInfo rxSignalInfo, WifiTxVector txVector, std::vector< bool > perMpduStatus)
Callback invoked when an AP receives an UL PPDU.
Test transmissions under different primary channel settings.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
void AddHeader(const Header &header)
Add header to this packet.
WifiPrimaryChannelsTest(uint16_t channelWidth, bool useDistinctBssColors)
Constructor.
Make it easy to create and manage PHY objects for the spectrum model.