diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index 63167d152..95f4395e9 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -354,7 +354,6 @@ WifiMac::DoDispose () it->second = 0; } - m_stationManager = 0; m_device = 0; } @@ -518,7 +517,7 @@ WifiMac::NotifyChannelSwitching (void) // SetupPhy not only resets the remote station manager, but also sets the // default TX mode and MCS, which is required when switching to a channel // in a different band - m_stationManager->SetupPhy (GetLink (SINGLE_LINK_OP_ID).phy); + GetLink (SINGLE_LINK_OP_ID).stationManager->SetupPhy (GetLink (SINGLE_LINK_OP_ID).phy); } void @@ -794,13 +793,36 @@ void WifiMac::SetWifiRemoteStationManager (const Ptr stationManager) { NS_LOG_FUNCTION (this << stationManager); - m_stationManager = stationManager; + SetWifiRemoteStationManagers ({stationManager}); +} + +void +WifiMac::SetWifiRemoteStationManagers (const std::vector>& stationManagers) +{ + NS_LOG_FUNCTION (this); + + NS_ABORT_MSG_UNLESS (m_links.size () == 0 || m_links.size () == stationManagers.size (), + "If links have been already created, the number of provided " + "Remote Manager objects (" << stationManagers.size () << ") must " + "match the number of links (" << m_links.size () << ")"); + + for (std::size_t i = 0; i < stationManagers.size (); i++) + { + // the link may already exist in case PHY objects were configured first + if (i == m_links.size ()) + { + m_links.push_back (CreateLinkEntity ()); + m_links.back ()->id = i; + } + NS_ABORT_IF (i != m_links[i]->id); + m_links[i]->stationManager = stationManagers[i]; + } } Ptr -WifiMac::GetWifiRemoteStationManager () const +WifiMac::GetWifiRemoteStationManager (uint8_t linkId) const { - return m_stationManager; + return GetLink (linkId).stationManager; } std::unique_ptr @@ -838,6 +860,7 @@ WifiMac::SetWifiPhys (const std::vector>& phys) { // the link may already exist in case we are setting new PHY objects // (ResetWifiPhys just nullified the PHY(s) but left the links) + // or the remote station managers were configured first if (i == m_links.size ()) { m_links.push_back (CreateLinkEntity ()); diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index 6c08b58f7..a39be0a82 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -280,9 +280,14 @@ public: */ void SetWifiRemoteStationManager (Ptr stationManager); /** - * \return the station manager attached to this MAC. + * \param stationManagers the station managers attached to this MAC. */ - Ptr GetWifiRemoteStationManager (void) const; + void SetWifiRemoteStationManagers (const std::vector>& stationManagers); + /** + * \param linkId the ID (starting at 0) of the link of the RemoteStationManager object to retrieve + * \return the remote station manager operating on the given link + */ + Ptr GetWifiRemoteStationManager (uint8_t linkId = 0) const; /** * This type defines the callback of a higher layer that a @@ -576,6 +581,8 @@ protected: Ptr phy; //!< Wifi PHY object Ptr channelAccessManager; //!< channel access manager object Ptr feManager; //!< Frame Exchange Manager object + Ptr stationManager; /**< Remote station manager (rate control, RTS/CTS/ + fragmentation thresholds etc.) */ bool erpSupported {false}; /**< set to \c true iff this WifiMac is to model 802.11g */ bool dsssSupported {false}; /**< set to \c true iff this WifiMac is @@ -726,7 +733,6 @@ private: TypeOfStation m_typeOfStation; //!< the type of station Ptr m_device; //!< Pointer to the device - Ptr m_stationManager; //!< Remote station manager (rate control, RTS/CTS/fragmentation thresholds etc.) std::vector> m_links; //!< vector of Link objects Mac48Address m_address; //!< MAC address of this station diff --git a/src/wifi/model/wifi-net-device.cc b/src/wifi/model/wifi-net-device.cc index 0c54fc8c0..d87e4c66a 100644 --- a/src/wifi/model/wifi-net-device.cc +++ b/src/wifi/model/wifi-net-device.cc @@ -75,8 +75,14 @@ WifiNetDevice::GetTypeId (void) .AddAttribute ("RemoteStationManager", "The station manager attached to this device.", PointerValue (), MakePointerAccessor (&WifiNetDevice::SetRemoteStationManager, - &WifiNetDevice::GetRemoteStationManager), + (Ptr (WifiNetDevice::*) (void) const) &WifiNetDevice::GetRemoteStationManager), MakePointerChecker ()) + .AddAttribute ("RemoteStationManagers", + "The remote station managers attached to this device (11be multi-link devices only).", + ObjectVectorValue (), + MakeObjectVectorAccessor (&WifiNetDevice::GetRemoteStationManager, + &WifiNetDevice::GetNRemoteStationManagers), + MakeObjectVectorChecker ()) .AddAttribute ("HtConfiguration", "The HtConfiguration object.", PointerValue (), @@ -132,11 +138,15 @@ WifiNetDevice::DoDispose (void) } } m_phys.clear (); - if (m_stationManager) + for (auto& stationManager : m_stationManagers) { - m_stationManager->Dispose (); - m_stationManager = 0; + if (stationManager != nullptr) + { + stationManager->Dispose (); + stationManager = nullptr; + } } + m_stationManagers.clear (); if (m_htConfiguration) { m_htConfiguration->Dispose (); @@ -176,9 +186,12 @@ WifiNetDevice::DoInitialize (void) { m_mac->Initialize (); } - if (m_stationManager) + for (const auto& stationManager : m_stationManagers) { - m_stationManager->Initialize (); + if (stationManager) + { + stationManager->Initialize (); + } } NetDevice::DoInitialize (); } @@ -188,19 +201,23 @@ WifiNetDevice::CompleteConfig (void) { if (m_mac == 0 || m_phys.empty () - || m_stationManager == 0 + || m_stationManagers.empty () || m_node == 0 || m_configComplete) { return; } - m_mac->SetWifiRemoteStationManager (m_stationManager); + NS_ABORT_IF (m_phys.size () != m_stationManagers.size ()); m_mac->SetWifiPhys (m_phys); + m_mac->SetWifiRemoteStationManagers (m_stationManagers); m_mac->SetForwardUpCallback (MakeCallback (&WifiNetDevice::ForwardUp, this)); m_mac->SetLinkUpCallback (MakeCallback (&WifiNetDevice::LinkUp, this)); m_mac->SetLinkDownCallback (MakeCallback (&WifiNetDevice::LinkDown, this)); - m_stationManager->SetupPhy (m_phys[SINGLE_LINK_OP_ID]); - m_stationManager->SetupMac (m_mac); + for (uint8_t linkId = 0; linkId < m_stationManagers.size (); linkId++) + { + m_stationManagers.at (linkId)->SetupPhy (m_phys.at (linkId)); + m_stationManagers.at (linkId)->SetupMac (m_mac); + } m_configComplete = true; } @@ -246,7 +263,17 @@ WifiNetDevice::SetPhys (const std::vector>& phys) void WifiNetDevice::SetRemoteStationManager (const Ptr manager) { - m_stationManager = manager; + m_stationManagers.clear (); + m_stationManagers.push_back (manager); + CompleteConfig (); +} + +void +WifiNetDevice::SetRemoteStationManagers (const std::vector>& managers) +{ + NS_ABORT_MSG_IF (managers.size () > 1 && m_ehtConfiguration == nullptr, + "Multiple remote station managers only allowed for 11be multi-link devices"); + m_stationManagers = managers; CompleteConfig (); } @@ -284,7 +311,26 @@ WifiNetDevice::GetNPhys (void) const Ptr WifiNetDevice::GetRemoteStationManager (void) const { - return m_stationManager; + return GetRemoteStationManager (0); +} + +Ptr +WifiNetDevice::GetRemoteStationManager (uint8_t linkId) const +{ + NS_ASSERT (linkId < GetRemoteStationManagers ().size ()); + return GetRemoteStationManagers ().at (linkId); +} + +const std::vector>& +WifiNetDevice::GetRemoteStationManagers (void) const +{ + return m_stationManagers; +} + +uint8_t +WifiNetDevice::GetNRemoteStationManagers (void) const +{ + return GetRemoteStationManagers ().size (); } void diff --git a/src/wifi/model/wifi-net-device.h b/src/wifi/model/wifi-net-device.h index 48cb1614f..1bfd9d162 100644 --- a/src/wifi/model/wifi-net-device.h +++ b/src/wifi/model/wifi-net-device.h @@ -98,6 +98,10 @@ public: * \param manager the manager to use. */ void SetRemoteStationManager (const Ptr manager); + /** + * \param managers the managers to use (for 11be multi-link devices only) + */ + void SetRemoteStationManagers (const std::vector>& managers); /** * \returns the MAC we are currently using. */ @@ -123,8 +127,25 @@ public: uint8_t GetNPhys (void) const; /** * \returns the remote station manager we are currently using. + * + * This GetRemoteStationManager variant is needed to keep using "RemoteStationManager" + * in the path names. */ Ptr GetRemoteStationManager (void) const; + /** + * \param linkId the ID (starting at 0) of the link of the RemoteStationManager + * object to retrieve + * \returns the requested remote station manager + */ + Ptr GetRemoteStationManager (uint8_t linkId) const; + /** + * \returns a const reference to the vector of remote station managers + */ + virtual const std::vector>& GetRemoteStationManagers (void) const; + /** + * \returns the number of remote station managers + */ + uint8_t GetNRemoteStationManagers (void) const; /** * \param htConfiguration pointer to HtConfiguration @@ -218,7 +239,7 @@ private: Ptr m_node; //!< the node std::vector> m_phys; //!< the phy objects Ptr m_mac; //!< the MAC - Ptr m_stationManager; //!< the station manager + std::vector> m_stationManagers; //!< the station managers Ptr m_htConfiguration; //!< the HtConfiguration Ptr m_vhtConfiguration; //!< the VhtConfiguration Ptr m_heConfiguration; //!< the HeConfiguration