wifi: Extend helpers to support multi-link devices

This commit is contained in:
Stefano Avallone
2021-03-30 16:47:11 +02:00
parent 7dce23fbd3
commit 422f24bfd0
9 changed files with 240 additions and 84 deletions

View File

@@ -182,10 +182,11 @@ MeshHelper::CreateInterface (const WifiPhyHelper &phyHelper, Ptr<Node> 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<WifiPhy> phy = phyHelper.Create (node, device);
std::vector<Ptr<WifiPhy>> 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<MeshWifiInterfaceMac> mac = macObjectFactory.Create<MeshWifiInterfaceMac> ();
NS_ASSERT (mac != 0);
mac->SetSsid (Ssid ());

View File

@@ -382,11 +382,12 @@ WaveHelper::Install (const WifiPhyHelper &phyHelper, const WifiMacHelper &macHe
for (uint32_t j = 0; j != m_physNumber; ++j)
{
Ptr<WifiPhy> 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<Ptr<WifiPhy>> 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<uint32_t>::const_iterator k = m_macsForChannelNumber.begin ();

View File

@@ -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<SpectrumChannel> channel)
{
m_channel = channel;
for (auto& ch : m_channels)
{
ch = channel;
}
}
void
SpectrumWifiPhyHelper::SetChannel (std::string channelName)
{
Ptr<SpectrumChannel> channel = Names::Find<SpectrumChannel> (channelName);
m_channel = channel;
for (auto& ch : m_channels)
{
ch = channel;
}
}
Ptr<WifiPhy>
void
SpectrumWifiPhyHelper::SetChannel (uint8_t linkId, Ptr<SpectrumChannel> channel)
{
m_channels.at (linkId) = channel;
}
void
SpectrumWifiPhyHelper::SetChannel (uint8_t linkId, std::string channelName)
{
Ptr<SpectrumChannel> channel = Names::Find<SpectrumChannel> (channelName);
m_channels.at (linkId) = channel;
}
std::vector<Ptr<WifiPhy>>
SpectrumWifiPhyHelper::Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const
{
Ptr<SpectrumWifiPhy> phy = m_phy.Create<SpectrumWifiPhy> ();
phy->CreateWifiSpectrumPhyInterface (device);
std::vector<Ptr<WifiPhy>> ret;
Ptr<InterferenceHelper> interference = m_interferenceHelper.Create<InterferenceHelper> ();
phy->SetInterferenceHelper (interference);
Ptr<ErrorRateModel> error = m_errorRateModel.Create<ErrorRateModel> ();
phy->SetErrorRateModel (error);
if (m_frameCaptureModel.IsTypeIdSet ())
for (std::size_t i = 0; i < m_phy.size (); i++)
{
auto frameCapture = m_frameCaptureModel.Create<FrameCaptureModel> ();
phy->SetFrameCaptureModel (frameCapture);
Ptr<SpectrumWifiPhy> phy = m_phy.at (i).Create<SpectrumWifiPhy> ();
phy->CreateWifiSpectrumPhyInterface (device);
phy->SetInterferenceHelper (interference);
Ptr<ErrorRateModel> error = m_errorRateModel.at (i).Create<ErrorRateModel> ();
phy->SetErrorRateModel (error);
if (m_frameCaptureModel.at (i).IsTypeIdSet ())
{
auto frameCapture = m_frameCaptureModel.at (i).Create<FrameCaptureModel> ();
phy->SetFrameCaptureModel (frameCapture);
}
if (m_preambleDetectionModel.at (i).IsTypeIdSet ())
{
auto preambleDetection = m_preambleDetectionModel.at (i).Create<PreambleDetectionModel> ();
phy->SetPreambleDetectionModel (preambleDetection);
}
phy->SetChannel (m_channels.at (i));
phy->SetDevice (device);
phy->SetMobility (node->GetObject<MobilityModel> ());
ret.push_back (phy);
}
if (m_preambleDetectionModel.IsTypeIdSet ())
{
auto preambleDetection = m_preambleDetectionModel.Create<PreambleDetectionModel> ();
phy->SetPreambleDetectionModel (preambleDetection);
}
phy->SetChannel (m_channel);
phy->SetDevice (device);
phy->SetMobility (node->GetObject<MobilityModel> ());
return phy;
return ret;
}
} //namespace ns3

View File

@@ -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<SpectrumChannel> 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<WifiPhy> Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const override;
std::vector<Ptr<WifiPhy>> Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const override;
Ptr<SpectrumChannel> m_channel; ///< the channel
std::vector<Ptr<SpectrumChannel>> m_channels; ///< the channels
};
} //namespace ns3

View File

