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;
337 spectrumChannel->AddPropagationLossModel (lossModel);
339 spectrumChannel->SetPropagationDelayModel (delayModel);
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 ());
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)
Test transmissions under different primary channel settings.
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.
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
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
uint8_t m_nBss
number of BSSes
void DoSetup(void) override
Implementation to do any local setup required for this TestCase.
virtual ~WifiPrimaryChannelsTest()
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.
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when PHY receives a PSDU to transmit.
Ptr< WifiPsdu > m_trigger
Basic Trigger Frame.
Time m_time
the time when the current action is executed
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 ...
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 ...
Time m_triggerTxDuration
TX duration for Basic Trigger Frame.
uint16_t m_channelWidth
operating channel width in MHz
WifiPrimaryChannelsTest(uint16_t channelWidth, bool useDistinctBssColors)
Constructor.
uint8_t m_nStationsPerBss
number of stations per AP
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.
std::vector< NetDeviceContainer > m_staDevices
containers for stations' NetDevices
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.
NetDeviceContainer m_apDevices
container for AP's NetDevice
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...
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 ...
bool m_useDistinctBssColors
true to set distinct BSS colors to BSSes
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...
WifiTxVector m_triggerTxVector
TX vector for Basic Trigger Frame.
void DoRun(void) override
Implementation to actually run this TestCase.
wifi primary channels test suite
WifiPrimaryChannelsTestSuite()
AttributeValue implementation for Boolean.
RuType
The different HE Resource Unit (RU) types.
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
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.
void AddHeader(const Header &header)
Add header to this packet.
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
AttributeValue implementation for Ssid.
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Simulation virtual time values and global simulation resolution.
bool IsZero(void) const
Exactly equivalent to t == 0.
AttributeValue implementation for Time.
Hold an unsigned integer type.
helps to create WifiNetDevice objects
create MAC layers for a ns3::WifiNetDevice.
Ptr< WifiMac > GetMac(void) const
Ptr< WifiPhy > GetPhy(void) const
uint32_t GetSize(void) const
Return the size of the PSDU in bytes.
const WifiMacHeader & GetHeader(std::size_t i) const
Get the header of the i-th MPDU.
std::size_t GetNMpdus(void) const
Return the number of MPDUs constituting the PSDU.
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 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.
bool IsUlMu(void) const
Return true if this TX vector is used for an uplink multi-user transmission.
void Connect(std::string path, const CallbackBase &cb)
#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_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
#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 Seconds(double value)
Construct a Time in the indicated unit.
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
@ WIFI_STANDARD_80211ax_5GHZ
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.
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...
RxSignalInfo structure containing info on the received signal.
static WifiPrimaryChannelsTestSuite g_wifiPrimaryChannelsTestSuite
the test suite