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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user