wifi: Implement UL MU CS mechanism

This commit is contained in:
Stefano Avallone
2023-01-23 12:13:51 +01:00
parent 9a812baf28
commit 17c4db1d27
4 changed files with 73 additions and 0 deletions

View File

@@ -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)
{

View File

@@ -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
*

View File

@@ -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,

View File

@@ -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;