diff --git a/src/wifi/helper/wifi-static-setup-helper.cc b/src/wifi/helper/wifi-static-setup-helper.cc index 54bd4ccdf..a0b76b9cd 100644 --- a/src/wifi/helper/wifi-static-setup-helper.cc +++ b/src/wifi/helper/wifi-static-setup-helper.cc @@ -12,6 +12,7 @@ #include "ns3/ap-wifi-mac.h" #include "ns3/assert.h" #include "ns3/boolean.h" +#include "ns3/emlsr-manager.h" #include "ns3/ht-configuration.h" #include "ns3/ht-frame-exchange-manager.h" #include "ns3/log.h" @@ -464,4 +465,76 @@ WifiStaticSetupHelper::GetBaRecipientAddr(Ptr originatorMac, Ptr apDev, Ptr clientDev) +{ + NS_LOG_FUNCTION_NOARGS(); + + Simulator::ScheduleNow(&WifiStaticSetupHelper::SetStaticEmlsrPostInit, apDev, clientDev); +} + +void +WifiStaticSetupHelper::SetStaticEmlsrPostInit(Ptr apDev, + Ptr clientDev) +{ + NS_LOG_FUNCTION_NOARGS(); + + auto clientMac = DynamicCast(clientDev->GetMac()); + NS_ASSERT_MSG(clientMac, "Expected StaWifiMac"); + NS_ASSERT_MSG(clientMac->IsAssociated(), "Expected Association complete"); + auto setupLinks = clientMac->GetSetupLinkIds(); + + if (const auto isMldAssoc = (setupLinks.size() > 1); !isMldAssoc) + { + NS_LOG_DEBUG("Multi-link setup not performed, skipping EMLSR static setup"); + return; + } + if (!clientDev->IsEmlsrActivated()) + { + NS_LOG_DEBUG("Non-AP MLD does not support EMLSR, not performing EMLSR static setup"); + return; + } + + auto emlsrManager = clientMac->GetEmlsrManager(); + NS_ASSERT_MSG(emlsrManager, "EMLSR Manager not set"); + emlsrManager->ComputeOperatingChannels(); + auto emlOmnReq = emlsrManager->GetEmlOmn(); + auto emlsrLinkId = emlsrManager->GetLinkToSendEmlOmn(); + emlsrManager->ChangeEmlsrMode(); + auto clientLinkAddr = clientMac->GetFrameExchangeManager(emlsrLinkId)->GetAddress(); + auto apMac = DynamicCast(apDev->GetMac()); + NS_ASSERT_MSG(apMac, "Expected ApWifiMac"); + apMac->ReceiveEmlOmn(emlOmnReq, clientLinkAddr, emlsrLinkId); + apMac->EmlOmnExchangeCompleted(emlOmnReq, clientLinkAddr, emlsrLinkId); +} + +void +WifiStaticSetupHelper::SetStaticEmlsr(Ptr apDev, + const NetDeviceContainer& clientDevs) +{ + NS_LOG_FUNCTION_NOARGS(); + + auto apMac = DynamicCast(apDev->GetMac()); + NS_ASSERT_MSG(apMac, "Expected ApWifiMac"); + // Check if AP supports EMLSR + if ((!apMac->GetEhtSupported()) || (apMac->GetNLinks() == 1)) + { + NS_LOG_DEBUG("AP does not support MLD, not performing EMLSR static setup"); + return; + } + + if (!apDev->IsEmlsrActivated()) + { + NS_LOG_DEBUG("AP MLD does not support EMLSR, not performing EMLSR static setup"); + return; + } + + for (auto i = clientDevs.Begin(); i != clientDevs.End(); ++i) + { + auto clientDev = DynamicCast(*i); + NS_ASSERT_MSG(clientDev, "WifiNetDevice expected"); + SetStaticEmlsr(apDev, clientDev); + } +} + } // namespace ns3 diff --git a/src/wifi/helper/wifi-static-setup-helper.h b/src/wifi/helper/wifi-static-setup-helper.h index df592fdd5..523537f57 100644 --- a/src/wifi/helper/wifi-static-setup-helper.h +++ b/src/wifi/helper/wifi-static-setup-helper.h @@ -32,6 +32,7 @@ class WifiMacHeader; * * - association/ML setup (note that scanning is disabled for this purpose) * - block ack agreement(s) + * - enabling EMLSR mode on EMLSR client links */ class WifiStaticSetupHelper { @@ -152,6 +153,25 @@ class WifiStaticSetupHelper /// @param recipientMac recipient MAC /// @return the Block Ack recipient address static Mac48Address GetBaRecipientAddr(Ptr originatorMac, Ptr recipientMac); + + /// Bypass EML Operating Mode Notification exchange sequence between AP MLD + /// and input non-AP devices + /// @param apDev AP MLD + /// @param clientDevs Non-AP devices + static void SetStaticEmlsr(Ptr apDev, const NetDeviceContainer& clientDevs); + + /// Bypass EML Operating Mode Notification exchange sequence between AP MLD and non-AP MLD + /// to enable EMLSR mode on the links specified via the EmlsrManager::EmlsrLinkSet attribute + /// @param apDev AP MLD + /// @param clientDev Non-AP MLD + static void SetStaticEmlsr(Ptr apDev, Ptr clientDev); + + /// Perform EML Operating Mode Notification exchange sequence between AP MLD and non-AP MLD + /// to enable EMLSR mode on the links specified via the EmlsrManager::EmlsrLinkSet attribute + /// post initialization at runtime begin + /// @param apDev AP MLD + /// @param clientDev Non-AP MLD + static void SetStaticEmlsrPostInit(Ptr apDev, Ptr clientDev); }; } // namespace ns3 diff --git a/src/wifi/model/eht/emlsr-manager.h b/src/wifi/model/eht/emlsr-manager.h index 86a59ec0f..26f1aa6ab 100644 --- a/src/wifi/model/eht/emlsr-manager.h +++ b/src/wifi/model/eht/emlsr-manager.h @@ -80,6 +80,7 @@ class EmlsrManager : public Object { /// Allow test cases to access private members friend class ::EmlsrCcaBusyTest; + friend class WifiStaticSetupHelper; public: /** diff --git a/src/wifi/model/wifi-net-device.cc b/src/wifi/model/wifi-net-device.cc index c33ed90a2..6f379a0b0 100644 --- a/src/wifi/model/wifi-net-device.cc +++ b/src/wifi/model/wifi-net-device.cc @@ -12,6 +12,7 @@ #include "sta-wifi-mac.h" #include "wifi-phy.h" +#include "ns3/boolean.h" #include "ns3/channel.h" #include "ns3/eht-configuration.h" #include "ns3/he-configuration.h" @@ -655,4 +656,20 @@ WifiNetDevice::GetEhtConfiguration() const return (m_standard >= WIFI_STANDARD_80211be ? m_ehtConfiguration : nullptr); } +bool +WifiNetDevice::IsEmlsrActivated() const +{ + if (!m_ehtConfiguration) + { + return false; + } + + BooleanValue emlsrActivated; + if (!m_ehtConfiguration->GetAttributeFailSafe("EmlsrActivated", emlsrActivated)) + { + return false; + } + return emlsrActivated.Get(); +} + } // namespace ns3 diff --git a/src/wifi/model/wifi-net-device.h b/src/wifi/model/wifi-net-device.h index 9514ca809..0e49f41b3 100644 --- a/src/wifi/model/wifi-net-device.h +++ b/src/wifi/model/wifi-net-device.h @@ -169,6 +169,11 @@ class WifiNetDevice : public NetDevice */ Ptr GetEhtConfiguration() const; + /** + * @return true if device supports EMLSR, otherwise false + */ + bool IsEmlsrActivated() const; + void SetIfIndex(const uint32_t index) override; uint32_t GetIfIndex() const override; Ptr GetChannel() const override;