wifi: Update EMLSR info in remote station manager upon receiving EML Notification frame
This commit is contained in:
committed by
Stefano Avallone
parent
66d2179a38
commit
ec1d25cc68
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user