wifi: Let EmlsrManager explicitly indicate whether UL TXOP can be started

...instead of relying on whether the delay to request channel access is
zero
This commit is contained in:
Stefano Avallone
2024-04-17 16:18:30 +02:00
parent bf1524f7e5
commit a46abc4dff
7 changed files with 51 additions and 50 deletions

View File

@@ -107,7 +107,7 @@ AdvancedEmlsrManager::DoSetWifiMac(Ptr<StaWifiMac> mac)
}
}
Time
std::pair<bool, Time>
AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId)
{
NS_LOG_FUNCTION(this << linkId);
@@ -131,7 +131,7 @@ AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId)
hdr.IsTrigger() &&
(hdr.GetAddr1().IsBroadcast() || hdr.GetAddr1() == GetEhtFem(id)->GetAddress()))
{
return phy->GetDelayUntilIdle();
return {false, phy->GetDelayUntilIdle()};
}
continue;
}
@@ -143,7 +143,7 @@ AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId)
if (!m_allowUlTxopInRx)
{
// retry channel access after the end of the current PHY header field
return phy->GetDelayUntilIdle();
return {false, phy->GetDelayUntilIdle()};
}
continue;
}
@@ -157,7 +157,7 @@ AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId)
if (!m_useNotifiedMacHdr)
{
// restart channel access at the end of PSDU reception
return phy->GetDelayUntilIdle();
return {false, phy->GetDelayUntilIdle()};
}
// retry channel access after the expected end of the MAC header reception
@@ -192,14 +192,14 @@ AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId)
.CalculateBytesTxTime(macHdrSize);
const auto timeSinceRxStart =
Simulator::Now() - phy->GetState()->GetLastTime({WifiPhyState::CCA_BUSY});
return Max(macHdrDuration - timeSinceRxStart, Time{0});
return {false, Max(macHdrDuration - timeSinceRxStart, Time{0})};
}
continue;
}
}
}
return Time{0};
return {true, Time{0}};
}
void
@@ -290,7 +290,7 @@ AdvancedEmlsrManager::DoNotifyTxopEnd(uint8_t linkId)
}
}
Time
std::pair<bool, Time>
AdvancedEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
{
NS_LOG_FUNCTION(this << linkId);
@@ -316,7 +316,7 @@ AdvancedEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
NS_LOG_DEBUG("Not enough time for main PHY to switch link (main PHY state: "
<< mainPhy->GetState()->GetState() << ")");
// retry channel access when the CTS was expected to be received
return timeToCtsEnd;
return {false, timeToCtsEnd};
}
// TXOP can be started, schedule main PHY switch. Main PHY shall terminate the channel switch
@@ -333,7 +333,7 @@ AdvancedEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
RESET_BACKOFF,
DONT_REQUEST_ACCESS);
return Time{0};
return {true, Time{0}};
}
void

View File

