From 422f24bfd07877cd052c7231f870871d7ed348ed Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Tue, 30 Mar 2021 16:47:11 +0200 Subject: [PATCH] wifi: Extend helpers to support multi-link devices --- src/mesh/helper/mesh-helper.cc | 7 +- src/wave/helper/wave-helper.cc | 11 +-- src/wifi/helper/spectrum-wifi-helper.cc | 77 +++++++++++----- src/wifi/helper/spectrum-wifi-helper.h | 26 +++++- src/wifi/helper/wifi-helper.cc | 33 +++++-- src/wifi/helper/wifi-helper.h | 112 ++++++++++++++++++++---- src/wifi/helper/wifi-mac-helper.cc | 33 ++++--- src/wifi/helper/yans-wifi-helper.cc | 21 ++--- src/wifi/helper/yans-wifi-helper.h | 4 +- 9 files changed, 240 insertions(+), 84 deletions(-) diff --git a/src/mesh/helper/mesh-helper.cc b/src/mesh/helper/mesh-helper.cc index a1ffc3d47..fee4371fc 100644 --- a/src/mesh/helper/mesh-helper.cc +++ b/src/mesh/helper/mesh-helper.cc @@ -182,10 +182,11 @@ MeshHelper::CreateInterface (const WifiPhyHelper &phyHelper, Ptr node, uin // this is a const method, but we need to force the correct QoS setting ObjectFactory macObjectFactory = m_mac; macObjectFactory.Set ("QosSupported", BooleanValue (true)); // a mesh station is a QoS station - Ptr phy = phyHelper.Create (node, device); + std::vector> phys = phyHelper.Create (node, device); + NS_ABORT_IF (phys.size () != 1); node->AddDevice (device); - phy->ConfigureStandard (m_standard); - device->SetPhy (phy); + phys[0]->ConfigureStandard (m_standard); + device->SetPhy (phys[0]); Ptr mac = macObjectFactory.Create (); NS_ASSERT (mac != 0); mac->SetSsid (Ssid ()); diff --git a/src/wave/helper/wave-helper.cc b/src/wave/helper/wave-helper.cc index 9dcb8ccc1..d081f601a 100644 --- a/src/wave/helper/wave-helper.cc +++ b/src/wave/helper/wave-helper.cc @@ -382,11 +382,12 @@ WaveHelper::Install (const WifiPhyHelper &phyHelper, const WifiMacHelper &macHe for (uint32_t j = 0; j != m_physNumber; ++j) { - Ptr phy = phyHelper.Create (node, device); - phy->ConfigureStandard (WIFI_STANDARD_80211p); - phy->SetOperatingChannel (WifiPhy::ChannelTuple {ChannelManager::GetCch (), 0, - WIFI_PHY_BAND_5GHZ, 0}); - device->AddPhy (phy); + std::vector> phys = phyHelper.Create (node, device); + NS_ABORT_IF (phys.size () != 1); + phys[0]->ConfigureStandard (WIFI_STANDARD_80211p); + phys[0]->SetOperatingChannel (WifiPhy::ChannelTuple {ChannelManager::GetCch (), 0, + WIFI_PHY_BAND_5GHZ, 0}); + device->AddPhy (phys[0]); } for (std::vector::const_iterator k = m_macsForChannelNumber.begin (); diff --git a/src/wifi/helper/spectrum-wifi-helper.cc b/src/wifi/helper/spectrum-wifi-helper.cc index eeea8d0ee..299757f60 100644 --- a/src/wifi/helper/spectrum-wifi-helper.cc +++ b/src/wifi/helper/spectrum-wifi-helper.cc @@ -34,10 +34,15 @@ namespace ns3 { NS_LOG_COMPONENT_DEFINE ("SpectrumWifiHelper"); -SpectrumWifiPhyHelper::SpectrumWifiPhyHelper () - : m_channel (0) +SpectrumWifiPhyHelper::SpectrumWifiPhyHelper (uint8_t nLinks) + : WifiPhyHelper (nLinks) { - m_phy.SetTypeId ("ns3::SpectrumWifiPhy"); + NS_ABORT_IF (m_phy.size () != nLinks); + for (auto& phy : m_phy) + { + phy.SetTypeId ("ns3::SpectrumWifiPhy"); + } + m_channels.resize (m_phy.size ()); SetInterferenceHelper ("ns3::InterferenceHelper"); SetErrorRateModel ("ns3::TableBasedErrorRateModel"); } @@ -45,39 +50,65 @@ SpectrumWifiPhyHelper::SpectrumWifiPhyHelper () void SpectrumWifiPhyHelper::SetChannel (Ptr channel) { - m_channel = channel; + for (auto& ch : m_channels) + { + ch = channel; + } } void SpectrumWifiPhyHelper::SetChannel (std::string channelName) { Ptr channel = Names::Find (channelName); - m_channel = channel; + for (auto& ch : m_channels) + { + ch = channel; + } } -Ptr +void +SpectrumWifiPhyHelper::SetChannel (uint8_t linkId, Ptr channel) +{ + m_channels.at (linkId) = channel; +} + +void +SpectrumWifiPhyHelper::SetChannel (uint8_t linkId, std::string channelName) +{ + Ptr channel = Names::Find (channelName); + m_channels.at (linkId) = channel; +} + +std::vector> SpectrumWifiPhyHelper::Create (Ptr node, Ptr device) const { - Ptr phy = m_phy.Create (); - phy->CreateWifiSpectrumPhyInterface (device); + std::vector> ret; Ptr interference = m_interferenceHelper.Create (); - phy->SetInterferenceHelper (interference); - Ptr error = m_errorRateModel.Create (); - phy->SetErrorRateModel (error); - if (m_frameCaptureModel.IsTypeIdSet ()) + + for (std::size_t i = 0; i < m_phy.size (); i++) { - auto frameCapture = m_frameCaptureModel.Create (); - phy->SetFrameCaptureModel (frameCapture); + Ptr phy = m_phy.at (i).Create (); + phy->CreateWifiSpectrumPhyInterface (device); + phy->SetInterferenceHelper (interference); + Ptr error = m_errorRateModel.at (i).Create (); + phy->SetErrorRateModel (error); + if (m_frameCaptureModel.at (i).IsTypeIdSet ()) + { + auto frameCapture = m_frameCaptureModel.at (i).Create (); + phy->SetFrameCaptureModel (frameCapture); + } + if (m_preambleDetectionModel.at (i).IsTypeIdSet ()) + { + auto preambleDetection = m_preambleDetectionModel.at (i).Create (); + phy->SetPreambleDetectionModel (preambleDetection); + } + phy->SetChannel (m_channels.at (i)); + phy->SetDevice (device); + phy->SetMobility (node->GetObject ()); + ret.push_back (phy); } - if (m_preambleDetectionModel.IsTypeIdSet ()) - { - auto preambleDetection = m_preambleDetectionModel.Create (); - phy->SetPreambleDetectionModel (preambleDetection); - } - phy->SetChannel (m_channel); - phy->SetDevice (device); - phy->SetMobility (node->GetObject ()); - return phy; + + return ret; } } //namespace ns3 diff --git a/src/wifi/helper/spectrum-wifi-helper.h b/src/wifi/helper/spectrum-wifi-helper.h index b1b7d105a..5218a2714 100644 --- a/src/wifi/helper/spectrum-wifi-helper.h +++ b/src/wifi/helper/spectrum-wifi-helper.h @@ -39,8 +39,10 @@ class SpectrumWifiPhyHelper : public WifiPhyHelper public: /** * Create a PHY helper. + * + * \param nLinks the number of links to configure (>1 only for 11be devices) */ - SpectrumWifiPhyHelper (); + SpectrumWifiPhyHelper (uint8_t nLinks = 1); /** * \param channel the channel to associate to this helper @@ -54,18 +56,34 @@ public: * Every PHY created by a call to Install is associated to this channel. */ void SetChannel (std::string channelName); + /** + * \param channel the channel to associate to this helper + * \param linkId ID of the link to configure (>0 only for 11be devices) + * + * The PHY associated with the given link and created by a call to Install + * is associated to this channel. + */ + void SetChannel (uint8_t linkId, Ptr channel); + /** + * \param channelName The name of the channel to associate to this helper + * \param linkId ID of the link to configure (>0 only for 11be devices) + * + * The PHY associated with the given link and created by a call to Install + * is associated to this channel. + */ + void SetChannel (uint8_t linkId, std::string channelName); private: /** * \param node the node on which we wish to create a wifi PHY * \param device the device within which this PHY will be created - * \returns a newly-created PHY object. + * \returns newly-created PHY objects. * * This method implements the pure virtual method defined in \ref ns3::WifiPhyHelper. */ - Ptr Create (Ptr node, Ptr device) const override; + std::vector> Create (Ptr node, Ptr device) const override; - Ptr m_channel; ///< the channel + std::vector> m_channels; ///< the channels }; } //namespace ns3 diff --git a/src/wifi/helper/wifi-helper.cc b/src/wifi/helper/wifi-helper.cc index 5c1894a9a..46e5f3f1e 100644 --- a/src/wifi/helper/wifi-helper.cc +++ b/src/wifi/helper/wifi-helper.cc @@ -141,9 +141,15 @@ AsciiPhyReceiveSinkWithoutContext ( *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << mode << " " << *pCopy << " " << fcs << std::endl; } -WifiPhyHelper::WifiPhyHelper () +WifiPhyHelper::WifiPhyHelper (uint8_t nLinks) : m_pcapDlt (PcapHelper::DLT_IEEE802_11) { + NS_ABORT_IF (nLinks == 0); + m_phy.resize (nLinks); + m_errorRateModel.resize (nLinks); + m_frameCaptureModel.resize (nLinks); + m_preambleDetectionModel.resize (nLinks); + SetPreambleDetectionModel ("ns3::ThresholdPreambleDetectionModel"); } @@ -154,13 +160,25 @@ WifiPhyHelper::~WifiPhyHelper () void WifiPhyHelper::Set (std::string name, const AttributeValue &v) { - m_phy.Set (name, v); + for (auto& phy : m_phy) + { + phy.Set (name, v); + } +} + +void +WifiPhyHelper::Set (uint8_t linkId, std::string name, const AttributeValue &v) +{ + m_phy.at (linkId).Set (name, v); } void WifiPhyHelper::DisablePreambleDetectionModel () { - m_preambleDetectionModel.SetTypeId (TypeId ()); + for (auto& preambleDetectionModel : m_preambleDetectionModel) + { + preambleDetectionModel.SetTypeId (TypeId ()); + } } void @@ -760,9 +778,12 @@ WifiHelper::Install (const WifiPhyHelper &phyHelper, } Ptr manager = m_stationManager.Create (); device->SetRemoteStationManager (manager); - Ptr phy = phyHelper.Create (node, device); - device->SetPhy (phy); - phy->ConfigureStandard (m_standard); + std::vector> phys = phyHelper.Create (node, device); + device->SetPhys (phys); + for (std::size_t i = 0; i < phys.size (); i++) + { + phys[i]->ConfigureStandard (m_standard); + } Ptr mac = macHelper.Create (device, m_standard); if ((m_standard >= WIFI_STANDARD_80211ax) && (m_obssPdAlgorithm.IsTypeIdSet ())) { diff --git a/src/wifi/helper/wifi-helper.h b/src/wifi/helper/wifi-helper.h index 847ff1d97..be9d7a04a 100644 --- a/src/wifi/helper/wifi-helper.h +++ b/src/wifi/helper/wifi-helper.h @@ -29,6 +29,7 @@ #include "ns3/deprecated.h" #include "wifi-mac-helper.h" #include +#include namespace ns3 { @@ -47,28 +48,42 @@ class WifiPhyHelper : public PcapHelperForDevice, public AsciiTraceHelperForDevice { public: - WifiPhyHelper (); + /** + * Constructor + * + * \param nLinks the number of links to configure (>1 only for 11be devices) + */ + WifiPhyHelper (uint8_t nLinks = 1); virtual ~WifiPhyHelper (); /** - * \param node the node on which the PHY object will reside - * \param device the device within which the PHY object will reside + * \param node the node on which the PHY object(s) will reside + * \param device the device within which the PHY object(s) will reside * - * \returns a new PHY object. + * \returns new PHY objects. * * Subclasses must implement this method to allow the ns3::WifiHelper class * to create PHY objects from ns3::WifiHelper::Install. */ - virtual Ptr Create (Ptr node, Ptr device) const = 0; + virtual std::vector> Create (Ptr node, Ptr device) const = 0; /** * \param name the name of the attribute to set * \param v the value of the attribute * - * Set an attribute of the underlying PHY object. + * Set an attribute of all the underlying PHY object. */ void Set (std::string name, const AttributeValue &v); + /** + * \param name the name of the attribute to set + * \param v the value of the attribute + * \param linkId ID of the link to configure (>0 only for 11be devices) + * + * Set an attribute of the given underlying PHY object. + */ + void Set (uint8_t linkId, std::string name, const AttributeValue &v); + /** * Helper function used to set the interference helper. * @@ -89,6 +104,17 @@ public: template void SetErrorRateModel (std::string type, Args&&... args); + /** + * \tparam Args \deduced Template type parameter pack for the sequence of name-value pairs. + * \param linkId ID of the link to configure (>0 only for 11be devices) + * \param type the type of the error rate model to set. + * \param args A sequence of name-value pairs of the attributes to set. + * + * Set the error rate model and its attributes to use for the given link when Install is called. + */ + template + void SetErrorRateModel (uint8_t linkId, std::string type, Args&&... args); + /** * Helper function used to set the frame capture model. * @@ -99,6 +125,17 @@ public: template void SetFrameCaptureModel (std::string type, Args&&... args); + /** + * \tparam Args \deduced Template type parameter pack for the sequence of name-value pairs. + * \param linkId ID of the link to configure (>0 only for 11be devices) + * \param type the type of the frame capture model to set. + * \param args A sequence of name-value pairs of the attributes to set. + * + * Set the frame capture model and its attributes to use for the given link when Install is called. + */ + template + void SetFrameCaptureModel (uint8_t linkId, std::string type, Args&&... args); + /** * Helper function used to set the preamble detection model. * @@ -110,7 +147,18 @@ public: void SetPreambleDetectionModel (std::string type, Args&&... args); /** - * Disable the preamble detection model. + * \tparam Args \deduced Template type parameter pack for the sequence of name-value pairs. + * \param linkId ID of the link to configure (>0 only for 11be devices) + * \param type the type of the preamble detection model to set. + * \param args A sequence of name-value pairs of the attributes to set. + * + * Set the preamble detection model and its attributes to use for the given link when Install is called. + */ + template + void SetPreambleDetectionModel (uint8_t linkId, std::string type, Args&&... args); + + /** + * Disable the preamble detection model on all links. */ void DisablePreambleDetectionModel (); @@ -183,11 +231,11 @@ protected: SignalNoiseDbm signalNoise, uint16_t staId = SU_STA_ID); - ObjectFactory m_phy; ///< PHY object + std::vector m_phy; ///< PHY object ObjectFactory m_interferenceHelper; ///< interference helper - ObjectFactory m_errorRateModel; ///< error rate model - ObjectFactory m_frameCaptureModel; ///< frame capture model - ObjectFactory m_preambleDetectionModel; ///< preamble detection model + std::vector m_errorRateModel; ///< error rate model + std::vector m_frameCaptureModel; ///< frame capture model + std::vector m_preambleDetectionModel; ///< preamble detection model private: @@ -482,24 +530,54 @@ template void WifiPhyHelper::SetErrorRateModel (std::string type, Args&&... args) { - m_errorRateModel.SetTypeId (type); - m_errorRateModel.Set (args...); + for (uint8_t linkId = 0; linkId < m_phy.size (); linkId++) + { + SetErrorRateModel (linkId, type, std::forward (args)...); + } +} + +template +void +WifiPhyHelper::SetErrorRateModel (uint8_t linkId, std::string type, Args&&... args) +{ + m_errorRateModel.at (linkId).SetTypeId (type); + m_errorRateModel.at (linkId).Set (args...); } template void WifiPhyHelper::SetFrameCaptureModel (std::string type, Args&&... args) { - m_frameCaptureModel.SetTypeId (type); - m_frameCaptureModel.Set (args...); + for (uint8_t linkId = 0; linkId < m_phy.size (); linkId++) + { + SetFrameCaptureModel (linkId, type, std::forward (args)...); + } +} + +template +void +WifiPhyHelper::SetFrameCaptureModel (uint8_t linkId, std::string type, Args&&... args) +{ + m_frameCaptureModel.at (linkId).SetTypeId (type); + m_frameCaptureModel.at (linkId).Set (args...); } template void WifiPhyHelper::SetPreambleDetectionModel (std::string type, Args&&... args) { - m_preambleDetectionModel.SetTypeId (type); - m_preambleDetectionModel.Set (args...); + for (uint8_t linkId = 0; linkId < m_phy.size (); linkId++) + { + SetPreambleDetectionModel (linkId, type, std::forward (args)...); + } +} + +template +void +WifiPhyHelper::SetPreambleDetectionModel (uint8_t linkId, std::string type, Args&&... args) +{ + m_preambleDetectionModel.at (linkId).SetTypeId (type); + m_preambleDetectionModel.at (linkId).Set (args...); } template diff --git a/src/wifi/helper/wifi-mac-helper.cc b/src/wifi/helper/wifi-mac-helper.cc index 261255fd5..8e949bd36 100644 --- a/src/wifi/helper/wifi-mac-helper.cc +++ b/src/wifi/helper/wifi-mac-helper.cc @@ -59,29 +59,34 @@ WifiMacHelper::Create (Ptr device, WifiStandard standard) const device->SetMac (mac); mac->ConfigureStandard (standard); - Ptr fem = mac->GetFrameExchangeManager (); - - if (fem != nullptr) + // WaveNetDevice 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) { + auto fem = mac->GetFrameExchangeManager (linkId); + Ptr protectionManager = m_protectionManager.Create (); protectionManager->SetWifiMac (mac); - protectionManager->SetLinkId (SINGLE_LINK_OP_ID); + protectionManager->SetLinkId (linkId); fem->SetProtectionManager (protectionManager); Ptr ackManager = m_ackManager.Create (); ackManager->SetWifiMac (mac); - ackManager->SetLinkId (SINGLE_LINK_OP_ID); + ackManager->SetLinkId (linkId); fem->SetAckManager (ackManager); - - // create and install the Multi User Scheduler if this is an HE AP - Ptr apMac = DynamicCast (mac); - if (apMac != nullptr && standard >= WIFI_STANDARD_80211ax - && m_muScheduler.IsTypeIdSet ()) - { - Ptr muScheduler = m_muScheduler.Create (); - apMac->AggregateObject (muScheduler); - } } + + // create and install the Multi User Scheduler if this is an HE AP + Ptr apMac; + if (standard >= WIFI_STANDARD_80211ax + && m_muScheduler.IsTypeIdSet () + && (apMac = DynamicCast (mac)) != nullptr) + { + Ptr muScheduler = m_muScheduler.Create (); + apMac->AggregateObject (muScheduler); + } + return mac; } diff --git a/src/wifi/helper/yans-wifi-helper.cc b/src/wifi/helper/yans-wifi-helper.cc index 79919ee3d..e1e5d3df1 100644 --- a/src/wifi/helper/yans-wifi-helper.cc +++ b/src/wifi/helper/yans-wifi-helper.cc @@ -126,9 +126,10 @@ YansWifiChannelHelper::AssignStreams (Ptr c, int64_t stream) } YansWifiPhyHelper::YansWifiPhyHelper () - : m_channel (0) + : WifiPhyHelper (1), // YANS phy is not used for 11be devices + m_channel (0) { - m_phy.SetTypeId ("ns3::YansWifiPhy"); + m_phy.at (0).SetTypeId ("ns3::YansWifiPhy"); SetInterferenceHelper ("ns3::InterferenceHelper"); SetErrorRateModel ("ns3::TableBasedErrorRateModel"); } @@ -146,27 +147,27 @@ YansWifiPhyHelper::SetChannel (std::string channelName) m_channel = channel; } -Ptr +std::vector> YansWifiPhyHelper::Create (Ptr node, Ptr device) const { - Ptr phy = m_phy.Create (); + Ptr phy = m_phy.at (0).Create (); Ptr interference = m_interferenceHelper.Create (); phy->SetInterferenceHelper (interference); - Ptr error = m_errorRateModel.Create (); + Ptr error = m_errorRateModel.at (0).Create (); phy->SetErrorRateModel (error); - if (m_frameCaptureModel.IsTypeIdSet ()) + if (m_frameCaptureModel.at (0).IsTypeIdSet ()) { - auto frameCapture = m_frameCaptureModel.Create (); + auto frameCapture = m_frameCaptureModel.at (0).Create (); phy->SetFrameCaptureModel (frameCapture); } - if (m_preambleDetectionModel.IsTypeIdSet ()) + if (m_preambleDetectionModel.at (0).IsTypeIdSet ()) { - auto preambleDetection = m_preambleDetectionModel.Create (); + auto preambleDetection = m_preambleDetectionModel.at (0).Create (); phy->SetPreambleDetectionModel (preambleDetection); } phy->SetChannel (m_channel); phy->SetDevice (device); - return phy; + return std::vector> ({phy}); } } //namespace ns3 diff --git a/src/wifi/helper/yans-wifi-helper.h b/src/wifi/helper/yans-wifi-helper.h index fd53c3078..872520648 100644 --- a/src/wifi/helper/yans-wifi-helper.h +++ b/src/wifi/helper/yans-wifi-helper.h @@ -183,11 +183,11 @@ private: /** * \param node the node on which we wish to create a wifi PHY * \param device the device within which this PHY will be created - * \returns a newly-created PHY object. + * \returns newly-created PHY objects. * * This method implements the pure virtual method defined in \ref ns3::WifiPhyHelper. */ - Ptr Create (Ptr node, Ptr device) const override; + std::vector> Create (Ptr node, Ptr device) const override; Ptr m_channel; ///< YANS wifi channel };