@@ -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<WifiRemoteStationManager> manager = m_stationManager.Create<WifiRemoteStationManager> ();
device->SetRemoteStationManager (manager);
Ptr<WifiPhy> phy = phyHelper.Create (node, device);
device->SetPhy (phy);
phy->ConfigureStandard (m_standard);
std::vector<Ptr<WifiPhy>> phys = phyHelper.Create (node, device);
device->SetPhys (phys);
for (std::size_t i = 0; i < phys.size (); i++)
{
phys[i]->ConfigureStandard (m_standard);
}
Ptr<WifiMac> mac = macHelper.Create (device, m_standard);
if ((m_standard >= WIFI_STANDARD_80211ax) && (m_obssPdAlgorithm.IsTypeIdSet ()))
{

View File

@@ -29,6 +29,7 @@
#include "ns3/deprecated.h"
#include "wifi-mac-helper.h"
#include <functional>
#include <vector>
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<WifiPhy> Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const = 0;
virtual std::vector<Ptr<WifiPhy>> Create (Ptr<Node> node, Ptr<WifiNetDevice> 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 <typename... Args>
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 <typename... Args>
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 <typename... Args>
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 <typename... Args>
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 <typename... Args>
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<ObjectFactory> 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<ObjectFactory> m_errorRateModel; ///< error rate model
std::vector<ObjectFactory> m_frameCaptureModel; ///< frame capture model
std::vector<ObjectFactory> m_preambleDetectionModel; ///< preamble detection model
private:
@@ -482,24 +530,54 @@ template <typename... Args>
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> (args)...);
}
}
template <typename... Args>
void
WifiPhyHelper::SetErrorRateModel (uint8_t linkId, std::string type, Args&&... args)
{
m_errorRateModel.at (linkId).SetTypeId (type);
m_errorRateModel.at (linkId).Set (args...);
}
template <typename... Args>
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> (args)...);
}
}
template <typename... Args>
void
WifiPhyHelper::SetFrameCaptureModel (uint8_t linkId, std::string type, Args&&... args)
{
m_frameCaptureModel.at (linkId).SetTypeId (type);
m_frameCaptureModel.at (linkId).Set (args...);
}
template <typename... Args>
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> (args)...);
}
}
template <typename... Args>
void
WifiPhyHelper::SetPreambleDetectionModel (uint8_t linkId, std::string type, Args&&... args)
{
m_preambleDetectionModel.at (linkId).SetTypeId (type);
m_preambleDetectionModel.at (linkId).Set (args...);
}
template <typename... Args>

View File

@@ -59,29 +59,34 @@ WifiMacHelper::Create (Ptr<WifiNetDevice> device, WifiStandard standard) const
device->SetMac (mac);
mac->ConfigureStandard (standard);
Ptr<FrameExchangeManager> 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<uint8_t> (device->GetNPhys (), 1); ++linkId)
{
auto fem = mac->GetFrameExchangeManager (linkId);
Ptr<WifiProtectionManager> protectionManager = m_protectionManager.Create<WifiProtectionManager> ();
protectionManager->SetWifiMac (mac);
protectionManager->SetLinkId (SINGLE_LINK_OP_ID);
protectionManager->SetLinkId (linkId);
fem->SetProtectionManager (protectionManager);
Ptr<WifiAckManager> ackManager = m_ackManager.Create<WifiAckManager> ();
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<ApWifiMac> apMac = DynamicCast<ApWifiMac> (mac);
if (apMac != nullptr && standard >= WIFI_STANDARD_80211ax
&& m_muScheduler.IsTypeIdSet ())
{
Ptr<MultiUserScheduler> muScheduler = m_muScheduler.Create<MultiUserScheduler> ();
apMac->AggregateObject (muScheduler);
}
}
// create and install the Multi User Scheduler if this is an HE AP
Ptr<ApWifiMac> apMac;
if (standard >= WIFI_STANDARD_80211ax
&& m_muScheduler.IsTypeIdSet ()
&& (apMac = DynamicCast<ApWifiMac> (mac)) != nullptr)
{
Ptr<MultiUserScheduler> muScheduler = m_muScheduler.Create<MultiUserScheduler> ();
apMac->AggregateObject (muScheduler);
}
return mac;
}

View File

@@ -126,9 +126,10 @@ YansWifiChannelHelper::AssignStreams (Ptr<YansWifiChannel> 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<WifiPhy>
std::vector<Ptr<WifiPhy>>
YansWifiPhyHelper::Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const
{
Ptr<YansWifiPhy> phy = m_phy.Create<YansWifiPhy> ();
Ptr<YansWifiPhy> phy = m_phy.at (0).Create<YansWifiPhy> ();
Ptr<InterferenceHelper> interference = m_interferenceHelper.Create<InterferenceHelper> ();
phy->SetInterferenceHelper (interference);
Ptr<ErrorRateModel> error = m_errorRateModel.Create<ErrorRateModel> ();
Ptr<ErrorRateModel> error = m_errorRateModel.at (0).Create<ErrorRateModel> ();
phy->SetErrorRateModel (error);
if (m_frameCaptureModel.IsTypeIdSet ())
if (m_frameCaptureModel.at (0).IsTypeIdSet ())
{
auto frameCapture = m_frameCaptureModel.Create<FrameCaptureModel> ();
auto frameCapture = m_frameCaptureModel.at (0).Create<FrameCaptureModel> ();
phy->SetFrameCaptureModel (frameCapture);
}
if (m_preambleDetectionModel.IsTypeIdSet ())
if (m_preambleDetectionModel.at (0).IsTypeIdSet ())
{
auto preambleDetection = m_preambleDetectionModel.Create<PreambleDetectionModel> ();
auto preambleDetection = m_preambleDetectionModel.at (0).Create<PreambleDetectionModel> ();
phy->SetPreambleDetectionModel (preambleDetection);
}
phy->SetChannel (m_channel);
phy->SetDevice (device);
return phy;
return std::vector<Ptr<WifiPhy>> ({phy});
}
} //namespace ns3

View File

@@ -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<WifiPhy> Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const override;
std::vector<Ptr<WifiPhy>> Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const override;
Ptr<YansWifiChannel> m_channel; ///< YANS wifi channel
};