@@ -34,8 +34,8 @@ class AdvancedEmlsrManager : public DefaultEmlsrManager
protected:
void DoDispose() override;
void DoSetWifiMac(Ptr<StaWifiMac> mac) override;
Time DoGetDelayUntilAccessRequest(uint8_t linkId) override;
Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override;
std::pair<bool, Time> DoGetDelayUntilAccessRequest(uint8_t linkId) override;
std::pair<bool, Time> GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override;
void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci) override;
/**

View File

@@ -171,11 +171,11 @@ DefaultEmlsrManager::NotifyMainPhySwitch(std::optional<uint8_t> currLinkId,
}
}
Time
std::pair<bool, Time>
DefaultEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId)
{
NS_LOG_FUNCTION(this << linkId);
return Time{0}; // start the TXOP
return {true, Time{0}}; // start the TXOP
}
void
@@ -271,7 +271,7 @@ DefaultEmlsrManager::GetTimeToCtsEnd(uint8_t linkId) const
return rtsTxTime + phy->GetSifs() + ctsTxTime + MicroSeconds(2 * MAX_PROPAGATION_DELAY_USEC);
}
Time
std::pair<bool, Time>
DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
{
NS_LOG_FUNCTION(this << linkId);
@@ -296,7 +296,7 @@ DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
NS_LOG_DEBUG("Not enough time for main PHY to switch link (main PHY state: "
<< mainPhy->GetState()->GetState() << ")");
// retry channel access when the CTS was expected to be received
return timeToCtsEnd;
return {false, timeToCtsEnd};
}
break;
default:
@@ -317,7 +317,7 @@ DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
RESET_BACKOFF,
DONT_REQUEST_ACCESS);
return Time{0};
return {true, Time{0}};
}
} // namespace ns3

View File

@@ -36,9 +36,9 @@ class DefaultEmlsrManager : public EmlsrManager
protected:
uint8_t GetLinkToSendEmlOmn() override;
std::optional<uint8_t> ResendNotification(Ptr<const WifiMpdu> mpdu) override;
Time DoGetDelayUntilAccessRequest(uint8_t linkId) override;
std::pair<bool, Time> DoGetDelayUntilAccessRequest(uint8_t linkId) override;
void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci) override;
Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override;
std::pair<bool, Time> GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override;
/**
* This function is intended to be called when an aux PHY is about to transmit an RTS on

View File

@@ -276,28 +276,24 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, MHz_u allowedWidth)
}
// let EMLSR manager decide whether to prevent or allow this UL TXOP
if (auto delay = emlsrManager->GetDelayUntilAccessRequest(
if (const auto [startTxop, delay] = emlsrManager->GetDelayUntilAccessRequest(
m_linkId,
DynamicCast<QosTxop>(edca)->GetAccessCategory());
delay.IsStrictlyPositive())
{
NotifyChannelReleased(edca);
Simulator::Schedule(delay,
&Txop::StartAccessAfterEvent,
edca,
m_linkId,
Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT, // queued frames cannot be
// transmitted until RX ends
Txop::CHECK_MEDIUM_BUSY); // generate backoff if medium busy
return false;
}
!startTxop)
// in case of aux PHY that is not TX capable, the main PHY can transmit if the medium is
// sensed idle for a PIFS after the end of channel switch (assuming main PHY is switching)
if (auto mainPhy = m_staMac->GetDevice()->GetPhy(emlsrManager->GetMainPhyId());
m_phy != mainPhy && !emlsrManager->GetAuxPhyTxCapable())
{
NS_LOG_DEBUG("Aux PHY is not capable of transmitting a PPDU");
if (delay.IsStrictlyPositive())
{
NotifyChannelReleased(edca);
Simulator::Schedule(
delay,
&Txop::StartAccessAfterEvent,
edca,
m_linkId,
Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT, // queued frames cannot be
// transmitted until RX ends
Txop::CHECK_MEDIUM_BUSY); // generate backoff if medium busy
}
return false;
}
}

View File

@@ -404,7 +404,7 @@ EmlsrManager::NotifyIcfReceived(uint8_t linkId)
DoNotifyIcfReceived(linkId);
}
Time
std::pair<bool, Time>
EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci)
{
auto phy = m_staMac->GetWifiPhy(linkId);
@@ -413,15 +413,15 @@ EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci)
auto mainPhy = m_staMac->GetDevice()->GetPhy(m_mainPhyId);
// check possible reasons to give up the TXOP that apply to both main PHY and aux PHYs
if (auto delay = DoGetDelayUntilAccessRequest(linkId); delay.IsStrictlyPositive())
if (const auto [startTxop, delay] = DoGetDelayUntilAccessRequest(linkId); !startTxop)
{
return delay;
return {false, delay};
}
if (phy == mainPhy)
{
// no more constraints to check if medium was gained by main PHY
return Time{0};
return {true, Time{0}};
}
// an aux PHY is operating on the given link; call the appropriate method depending on
@@ -433,7 +433,8 @@ EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci)
// PHY switches link, the UL TXOP will be started; if the main PHY does not switch, it is
// because it is going to start an UL TXOP on another link and this link will be restarted
// at the end of that UL TXOP when this link will be unblocked
return Time{0};
NS_LOG_DEBUG("Aux PHY is not capable of transmitting a PPDU");
return {false, Time{0}};
}
return GetDelayUnlessMainPhyTakesOverUlTxop(linkId);

View File

@@ -18,6 +18,7 @@
#include <map>
#include <optional>
#include <set>
#include <utility>
class EmlsrCcaBusyTest;
@@ -147,10 +148,11 @@ class EmlsrManager : public Object
*
* \param linkId the ID of the given link
* \param aci the index of the given AC
* \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client
* restarts channel access, otherwise
* \return a pair consisting of a boolean value indicating whether the UL TXOP can be started
* and a Time value indicating the delay after which the EMLSR client must restart
* channel access (if needed) in case the UL TXOP is not started
*/
Time GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci);
std::pair<bool, Time> GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci);
/**
* Set the member variable indicating whether Aux PHYs are capable of transmitting PPDUs.
@@ -357,10 +359,11 @@ class EmlsrManager : public Object
* check possible reasons to give up the TXOP that apply to both main PHY and aux PHYs.
*
* \param linkId the ID of the given link
* \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client
* restarts channel access, otherwise
* \return a pair consisting of a boolean value indicating whether the UL TXOP can be started
* and a Time value indicating the delay after which the EMLSR client must restart
* channel access (if needed) in case the UL TXOP is not started
*/
virtual Time DoGetDelayUntilAccessRequest(uint8_t linkId) = 0;
virtual std::pair<bool, Time> DoGetDelayUntilAccessRequest(uint8_t linkId) = 0;
/**
* Subclasses have to provide an implementation for this method, that is called by the base
@@ -381,10 +384,11 @@ class EmlsrManager : public Object
* EMLSR client restarts channel access on the given link, otherwise.
*
* \param linkId the ID of the given link
* \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client
* restarts channel access, otherwise
* \return a pair consisting of a boolean value indicating whether the UL TXOP can be started
* and a Time value indicating the delay after which the EMLSR client must restart
* channel access (if needed) in case the UL TXOP is not started
*/
virtual Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) = 0;
virtual std::pair<bool, Time> GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) = 0;
Time m_emlsrPaddingDelay; //!< EMLSR Padding delay
Time m_emlsrTransitionDelay; //!< EMLSR Transition delay