wifi: Update EMLSR info in remote station manager upon receiving EML Notification frame

This commit is contained in:
Stefano Avallone
2023-02-22 17:54:22 +01:00
committed by Stefano Avallone
parent 66d2179a38
commit ec1d25cc68
4 changed files with 162 additions and 0 deletions

View File

@@ -1468,6 +1468,25 @@ ApWifiMac::TxOk(Ptr<const WifiMpdu> mpdu)
}
}
}
else if (hdr.IsAction())
{
if (auto [category, action] = WifiActionHeader::Peek(mpdu->GetPacket());
category == WifiActionHeader::PROTECTED_EHT &&
action.protectedEhtAction ==
WifiActionHeader::PROTECTED_EHT_EML_OPERATING_MODE_NOTIFICATION)
{
// the EMLSR client acknowledged the EML Operating Mode Notification frame;
// we can stop the timer and enforce the configuration deriving from the
// EML Notification frame sent by the EMLSR client
if (auto eventIt = m_transitionTimeoutEvents.find(hdr.GetAddr1());
eventIt != m_transitionTimeoutEvents.cend() && eventIt->second.IsRunning())
{
// no need to wait until the expiration of the transition timeout
eventIt->second.PeekEventImpl()->Invoke();
eventIt->second.Cancel();
}
}
}
}
void
@@ -2043,6 +2062,107 @@ ApWifiMac::ReceiveEmlNotification(MgtEmlOperatingModeNotification& frame,
return;
}
if (frame.m_emlControl.emlsrParamUpdateCtrl)
{
NS_ASSERT(frame.m_emlsrParamUpdate);
auto emlCapabilities =
GetWifiRemoteStationManager(linkId)->GetStationEmlCapabilities(sender);
NS_ASSERT_MSG(emlCapabilities, "EML Capabilities not stored for STA " << sender);
// update values stored in remote station manager
emlCapabilities->emlsrPaddingDelay = frame.m_emlsrParamUpdate->paddingDelay;
emlCapabilities->emlsrTransitionDelay = frame.m_emlsrParamUpdate->transitionDelay;
}
auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(sender);
NS_ASSERT_MSG(mldAddress, "No MLD address stored for STA " << sender);
auto emlsrLinks =
frame.m_emlControl.emlsrMode == 1 ? frame.GetLinkBitmap() : std::list<uint8_t>{};
// The AP MLD has to consider the changes carried by the received EML Notification frame
// as effective at the same time as the non-AP MLD. Therefore, we need to start a time
// when the transmission of the Ack following the received EML Notification frame is
// completed. For this purpose, we connect a callback to the PHY TX begin trace to catch
// the Ack transmitted after the EML Notification frame.
CallbackBase cb = Callback<void, WifiConstPsduMap, WifiTxVector, double>(
[=](WifiConstPsduMap psduMap, WifiTxVector txVector, double /* txPowerW */) {
NS_ASSERT_MSG(psduMap.size() == 1 && psduMap.begin()->second->GetNMpdus() == 1 &&
psduMap.begin()->second->GetHeader(0).IsAck(),
"Expected a Normal Ack after EML Notification frame");
auto ackDuration =
WifiPhy::CalculateTxDuration(psduMap, txVector, GetLink(linkId).phy->GetPhyBand());
TimeValue transitionTimeout;
ehtConfiguration->GetAttribute("TransitionTimeout", transitionTimeout);
m_transitionTimeoutEvents[sender] =
Simulator::Schedule(ackDuration + transitionTimeout.Get(), [=]() {
for (uint8_t id = 0; id < GetNLinks(); id++)
{
auto linkAddress =
GetWifiRemoteStationManager(id)->GetAffiliatedStaAddress(*mldAddress);
if (!linkAddress)
{
// this link has not been setup by the non-AP MLD
continue;
}
if (!emlsrLinks.empty())
{
// the non-AP MLD is enabling EMLSR mode
/**
* After the successful transmission of the EML Operating Mode
* Notification frame by the non-AP STA affiliated with the non-AP MLD,
* the non-AP MLD shall operate in the EMLSR mode and the other non-AP
* STAs operating on the corresponding EMLSR links shall transition to
* active mode after the transition delay indicated in the Transition
* Timeout subfield in the EML Capabilities subfield of the Basic
* Multi-Link element or immediately after receiving an EML Operating
* Mode Notification frame from one of the APs operating on the EMLSR
* links and affiliated with the AP MLD (Sec. 35.3.17 of 802.11be D3.0)
*/
auto enabled = std::find(emlsrLinks.cbegin(), emlsrLinks.cend(), id) !=
emlsrLinks.cend();
if (enabled)
{
StaSwitchingToActiveModeOrDeassociated(*linkAddress, id);
}
GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, enabled);
}
else
{
// the non-AP MLD is disabling EMLSR mode
/**
* After the successful transmission of the EML Operating Mode
* Notification frame by the non-AP STA affiliated with the non-AP MLD,
* the non-AP MLD shall disable the EMLSR mode and the other non-AP
* STAs operating on the corresponding EMLSR links shall transition to
* power save mode after the transition delay indicated in the
* Transition Timeout subfield in the EML Capabilities subfield of the
* Basic Multi-Link element or immediately after receiving an EML
* Operating Mode Notification frame from one of the APs operating on
* the EMLSR links and affiliated with the AP MLD. (Sec. 35.3.17 of
* 802.11be D3.0)
*/
if (id != linkId &&
GetWifiRemoteStationManager(id)->GetEmlsrEnabled(*linkAddress))
{
StaSwitchingToPsMode(*linkAddress, id);
}
GetWifiRemoteStationManager(id)->SetEmlsrEnabled(*linkAddress, false);
}
}
});
});
// connect the callback to the PHY TX begin trace to catch the Ack and disconnect
// after its transmission begins
auto phy = GetLink(linkId).phy;
phy->TraceConnectWithoutContext("PhyTxPsduBegin", cb);
Simulator::Schedule(phy->GetSifs() + NanoSeconds(1),
[=]() { phy->TraceDisconnectWithoutContext("PhyTxPsduBegin", cb); });
// An AP MLD with dot11EHTEMLSROptionActivated equal to true sets the EMLSR Mode subfield
// to the value obtained from the EMLSR Mode subfield of the received EML Operating Mode
// Notification frame. (Sec. 9.6.35.8 of 802.11be D3.0)

