From f004f0109fa10748c7669df19d946e964ac0ecee Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 29 Apr 2024 10:38:52 +0200 Subject: [PATCH] wifi: ChannelAccessManager attributes can be set through WifiMacHelper --- src/mesh/helper/mesh-helper.cc | 1 + src/wifi/helper/wifi-mac-helper.cc | 20 +++++++++++--- src/wifi/helper/wifi-mac-helper.h | 29 +++++++++++++++----- src/wifi/model/wifi-mac.cc | 30 ++++++++++++++++----- src/wifi/model/wifi-mac.h | 5 ++++ src/wifi/test/power-rate-adaptation-test.cc | 1 + src/wifi/test/wifi-aggregation-test.cc | 6 +++++ src/wifi/test/wifi-test.cc | 5 ++++ 8 files changed, 80 insertions(+), 17 deletions(-) diff --git a/src/mesh/helper/mesh-helper.cc b/src/mesh/helper/mesh-helper.cc index 7bac7bd95..c5f008609 100644 --- a/src/mesh/helper/mesh-helper.cc +++ b/src/mesh/helper/mesh-helper.cc @@ -143,6 +143,7 @@ MeshHelper::CreateInterface(const WifiPhyHelper& phyHelper, mac->SetAddress(Mac48Address::Allocate()); device->SetMac(mac); mac->SetMacQueueScheduler(CreateObject()); + mac->SetChannelAccessManagers({CreateObject()}); mac->ConfigureStandard(m_standard); Ptr fem = mac->GetFrameExchangeManager(); if (fem) diff --git a/src/wifi/helper/wifi-mac-helper.cc b/src/wifi/helper/wifi-mac-helper.cc index 8c6374f87..587a0e52a 100644 --- a/src/wifi/helper/wifi-mac-helper.cc +++ b/src/wifi/helper/wifi-mac-helper.cc @@ -33,6 +33,7 @@ #include "ns3/wifi-protection-manager.h" #include +#include namespace ns3 { @@ -48,6 +49,7 @@ WifiMacHelper::WifiMacHelper() auto [it, inserted] = m_edca.try_emplace(aci); it->second.SetTypeId("ns3::QosTxop"); } + m_channelAccessManager.SetTypeId("ns3::ChannelAccessManager"); m_assocManager.SetTypeId("ns3::WifiDefaultAssocManager"); m_queueScheduler.SetTypeId("ns3::FcfsWifiQueueScheduler"); m_protectionManager.SetTypeId("ns3::WifiDefaultProtectionManager"); @@ -88,19 +90,29 @@ WifiMacHelper::Create(Ptr device, WifiStandard standard) const macObjectFactory.Set(s, PointerValue(edca.Create())); } + // WaveNetDevice (through ns-3.38) stores PHY entities in a different member than WifiNetDevice, + // hence GetNPhys() would return 0 + auto nLinks = std::max(device->GetNPhys(), 1); + + // create Channel Access Managers + std::vector> caManagers; + for (uint8_t linkId = 0; linkId < nLinks; ++linkId) + { + caManagers.emplace_back(m_channelAccessManager.Create()); + } + Ptr mac = macObjectFactory.Create(); mac->SetDevice(device); mac->SetAddress(Mac48Address::Allocate()); device->SetMac(mac); + mac->SetChannelAccessManagers(caManagers); mac->ConfigureStandard(standard); Ptr queueScheduler = m_queueScheduler.Create(); mac->SetMacQueueScheduler(queueScheduler); - // WaveNetDevice (through ns-3.38) stores PHY entities in a different member than WifiNetDevice, - // hence GetNPhys() would return 0. We have to attach a protection manager and an ack manager to - // the unique instance of frame exchange manager anyway - for (uint8_t linkId = 0; linkId < std::max(device->GetNPhys(), 1); ++linkId) + // attach a protection manager and an ack manager to every instance of frame exchange manager + for (uint8_t linkId = 0; linkId < nLinks; ++linkId) { auto fem = mac->GetFrameExchangeManager(linkId); diff --git a/src/wifi/helper/wifi-mac-helper.h b/src/wifi/helper/wifi-mac-helper.h index 69d76a0d1..ff6019f70 100644 --- a/src/wifi/helper/wifi-mac-helper.h +++ b/src/wifi/helper/wifi-mac-helper.h @@ -90,6 +90,15 @@ class WifiMacHelper template void SetEdca(AcIndex aci, Args&&... args); + /** + * Helper function used to set the Channel Access Manager object. + * + * \tparam Args \deduced Template type parameter pack for the sequence of name-value pairs. + * \param args A sequence of name-value pairs of the attributes to set. + */ + template + void SetChannelAccessManager(Args&&... args); + /** * Helper function used to set the Association Manager. * @@ -164,12 +173,13 @@ class WifiMacHelper ObjectFactory m_mac; ///< MAC object factory ObjectFactory m_dcf; ///< Txop (DCF) object factory std::map> m_edca; ///< QosTxop (EDCA) object factories - ObjectFactory m_assocManager; ///< Association Manager - ObjectFactory m_queueScheduler; ///< MAC queue scheduler - ObjectFactory m_protectionManager; ///< Factory to create a protection manager - ObjectFactory m_ackManager; ///< Factory to create an acknowledgment manager - ObjectFactory m_muScheduler; ///< Multi-user Scheduler object factory - ObjectFactory m_emlsrManager; ///< EMLSR Manager object factory + ObjectFactory m_channelAccessManager; ///< Channel Access Manager object factory + ObjectFactory m_assocManager; ///< Association Manager + ObjectFactory m_queueScheduler; ///< MAC queue scheduler + ObjectFactory m_protectionManager; ///< Factory to create a protection manager + ObjectFactory m_ackManager; ///< Factory to create an acknowledgment manager + ObjectFactory m_muScheduler; ///< Multi-user Scheduler object factory + ObjectFactory m_emlsrManager; ///< EMLSR Manager object factory }; } // namespace ns3 @@ -205,6 +215,13 @@ WifiMacHelper::SetEdca(AcIndex aci, Args&&... args) it->second.Set(args...); } +template +void +WifiMacHelper::SetChannelAccessManager(Args&&... args) +{ + m_channelAccessManager.Set(args...); +} + template void WifiMacHelper::SetAssocManager(std::string type, Args&&... args) diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index b237ae815..972b36bfa 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -867,12 +867,9 @@ WifiMac::ConfigureStandard(WifiStandard standard) "[LinkID " << +id << "] PHY must have been set and an operating channel must have been set"); - // do not create a ChannelAccessManager and a FrameExchangeManager if they - // already exist (this function may be called after ResetWifiPhys) - if (!link->channelAccessManager) - { - link->channelAccessManager = CreateObject(); - } + NS_ABORT_MSG_IF(!link->channelAccessManager, + "[LinkID " << +id << "] A channel access manager must have been set"); + link->channelAccessManager->SetupPhyListener(link->phy); if (!link->feManager) @@ -882,7 +879,6 @@ WifiMac::ConfigureStandard(WifiStandard standard) link->feManager->SetWifiPhy(link->phy); link->feManager->SetWifiMac(this); link->feManager->SetLinkId(id); - link->channelAccessManager->SetLinkId(id); link->channelAccessManager->SetupFrameExchangeManager(link->feManager); if (m_txop) @@ -991,6 +987,26 @@ WifiMac::GetFrameExchangeManager(uint8_t linkId) const return GetLink(linkId).feManager; } +void +WifiMac::SetChannelAccessManagers(const std::vector>& caManagers) +{ + NS_LOG_FUNCTION(this); + + if (!CreateLinksIfNeeded(caManagers.size())) + { + NS_ABORT_MSG_IF(caManagers.size() != m_links.size(), + "The number of provided Channel Access Manager objects (" + << caManagers.size() << ") must match the number of existing links (" + << m_links.size() << ")"); + } + + for (auto managerIt = caManagers.cbegin(); auto& [id, link] : m_links) + { + link->channelAccessManager = *managerIt++; + link->channelAccessManager->SetLinkId(id); + } +} + Ptr WifiMac::GetChannelAccessManager(uint8_t linkId) const { diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index dfa4e7375..4a2e92ea1 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -151,6 +151,11 @@ class WifiMac : public Object */ Ptr GetChannelAccessManager(uint8_t linkId = SINGLE_LINK_OP_ID) const; + /** + * \param caManagers the channel access managers attached to this MAC. + */ + void SetChannelAccessManagers(const std::vector>& caManagers); + /** * Get the number of links (can be greater than 1 for 11be devices only). * diff --git a/src/wifi/test/power-rate-adaptation-test.cc b/src/wifi/test/power-rate-adaptation-test.cc index 626e19382..d39e70a94 100644 --- a/src/wifi/test/power-rate-adaptation-test.cc +++ b/src/wifi/test/power-rate-adaptation-test.cc @@ -123,6 +123,7 @@ PowerRateAdaptationTest::ConfigureNode() mac->SetDevice(dev); mac->SetAddress(Mac48Address::Allocate()); dev->SetMac(mac); + mac->SetChannelAccessManagers({CreateObject()}); mac->ConfigureStandard(WIFI_STANDARD_80211a); mac->SetMacQueueScheduler(CreateObject()); Ptr fem = mac->GetFrameExchangeManager(); diff --git a/src/wifi/test/wifi-aggregation-test.cc b/src/wifi/test/wifi-aggregation-test.cc index fb993f46b..b3b5988a7 100644 --- a/src/wifi/test/wifi-aggregation-test.cc +++ b/src/wifi/test/wifi-aggregation-test.cc @@ -234,6 +234,12 @@ AmpduAggregationTest::DoSetup() m_mac->SetAddress(Mac48Address("00:00:00:00:00:01")); m_device->SetMac(m_mac); m_mac->SetWifiPhys(m_phys); + std::vector> caManagers; + for (uint8_t i = 0; i < m_params.nLinks; i++) + { + caManagers.emplace_back(CreateObject()); + } + m_mac->SetChannelAccessManagers(caManagers); m_mac->ConfigureStandard(m_params.standard); for (uint8_t i = 0; i < m_params.nLinks; i++) { diff --git a/src/wifi/test/wifi-test.cc b/src/wifi/test/wifi-test.cc index a557e8562..cf6d6deda 100644 --- a/src/wifi/test/wifi-test.cc +++ b/src/wifi/test/wifi-test.cc @@ -165,6 +165,7 @@ WifiTest::CreateOne(Vector pos, Ptr channel) mac->SetDevice(dev); mac->SetAddress(Mac48Address::Allocate()); dev->SetMac(mac); + mac->SetChannelAccessManagers({CreateObject()}); mac->ConfigureStandard(WIFI_STANDARD_80211a); if (mac->GetTypeOfStation() == STA) { @@ -360,6 +361,7 @@ InterferenceHelperSequenceTest::CreateOne(Vector pos, Ptr chann mac->SetDevice(dev); mac->SetAddress(Mac48Address::Allocate()); dev->SetMac(mac); + mac->SetChannelAccessManagers({CreateObject()}); mac->ConfigureStandard(WIFI_STANDARD_80211a); mac->SetMacQueueScheduler(CreateObject()); Ptr fem = mac->GetFrameExchangeManager(); @@ -580,6 +582,7 @@ DcfImmediateAccessBroadcastTestCase::DoRun() txMac->SetDevice(txDev); txMac->SetAddress(Mac48Address::Allocate()); txDev->SetMac(txMac); + txMac->SetChannelAccessManagers({CreateObject()}); txMac->ConfigureStandard(WIFI_STANDARD_80211a); txMac->SetMacQueueScheduler(CreateObject()); auto fem = txMac->GetFrameExchangeManager(); @@ -1865,6 +1868,7 @@ Bug2831TestCase::DoRun() apMac->SetDevice(apDev); apMac->SetAddress(Mac48Address::Allocate()); apDev->SetMac(apMac); + apMac->SetChannelAccessManagers({CreateObject()}); apMac->ConfigureStandard(WIFI_STANDARD_80211ax); apMac->SetMacQueueScheduler(CreateObject()); Ptr fem = apMac->GetFrameExchangeManager(); @@ -1909,6 +1913,7 @@ Bug2831TestCase::DoRun() staDev->SetMac(staMac); staMac->SetDevice(staDev); staMac->SetAddress(Mac48Address::Allocate()); + staMac->SetChannelAccessManagers({CreateObject()}); staMac->ConfigureStandard(WIFI_STANDARD_80211ax); StaticCast(staMac)->SetAssocManager(CreateObject()); staMac->SetMacQueueScheduler(CreateObject());