wifi: Schedule main PHY switch based on actual RTS TXVECTOR
This commit is contained in:
@@ -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}};
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user