From 5d7a25a2fb9db782669005a63336972c0ffbb7cd Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Tue, 16 Jul 2024 15:54:15 +0200 Subject: [PATCH] wifi: Schedule main PHY switch based on actual RTS TXVECTOR --- src/wifi/model/eht/advanced-emlsr-manager.cc | 16 +----- src/wifi/model/eht/default-emlsr-manager.cc | 56 +++++++++++++++---- src/wifi/model/eht/default-emlsr-manager.h | 19 ++++++- .../model/eht/eht-frame-exchange-manager.cc | 7 +++ src/wifi/model/eht/emlsr-manager.cc | 6 ++ src/wifi/model/eht/emlsr-manager.h | 11 ++++ 6 files changed, 89 insertions(+), 26 deletions(-) diff --git a/src/wifi/model/eht/advanced-emlsr-manager.cc b/src/wifi/model/eht/advanced-emlsr-manager.cc index c33f81d6f..6c74c5164 100644 --- a/src/wifi/model/eht/advanced-emlsr-manager.cc +++ b/src/wifi/model/eht/advanced-emlsr-manager.cc @@ -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}}; } diff --git a/src/wifi/model/eht/default-emlsr-manager.cc b/src/wifi/model/eht/default-emlsr-manager.cc index ca6de4fdb..8a7813c71 100644 --- a/src/wifi/model/eht/default-emlsr-manager.cc +++ b/src/wifi/model/eht/default-emlsr-manager.cc @@ -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 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 diff --git a/src/wifi/model/eht/default-emlsr-manager.h b/src/wifi/model/eht/default-emlsr-manager.h index 473c53d81..cd128bb6f 100644 --- a/src/wifi/model/eht/default-emlsr-manager.h +++ b/src/wifi/model/eht/default-emlsr-manager.h @@ -33,6 +33,10 @@ class DefaultEmlsrManager : public EmlsrManager DefaultEmlsrManager(); ~DefaultEmlsrManager() override; + void NotifyRtsSent(uint8_t linkId, + Ptr rts, + const WifiTxVector& txVector) override; + protected: uint8_t GetLinkToSendEmlOmn() override; std::optional ResendNotification(Ptr 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 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 mpdu, uint8_t linkId) override; diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index aaefaa5e6..5010cc407 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -371,6 +371,13 @@ EhtFrameExchangeManager::ForwardPsduDown(Ptr 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()); diff --git a/src/wifi/model/eht/emlsr-manager.cc b/src/wifi/model/eht/emlsr-manager.cc index e2d76e388..2d60e3ca7 100644 --- a/src/wifi/model/eht/emlsr-manager.cc +++ b/src/wifi/model/eht/emlsr-manager.cc @@ -518,6 +518,12 @@ EmlsrManager::NotifyUlTxopStart(uint8_t linkId) DoNotifyUlTxopStart(linkId); } +void +EmlsrManager::NotifyRtsSent(uint8_t linkId, Ptr rts, const WifiTxVector& txVector) +{ + NS_LOG_FUNCTION(this << *rts << txVector); +} + void EmlsrManager::NotifyProtectionCompleted(uint8_t linkId) { diff --git a/src/wifi/model/eht/emlsr-manager.h b/src/wifi/model/eht/emlsr-manager.h index bd37ed481..609458221 100644 --- a/src/wifi/model/eht/emlsr-manager.h +++ b/src/wifi/model/eht/emlsr-manager.h @@ -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 rts, + const WifiTxVector& txVector); + /** * Notify that protection (if required) is completed and data frame exchange can start * on the given link.