wifi: Take channel switch delay into account when main PHY switches to take over UL TXOP

This commit is contained in:
Stefano Avallone
2023-09-12 20:25:33 +02:00
committed by Stefano Avallone
parent 5ae9fabf49
commit 38b4db155b
5 changed files with 79 additions and 37 deletions

View File

@@ -39,6 +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;
/**
* Additional time (exceeding 20 us) to wait for a PHY-RXSTART.indication when the PHY is
* decoding a PHY header.
@@ -176,6 +177,8 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, uint16_t allowedWidth
{
NS_LOG_FUNCTION(this << edca << allowedWidth);
std::optional<Time> timeToCtsEnd;
if (m_staMac && m_staMac->IsEmlsrLink(m_linkId))
{
// Cannot start a transmission on a link blocked because another EMLSR link is being used
@@ -204,6 +207,13 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, uint16_t allowedWidth
return false;
}
if (!m_phy)
{
NS_LOG_DEBUG("No PHY is currently operating on EMLSR link " << +m_linkId);
NotifyChannelReleased(edca);
return false;
}
if (auto mainPhy = m_staMac->GetDevice()->GetPhy(emlsrManager->GetMainPhyId());
mainPhy != m_phy)
{
@@ -229,6 +239,39 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, uint16_t allowedWidth
NotifyChannelReleased(edca);
return false;
}
const auto rtsTxVector =
GetWifiRemoteStationManager()->GetRtsTxVector(m_bssid, allowedWidth);
const auto rtsTxTime =
m_phy->CalculateTxDuration(GetRtsSize(), rtsTxVector, m_phy->GetPhyBand());
const auto ctsTxVector =
GetWifiRemoteStationManager()->GetCtsTxVector(m_bssid, rtsTxVector.GetMode());
const auto ctsTxTime =
m_phy->CalculateTxDuration(GetCtsSize(), ctsTxVector, m_phy->GetPhyBand());
// the main PHY shall terminate the channel switch at the end of CTS reception;
// the time remaining to the end of CTS reception includes two propagation delays
timeToCtsEnd = rtsTxTime + m_phy->GetSifs() + ctsTxTime +
MicroSeconds(2 * MAX_PROPAGATION_DELAY_USEC);
auto switchingTime = mainPhy->GetChannelSwitchDelay();
if (mainPhy->IsStateSwitching())
{
// the main PHY is switching (to another link), hence the remaining time to the
// end of the current channel switch needs to be added up
switchingTime += mainPhy->GetDelayUntilIdle();
}
if (switchingTime > timeToCtsEnd)
{
// switching takes longer than RTS/CTS exchange, do not transmit anything to
// avoid that the main PHY is requested to switch while already switching
NS_LOG_DEBUG("Main PHY will still be switching channel when RTS/CTS ends, thus it "
"will not be able to take over this TXOP");
NotifyChannelReleased(edca);
return false;
}
}
}
@@ -238,7 +281,7 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, uint16_t allowedWidth
{
// notify the EMLSR Manager of the UL TXOP start on an EMLSR link
NS_ASSERT(m_staMac->GetEmlsrManager());
m_staMac->GetEmlsrManager()->NotifyUlTxopStart(m_linkId);
m_staMac->GetEmlsrManager()->NotifyUlTxopStart(m_linkId, timeToCtsEnd);
}
return started;
@@ -924,8 +967,8 @@ EhtFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
}
}
// We impose that an aux PHY is only able to receive an ICF or a management frame (we are
// interested in receiving mainly Beacon frames). Note that other frames are still
// We impose that an aux PHY is only able to receive an ICF, a CTS or a management frame
// (we are interested in receiving mainly Beacon frames). Note that other frames are still
// post-processed, e.g., used to set the NAV and the TXOP holder.
// The motivation is that, e.g., an AP MLD may send an ICF to EMLSR clients A and B;
// A responds while B does not; the AP MLD sends a DL MU PPDU to both clients followed
@@ -934,7 +977,7 @@ EhtFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
// through the aux PHY.
if (m_staMac && m_staMac->IsEmlsrLink(m_linkId) &&
m_mac->GetLinkForPhy(m_staMac->GetEmlsrManager()->GetMainPhyId()) != m_linkId &&
!icfReceived && !mpdu->GetHeader().IsMgt())
!icfReceived && !mpdu->GetHeader().IsCts() && !mpdu->GetHeader().IsMgt())
{
NS_LOG_DEBUG("Dropping " << *mpdu << " received by an aux PHY on link " << +m_linkId);
return;

View File

@@ -383,7 +383,7 @@ EmlsrManager::NotifyIcfReceived(uint8_t linkId)
}
void
EmlsrManager::NotifyUlTxopStart(uint8_t linkId)
EmlsrManager::NotifyUlTxopStart(uint8_t linkId, std::optional<Time> timeToCtsEnd)
{
NS_LOG_FUNCTION(this << linkId);
@@ -403,21 +403,27 @@ EmlsrManager::NotifyUlTxopStart(uint8_t linkId)
}
}
// if this TXOP is being started by an aux PHY, wait until the end of RTS transmission and
// then have the main PHY (instantaneously) take over the TXOP on this link. We may start the
// channel switch now and use the channel switch delay configured for the main PHY, but then
// we would have no guarantees that the channel switch is completed in RTS TX time plus SIFS.
// if this TXOP is being started by an aux PHY, schedule a channel switch for the main PHY
// such that the channel switch is completed by the time the CTS response is received. The
// delay has been passed by the FEM.
if (m_staMac->GetLinkForPhy(m_mainPhyId) != linkId)
{
auto stateHelper = m_staMac->GetWifiPhy(linkId)->GetState();
NS_ASSERT(stateHelper);
NS_ASSERT_MSG(stateHelper->GetState() == TX,
"Expecting the aux PHY to be transmitting (an RTS frame)");
Simulator::Schedule(stateHelper->GetDelayUntilIdle(),
&EmlsrManager::SwitchMainPhy,
this,
linkId,
true); // channel switch should occur instantaneously
NS_ASSERT_MSG(timeToCtsEnd.has_value(),
"Aux PHY is sending RTS, expected to get the time to CTS end");
auto mainPhy = m_staMac->GetDevice()->GetPhy(m_mainPhyId);
// the main PHY shall terminate the channel switch at the end of CTS reception;
// the time remaining to the end of CTS reception includes two propagation delays
const auto delay = *timeToCtsEnd - mainPhy->GetChannelSwitchDelay();
NS_ASSERT(delay.IsPositive());
NS_LOG_DEBUG("Schedule main Phy switch in " << delay.As(Time::US));
Simulator::Schedule(delay, &EmlsrManager::SwitchMainPhy, this, linkId, false);
}
DoNotifyUlTxopStart(linkId);
@@ -436,31 +442,16 @@ EmlsrManager::NotifyTxopEnd(uint8_t linkId)
DoNotifyTxopEnd(linkId);
// if the main PHY starts switching link at the end of the TXOP (which happens, e.g., when the
// aux PHY does not switch link), we have to keep blocking transmissions until the channel
// switch is complete. Otherwise, an aux PHY may get channel access, transmit an RTS and
// request the main PHY to switch to its link, but the main PHY may still be completing the
// previous channel switch
Simulator::ScheduleNow([=, this]() {
auto mainPhy = m_staMac->GetDevice()->GetPhy(m_mainPhyId);
auto delay = mainPhy->IsStateSwitching() ? mainPhy->GetDelayUntilIdle() : Seconds(0);
NS_LOG_DEBUG("Main PHY is switching, postpone unblocking links by " << delay.As(Time::US));
// block transmissions on the link on which the TXOP was carried out
m_staMac->BlockTxOnLink(linkId, WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK);
m_staMac->GetChannelAccessManager(linkId)->NotifyStartUsingOtherEmlsrLink();
Simulator::Schedule(delay, [=, this]() {
// unblock transmissions and resume medium access on other EMLSR links
for (auto id : m_staMac->GetLinkIds())
// unblock transmissions and resume medium access on other EMLSR links
for (auto id : m_staMac->GetLinkIds())
{
if (m_staMac->IsEmlsrLink(id))
{
if (m_staMac->IsEmlsrLink(id))
{
m_staMac->UnblockTxOnLink(id, WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK);
m_staMac->GetChannelAccessManager(id)->NotifyStopUsingOtherEmlsrLink();
}
m_staMac->UnblockTxOnLink(id, WifiQueueBlockedReason::USING_OTHER_EMLSR_LINK);
m_staMac->GetChannelAccessManager(id)->NotifyStopUsingOtherEmlsrLink();
}
});
}
StartMediumSyncDelayTimer(linkId);
});

View File

@@ -178,8 +178,10 @@ class EmlsrManager : public Object
* Notify the start of an UL TXOP on the given link
*
* \param linkId the ID of the given link
* \param timeToCtsEnd time remaining to the end of CTS reception, in case the UL TXOP is
* started by an aux PHY
*/
void NotifyUlTxopStart(uint8_t linkId);
void NotifyUlTxopStart(uint8_t linkId, std::optional<Time> timeToCtsEnd);
/**
* Notify the end of a TXOP on the given link.

View File

@@ -48,6 +48,9 @@ class WifiNetDevice;
class WifiMode;
class Time;
/// maximum propagation delay
static constexpr uint8_t MAX_PROPAGATION_DELAY_USEC = 1;
/**
* typedef for a pair of start and stop frequencies in Hz to represent a band
*/

View File

@@ -2304,6 +2304,9 @@ EmlsrUlTxopTest::DoSetup()
Config::SetDefault("ns3::EhtConfiguration::MsdMaxNTxops", UintegerValue(m_msdMaxNTxops));
Config::SetDefault("ns3::ChannelAccessManager::GenerateBackoffIfTxopWithoutTx",
BooleanValue(m_genBackoffIfTxopWithoutTx));
// Channel switch delay should be less than RTS TX time + SIFS + CTS TX time, otherwise
// UL TXOPs cannot be initiated by aux PHYs
Config::SetDefault("ns3::WifiPhy::ChannelSwitchDelay", TimeValue(MicroSeconds(75)));
EmlsrOperationsTestBase::DoSetup();