wifi: Improve logic for switching main PHY when aux PHY that is not TX capable gains a TXOP

This commit is contained in:
Stefano Avallone
2023-12-28 18:17:19 +01:00
parent e52c29fe33
commit 95121dcd07
5 changed files with 34 additions and 23 deletions

View File

@@ -229,9 +229,9 @@ DefaultEmlsrManager::DoNotifyTxopEnd(uint8_t linkId)
}
void
DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId)
DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci)
{
NS_LOG_FUNCTION(this << linkId);
NS_LOG_FUNCTION(this << linkId << aci);
NS_ASSERT_MSG(!m_auxPhyTxCapable,
"This function should only be called if aux PHY is not TX capable");
@@ -239,9 +239,12 @@ DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId)
// the aux PHY is not TX capable; check if main PHY has to switch to the aux PHY's link
auto mainPhy = GetStaMac()->GetDevice()->GetPhy(m_mainPhyId);
// if the main PHY is idle, check whether the remaining backoff counter on at least an AC with
// queued packets is greater than the main PHY channel switch delay
auto backoffGreaterThanSwitchDelay = false;
// if the main PHY is idle, switch main PHY if we expect the main PHY to get channel access on
// this link more quicky, i.e., if ALL the ACs with queued frames and with priority higher than
// or equal to that of the AC for which Aux PHY gained TXOP have their backoff counter greater
// than the channel switch delay plus PIFS
auto requestSwitch = false;
if (mainPhy->IsStateIdle())
{
@@ -255,19 +258,23 @@ DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId)
Txop::HAD_FRAMES_TO_TRANSMIT,
Txop::CHECK_MEDIUM_BUSY);
for (const auto& [aci, ac] : wifiAcList)
for (const auto& [acIndex, ac] : wifiAcList)
{
if (auto edca = GetStaMac()->GetQosTxop(aci); edca->HasFramesToTransmit(linkId))
if (auto edca = GetStaMac()->GetQosTxop(acIndex);
acIndex >= aci && edca->HasFramesToTransmit(linkId))
{
requestSwitch = true;
auto backoffEnd =
GetStaMac()->GetChannelAccessManager(*mainPhyLinkId)->GetBackoffEndFor(edca);
NS_LOG_DEBUG("Backoff end for " << aci
NS_LOG_DEBUG("Backoff end for " << acIndex
<< " on primary link: " << backoffEnd.As(Time::US));
if (backoffEnd > Simulator::Now() + mainPhy->GetChannelSwitchDelay() +
GetStaMac()->GetWifiPhy(linkId)->GetPifs())
if (backoffEnd <= Simulator::Now() + mainPhy->GetChannelSwitchDelay() +
GetStaMac()->GetWifiPhy(linkId)->GetPifs() &&
edca->HasFramesToTransmit(*mainPhyLinkId))
{
backoffGreaterThanSwitchDelay = true;
requestSwitch = false;
break;
}
}
@@ -275,7 +282,7 @@ DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId)
}
if ((mainPhy->IsStateCcaBusy() && !mainPhy->IsReceivingPhyHeader()) ||
(mainPhy->IsStateIdle() && backoffGreaterThanSwitchDelay))
(mainPhy->IsStateIdle() && requestSwitch))
{
// switch main PHY
SwitchMainPhy(linkId, false, RESET_BACKOFF, REQUEST_ACCESS);

View File

@@ -37,7 +37,7 @@ class DefaultEmlsrManager : public EmlsrManager
uint8_t GetLinkToSendEmlOmn() override;
std::optional<uint8_t> ResendNotification(Ptr<const WifiMpdu> mpdu) override;
Time DoGetDelayUntilAccessRequest(uint8_t linkId) override;
void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId) override;
void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci) override;
Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override;
/**

View File

@@ -279,7 +279,9 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, MHz_u allowedWidth)
const auto mainPhySwitching = mainPhy->IsStateSwitching();
// let EMLSR manager decide whether to prevent or allow this UL TXOP
if (auto delay = emlsrManager->GetDelayUntilAccessRequest(m_linkId);
if (auto delay = emlsrManager->GetDelayUntilAccessRequest(
m_linkId,
DynamicCast<QosTxop>(edca)->GetAccessCategory());
delay.IsStrictlyPositive())
{
NotifyChannelReleased(edca);

View File

@@ -409,7 +409,7 @@ EmlsrManager::NotifyIcfReceived(uint8_t linkId)
}
Time
EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId)
EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci)
{
auto phy = m_staMac->GetWifiPhy(linkId);
NS_ASSERT_MSG(phy, "No PHY operating on link " << +linkId);
@@ -432,7 +432,7 @@ EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId)
// whether the aux PHY is TX capable or not
if (!m_auxPhyTxCapable)
{
SwitchMainPhyIfTxopGainedByAuxPhy(linkId);
SwitchMainPhyIfTxopGainedByAuxPhy(linkId, aci);
// if the aux PHY is not TX capable, we don't have to request channel access: if the main
// 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

View File

@@ -142,14 +142,15 @@ class EmlsrManager : public Object
bool GetCamStateReset() const;
/**
* Notify that an UL TXOP is gained on the given link. This method has to determine whether to
* start the UL TXOP or release the channel.
* Notify that an UL TXOP is gained on the given link by the given AC. This method has to
* determine whether to start the UL TXOP or release the channel.
*
* \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
*/
Time GetDelayUntilAccessRequest(uint8_t linkId);
Time GetDelayUntilAccessRequest(uint8_t linkId, AcIndex aci);
/**
* Set the member variable indicating whether Aux PHYs are capable of transmitting PPDUs.
@@ -363,13 +364,14 @@ class EmlsrManager : public Object
/**
* Subclasses have to provide an implementation for this method, that is called by the base
* class when the EMLSR client gets channel access on the given link, on which an aux PHY that
* is not TX capable is operating. This method has to request the main PHY to switch to the
* given link to take over the TXOP, unless it is decided to give up the TXOP.
* class when the given AC of the EMLSR client gets channel access on the given link, on which
* an aux PHY that is not TX capable is operating. This method has to request the main PHY to
* switch to the given link to take over the TXOP, unless it is decided to give up the TXOP.
*
* \param linkId the ID of the given link
* \param aci the index of the given AC
*/
virtual void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId) = 0;
virtual void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId, AcIndex aci) = 0;
/**
* Subclasses have to provide an implementation for this method, that is called by the base