wifi: Reset backoff and request access if needed when switching EMLSR links

This commit is contained in:
Stefano Avallone
2023-11-17 17:25:43 +01:00
committed by Stefano Avallone
parent fb18aa503c
commit 942e0baca3
3 changed files with 66 additions and 7 deletions

View File

@@ -153,9 +153,11 @@ DefaultEmlsrManager::DoNotifyTxopEnd(uint8_t linkId)
// is not received and the UL TXOP ends before the main PHY channel switch is completed.
// In such cases, wait until the main PHY channel switch is completed before requesting
// a new channel switch.
// Backoff shall not be reset on the link left by the main PHY because a TXOP ended and
// a new backoff value must be generated.
if (!mainPhy->IsStateSwitching())
{
SwitchMainPhy(GetMainPhyId(), false);
SwitchMainPhy(GetMainPhyId(), false, DONT_RESET_BACKOFF, REQUEST_ACCESS);
}
else
{
@@ -163,7 +165,9 @@ DefaultEmlsrManager::DoNotifyTxopEnd(uint8_t linkId)
&DefaultEmlsrManager::SwitchMainPhy,
this,
GetMainPhyId(),
false);
false,
DONT_RESET_BACKOFF,
REQUEST_ACCESS);
}
return;
}

View File

@@ -372,7 +372,10 @@ EmlsrManager::NotifyIcfReceived(uint8_t linkId)
}
Simulator::ScheduleNow([=, this]() {
SwitchMainPhy(linkId, true); // channel switch should occur instantaneously
SwitchMainPhy(linkId,
true, // channel switch should occur instantaneously
RESET_BACKOFF,
DONT_REQUEST_ACCESS);
// aux PHY received the ICF but main PHY will send the response
auto uid = auxPhy->GetPreviouslyRxPpduUid();
@@ -423,7 +426,13 @@ EmlsrManager::NotifyUlTxopStart(uint8_t linkId, std::optional<Time> timeToCtsEnd
NS_ASSERT(delay.IsPositive());
NS_LOG_DEBUG("Schedule main Phy switch in " << delay.As(Time::US));
Simulator::Schedule(delay, &EmlsrManager::SwitchMainPhy, this, linkId, false);
Simulator::Schedule(delay,
&EmlsrManager::SwitchMainPhy,
this,
linkId,
false,
RESET_BACKOFF,
DONT_REQUEST_ACCESS);
}
DoNotifyUlTxopStart(linkId);
@@ -487,9 +496,12 @@ EmlsrManager::SetCcaEdThresholdOnLinkSwitch(Ptr<WifiPhy> phy, uint8_t linkId)
}
void
EmlsrManager::SwitchMainPhy(uint8_t linkId, bool noSwitchDelay)
EmlsrManager::SwitchMainPhy(uint8_t linkId,
bool noSwitchDelay,
bool resetBackoff,
bool requestAccess)
{
NS_LOG_FUNCTION(this << linkId << noSwitchDelay);
NS_LOG_FUNCTION(this << linkId << noSwitchDelay << resetBackoff << requestAccess);
auto mainPhy = m_staMac->GetDevice()->GetPhy(m_mainPhyId);
@@ -535,6 +547,28 @@ EmlsrManager::SwitchMainPhy(uint8_t linkId, bool noSwitchDelay)
mainPhy->SetSlot(MicroSeconds(9));
}
if (resetBackoff)
{
// reset the backoffs on the link left by the main PHY
m_staMac->GetChannelAccessManager(*currMainPhyLinkId)->ResetAllBackoffs();
}
const auto timeToSwitchEnd = noSwitchDelay ? Seconds(0) : mainPhy->GetChannelSwitchDelay();
if (requestAccess)
{
// schedule channel access request on the new link when switch is completed
Simulator::Schedule(timeToSwitchEnd, [=, this]() {
for (const auto& [acIndex, ac] : wifiAcList)
{
m_staMac->GetQosTxop(acIndex)->StartAccessAfterEvent(
linkId,
Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT,
Txop::CHECK_MEDIUM_BUSY);
}
});
}
SetCcaEdThresholdOnLinkSwitch(mainPhy, linkId);
NotifyMainPhySwitch(*currMainPhyLinkId, linkId);
}
@@ -562,6 +596,17 @@ EmlsrManager::SwitchAuxPhy(uint8_t currLinkId, uint8_t nextLinkId)
auxPhy->SetSlot(MicroSeconds(9));
}
// schedule channel access request on the new link when switch is completed
Simulator::Schedule(auxPhy->GetChannelSwitchDelay(), [=, this]() {
for (const auto& [acIndex, ac] : wifiAcList)
{
m_staMac->GetQosTxop(acIndex)->StartAccessAfterEvent(
nextLinkId,
Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT,
Txop::CHECK_MEDIUM_BUSY);
}
});
SetCcaEdThresholdOnLinkSwitch(auxPhy, nextLinkId);
}

View File

@@ -285,8 +285,18 @@ class EmlsrManager : public Object
*
* \param linkId the ID of the link on which the main PHY has to operate
* \param noSwitchDelay whether switching delay should be zero
* \param resetBackoff whether backoff should be reset on the link on which the main PHY
* is operating
* \param requestAccess whether channel access should be requested on the link on which the
* main PHY is moving onto
*/
void SwitchMainPhy(uint8_t linkId, bool noSwitchDelay);
void SwitchMainPhy(uint8_t linkId, bool noSwitchDelay, bool resetBackoff, bool requestAccess);
static constexpr bool RESET_BACKOFF = true; //!< reset backoff on main PHY switch
static constexpr bool DONT_RESET_BACKOFF = false; //!< do not reset backoff on main PHY switch
static constexpr bool REQUEST_ACCESS = true; //!< request channel access when PHY switch ends
static constexpr bool DONT_REQUEST_ACCESS =
false; //!< do not request channel access when PHY switch ends
/**
* Switch channel on the Aux PHY operating on the given current link so that it operates