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:
committed by
Stefano Avallone
parent
55bae2ed3f
commit
092c56d6b9
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user