wifi: Handle CCA for 802.11be PHY

This commit is contained in:
Sébastien Deronne
2024-10-05 08:47:36 +02:00
parent 176e382b41
commit fae13d9de5
5 changed files with 160 additions and 2 deletions

View File

@@ -18,6 +18,7 @@ This file is a best-effort approach to solving this issue; we will do our best b
* (network) Added a function to detect IPv4 APIPA addresses (169.254.0.0/16).
* (wifi) Added a new `AssocType` attribute to `StaWifiMac` to configure the type of association performed by a device, provided that it is supported by the standard configured for the device. By using this attribute, it is possible for an EHT single-link device to perform ML setup with an AP MLD and for an EHT multi-link device to perform legacy association with an AP MLD.
* (wifi) Added a new attribute `Per20CcaSensitivityThreshold` to `EhtConfiguration` for tuning the Per 20MHz CCA threshold when 802.11be is used.
### Changes to existing API

View File

@@ -11,6 +11,7 @@
#include "ns3/attribute-container.h"
#include "ns3/boolean.h"
#include "ns3/double.h"
#include "ns3/enum.h"
#include "ns3/integer.h"
#include "ns3/log.h"
@@ -162,7 +163,12 @@ EhtConfiguration::GetTypeId()
MakeAttributeContainerChecker<UintegerValue>(
MakeUintegerChecker<uint8_t>()),
MakeAttributeContainerChecker<UintegerValue>(
MakeUintegerChecker<uint8_t>()))));
MakeUintegerChecker<uint8_t>()))))
.AddAttribute("Per20CcaSensitivityThreshold",
"CCA threshold (dBm) for Per 20MHz check.",
DoubleValue(-72.0),
MakeDoubleAccessor(&EhtConfiguration::m_per20CcaSensitivityThreshold),
MakeDoubleChecker<dBm_u>());
return tid;
}

View File

@@ -110,7 +110,8 @@ class EhtConfiguration : public Object
std::map<std::list<uint64_t>, std::list<uint64_t>>
m_linkMappingDl; //!< TIDs-indexed Link Mapping for downlink
std::map<std::list<uint64_t>, std::list<uint64_t>>
m_linkMappingUl; //!< TIDs-indexed Link Mapping for uplink
m_linkMappingUl; //!< TIDs-indexed Link Mapping for uplink
dB_u m_per20CcaSensitivityThreshold; //!< CCA threshold for Per 20MHz check
};
} // namespace ns3

View File

