wifi: Schedule main PHY switch based on actual RTS TXVECTOR

This commit is contained in:
Stefano Avallone
2024-07-16 15:54:15 +02:00
parent 15a7c24159
commit 5d7a25a2fb
6 changed files with 89 additions and 26 deletions

View File

@@ -350,19 +350,9 @@ AdvancedEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
return {false, timeToCtsEnd};
}
// TXOP can be started, schedule main PHY switch. Main PHY shall terminate the channel switch
// at the end of CTS reception
const auto delay = timeToCtsEnd - switchingTime;
NS_ASSERT(delay.IsPositive());
NS_LOG_DEBUG("Schedule main Phy switch in " << delay.As(Time::US));
m_ulMainPhySwitch[linkId] = Simulator::Schedule(delay,
&AdvancedEmlsrManager::SwitchMainPhy,
this,
linkId,
false,
RESET_BACKOFF,
DONT_REQUEST_ACCESS);
// TXOP can be started, main PHY will be scheduled to switch by NotifyRtsSent as soon as the
// transmission of the RTS is notified
m_switchMainPhyOnRtsTx[linkId] = Simulator::Now();
return {true, Time{0}};
}

View File

@@ -243,17 +243,26 @@ DefaultEmlsrManager::GetTimeToCtsEnd(uint8_t linkId) const
{
NS_LOG_FUNCTION(this << linkId);
auto phy = GetStaMac()->GetWifiPhy(linkId);
NS_ASSERT_MSG(phy, "No PHY operating on link " << +linkId);
// we have to check whether the main PHY can switch to take over the UL TXOP
const auto stationManager = GetStaMac()->GetWifiRemoteStationManager(linkId);
const auto bssid = GetEhtFem(linkId)->GetBssid();
const auto allowedWidth = GetEhtFem(linkId)->GetAllowedWidth();
const auto rtsTxVector = stationManager->GetRtsTxVector(bssid, allowedWidth);
const auto rtsTxTime = phy->CalculateTxDuration(GetRtsSize(), rtsTxVector, phy->GetPhyBand());
return GetTimeToCtsEnd(linkId, stationManager->GetRtsTxVector(bssid, allowedWidth));
}
Time
DefaultEmlsrManager::GetTimeToCtsEnd(uint8_t linkId, const WifiTxVector& rtsTxVector) const
{
NS_LOG_FUNCTION(this << linkId << rtsTxVector);
auto phy = GetStaMac()->GetWifiPhy(linkId);
NS_ASSERT_MSG(phy, "No PHY operating on link " << +linkId);
const auto stationManager = GetStaMac()->GetWifiRemoteStationManager(linkId);
const auto bssid = GetEhtFem(linkId)->GetBssid();
const auto ctsTxVector = stationManager->GetCtsTxVector(bssid, rtsTxVector.GetMode());
const auto rtsTxTime = phy->CalculateTxDuration(GetRtsSize(), rtsTxVector, phy->GetPhyBand());
const auto ctsTxTime = phy->CalculateTxDuration(GetCtsSize(), ctsTxVector, phy->GetPhyBand());
// the main PHY shall terminate the channel switch at the end of CTS reception;
@@ -267,7 +276,7 @@ DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
NS_LOG_FUNCTION(this << linkId);
auto mainPhy = GetStaMac()->GetDevice()->GetPhy(m_mainPhyId);
auto timeToCtsEnd = GetTimeToCtsEnd(linkId);
const auto timeToCtsEnd = GetTimeToCtsEnd(linkId);
auto switchingTime = mainPhy->GetChannelSwitchDelay();
switch (mainPhy->GetState()->GetState())
@@ -293,11 +302,34 @@ DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
NS_ABORT_MSG("Main PHY cannot be in state " << mainPhy->GetState()->GetState());
}
// TXOP can be started, schedule main PHY switch. Main PHY shall terminate the channel switch
// at the end of CTS reception
const auto delay = timeToCtsEnd - mainPhy->GetChannelSwitchDelay();
// TXOP can be started, main PHY will be scheduled to switch by NotifyRtsSent as soon as the
// transmission of the RTS is notified
m_switchMainPhyOnRtsTx[linkId] = Simulator::Now();
return {true, Time{0}};
}
void
DefaultEmlsrManager::NotifyRtsSent(uint8_t linkId,
Ptr<const WifiPsdu> rts,
const WifiTxVector& txVector)
{
NS_LOG_FUNCTION(this << *rts << txVector);
const auto it = m_switchMainPhyOnRtsTx.find(linkId);
if (it == m_switchMainPhyOnRtsTx.cend() || it->second != Simulator::Now())
{
// No request for main PHY to switch or obsolete request
return;
}
// Main PHY shall terminate the channel switch at the end of CTS reception
auto mainPhy = GetStaMac()->GetDevice()->GetPhy(m_mainPhyId);
const auto delay = GetTimeToCtsEnd(linkId, txVector) - mainPhy->GetChannelSwitchDelay();
NS_ASSERT_MSG(delay.IsPositive(),
"RTS is being sent, but not enough time for main PHY to switch");
NS_ASSERT(delay.IsPositive());
NS_LOG_DEBUG("Schedule main Phy switch in " << delay.As(Time::US));
m_ulMainPhySwitch[linkId] = Simulator::Schedule(delay,
&DefaultEmlsrManager::SwitchMainPhy,
@@ -307,7 +339,7 @@ DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
RESET_BACKOFF,
DONT_REQUEST_ACCESS);
return {true, Time{0}};
m_switchMainPhyOnRtsTx.erase(it);
}
} // namespace ns3

