wifi: Do not double CW if CTS missing after ICF because of EMLSR clients starting UL TXOPs
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -60,4 +60,10 @@ DefaultApEmlsrManager::GetDelayOnTxPsduNotForEmlsr(Ptr<const WifiPsdu> psdu,
|
||||
return WifiPhy::CalculateTxDuration(psdu, txVector, band);
|
||||
}
|
||||
|
||||
bool
|
||||
DefaultApEmlsrManager::UpdateCwAfterFailedIcf()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user