wifi: Advanced AP EMLSR Manager blocks transmissions to EMLSR client as soon as it receives a MAC header sent by the EMLSR client

...to start an UL TXOP
This commit is contained in:
Stefano Avallone
2024-01-26 17:30:25 +01:00
committed by Stefano Avallone
parent 55bae2ed3f
commit 092c56d6b9
4 changed files with 167 additions and 10 deletions

View File

@@ -19,7 +19,12 @@
#include "advanced-ap-emlsr-manager.h"
#include "eht-frame-exchange-manager.h"
#include "ns3/ap-wifi-mac.h"
#include "ns3/boolean.h"
#include "ns3/log.h"
#include "ns3/wifi-phy.h"
namespace ns3
{
@@ -31,10 +36,26 @@ NS_OBJECT_ENSURE_REGISTERED(AdvancedApEmlsrManager);
TypeId
AdvancedApEmlsrManager::GetTypeId()
{
static TypeId tid = TypeId("ns3::AdvancedApEmlsrManager")
.SetParent<DefaultApEmlsrManager>()
.SetGroupName("Wifi")
.AddConstructor<AdvancedApEmlsrManager>();
static TypeId tid =
TypeId("ns3::AdvancedApEmlsrManager")
.SetParent<DefaultApEmlsrManager>()
.SetGroupName("Wifi")
.AddConstructor<AdvancedApEmlsrManager>()
.AddAttribute("UseNotifiedMacHdr",
"Whether to use the information about the MAC header of the MPDU "
"being received, if notified by the PHY.",
BooleanValue(true),
MakeBooleanAccessor(&AdvancedApEmlsrManager::m_useNotifiedMacHdr),
MakeBooleanChecker())
.AddAttribute(
"WaitTransDelayOnPsduRxError",
"If true, the AP MLD waits for a response timeout after a PSDU reception "
"error before starting the transition delay for the EMLSR client that "
"sent the failed PSDU. Otherwise, the AP MLD does not start the "
"transition delay timer for the EMLSR client that sent the failed PSDU.",
BooleanValue(true),
MakeBooleanAccessor(&AdvancedApEmlsrManager::m_waitTransDelayOnPsduRxError),
MakeBooleanChecker());
return tid;
}
@@ -48,4 +69,101 @@ AdvancedApEmlsrManager::~AdvancedApEmlsrManager()
NS_LOG_FUNCTION_NOARGS();
}
void
AdvancedApEmlsrManager::DoDispose()
{
NS_LOG_FUNCTION(this);
for (uint8_t linkId = 0; linkId < GetApMac()->GetNLinks(); linkId++)
{
auto phy = GetApMac()->GetWifiPhy(linkId);
phy->TraceDisconnectWithoutContext(
"PhyRxMacHeaderEnd",
MakeCallback(&AdvancedApEmlsrManager::ReceivedMacHdr, this).Bind(linkId));
}
DefaultApEmlsrManager::DoDispose();
}
void
AdvancedApEmlsrManager::DoSetWifiMac(Ptr<ApWifiMac> mac)
{
NS_LOG_FUNCTION(this << mac);
for (uint8_t linkId = 0; linkId < GetApMac()->GetNLinks(); linkId++)
{
auto phy = GetApMac()->GetWifiPhy(linkId);
phy->TraceConnectWithoutContext(
"PhyRxMacHeaderEnd",
MakeCallback(&AdvancedApEmlsrManager::ReceivedMacHdr, this).Bind(linkId));
}
}
void
AdvancedApEmlsrManager::ReceivedMacHdr(uint8_t linkId,
const WifiMacHeader& macHdr,
const WifiTxVector& txVector,
Time psduDuration)
{
NS_LOG_FUNCTION(this << linkId << macHdr << txVector << psduDuration.As(Time::MS));
if (m_useNotifiedMacHdr && GetEhtFem(linkId)->CheckEmlsrClientStartingTxop(macHdr, txVector))
{
// the AP MLD is receiving an MPDU from an EMLSR client that is starting an UL TXOP.
// CheckEmlsrClientStartingTxop has blocked transmissions to the EMLSR client on other
// links. If the reception of the PSDU fails, however, the AP MLD does not respond and
// the EMLSR client will switch to listening mode after the ack timeout.
m_blockedLinksOnMacHdrRx.insert(linkId);
}
}
void
AdvancedApEmlsrManager::NotifyPsduRxOk(uint8_t linkId, Ptr<const WifiPsdu> psdu)
{
NS_LOG_FUNCTION(this << linkId << *psdu);
m_blockedLinksOnMacHdrRx.erase(linkId);
}
void
AdvancedApEmlsrManager::NotifyPsduRxError(uint8_t linkId, Ptr<const WifiPsdu> psdu)
{
NS_LOG_FUNCTION(this << linkId << *psdu);
if (auto it = m_blockedLinksOnMacHdrRx.find(linkId); it == m_blockedLinksOnMacHdrRx.cend())
{
return;
}
else
{
m_blockedLinksOnMacHdrRx.erase(it);
}
if (m_waitTransDelayOnPsduRxError)
{
auto phy = GetApMac()->GetWifiPhy(linkId);
auto delay = phy->GetSifs() + phy->GetSlot() + EMLSR_RX_PHY_START_DELAY;
GetEhtFem(linkId)->EmlsrSwitchToListening(psdu->GetAddr2(), delay);
return;
}
// all other EMLSR links were blocked when receiving MAC header; unblock them now
auto mldAddress =
GetApMac()->GetWifiRemoteStationManager(linkId)->GetMldAddress(psdu->GetAddr2());
if (!mldAddress.has_value())
{
NS_LOG_DEBUG(psdu->GetAddr2() << " is not an EMLSR client");
return;
}
std::set<uint8_t> linkIds;
for (uint8_t id = 0; id < GetApMac()->GetNLinks(); id++)
{
if (GetApMac()->GetWifiRemoteStationManager(id)->GetEmlsrEnabled(*mldAddress))
{
linkIds.insert(id);
}
}
GetApMac()->UnblockUnicastTxOnLinks(WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK,
*mldAddress,
linkIds);
}
} // namespace ns3

