diff --git a/src/wifi/model/dsss-phy.cc b/src/wifi/model/dsss-phy.cc index 560791280..da43e1031 100644 --- a/src/wifi/model/dsss-phy.cc +++ b/src/wifi/model/dsss-phy.cc @@ -21,6 +21,7 @@ */ #include "dsss-phy.h" +#include "wifi-phy.h" //only used for static mode constructor #include "ns3/log.h" namespace ns3 { @@ -197,6 +198,9 @@ public: ConstructorDsss () { ns3::DsssPhy::InitializeModes (); + ns3::Ptr phyEntity = ns3::Create (); + ns3::WifiPhy::AddStaticPhyEntity (ns3::WIFI_MOD_CLASS_HR_DSSS, phyEntity); + ns3::WifiPhy::AddStaticPhyEntity (ns3::WIFI_MOD_CLASS_DSSS, phyEntity); //use same entity when plain DSSS modes are used } } g_constructor_dsss; ///< the constructor for DSSS modes diff --git a/src/wifi/model/erp-ofdm-phy.cc b/src/wifi/model/erp-ofdm-phy.cc index 51244002b..558f188a6 100644 --- a/src/wifi/model/erp-ofdm-phy.cc +++ b/src/wifi/model/erp-ofdm-phy.cc @@ -21,6 +21,7 @@ */ #include "erp-ofdm-phy.h" +#include "wifi-phy.h" //only used for static mode constructor #include "ns3/log.h" #include "ns3/assert.h" @@ -207,6 +208,7 @@ public: ConstructorErpOfdm () { ns3::ErpOfdmPhy::InitializeModes (); + ns3::WifiPhy::AddStaticPhyEntity (ns3::WIFI_MOD_CLASS_ERP_OFDM, ns3::Create ()); } } g_constructor_erp_ofdm; ///< the constructor for ERP-OFDM modes diff --git a/src/wifi/model/he-phy.cc b/src/wifi/model/he-phy.cc index 51c8945d9..3840117df 100644 --- a/src/wifi/model/he-phy.cc +++ b/src/wifi/model/he-phy.cc @@ -20,6 +20,7 @@ */ #include "he-phy.h" +#include "wifi-phy.h" //only used for static mode constructor #include "ns3/log.h" #include "ns3/assert.h" @@ -286,6 +287,7 @@ public: ConstructorHe () { ns3::HePhy::InitializeModes (); + ns3::WifiPhy::AddStaticPhyEntity (ns3::WIFI_MOD_CLASS_HE, ns3::Create ()); } } g_constructor_he; ///< the constructor for HE modes diff --git a/src/wifi/model/ht-phy.cc b/src/wifi/model/ht-phy.cc index 22786516b..56aeaaa6c 100644 --- a/src/wifi/model/ht-phy.cc +++ b/src/wifi/model/ht-phy.cc @@ -20,6 +20,7 @@ */ #include "ht-phy.h" +#include "wifi-phy.h" //only used for static mode constructor #include "ns3/log.h" #include "ns3/assert.h" @@ -546,6 +547,7 @@ public: ConstructorHt () { ns3::HtPhy::InitializeModes (); + ns3::WifiPhy::AddStaticPhyEntity (ns3::WIFI_MOD_CLASS_HT, ns3::Create ()); //dummy Nss } } g_constructor_ht; ///< the constructor for HT modes diff --git a/src/wifi/model/ofdm-phy.cc b/src/wifi/model/ofdm-phy.cc index 9fad0df1c..0aa85af7d 100644 --- a/src/wifi/model/ofdm-phy.cc +++ b/src/wifi/model/ofdm-phy.cc @@ -21,6 +21,7 @@ */ #include "ofdm-phy.h" +#include "wifi-phy.h" //only used for static mode constructor #include "ns3/log.h" #include "ns3/assert.h" @@ -558,6 +559,7 @@ public: ConstructorOfdm () { ns3::OfdmPhy::InitializeModes (); + ns3::WifiPhy::AddStaticPhyEntity (ns3::WIFI_MOD_CLASS_OFDM, ns3::Create ()); //default variant will do } } g_constructor_ofdm; ///< the constructor for OFDM modes diff --git a/src/wifi/model/vht-phy.cc b/src/wifi/model/vht-phy.cc index e35482592..946a1a492 100644 --- a/src/wifi/model/vht-phy.cc +++ b/src/wifi/model/vht-phy.cc @@ -20,6 +20,7 @@ */ #include "vht-phy.h" +#include "wifi-phy.h" //only used for static mode constructor #include "ns3/log.h" #include "ns3/assert.h" @@ -252,6 +253,7 @@ public: ConstructorVht () { ns3::VhtPhy::InitializeModes (); + ns3::WifiPhy::AddStaticPhyEntity (ns3::WIFI_MOD_CLASS_VHT, ns3::Create ()); } } g_constructor_vht; ///< the constructor for VHT modes diff --git a/src/wifi/model/wifi-phy.cc b/src/wifi/model/wifi-phy.cc index 12b6d90bb..9186c1ba5 100644 --- a/src/wifi/model/wifi-phy.cc +++ b/src/wifi/model/wifi-phy.cc @@ -40,6 +40,8 @@ #include "mpdu-aggregator.h" #include "wifi-psdu.h" #include "ap-wifi-mac.h" +#include "dsss-phy.h" +#include "erp-ofdm-phy.h" #include "he-phy.h" //includes OFDM, HT, and VHT namespace ns3 { @@ -288,6 +290,8 @@ WifiPhy::ChannelToFrequencyWidthMap WifiPhy::m_channelToFrequencyWidth = { { {207, WIFI_PHY_BAND_6GHZ}, WIFI_PHY_STANDARD_80211ax}, {6975, 160} } }; +std::map > WifiPhy::m_staticPhyEntities; //will be filled by g_constructor_XXX + TypeId WifiPhy::GetTypeId (void) { @@ -583,6 +587,12 @@ WifiPhy::DoDispose (void) m_deviceMcsSet.clear (); m_mcsIndexMap.clear (); m_currentPreambleEvents.clear (); + + for (auto & phyEntity : m_phyEntities) + { + phyEntity.second = 0; + } + m_phyEntities.clear (); } void @@ -965,6 +975,48 @@ WifiPhy::ConfigureDefaultsForStandard (void) } } +const Ptr +WifiPhy::GetStaticPhyEntity (WifiModulationClass modulation) +{ + const auto it = m_staticPhyEntities.find (modulation); + NS_ABORT_MSG_IF (it == m_staticPhyEntities.end (), "Unimplemented Wi-Fi modulation class"); + return it->second; +} + +const Ptr +WifiPhy::GetPhyEntity (WifiModulationClass modulation) const +{ + const auto it = m_phyEntities.find (modulation); + NS_ABORT_MSG_IF (it == m_phyEntities.end (), "Unsupported Wi-Fi modulation class"); + return it->second; +} + +Ptr +WifiPhy::GetPhyEntity (WifiModulationClass modulation) +{ + //This method returns a non-const pointer to be used by child classes + const auto it = m_phyEntities.find (modulation); + NS_ABORT_MSG_IF (it == m_phyEntities.end (), "Unsupported Wi-Fi modulation class"); + return it->second; +} + +void +WifiPhy::AddStaticPhyEntity (WifiModulationClass modulation, Ptr phyEntity) +{ + NS_LOG_FUNCTION (modulation); + NS_ASSERT_MSG (m_staticPhyEntities.find (modulation) == m_staticPhyEntities.end (), "The PHY entity has already been added. The setting should only be done once per modulation class"); + m_staticPhyEntities[modulation] = phyEntity; +} + +void +WifiPhy::AddPhyEntity (WifiModulationClass modulation, Ptr phyEntity) +{ + NS_LOG_FUNCTION (this << modulation); + NS_ABORT_MSG_IF (m_staticPhyEntities.find (modulation) == m_staticPhyEntities.end (), "Cannot add an unimplemented PHY to supported list. Update the former first."); + NS_ASSERT_MSG (m_phyEntities.find (modulation) == m_phyEntities.end (), "The PHY entity has already been added. The setting should only be done once per modulation class"); + m_phyEntities[modulation] = phyEntity; +} + void WifiPhy::SetSifs (Time sifs) { @@ -1017,6 +1069,7 @@ void WifiPhy::Configure80211a (void) { NS_LOG_FUNCTION (this); + AddPhyEntity (WIFI_MOD_CLASS_OFDM, Create ()); // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016 SetSifs (MicroSeconds (16)); @@ -1040,6 +1093,9 @@ void WifiPhy::Configure80211b (void) { NS_LOG_FUNCTION (this); + Ptr phyEntity = Create (); + AddPhyEntity (WIFI_MOD_CLASS_HR_DSSS, phyEntity); + AddPhyEntity (WIFI_MOD_CLASS_DSSS, phyEntity); //when plain DSSS modes are used // See Table 16-4 "HR/DSSS PHY characteristics" of 802.11-2016 SetSifs (MicroSeconds (10)); @@ -1065,6 +1121,7 @@ WifiPhy::Configure80211g (void) // if the user sets the ShortSlotTimeSupported flag to true and when the BSS // consists of only ERP STAs capable of supporting this option. Configure80211b (); + AddPhyEntity (WIFI_MOD_CLASS_ERP_OFDM, Create ()); m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate6Mbps ()); m_deviceRateSet.push_back (WifiPhy::GetErpOfdmRate9Mbps ()); @@ -1082,6 +1139,8 @@ WifiPhy::Configure80211p (void) NS_LOG_FUNCTION (this); if (GetChannelWidth () == 10) { + AddPhyEntity (WIFI_MOD_CLASS_OFDM, Create (OFDM_PHY_10_MHZ)); + // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016 SetSifs (MicroSeconds (32)); SetSlot (MicroSeconds (13)); @@ -1099,6 +1158,8 @@ WifiPhy::Configure80211p (void) } else if (GetChannelWidth () == 5) { + AddPhyEntity (WIFI_MOD_CLASS_OFDM, Create (OFDM_PHY_5_MHZ)); + // See Table 17-21 "OFDM PHY characteristics" of 802.11-2016 SetSifs (MicroSeconds (64)); SetSlot (MicroSeconds (21)); @@ -1124,6 +1185,7 @@ void WifiPhy::ConfigureHolland (void) { NS_LOG_FUNCTION (this); + AddPhyEntity (WIFI_MOD_CLASS_OFDM, Create (OFDM_PHY_HOLLAND)); SetSifs (MicroSeconds (16)); SetSlot (MicroSeconds (9)); @@ -1243,6 +1305,8 @@ WifiPhy::Configure80211n (void) { Configure80211a (); } + AddPhyEntity (WIFI_MOD_CLASS_HT, Create (m_txSpatialStreams)); + // See Table 10-5 "Determination of the EstimatedAckTxTime based on properties // of the PPDU causing the EIFS" of 802.11-2016 m_blockAckTxTime = MicroSeconds (68); @@ -1255,6 +1319,7 @@ WifiPhy::Configure80211ac (void) { NS_LOG_FUNCTION (this); Configure80211n (); + AddPhyEntity (WIFI_MOD_CLASS_VHT, Create ()); PushMcs (WifiPhy::GetVhtMcs0 ()); PushMcs (WifiPhy::GetVhtMcs1 ()); @@ -1282,6 +1347,7 @@ WifiPhy::Configure80211ax (void) { Configure80211ac (); } + AddPhyEntity (WIFI_MOD_CLASS_HE, Create ()); PushMcs (WifiPhy::GetHeMcs0 ()); PushMcs (WifiPhy::GetHeMcs1 ()); @@ -1442,7 +1508,7 @@ WifiPhy::ConfigureStandardAndBand (WifiPhyStandard standard, WifiPhyBand band) break; case WIFI_PHY_STANDARD_UNSPECIFIED: default: - NS_ASSERT (false); + NS_ASSERT_MSG (false, "Unsupported standard"); break; } } @@ -1564,9 +1630,22 @@ WifiPhy::SetMaxSupportedTxSpatialStreams (uint8_t streams) bool changed = (m_txSpatialStreams != streams); m_txSpatialStreams = streams; ConfigureHtDeviceMcsSet (); - if (changed && !m_capabilitiesChangedCallback.IsNull ()) + if (changed) { - m_capabilitiesChangedCallback (); + auto phyEntity = m_phyEntities.find (WIFI_MOD_CLASS_HT); + if (phyEntity != m_phyEntities.end ()) + { + Ptr htPhy = DynamicCast (phyEntity->second); + if (htPhy) + { + htPhy->SetMaxSupportedNss (m_txSpatialStreams); //this is essential to have the right MCSs configured + } + + if (!m_capabilitiesChangedCallback.IsNull ()) + { + m_capabilitiesChangedCallback (); + } + } } } diff --git a/src/wifi/model/wifi-phy.h b/src/wifi/model/wifi-phy.h index 6be9c5dba..2475ecb64 100644 --- a/src/wifi/model/wifi-phy.h +++ b/src/wifi/model/wifi-phy.h @@ -41,7 +41,7 @@ class FrameCaptureModel; class PreambleDetectionModel; class WifiRadioEnergyModel; class UniformRandomVariable; -class WifiPsdu; +class PhyEntity; /** * Enumeration of the possible reception failure reasons. @@ -1835,6 +1835,36 @@ public: */ WifiSpectrumBand GetNonOfdmaBand (WifiTxVector txVector, uint16_t staId) const; + /** + * Add the PHY entity to the map of __implemented__ PHY entities for the + * given modulation class. + * Through this method, child classes can add their own PHY entities in + * a static manner. + * + * \param modulation the modulation class + * \param phyEntity the PHY entity + */ + static void AddStaticPhyEntity (WifiModulationClass modulation, Ptr phyEntity); + + /** + * Get the __implemented__ PHY entity corresponding to the modulation class. + * This is used to compute the different amendment-specific parameters within + * calling static methods. + * + * \param modulation the modulation class + * \return the pointer to the static implemented PHY entity + */ + static const Ptr GetStaticPhyEntity (WifiModulationClass modulation); + + /** + * Get the supported PHY entity corresponding to the modulation class, for + * the WifiPhy instance. + * + * \param modulation the modulation class + * \return the const pointer to the supported PHY entity + */ + const Ptr GetPhyEntity (WifiModulationClass modulation) const; + protected: // Inherited @@ -1915,6 +1945,29 @@ protected: */ virtual WifiSpectrumBand ConvertHeRuSubcarriers (uint16_t channelWidth, HeRu::SubcarrierRange range) const; + /** + * Add the PHY entity to the map of supported PHY entities for the + * given modulation class for the WifiPhy instance. + * This is a wrapper method used to check that the PHY entity is + * in the static map of implemented PHY entities (\see m_staticPhyEntities). + * In addition, child classes can add their own PHY entities. + * + * \param modulation the modulation class + * \param phyEntity the PHY entity + */ + void AddPhyEntity (WifiModulationClass modulation, Ptr phyEntity); + /** + * Get the supported PHY entity corresponding to the modulation class, for + * the WifiPhy instance. + * + * This method enables child classes to retrieve the non-const pointer to + * the supported PHY entity. + * + * \param modulation the modulation class + * \return the non-const pointer to the supported PHY entity + */ + Ptr GetPhyEntity (WifiModulationClass modulation); + InterferenceHelper m_interference; //!< Pointer to InterferenceHelper Ptr m_random; //!< Provides uniform random variables. Ptr m_state; //!< Pointer to WifiPhyStateHelper @@ -1940,6 +1993,14 @@ protected: static uint64_t m_globalPpduUid; //!< Global counter of the PPDU UID + /** + * This map holds the supported PHY entities. + * + * The set of parameters (e.g. mode) that this WifiPhy(-derived class) can + * support can be obtained through it. + */ + std::map > m_phyEntities; + private: /** @@ -2225,6 +2286,13 @@ private: */ TracedCallback m_phyEndOfHeSigATrace; + /** + * Map of __implemented__ PHY entities. This is used to compute the different + * amendment-specific parameters in a static manner. + * For PHY entities supported by a given WifiPhy instance, + * \see m_phyEntities. + */ + static std::map > m_staticPhyEntities; /** * This vector holds the set of transmission modes that this * WifiPhy(-derived class) can support. In conversation we call this diff --git a/src/wifi/model/wifi-tx-vector.cc b/src/wifi/model/wifi-tx-vector.cc index 9899887a1..a0a4360af 100644 --- a/src/wifi/model/wifi-tx-vector.cc +++ b/src/wifi/model/wifi-tx-vector.cc @@ -128,10 +128,7 @@ WifiTxVector::GetModulationClass (void) const { NS_ABORT_MSG_IF (!m_modeInitialized, "WifiTxVector mode must be set before using"); - // TODO Replace the following with IsMu when available - if (m_preamble == WIFI_PREAMBLE_VHT_MU - || m_preamble == WIFI_PREAMBLE_HE_MU - || m_preamble == WIFI_PREAMBLE_HE_TB) + if (IsMu ()) { NS_ASSERT (!m_muUserInfos.empty ()); // all the modes belong to the same modulation class