wifi: Do not double CW if CTS missing after ICF because of EMLSR clients starting UL TXOPs

This commit is contained in:
Stefano Avallone
2024-01-18 00:14:28 +01:00
parent 69aa538451
commit 4c0c96eaa7
6 changed files with 82 additions and 11 deletions

View File

@@ -85,6 +85,13 @@ class ApEmlsrManager : public Object
const WifiTxVector& txVector,
WifiPhyBand band) = 0;
/**
* \return whether the AP MLD shall double the CW upon CTS timeout after an MU-RTS in case
* all the clients solicited by the MU-RTS are EMLSR clients that have sent (or
* are sending) a frame to the AP
*/
virtual bool UpdateCwAfterFailedIcf() = 0;
protected:
void DoDispose() override;

View File

@@ -60,4 +60,10 @@ DefaultApEmlsrManager::GetDelayOnTxPsduNotForEmlsr(Ptr<const WifiPsdu> psdu,
return WifiPhy::CalculateTxDuration(psdu, txVector, band);
}
bool
DefaultApEmlsrManager::UpdateCwAfterFailedIcf()
{
return true;
}
} // namespace ns3

View File

@@ -45,6 +45,7 @@ class DefaultApEmlsrManager : public ApEmlsrManager
Time GetDelayOnTxPsduNotForEmlsr(Ptr<const WifiPsdu> psdu,
const WifiTxVector& txVector,
WifiPhyBand band) override;
bool UpdateCwAfterFailedIcf() override;
};
} // namespace ns3

View File

@@ -33,6 +33,8 @@
#include "ns3/wifi-net-device.h"
#include "ns3/wifi-spectrum-phy-interface.h"
#include <algorithm>
#undef NS_LOG_APPEND_CONTEXT
#define NS_LOG_APPEND_CONTEXT WIFI_FEM_NS_LOG_APPEND_CONTEXT
@@ -803,6 +805,10 @@ EhtFrameExchangeManager::CtsAfterMuRtsTimeout(Ptr<WifiMpdu> muRts, const WifiTxV
{
NS_LOG_FUNCTION(this << *muRts << txVector);
// check if all the clients solicited by the MU-RTS are EMLSR clients that have sent (or
// are sending) a frame to the AP
auto crossLinkCollision = true;
// we blocked transmissions on the other EMLSR links for the EMLSR clients we sent the ICF to.
// Given that no client responded, we can unblock transmissions for a client if there is no
// ongoing UL TXOP held by that client
@@ -810,33 +816,61 @@ EhtFrameExchangeManager::CtsAfterMuRtsTimeout(Ptr<WifiMpdu> muRts, const WifiTxV
{
if (!GetWifiRemoteStationManager()->GetEmlsrEnabled(address))
{
crossLinkCollision = false;
continue;
}
auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(address);
NS_ASSERT(mldAddress);
if (m_ongoingTxopEnd.IsPending() && m_txopHolder &&
m_mac->GetMldAddress(*m_txopHolder) == mldAddress)
{
continue;
}
std::set<uint8_t> linkIds;
std::set<uint8_t> linkIds; // all EMLSR links of EMLSR client
for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++)
{
if (linkId != m_linkId &&
m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
if (m_mac->GetWifiRemoteStationManager(linkId)->GetEmlsrEnabled(*mldAddress))
{
linkIds.insert(linkId);
}
}
if (std::any_of(linkIds.cbegin(),
linkIds.cend(),
/* lambda returning true if an UL TXOP is ongoing on the given link ID */
[=, this](uint8_t id) {
auto ehtFem = StaticCast<EhtFrameExchangeManager>(
m_mac->GetFrameExchangeManager(id));
return ehtFem->m_ongoingTxopEnd.IsPending() && ehtFem->m_txopHolder &&
m_mac->GetMldAddress(ehtFem->m_txopHolder.value()) == mldAddress;
}))
{
// an UL TXOP is ongoing on one EMLSR link, do not unblock links
continue;
}
// no UL TXOP is ongoing on any EMLSR link; if the EMLSR client is not transmitting a
// frame to the AP on any EMLSR link, then the lack of response to the MU-RTS was not
// caused by a simultaneous UL transmission
if (std::none_of(linkIds.cbegin(),
linkIds.cend(),
/* lambda returning true if an MPDU from the EMLSR client is being received
on the given link ID */
[=, this](uint8_t id) {
auto macHdr = m_mac->GetFrameExchangeManager(id)->GetReceivedMacHdr();
return macHdr.has_value() &&
m_mac->GetMldAddress(macHdr->get().GetAddr2()) == mldAddress;
}))
{
crossLinkCollision = false;
}
linkIds.erase(m_linkId);
m_mac->UnblockUnicastTxOnLinks(WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
*mldAddress,
linkIds);
}
HeFrameExchangeManager::CtsAfterMuRtsTimeout(muRts, txVector);
auto updateFailedCw =
crossLinkCollision ? m_apMac->GetApEmlsrManager()->UpdateCwAfterFailedIcf() : true;
DoCtsAfterMuRtsTimeout(muRts, txVector, updateFailedCw);
}
void

View File

@@ -399,6 +399,15 @@ void
HeFrameExchangeManager::CtsAfterMuRtsTimeout(Ptr<WifiMpdu> muRts, const WifiTxVector& txVector)
{
NS_LOG_FUNCTION(this << *muRts << txVector);
DoCtsAfterMuRtsTimeout(muRts, txVector, true);
}
void
HeFrameExchangeManager::DoCtsAfterMuRtsTimeout(Ptr<WifiMpdu> muRts,
const WifiTxVector& txVector,
bool updateFailedCw)
{
NS_LOG_FUNCTION(this << *muRts << txVector << updateFailedCw);
if (m_psduMap.empty())
{
@@ -446,7 +455,10 @@ HeFrameExchangeManager::CtsAfterMuRtsTimeout(Ptr<WifiMpdu> muRts, const WifiTxVe
else
{
NS_LOG_DEBUG("Missed CTS, retransmit MPDUs");
m_edca->UpdateFailedCw(m_linkId);
if (updateFailedCw)
{
m_edca->UpdateFailedCw(m_linkId);
}
}
// Make the sequence numbers of the MPDUs available again if the MPDUs have never
// been transmitted, both in case the MPDUs have been discarded and in case the

View File

@@ -213,6 +213,17 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
*/
virtual void CtsAfterMuRtsTimeout(Ptr<WifiMpdu> muRts, const WifiTxVector& txVector);
/**
* Called when no CTS frame is received after an MU-RTS.
*
* \param muRts the MU-RTS that solicited CTS responses
* \param txVector the TXVECTOR used to transmit the MU-RTS frame
* \param updateFailedCw whether to update CW in case of retransmission after TX failure
*/
void DoCtsAfterMuRtsTimeout(Ptr<WifiMpdu> muRts,
const WifiTxVector& txVector,
bool updateFailedCw);
/**
* Send CTS after receiving an MU-RTS.
*