wifi: Implement UL MU CS mechanism
This commit is contained in:
@@ -627,6 +627,30 @@ ChannelAccessManager::GetLargestIdlePrimaryChannel(Time interval, Time end)
|
||||
return width;
|
||||
}
|
||||
|
||||
bool
|
||||
ChannelAccessManager::GetPer20MHzBusy(const std::set<uint8_t>& indices) const
|
||||
{
|
||||
const auto now = Simulator::Now();
|
||||
|
||||
if (m_phy->GetChannelWidth() < 40)
|
||||
{
|
||||
NS_ASSERT_MSG(indices.size() == 1 && *indices.cbegin() == 0,
|
||||
"Index 0 only can be specified if the channel width is less than 40 MHz");
|
||||
return m_lastBusyEnd.at(WIFI_CHANLIST_PRIMARY) > now;
|
||||
}
|
||||
|
||||
for (const auto index : indices)
|
||||
{
|
||||
NS_ASSERT(index < m_lastPer20MHzBusyEnd.size());
|
||||
if (m_lastPer20MHzBusyEnd.at(index) > now)
|
||||
{
|
||||
NS_LOG_DEBUG("20 MHz channel with index " << +index << " is busy");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ChannelAccessManager::DisableEdcaFor(Ptr<Txop> qosTxop, Time duration)
|
||||
{
|
||||
|
||||
@@ -149,6 +149,13 @@ class ChannelAccessManager : public Object
|
||||
*/
|
||||
uint16_t GetLargestIdlePrimaryChannel(Time interval, Time end);
|
||||
|
||||
/**
|
||||
* \param indices a set of indices (starting at 0) specifying the 20 MHz channels to test
|
||||
* \return true if per-20 MHz CCA indicates busy for at least one of the
|
||||
* specified 20 MHz channels, false otherwise
|
||||
*/
|
||||
bool GetPer20MHzBusy(const std::set<uint8_t>& indices) const;
|
||||
|
||||
/**
|
||||
* \param duration expected duration of reception
|
||||
*
|
||||
|
||||
@@ -1752,6 +1752,38 @@ HeFrameExchangeManager::VirtualCsMediumIdle() const
|
||||
return m_navEnd <= Simulator::Now() && m_intraBssNavEnd <= Simulator::Now();
|
||||
}
|
||||
|
||||
bool
|
||||
HeFrameExchangeManager::UlMuCsMediumIdle(const CtrlTriggerHeader& trigger) const
|
||||
{
|
||||
if (!trigger.GetCsRequired())
|
||||
{
|
||||
NS_LOG_DEBUG("CS not required");
|
||||
return true;
|
||||
}
|
||||
|
||||
// A non-AP STA does not consider the intra-BSS NAV in determining whether to respond to a
|
||||
// Trigger frame sent by the AP with which the non-AP STA is associated.
|
||||
// A non-AP STA considers the basic NAV in determining whether to respond to a Trigger frame
|
||||
// sent by the AP with which the non-AP STA is associated. (Sec. 26.5.2.5 of 802.11ax-2021)
|
||||
const Time now = Simulator::Now();
|
||||
if (m_navEnd > now)
|
||||
{
|
||||
NS_LOG_DEBUG("Basic NAV indicates medium busy");
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_ASSERT_MSG(m_staMac, "UL MU CS is only performed by non-AP STAs");
|
||||
const auto userInfoIt = trigger.FindUserInfoWithAid(m_staMac->GetAssociationId());
|
||||
NS_ASSERT_MSG(userInfoIt != trigger.end(),
|
||||
"No User Info field for STA (" << m_self
|
||||
<< ") AID=" << m_staMac->GetAssociationId());
|
||||
|
||||
const auto indices =
|
||||
m_phy->GetOperatingChannel().Get20MHzIndicesCoveringRu(userInfoIt->GetRuAllocation(),
|
||||
trigger.GetUlBandwidth());
|
||||
return !m_channelAccessManager->GetPer20MHzBusy(indices);
|
||||
}
|
||||
|
||||
void
|
||||
HeFrameExchangeManager::ReceiveMpdu(Ptr<const WifiMpdu> mpdu,
|
||||
RxSignalInfo rxSignalInfo,
|
||||
|
||||
@@ -116,6 +116,16 @@ class HeFrameExchangeManager : public VhtFrameExchangeManager
|
||||
*/
|
||||
bool IsIntraBssPpdu(Ptr<const WifiPsdu> psdu, const WifiTxVector& txVector) const;
|
||||
|
||||
/**
|
||||
* This method is intended to be called a SIFS after the reception of a Trigger Frame
|
||||
* to determine whether the station is allowed to respond.
|
||||
*
|
||||
* \param trigger the Trigger Frame soliciting a response
|
||||
* \return true if CS is not required or the UL MU CS mechanism indicates that the medium
|
||||
* is idle, false otherwise
|
||||
*/
|
||||
bool UlMuCsMediumIdle(const CtrlTriggerHeader& trigger) const;
|
||||
|
||||
protected:
|
||||
void DoDispose() override;
|
||||
void Reset() override;
|
||||
|
||||
Reference in New Issue
Block a user