wifi: Take channel switch delay into account when main PHY switches to take over UL TXOP
This commit is contained in:
committed by
Stefano Avallone
parent
5ae9fabf49
commit
38b4db155b
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user