wifi: Modularize code handling UL TXOP start
This commit is contained in:
@@ -89,7 +89,7 @@ AdvancedEmlsrManager::DoSetWifiMac(Ptr<StaWifiMac> mac)
|
||||
}
|
||||
|
||||
Time
|
||||
AdvancedEmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId)
|
||||
AdvancedEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
|
||||
|
||||
@@ -31,11 +31,10 @@ class AdvancedEmlsrManager : public DefaultEmlsrManager
|
||||
AdvancedEmlsrManager();
|
||||
~AdvancedEmlsrManager() override;
|
||||
|
||||
Time GetDelayUntilAccessRequest(uint8_t linkId) override;
|
||||
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
void DoSetWifiMac(Ptr<StaWifiMac> mac) override;
|
||||
Time DoGetDelayUntilAccessRequest(uint8_t linkId) override;
|
||||
|
||||
/**
|
||||
* Possibly take actions when notified of the MAC header of the MPDU being received by the
|
||||
|
||||
@@ -172,7 +172,7 @@ DefaultEmlsrManager::NotifyMainPhySwitch(std::optional<uint8_t> currLinkId,
|
||||
}
|
||||
|
||||
Time
|
||||
DefaultEmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId)
|
||||
DefaultEmlsrManager::DoGetDelayUntilAccessRequest(uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
return Time{0}; // start the TXOP
|
||||
@@ -228,7 +228,7 @@ DefaultEmlsrManager::DoNotifyTxopEnd(uint8_t linkId)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
@@ -280,7 +280,7 @@ DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId)
|
||||
// switch main PHY
|
||||
SwitchMainPhy(linkId, false, RESET_BACKOFF, REQUEST_ACCESS);
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine if and when we need to request channel access again for the aux PHY based on
|
||||
@@ -307,7 +307,7 @@ DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId)
|
||||
if (!mainPhy->IsStateSwitching() && !mainPhy->IsStateCcaBusy())
|
||||
{
|
||||
NS_LOG_DEBUG("Main PHY state is " << mainPhy->GetState()->GetState() << ". Do nothing");
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto delay = mainPhy->GetDelayUntilIdle();
|
||||
@@ -329,8 +329,78 @@ DefaultEmlsrManager::SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId)
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
Time
|
||||
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());
|
||||
const auto ctsTxVector = stationManager->GetCtsTxVector(bssid, rtsTxVector.GetMode());
|
||||
const auto ctsTxTime = phy->CalculateTxDuration(GetCtsSize(), ctsTxVector, 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
|
||||
return rtsTxTime + phy->GetSifs() + ctsTxTime + MicroSeconds(2 * MAX_PROPAGATION_DELAY_USEC);
|
||||
}
|
||||
|
||||
Time
|
||||
DefaultEmlsrManager::GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
|
||||
auto mainPhy = GetStaMac()->GetDevice()->GetPhy(m_mainPhyId);
|
||||
auto timeToCtsEnd = GetTimeToCtsEnd(linkId);
|
||||
auto switchingTime = mainPhy->GetChannelSwitchDelay();
|
||||
|
||||
switch (mainPhy->GetState()->GetState())
|
||||
{
|
||||
case WifiPhyState::SWITCHING:
|
||||
// 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();
|
||||
[[fallthrough]];
|
||||
case WifiPhyState::RX:
|
||||
case WifiPhyState::IDLE:
|
||||
case WifiPhyState::CCA_BUSY:
|
||||
if (switchingTime > timeToCtsEnd)
|
||||
{
|
||||
// switching takes longer than RTS/CTS exchange, release channel
|
||||
NS_LOG_DEBUG("Not enough time for main PHY to switch link (main PHY state: "
|
||||
<< mainPhy->GetState()->GetState() << ")");
|
||||
// retry channel access when the CTS was expected to be received
|
||||
return timeToCtsEnd;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
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();
|
||||
|
||||
NS_ASSERT(delay.IsPositive());
|
||||
NS_LOG_DEBUG("Schedule main Phy switch in " << delay.As(Time::US));
|
||||
m_ulMainPhySwitch[linkId] = Simulator::Schedule(delay,
|
||||
&DefaultEmlsrManager::SwitchMainPhy,
|
||||
this,
|
||||
linkId,
|
||||
false,
|
||||
RESET_BACKOFF,
|
||||
DONT_REQUEST_ACCESS);
|
||||
|
||||
return Time{0};
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -33,17 +33,21 @@ class DefaultEmlsrManager : public EmlsrManager
|
||||
DefaultEmlsrManager();
|
||||
~DefaultEmlsrManager() override;
|
||||
|
||||
bool SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId) override;
|
||||
|
||||
/**
|
||||
* \param linkId the ID of the link on which TXOP is gained
|
||||
* \return zero, indicating that the TXOP can be started
|
||||
*/
|
||||
Time GetDelayUntilAccessRequest(uint8_t linkId) override;
|
||||
|
||||
protected:
|
||||
uint8_t GetLinkToSendEmlOmn() override;
|
||||
std::optional<uint8_t> ResendNotification(Ptr<const WifiMpdu> mpdu) override;
|
||||
Time DoGetDelayUntilAccessRequest(uint8_t linkId) override;
|
||||
void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId) override;
|
||||
Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) override;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* \return the time remaining to the end of the CTS reception
|
||||
*/
|
||||
Time GetTimeToCtsEnd(uint8_t linkId) const;
|
||||
|
||||
/// Store information about a main PHY switch.
|
||||
struct MainPhySwitchInfo
|
||||
|
||||
@@ -169,6 +169,8 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, MHz_u allowedWidth)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << edca << allowedWidth);
|
||||
|
||||
m_allowedWidth = allowedWidth;
|
||||
|
||||
if (m_apMac)
|
||||
{
|
||||
for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++)
|
||||
@@ -273,6 +275,9 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, MHz_u allowedWidth)
|
||||
return false;
|
||||
}
|
||||
|
||||
auto mainPhy = m_staMac->GetDevice()->GetPhy(emlsrManager->GetMainPhyId());
|
||||
const auto mainPhySwitching = mainPhy->IsStateSwitching();
|
||||
|
||||
// let EMLSR manager decide whether to prevent or allow this UL TXOP
|
||||
if (auto delay = emlsrManager->GetDelayUntilAccessRequest(m_linkId);
|
||||
delay.IsStrictlyPositive())
|
||||
@@ -288,98 +293,44 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, MHz_u allowedWidth)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto mainPhy = m_staMac->GetDevice()->GetPhy(emlsrManager->GetMainPhyId());
|
||||
mainPhy != m_phy)
|
||||
// in case of aux PHY that is not TX capable, the main PHY can transmit if the medium is
|
||||
// sensed idle for a PIFS after the end of channel switch (assuming main PHY is switching)
|
||||
if (m_phy != mainPhy && !emlsrManager->GetAuxPhyTxCapable())
|
||||
{
|
||||
// an aux PHY is operating on this link
|
||||
NS_LOG_DEBUG("Aux PHY is not capable of transmitting a PPDU");
|
||||
|
||||
if (!emlsrManager->GetAuxPhyTxCapable())
|
||||
if (!mainPhySwitching && mainPhy->IsStateSwitching())
|
||||
{
|
||||
NS_LOG_DEBUG("Aux PHY is not capable of transmitting a PPDU");
|
||||
// main PHY switch has been requested by GetDelayUntilAccessRequest
|
||||
const auto pifs = m_phy->GetSifs() + m_phy->GetSlot();
|
||||
auto checkMediumLastPifs = [=, this]() {
|
||||
// check if the medium has been idle for the last PIFS interval
|
||||
auto width =
|
||||
m_staMac->GetChannelAccessManager(m_linkId)->GetLargestIdlePrimaryChannel(
|
||||
pifs,
|
||||
Simulator::Now());
|
||||
|
||||
if (emlsrManager->SwitchMainPhyIfTxopGainedByAuxPhy(m_linkId))
|
||||
{
|
||||
NS_ASSERT_MSG(mainPhy->IsStateSwitching(),
|
||||
"SwitchMainPhyIfTxopGainedByAuxPhy returned true but main PHY is "
|
||||
"not switching");
|
||||
if (width == 0)
|
||||
{
|
||||
NS_LOG_DEBUG("Medium busy in the last PIFS after channel switch end");
|
||||
edca->StartAccessAfterEvent(m_linkId,
|
||||
Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT,
|
||||
Txop::CHECK_MEDIUM_BUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto pifs = m_phy->GetSifs() + m_phy->GetSlot();
|
||||
auto checkMediumLastPifs = [=, this]() {
|
||||
// check if the medium has been idle for the last PIFS interval
|
||||
auto width = m_staMac->GetChannelAccessManager(m_linkId)
|
||||
->GetLargestIdlePrimaryChannel(pifs, Simulator::Now());
|
||||
|
||||
if (width == 0)
|
||||
{
|
||||
NS_LOG_DEBUG("Medium busy in the last PIFS after channel switch end");
|
||||
edca->StartAccessAfterEvent(m_linkId,
|
||||
Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT,
|
||||
Txop::CHECK_MEDIUM_BUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
// medium idle, start a TXOP
|
||||
if (HeFrameExchangeManager::StartTransmission(edca, width))
|
||||
{
|
||||
// notify the EMLSR Manager of the UL TXOP start on an EMLSR link
|
||||
emlsrManager->NotifyUlTxopStart(m_linkId, std::nullopt);
|
||||
}
|
||||
};
|
||||
Simulator::Schedule(mainPhy->GetDelayUntilIdle() + pifs, checkMediumLastPifs);
|
||||
}
|
||||
|
||||
NotifyChannelReleased(edca);
|
||||
return false;
|
||||
// medium idle, start a TXOP
|
||||
if (HeFrameExchangeManager::StartTransmission(edca, width))
|
||||
{
|
||||
// notify the EMLSR Manager of the UL TXOP start on an EMLSR link
|
||||
emlsrManager->NotifyUlTxopStart(m_linkId);
|
||||
}
|
||||
};
|
||||
Simulator::Schedule(mainPhy->GetDelayUntilIdle() + pifs, checkMediumLastPifs);
|
||||
}
|
||||
|
||||
// we have to check whether the main PHY can switch to take over the UL TXOP
|
||||
|
||||
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();
|
||||
|
||||
switch (mainPhy->GetState()->GetState())
|
||||
{
|
||||
case WifiPhyState::SWITCHING:
|
||||
// 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();
|
||||
[[fallthrough]];
|
||||
case WifiPhyState::RX:
|
||||
case WifiPhyState::IDLE:
|
||||
case WifiPhyState::CCA_BUSY:
|
||||
if (switchingTime <= timeToCtsEnd)
|
||||
{
|
||||
break; // start TXOP
|
||||
}
|
||||
// switching takes longer than RTS/CTS exchange, release channel
|
||||
NS_LOG_DEBUG("Not enough time for main PHY to switch link (main PHY state: "
|
||||
<< mainPhy->GetState() << ")");
|
||||
// retry channel access when the CTS was expected to be received
|
||||
NotifyChannelReleased(edca);
|
||||
Simulator::Schedule(*timeToCtsEnd,
|
||||
&Txop::StartAccessAfterEvent,
|
||||
edca,
|
||||
m_linkId,
|
||||
Txop::DIDNT_HAVE_FRAMES_TO_TRANSMIT, // queued frames cannot be
|
||||
// transmitted now
|
||||
Txop::CHECK_MEDIUM_BUSY); // generate backoff if medium busy
|
||||
return false;
|
||||
default:
|
||||
NS_ABORT_MSG("Main PHY cannot be in state " << mainPhy->GetState());
|
||||
}
|
||||
NotifyChannelReleased(edca);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +340,7 @@ EhtFrameExchangeManager::StartTransmission(Ptr<Txop> edca, MHz_u 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, timeToCtsEnd);
|
||||
m_staMac->GetEmlsrManager()->NotifyUlTxopStart(m_linkId);
|
||||
}
|
||||
|
||||
if (started)
|
||||
|
||||
@@ -408,8 +408,43 @@ EmlsrManager::NotifyIcfReceived(uint8_t linkId)
|
||||
});
|
||||
}
|
||||
|
||||
Time
|
||||
EmlsrManager::GetDelayUntilAccessRequest(uint8_t linkId)
|
||||
{
|
||||
auto phy = m_staMac->GetWifiPhy(linkId);
|
||||
NS_ASSERT_MSG(phy, "No PHY operating on link " << +linkId);
|
||||
|
||||
auto mainPhy = m_staMac->GetDevice()->GetPhy(m_mainPhyId);
|
||||
|
||||
// check possible reasons to give up the TXOP that apply to both main PHY and aux PHYs
|
||||
if (auto delay = DoGetDelayUntilAccessRequest(linkId); delay.IsStrictlyPositive())
|
||||
{
|
||||
return delay;
|
||||
}
|
||||
|
||||
if (phy == mainPhy)
|
||||
{
|
||||
// no more constraints to check if medium was gained by main PHY
|
||||
return Time{0};
|
||||
}
|
||||
|
||||
// an aux PHY is operating on the given link; call the appropriate method depending on
|
||||
// whether the aux PHY is TX capable or not
|
||||
if (!m_auxPhyTxCapable)
|
||||
{
|
||||
SwitchMainPhyIfTxopGainedByAuxPhy(linkId);
|
||||
// if the aux PHY is not TX capable, we don't have to request channel access: if the main
|
||||
// PHY switches link, the UL TXOP will be started; if the main PHY does not switch, it is
|
||||
// because it is going to start an UL TXOP on another link and this link will be restarted
|
||||
// at the end of that UL TXOP when this link will be unblocked
|
||||
return Time{0};
|
||||
}
|
||||
|
||||
return GetDelayUnlessMainPhyTakesOverUlTxop(linkId);
|
||||
}
|
||||
|
||||
void
|
||||
EmlsrManager::NotifyUlTxopStart(uint8_t linkId, std::optional<Time> timeToCtsEnd)
|
||||
EmlsrManager::NotifyUlTxopStart(uint8_t linkId)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << linkId);
|
||||
|
||||
@@ -428,35 +463,6 @@ EmlsrManager::NotifyUlTxopStart(uint8_t linkId, std::optional<Time> timeToCtsEnd
|
||||
}
|
||||
}
|
||||
|
||||
// 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() == WifiPhyState::TX,
|
||||
"Expecting the aux PHY to be transmitting (an RTS frame)");
|
||||
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));
|
||||
m_ulMainPhySwitch[linkId] = Simulator::Schedule(delay,
|
||||
&EmlsrManager::SwitchMainPhy,
|
||||
this,
|
||||
linkId,
|
||||
false,
|
||||
RESET_BACKOFF,
|
||||
DONT_REQUEST_ACCESS);
|
||||
}
|
||||
|
||||
DoNotifyUlTxopStart(linkId);
|
||||
}
|
||||
|
||||
|
||||
@@ -137,14 +137,14 @@ class EmlsrManager : public Object
|
||||
bool GetCamStateReset() const;
|
||||
|
||||
/**
|
||||
* Notify that a TXOP is gained on the given link. This method has to determine whether to
|
||||
* start the TXOP or release the channel.
|
||||
* Notify that an UL TXOP is gained on the given link. This method has to determine whether to
|
||||
* start the UL TXOP or release the channel.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return zero, if the TXOP can be started, or the delay after which the EMLSR restarts
|
||||
* channel access, otherwise
|
||||
* \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client
|
||||
* restarts channel access, otherwise
|
||||
*/
|
||||
virtual Time GetDelayUntilAccessRequest(uint8_t linkId) = 0;
|
||||
Time GetDelayUntilAccessRequest(uint8_t linkId);
|
||||
|
||||
/**
|
||||
* Set the member variable indicating whether Aux PHYs are capable of transmitting PPDUs.
|
||||
@@ -192,10 +192,8 @@ 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, std::optional<Time> timeToCtsEnd);
|
||||
void NotifyUlTxopStart(uint8_t linkId);
|
||||
|
||||
/**
|
||||
* Notify the end of a TXOP on the given link.
|
||||
@@ -208,16 +206,6 @@ class EmlsrManager : public Object
|
||||
*/
|
||||
void NotifyTxopEnd(uint8_t linkId, bool ulTxopNotStarted = false, bool ongoingDlTxop = false);
|
||||
|
||||
/**
|
||||
* This method is intended to notify the EMLSR Manager that an aux PHY that is NOT TX capable
|
||||
* has gained a TXOP on a given link and returns whether the main PHY has been requested to
|
||||
* switch to the given link to take over the TXOP.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return whether main PHY has been requested to switch
|
||||
*/
|
||||
virtual bool SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId) = 0;
|
||||
|
||||
/**
|
||||
* Check whether the MediumSyncDelay timer is running for the STA operating on the given link.
|
||||
* If so, returns the time elapsed since the timer started.
|
||||
@@ -357,12 +345,49 @@ class EmlsrManager : public Object
|
||||
*/
|
||||
MgtEmlOmn GetEmlOmn();
|
||||
|
||||
/**
|
||||
* Subclasses have to provide an implementation for this method, that is called by the base
|
||||
* class when the EMLSR client gets channel access on the given link. This method has to
|
||||
* check possible reasons to give up the TXOP that apply to both main PHY and aux PHYs.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client
|
||||
* restarts channel access, otherwise
|
||||
*/
|
||||
virtual Time DoGetDelayUntilAccessRequest(uint8_t linkId) = 0;
|
||||
|
||||
/**
|
||||
* Subclasses have to provide an implementation for this method, that is called by the base
|
||||
* class when the EMLSR client gets channel access on the given link, on which an aux PHY that
|
||||
* is not TX capable is operating. This method has to request the main PHY to switch to the
|
||||
* given link to take over the TXOP, unless it is decided to give up the TXOP.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
*/
|
||||
virtual void SwitchMainPhyIfTxopGainedByAuxPhy(uint8_t linkId) = 0;
|
||||
|
||||
/**
|
||||
* Subclasses have to provide an implementation for this method, that is called by the base
|
||||
* class when the EMLSR client gets channel access on the given link, on which an aux PHY that
|
||||
* is TX capable is operating. This method has to request the main PHY to switch to the
|
||||
* given link to take over the TXOP, if possible, or determine the delay after which the
|
||||
* EMLSR client restarts channel access on the given link, otherwise.
|
||||
*
|
||||
* \param linkId the ID of the given link
|
||||
* \return zero, if the UL TXOP can be started, or the delay after which the EMLSR client
|
||||
* restarts channel access, otherwise
|
||||
*/
|
||||
virtual Time GetDelayUnlessMainPhyTakesOverUlTxop(uint8_t linkId) = 0;
|
||||
|
||||
Time m_emlsrPaddingDelay; //!< EMLSR Padding delay
|
||||
Time m_emlsrTransitionDelay; //!< EMLSR Transition delay
|
||||
uint8_t m_mainPhyId; //!< ID of main PHY (position in the vector of PHYs held by WifiNetDevice)
|
||||
MHz_u m_auxPhyMaxWidth; //!< max channel width supported by aux PHYs
|
||||
WifiModulationClass m_auxPhyMaxModClass; //!< max modulation class supported by aux PHYs
|
||||
bool m_auxPhyTxCapable; //!< whether Aux PHYs are capable of transmitting PPDUs
|
||||
std::map<uint8_t, EventId> m_ulMainPhySwitch; //!< link ID-indexed map of timers started when
|
||||
//!< an aux PHY gains an UL TXOP and schedules
|
||||
//!< a channel switch for the main PHY
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -514,9 +539,6 @@ class EmlsrManager : public Object
|
||||
m_mainPhyChannels; //!< link ID-indexed map of operating channels for the main PHY
|
||||
std::map<uint8_t, WifiPhyOperatingChannel>
|
||||
m_auxPhyChannels; //!< link ID-indexed map of operating channels for the aux PHYs
|
||||
std::map<uint8_t, EventId> m_ulMainPhySwitch; //!< link ID-indexed map of timers started when
|
||||
//!< an aux PHY gains an UL TXOP and schedules
|
||||
//!< a channel switch for the main PHY
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -226,6 +226,12 @@ FrameExchangeManager::GetBssid() const
|
||||
return m_bssid;
|
||||
}
|
||||
|
||||
MHz_u
|
||||
FrameExchangeManager::GetAllowedWidth() const
|
||||
{
|
||||
return m_allowedWidth;
|
||||
}
|
||||
|
||||
void
|
||||
FrameExchangeManager::SetDroppedMpduCallback(DroppedMpdu callback)
|
||||
{
|
||||
|
||||
@@ -200,6 +200,10 @@ class FrameExchangeManager : public Object
|
||||
* \return the BSSID
|
||||
*/
|
||||
Mac48Address GetBssid() const;
|
||||
/**
|
||||
* \return the width of the channel that the FEM is allowed to use for the current transmission
|
||||
*/
|
||||
MHz_u GetAllowedWidth() const;
|
||||
/**
|
||||
* Set the callback to invoke when an MPDU is dropped.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user