View File

@@ -22,9 +22,18 @@
#include "default-ap-emlsr-manager.h"
#include "ns3/nstime.h"
#include <set>
namespace ns3
{
class ApWifiMac;
class WifiMacHeader;
class WifiPsdu;
class WifiTxVector;
/**
* \ingroup wifi
*
@@ -41,6 +50,35 @@ class AdvancedApEmlsrManager : public DefaultApEmlsrManager
AdvancedApEmlsrManager();
~AdvancedApEmlsrManager() override;
void NotifyPsduRxOk(uint8_t linkId, Ptr<const WifiPsdu> psdu) override;
void NotifyPsduRxError(uint8_t linkId, Ptr<const WifiPsdu> psdu) override;
protected:
void DoDispose() override;
void DoSetWifiMac(Ptr<ApWifiMac> mac) override;
/**
* Store information about the MAC header of the MPDU being received on the given link.
*
* \param linkId the ID of the given link
* \param macHdr the MAC header of the MPDU being received
* \param txVector the TXVECTOR used to transmit the PSDU
* \param psduDuration the remaining duration of the PSDU
*/
void ReceivedMacHdr(uint8_t linkId,
const WifiMacHeader& macHdr,
const WifiTxVector& txVector,
Time psduDuration);
private:
std::set<uint8_t>
m_blockedLinksOnMacHdrRx; //!< links that have been blocked upon receiving a MAC header
bool m_useNotifiedMacHdr; //!< whether to use the information about the MAC header of
//!< the MPDU being received (if notified by the PHY)
bool m_waitTransDelayOnPsduRxError; //!< Whether the AP MLD waits for a response timeout after a
//!< PSDU reception error before starting the transition
//!< delay
};
} // namespace ns3

View File

@@ -39,9 +39,7 @@
namespace ns3
{
/// aRxPHYStartDelay value to use when waiting for a new frame in the context of EMLSR operations
/// (Sec. 35.3.17 of 802.11be D3.1)
static constexpr uint8_t RX_PHY_START_DELAY_USEC = 20;
const Time EMLSR_RX_PHY_START_DELAY = MicroSeconds(20);
/**
* Additional time (exceeding 20 us) to wait for a PHY-RXSTART.indication when the PHY is
@@ -1364,8 +1362,7 @@ EhtFrameExchangeManager::UpdateTxopEndOnTxStart(Time txDuration, Time durationId
// transmitting a CTS after ICS). The TXOP holder may transmit a frame a SIFS
// after the end of this PPDU, hence we need to postpone the TXOP end in order to
// get the PHY-RXSTART.indication
delay = txDuration + m_phy->GetSifs() + m_phy->GetSlot() +
MicroSeconds(RX_PHY_START_DELAY_USEC);
delay = txDuration + m_phy->GetSifs() + m_phy->GetSlot() + EMLSR_RX_PHY_START_DELAY;
}
NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
@@ -1418,7 +1415,7 @@ EhtFrameExchangeManager::UpdateTxopEndOnRxEnd(Time durationId)
// we may send a response after a SIFS or we may receive another frame after a SIFS.
// Postpone the TXOP end by considering the latter (which takes longer)
auto delay = m_phy->GetSifs() + m_phy->GetSlot() + MicroSeconds(RX_PHY_START_DELAY_USEC);
auto delay = m_phy->GetSifs() + m_phy->GetSlot() + EMLSR_RX_PHY_START_DELAY;
NS_LOG_DEBUG("Expected TXOP end=" << (Simulator::Now() + delay).As(Time::S));
m_ongoingTxopEnd =
Simulator::Schedule(delay, &EhtFrameExchangeManager::TxopEnd, this, m_txopHolder);

View File

@@ -28,6 +28,10 @@
namespace ns3
{
/// aRxPHYStartDelay value to use when waiting for a new frame in the context of EMLSR operations
/// (Sec. 35.3.17 of 802.11be D3.1)
extern const Time EMLSR_RX_PHY_START_DELAY;
class MgtEmlOmn;
/**