View File

@@ -33,6 +33,10 @@ class DefaultEmlsrManager : public EmlsrManager
DefaultEmlsrManager();
~DefaultEmlsrManager() override;
void NotifyRtsSent(uint8_t linkId,
Ptr<const WifiPsdu> rts,
const WifiTxVector& txVector) override;
protected:
uint8_t GetLinkToSendEmlOmn() override;
std::optional<uint8_t> ResendNotification(Ptr<const WifiMpdu> mpdu) override;
@@ -50,6 +54,16 @@ class DefaultEmlsrManager : public EmlsrManager
*/
Time GetTimeToCtsEnd(uint8_t linkId) const;
/**
* This function is intended to be called when an aux PHY is about to transmit an RTS on
* the given link to calculate the time remaining to the end of the CTS reception.
*
* \param linkId the ID of the given link
* \param rtsTxVector the TXVECTOR used to transmit the RTS
* \return the time remaining to the end of the CTS reception
*/
Time GetTimeToCtsEnd(uint8_t linkId, const WifiTxVector& rtsTxVector) const;
/**
* This method can only be called when aux PHYs do not switch link. Switch the main PHY back
* to the preferred link and reconnect the aux PHY that was operating on the link left by the
@@ -73,7 +87,10 @@ class DefaultEmlsrManager : public EmlsrManager
//!< the main PHY is operating has to connect a listener to
//!< when the main PHY is back operating on its previous link
EventId m_auxPhySwitchEvent; //!< event scheduled for an aux PHY to switch link
MainPhySwitchInfo m_mainPhySwitchInfo; //!< main PHY switch info
MainPhySwitchInfo m_mainPhySwitchInfo; //!< main PHY switch info
std::map<uint8_t, Time> m_switchMainPhyOnRtsTx; //!< link ID-indexed map of the time when an RTS
//!< that requires the main PHY to switch link
//!< is expected to be transmitted on the link
private:
void DoNotifyMgtFrameReceived(Ptr<const WifiMpdu> mpdu, uint8_t linkId) override;

View File

@@ -371,6 +371,13 @@ EhtFrameExchangeManager::ForwardPsduDown(Ptr<const WifiPsdu> psdu, WifiTxVector&
}
}
if (m_staMac && m_staMac->IsEmlsrLink(m_linkId) && psdu->GetAddr1() == m_bssid &&
psdu->GetHeader(0).IsRts())
{
NS_ASSERT(m_staMac->GetEmlsrManager());
m_staMac->GetEmlsrManager()->NotifyRtsSent(m_linkId, psdu, txVector);
}
HeFrameExchangeManager::ForwardPsduDown(psdu, txVector);
UpdateTxopEndOnTxStart(txDuration, psdu->GetDuration());

View File

@@ -518,6 +518,12 @@ EmlsrManager::NotifyUlTxopStart(uint8_t linkId)
DoNotifyUlTxopStart(linkId);
}
void
EmlsrManager::NotifyRtsSent(uint8_t linkId, Ptr<const WifiPsdu> rts, const WifiTxVector& txVector)
{
NS_LOG_FUNCTION(this << *rts << txVector);
}
void
EmlsrManager::NotifyProtectionCompleted(uint8_t linkId)
{

View File

@@ -206,6 +206,17 @@ class EmlsrManager : public Object
*/
void NotifyUlTxopStart(uint8_t linkId);
/**
* Notify that RTS transmission is starting on the given link.
*
* \param linkId the ID of the given link
* \param rts the RTS being transmitted
* \param txVector the TXVECTOR used to transmit the RTS
*/
virtual void NotifyRtsSent(uint8_t linkId,
Ptr<const WifiPsdu> rts,
const WifiTxVector& txVector);
/**
* Notify that protection (if required) is completed and data frame exchange can start
* on the given link.