View File

@@ -527,6 +527,8 @@ class ApWifiMac : public WifiMac
bool m_enableNonErpProtection; //!< Flag whether protection mechanism is used or not when
//!< non-ERP STAs are present within the BSS
Time m_bsrLifetime; //!< Lifetime of Buffer Status Reports
/// transition timeout events running for EMLSR clients
std::map<Mac48Address, EventId> m_transitionTimeoutEvents;
/// store value and timestamp for each Buffer Status Report
struct BsrType

View File

@@ -1389,6 +1389,7 @@ WifiRemoteStationManager::LookupState(Mac48Address address) const
state->m_heCapabilities = nullptr;
state->m_ehtCapabilities = nullptr;
state->m_emlCapabilities = nullptr;
state->m_emlsrEnabled = false;
state->m_channelWidth = m_wifiPhy->GetChannelWidth();
state->m_guardInterval = GetGuardInterval();
state->m_ness = 0;
@@ -1432,6 +1433,13 @@ WifiRemoteStationManager::SetQosSupport(Mac48Address from, bool qosSupported)
LookupState(from)->m_qosSupported = qosSupported;
}
void
WifiRemoteStationManager::SetEmlsrEnabled(const Mac48Address& from, bool emlsrEnabled)
{
NS_LOG_FUNCTION(this << from << emlsrEnabled);
LookupState(from)->m_emlsrEnabled = emlsrEnabled;
}
void
WifiRemoteStationManager::AddStationHtCapabilities(Mac48Address from, HtCapabilities htCapabilities)
{
@@ -1976,6 +1984,12 @@ WifiRemoteStationManager::GetEmlsrSupported(const WifiRemoteStation* station) co
return emlCapabilities && emlCapabilities->emlsrSupport == 1;
}
bool
WifiRemoteStationManager::GetEmlsrEnabled(const WifiRemoteStation* station) const
{
return station->m_state->m_emlsrEnabled;
}
uint8_t
WifiRemoteStationManager::GetNMcsSupported(const WifiRemoteStation* station) const
{
@@ -2084,6 +2098,16 @@ WifiRemoteStationManager::GetEmlsrSupported(const Mac48Address& address) const
return emlCapabilities && emlCapabilities->emlsrSupport == 1;
}
bool
WifiRemoteStationManager::GetEmlsrEnabled(const Mac48Address& address) const
{
if (auto stateIt = m_states.find(address); stateIt != m_states.cend())
{
return stateIt->second->m_emlsrEnabled;
}
return false;
}
void
WifiRemoteStationManager::SetDefaultTxPowerLevel(uint8_t txPower)
{

View File

@@ -116,6 +116,7 @@ struct WifiRemoteStationState
Ptr<const EhtCapabilities> m_ehtCapabilities; //!< remote station EHT capabilities
/// remote station EML capabilities
std::shared_ptr<CommonInfoBasicMle::EmlCapabilities> m_emlCapabilities;
bool m_emlsrEnabled; //!< whether EMLSR mode is enabled on this link
uint16_t m_channelWidth; //!< Channel width (in MHz) supported by the remote station
uint16_t m_guardInterval; //!< HE Guard interval duration (in nanoseconds) supported by the
@@ -235,6 +236,11 @@ class WifiRemoteStationManager : public Object
* \param qosSupported whether the station supports QoS
*/
void SetQosSupport(Mac48Address from, bool qosSupported);
/**
* \param from the address of the station being recorded
* \param emlsrEnabled whether EMLSR mode is enabled for the station on this link
*/
void SetEmlsrEnabled(const Mac48Address& from, bool emlsrEnabled);
/**
* Records HT capabilities of the remote station.
*
@@ -633,6 +639,11 @@ class WifiRemoteStationManager : public Object
* \return whether the non-AP MLD supports EMLSR
*/
bool GetEmlsrSupported(const Mac48Address& address) const;
/**
* \param address the (MLD or link) address of the non-AP MLD
* \return whether EMLSR mode is enabled for the non-AP MLD on this link
*/
bool GetEmlsrEnabled(const Mac48Address& address) const;
/**
* Return a mode for non-unicast packets.
@@ -1141,6 +1152,11 @@ class WifiRemoteStationManager : public Object
* \return whether the non-AP MLD supports EMLSR
*/
bool GetEmlsrSupported(const WifiRemoteStation* station) const;
/**
* \param station the station of a non-AP MLD
* \return whether EMLSR mode is enabled for the non-AP MLD on this link
*/
bool GetEmlsrEnabled(const WifiRemoteStation* station) const;
/**
* Return the WifiMode supported by the specified station at the specified index.
*