@@ -8,9 +8,12 @@
#include "eht-phy.h"
#include "eht-configuration.h"
#include "eht-ppdu.h"
#include "ns3/interference-helper.h"
#include "ns3/obss-pd-algorithm.h"
#include "ns3/wifi-net-device.h"
#include "ns3/wifi-phy.h"
#include "ns3/wifi-psdu.h"
#include "ns3/wifi-utils.h"
@@ -43,6 +46,15 @@ const PhyEntity::PpduFormats EhtPhy::m_ehtPpduFormats {
WIFI_PPDU_FIELD_DATA } }
};
/**
* \brief map a given secondary channel width to its channel list type
*/
const std::map<MHz_u, WifiChannelListType> ehtSecondaryChannels {
{20, WIFI_CHANLIST_SECONDARY},
{40, WIFI_CHANLIST_SECONDARY40},
{80, WIFI_CHANLIST_SECONDARY80},
};
// clang-format on
EhtPhy::EhtPhy(bool buildModeList /* = true */)
@@ -405,6 +417,129 @@ EhtPhy::CalculateNonHtReferenceRate(WifiCodeRate codeRate, uint16_t constellatio
return dataRate;
}
dBm_u
EhtPhy::Per20MHzCcaThreshold(const Ptr<const WifiPpdu> ppdu) const
{
if (!ppdu)
{
/**
* A signal is present on the 20 MHz subchannel at or above a threshold of 62 dBm at the
* receiver's antenna(s). The PHY shall indicate that the 20 MHz subchannel is busy a period
* aCCATime after the signal starts and shall continue to indicate the 20 MHz subchannel is
* busy while the threshold continues to be exceeded (Sec. 36.3.21.6.4 - Per 20 MHz CCA
* sensitivity - of 802.11be D7.0).
*/
return m_wifiPhy->GetCcaEdThreshold();
}
/**
* A non-HT, HT_MF, HT_GF, VHT, HE, or EHT PPDU for which the power measured within
* this 20 MHz subchannel is at or above max(72 dBm, OBSS_PD level) at the
* receivers antenna(s). The PHY shall indicate that the 20 MHz subchannel is busy
* with greater than 90% probability within a period aCCAMidTime (Sec. 36.3.21.6.4 - Per 20 MHz
* CCA sensitivity - of 802.11be D7.0).
*/
auto ehtConfiguration = m_wifiPhy->GetDevice()->GetEhtConfiguration();
NS_ASSERT(ehtConfiguration);
const auto ccaThresholdNonObss = ehtConfiguration->m_per20CcaSensitivityThreshold;
return GetObssPdAlgorithm()
? std::max(ccaThresholdNonObss, GetObssPdAlgorithm()->GetObssPdLevel())
: ccaThresholdNonObss;
}
dBm_u
EhtPhy::GetCcaThreshold(const Ptr<const WifiPpdu> ppdu, WifiChannelListType channelType) const
{
if (channelType != WIFI_CHANLIST_PRIMARY)
{
return Per20MHzCcaThreshold(ppdu);
}
return HePhy::GetCcaThreshold(ppdu, channelType);
}
const std::map<MHz_u, WifiChannelListType>&
EhtPhy::GetCcaSecondaryChannels() const
{
return ehtSecondaryChannels;
}
PhyEntity::CcaIndication
EhtPhy::GetCcaIndicationOnSecondary(const Ptr<const WifiPpdu> ppdu)
{
const auto secondaryWidthsToCheck = GetCcaSecondaryWidths(ppdu);
for (auto secondaryWidth : secondaryWidthsToCheck)
{
const auto channelType = ehtSecondaryChannels.at(secondaryWidth);
const auto ccaThreshold = GetCcaThreshold(ppdu, channelType);
const auto indices =
m_wifiPhy->GetOperatingChannel().GetAll20MHzChannelIndicesInSecondary(secondaryWidth);
for (auto index : indices)
{
const auto band = m_wifiPhy->GetBand(20, index);
if (const auto delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, band);
delayUntilCcaEnd.IsStrictlyPositive())
{
return std::make_pair(delayUntilCcaEnd, channelType);
}
}
}
return std::nullopt;
}
std::vector<Time>
EhtPhy::GetPer20MHzDurations(const Ptr<const WifiPpdu> ppdu)
{
NS_LOG_FUNCTION(this);
/**
* 36.3.21.6.4 Per 20 MHz CCA sensitivity:
* If the operating channel width is greater than 20 MHz and the PHY issues a PHY-CCA.indication
* primitive, the PHY shall set the per20bitmap to indicate the busy/idle status of each 20 MHz
* subchannel.
*/
if (m_wifiPhy->GetChannelWidth() < 40)
{
return {};
}
std::vector<Time> per20MhzDurations{};
const auto indices = m_wifiPhy->GetOperatingChannel().GetAll20MHzChannelIndicesInPrimary(
m_wifiPhy->GetChannelWidth());
for (auto index : indices)
{
auto band = m_wifiPhy->GetBand(20, index);
/**
* A signal is present on the 20 MHz subchannel at or above a threshold of 62 dBm at the
* receiver's antenna(s). The PHY shall indicate that the 20 MHz subchannel is busy a period
* aCCATime after the signal starts and shall continue to indicate the 20 MHz subchannel is
* busy while the threshold continues to be exceeded.
*/
dBm_u ccaThreshold = -62;
auto delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, band);
if (ppdu)
{
const MHz_u subchannelMinFreq =
m_wifiPhy->GetFrequency() - (m_wifiPhy->GetChannelWidth() / 2) + (index * 20);
const MHz_u subchannelMaxFreq = subchannelMinFreq + 20;
const auto ppduBw = ppdu->GetTxVector().GetChannelWidth();
if ((ppduBw <= m_wifiPhy->GetChannelWidth()) &&
ppdu->DoesOverlapChannel(subchannelMinFreq, subchannelMaxFreq))
{
ccaThreshold = Per20MHzCcaThreshold(ppdu);
const auto ppduCcaDuration = GetDelayUntilCcaEnd(ccaThreshold, band);
delayUntilCcaEnd = std::max(delayUntilCcaEnd, ppduCcaDuration);
}
}
per20MhzDurations.push_back(delayUntilCcaEnd);
}
return per20MhzDurations;
}
} // namespace ns3
namespace

View File

@@ -252,6 +252,11 @@ class EhtPhy : public HePhy
WifiPpduField field) override;
WifiPhyRxfailureReason GetFailureReason(WifiPpduField field) const override;
uint32_t GetSigBSize(const WifiTxVector& txVector) const override;
dBm_u GetCcaThreshold(const Ptr<const WifiPpdu> ppdu,
WifiChannelListType channelType) const override;
const std::map<MHz_u, WifiChannelListType>& GetCcaSecondaryChannels() const override;
PhyEntity::CcaIndication GetCcaIndicationOnSecondary(const Ptr<const WifiPpdu> ppdu) override;
std::vector<Time> GetPer20MHzDurations(const Ptr<const WifiPpdu> ppdu) override;
/**
* Create and return the EHT MCS corresponding to
@@ -278,6 +283,16 @@ class EhtPhy : public HePhy
*/
static uint64_t CalculateNonHtReferenceRate(WifiCodeRate codeRate, uint16_t constellationSize);
/**
* Compute the CCA threshold for Per 20MHz check.
* This threshold is used for CCA check when signal is not occupying P20 or for Per 20MHz CCA
* check.
*
* @param ppdu the incoming PPDU or nullptr for any signal
* @return the CCA threshold for Per 20MHz check
*/
dBm_u Per20MHzCcaThreshold(const Ptr<const WifiPpdu> ppdu) const;
static const PpduFormats m_ehtPpduFormats; //!< EHT PPDU formats
};