wifi: Make CCA PHY indication more reusable over PHY entities
This commit is contained in:
@@ -1186,7 +1186,7 @@ HePhy::GetPer20MHzDurations(const Ptr<const WifiPpdu> ppdu)
|
||||
* 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 ccaThreshold = m_wifiPhy->GetCcaEdThreshold();
|
||||
auto delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, band);
|
||||
|
||||
if (ppdu)
|
||||
|
||||
@@ -540,6 +540,18 @@ class HePhy : public VhtPhy
|
||||
*/
|
||||
static uint16_t GetUsableSubcarriers(MHz_u channelWidth);
|
||||
|
||||
/**
|
||||
* Compute the per-20 MHz CCA durations vector that indicates
|
||||
* for how long each 20 MHz subchannel (corresponding to the
|
||||
* index of the element in the vector) is busy and where a zero duration
|
||||
* indicates that the subchannel is idle. The vector is non-empty if the
|
||||
* operational channel width is larger than 20 MHz.
|
||||
*
|
||||
* @param ppdu the incoming PPDU or nullptr for any signal
|
||||
* @return the per-20 MHz CCA durations vector
|
||||
*/
|
||||
virtual std::vector<Time> GetPer20MHzDurations(const Ptr<const WifiPpdu> ppdu);
|
||||
|
||||
uint64_t m_previouslyTxPpduUid; //!< UID of the previously sent PPDU, used by AP to recognize
|
||||
//!< response HE TB PPDUs
|
||||
uint64_t m_currentMuPpduUid; //!< UID of the HE MU or HE TB PPDU being received
|
||||
@@ -595,18 +607,6 @@ class HePhy : public VhtPhy
|
||||
WifiChannelListType channelType,
|
||||
const std::vector<Time>& per20MHzDurations);
|
||||
|
||||
/**
|
||||
* Compute the per-20 MHz CCA durations vector that indicates
|
||||
* for how long each 20 MHz subchannel (corresponding to the
|
||||
* index of the element in the vector) is busy and where a zero duration
|
||||
* indicates that the subchannel is idle. The vector is non-empty if the
|
||||
* operational channel width is larger than 20 MHz.
|
||||
*
|
||||
* @param ppdu the incoming PPDU or nullptr for any signal
|
||||
* @return the per-20 MHz CCA durations vector
|
||||
*/
|
||||
std::vector<Time> GetPer20MHzDurations(const Ptr<const WifiPpdu> ppdu);
|
||||
|
||||
/**
|
||||
* Given a PPDU duration value, the TXVECTOR used to transmit the PPDU and
|
||||
* the PHY band, compute a valid PPDU duration considering the number and
|
||||
|
||||
@@ -40,6 +40,13 @@ const PhyEntity::PpduFormats HtPhy::m_htPpduFormats {
|
||||
WIFI_PPDU_FIELD_DATA } }
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief map a given secondary channel width to its channel list type
|
||||
*/
|
||||
const std::map<MHz_u, WifiChannelListType> htSecondaryChannels {
|
||||
{20, WIFI_CHANLIST_SECONDARY},
|
||||
};
|
||||
|
||||
// clang-format on
|
||||
|
||||
HtPhy::HtPhy(uint8_t maxNss /* = 1 */, bool buildModeList /* = true */)
|
||||
@@ -813,6 +820,71 @@ HtPhy::GetMaxPsduSize() const
|
||||
return 65535;
|
||||
}
|
||||
|
||||
const std::map<MHz_u, WifiChannelListType>&
|
||||
HtPhy::GetCcaSecondaryChannels() const
|
||||
{
|
||||
return htSecondaryChannels;
|
||||
}
|
||||
|
||||
std::vector<MHz_u>
|
||||
HtPhy::GetCcaSecondaryWidths(const Ptr<const WifiPpdu> ppdu) const
|
||||
{
|
||||
std::vector<MHz_u> secondaryWidthsToCheck{};
|
||||
if (ppdu)
|
||||
{
|
||||
for (const auto& secondaryChannel : GetCcaSecondaryChannels())
|
||||
{
|
||||
const auto secondaryWidth = secondaryChannel.first;
|
||||
if (secondaryWidth >= m_wifiPhy->GetChannelWidth())
|
||||
{
|
||||
break;
|
||||
}
|
||||
const MHz_u secondaryMinFreq =
|
||||
m_wifiPhy->GetOperatingChannel().GetSecondaryChannelCenterFrequency(
|
||||
secondaryWidth) -
|
||||
(secondaryWidth / 2);
|
||||
const MHz_u secondaryMaxFreq =
|
||||
m_wifiPhy->GetOperatingChannel().GetSecondaryChannelCenterFrequency(
|
||||
secondaryWidth) +
|
||||
(secondaryWidth / 2);
|
||||
if (ppdu->DoesOverlapChannel(secondaryMinFreq, secondaryMaxFreq))
|
||||
{
|
||||
secondaryWidthsToCheck.push_back(secondaryWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (MHz_u secondaryWidth = 20; secondaryWidth < m_wifiPhy->GetChannelWidth();
|
||||
secondaryWidth *= 2)
|
||||
{
|
||||
secondaryWidthsToCheck.push_back(secondaryWidth);
|
||||
}
|
||||
}
|
||||
return secondaryWidthsToCheck;
|
||||
}
|
||||
|
||||
PhyEntity::CcaIndication
|
||||
HtPhy::GetCcaIndicationOnSecondary(const Ptr<const WifiPpdu> ppdu)
|
||||
{
|
||||
const auto& secondaryChannels = GetCcaSecondaryChannels();
|
||||
const auto secondaryWidthsToCheck = GetCcaSecondaryWidths(ppdu);
|
||||
for (auto secondaryWidth : secondaryWidthsToCheck)
|
||||
{
|
||||
const auto channelType = secondaryChannels.at(secondaryWidth);
|
||||
|
||||
const auto ccaThreshold = GetCcaThreshold(ppdu, channelType);
|
||||
const auto band = GetSecondaryBand(secondaryWidth);
|
||||
if (const auto delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, band);
|
||||
delayUntilCcaEnd.IsStrictlyPositive())
|
||||
{
|
||||
return std::make_pair(delayUntilCcaEnd, channelType);
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
PhyEntity::CcaIndication
|
||||
HtPhy::GetCcaIndication(const Ptr<const WifiPpdu> ppdu)
|
||||
{
|
||||
@@ -820,6 +892,7 @@ HtPhy::GetCcaIndication(const Ptr<const WifiPpdu> ppdu)
|
||||
{
|
||||
return OfdmPhy::GetCcaIndication(ppdu);
|
||||
}
|
||||
|
||||
auto ccaThreshold = GetCcaThreshold(ppdu, WIFI_CHANLIST_PRIMARY);
|
||||
auto delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, GetPrimaryBand(MHz_u{20}));
|
||||
if (delayUntilCcaEnd.IsStrictlyPositive())
|
||||
@@ -828,6 +901,7 @@ HtPhy::GetCcaIndication(const Ptr<const WifiPpdu> ppdu)
|
||||
delayUntilCcaEnd,
|
||||
WIFI_CHANLIST_PRIMARY); // if Primary is busy, ignore CCA for Secondary
|
||||
}
|
||||
|
||||
if (ppdu)
|
||||
{
|
||||
const MHz_u primaryWidth{20};
|
||||
@@ -847,24 +921,7 @@ HtPhy::GetCcaIndication(const Ptr<const WifiPpdu> ppdu)
|
||||
}
|
||||
}
|
||||
|
||||
const MHz_u secondaryWidth{20};
|
||||
const MHz_u s20MinFreq =
|
||||
m_wifiPhy->GetOperatingChannel().GetSecondaryChannelCenterFrequency(secondaryWidth) -
|
||||
(secondaryWidth / 2);
|
||||
const MHz_u s20MaxFreq =
|
||||
m_wifiPhy->GetOperatingChannel().GetSecondaryChannelCenterFrequency(secondaryWidth) +
|
||||
(secondaryWidth / 2);
|
||||
if (!ppdu || ppdu->DoesOverlapChannel(s20MinFreq, s20MaxFreq))
|
||||
{
|
||||
ccaThreshold = GetCcaThreshold(ppdu, WIFI_CHANLIST_SECONDARY);
|
||||
delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, GetSecondaryBand(MHz_u{20}));
|
||||
if (delayUntilCcaEnd.IsStrictlyPositive())
|
||||
{
|
||||
return std::make_pair(delayUntilCcaEnd, WIFI_CHANLIST_SECONDARY);
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return GetCcaIndicationOnSecondary(ppdu);
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -460,6 +460,32 @@ class HtPhy : public OfdmPhy
|
||||
uint32_t GetMaxPsduSize() const override;
|
||||
CcaIndication GetCcaIndication(const Ptr<const WifiPpdu> ppdu) override;
|
||||
|
||||
/**
|
||||
* Get the secondary channel widths and their corresponding channel list types that are
|
||||
* supported by the PHY entity.
|
||||
*
|
||||
* @return the channel list type per supported secondary channel width
|
||||
*/
|
||||
virtual const std::map<MHz_u, WifiChannelListType>& GetCcaSecondaryChannels() const;
|
||||
|
||||
/**
|
||||
* Get the widths of the secondary channels to inspect for CCA indication.
|
||||
*
|
||||
* @param ppdu the incoming PPDU or nullptr for any signal
|
||||
* @return the widths of the secondary channels to inspect for CCA indication
|
||||
*/
|
||||
std::vector<MHz_u> GetCcaSecondaryWidths(const Ptr<const WifiPpdu> ppdu) const;
|
||||
|
||||
/**
|
||||
* Get CCA end time and its corresponding channel list type when a new signal not occupying the
|
||||
* primary 20 MHz channel has been received by the PHY.
|
||||
*
|
||||
* @param ppdu the incoming PPDU or nullptr for any signal
|
||||
* @return CCA end time and its corresponding channel list type or std::nullopt if all channel
|
||||
* list types are IDLE
|
||||
*/
|
||||
virtual PhyEntity::CcaIndication GetCcaIndicationOnSecondary(const Ptr<const WifiPpdu> ppdu);
|
||||
|
||||
/**
|
||||
* Build mode list.
|
||||
* Should be redone whenever the maximum MCS index per spatial stream
|
||||
|
||||
@@ -80,7 +80,7 @@ const std::map<WifiChannelListType, dBm_u> channelTypeToScalingFactor{
|
||||
/**
|
||||
* @brief map a given secondary channel width to its channel list type
|
||||
*/
|
||||
const std::map<MHz_u, WifiChannelListType> secondaryChannels{
|
||||
const std::map<MHz_u, WifiChannelListType> vhtSecondaryChannels{
|
||||
{MHz_u{20}, WIFI_CHANLIST_SECONDARY},
|
||||
{MHz_u{40}, WIFI_CHANLIST_SECONDARY40},
|
||||
{MHz_u{80}, WIFI_CHANLIST_SECONDARY80},
|
||||
@@ -573,85 +573,10 @@ VhtPhy::GetCcaThreshold(const Ptr<const WifiPpdu> ppdu, WifiChannelListType chan
|
||||
}
|
||||
}
|
||||
|
||||
PhyEntity::CcaIndication
|
||||
VhtPhy::GetCcaIndication(const Ptr<const WifiPpdu> ppdu)
|
||||
const std::map<MHz_u, WifiChannelListType>&
|
||||
VhtPhy::GetCcaSecondaryChannels() const
|
||||
{
|
||||
if (m_wifiPhy->GetChannelWidth() < 80)
|
||||
{
|
||||
return HtPhy::GetCcaIndication(ppdu);
|
||||
}
|
||||
|
||||
auto ccaThreshold = GetCcaThreshold(ppdu, WIFI_CHANLIST_PRIMARY);
|
||||
auto delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, GetPrimaryBand(20));
|
||||
if (delayUntilCcaEnd.IsStrictlyPositive())
|
||||
{
|
||||
return std::make_pair(
|
||||
delayUntilCcaEnd,
|
||||
WIFI_CHANLIST_PRIMARY); // if Primary is busy, ignore CCA for Secondary
|
||||
}
|
||||
|
||||
if (ppdu)
|
||||
{
|
||||
const MHz_u primaryWidth{20};
|
||||
const MHz_u p20MinFreq =
|
||||
m_wifiPhy->GetOperatingChannel().GetPrimaryChannelCenterFrequency(primaryWidth) -
|
||||
(primaryWidth / 2);
|
||||
const MHz_u p20MaxFreq =
|
||||
m_wifiPhy->GetOperatingChannel().GetPrimaryChannelCenterFrequency(primaryWidth) +
|
||||
(primaryWidth / 2);
|
||||
if (ppdu->DoesOverlapChannel(p20MinFreq, p20MaxFreq))
|
||||
{
|
||||
/*
|
||||
* PPDU occupies primary 20 MHz channel, hence we skip CCA sensitivity rules
|
||||
* for signals not occupying the primary 20 MHz channel.
|
||||
*/
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<MHz_u> secondaryWidthsToCheck;
|
||||
if (ppdu)
|
||||
{
|
||||
for (const auto& secondaryChannel : secondaryChannels)
|
||||
{
|
||||
const auto secondaryWidth = secondaryChannel.first;
|
||||
const MHz_u secondaryMinFreq =
|
||||
m_wifiPhy->GetOperatingChannel().GetSecondaryChannelCenterFrequency(
|
||||
secondaryWidth) -
|
||||
(secondaryWidth / 2);
|
||||
const MHz_u secondaryMaxFreq =
|
||||
m_wifiPhy->GetOperatingChannel().GetSecondaryChannelCenterFrequency(
|
||||
secondaryWidth) +
|
||||
(secondaryWidth / 2);
|
||||
if ((m_wifiPhy->GetChannelWidth() > secondaryWidth) &&
|
||||
ppdu->DoesOverlapChannel(secondaryMinFreq, secondaryMaxFreq))
|
||||
{
|
||||
secondaryWidthsToCheck.push_back(secondaryWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
secondaryWidthsToCheck.push_back(20);
|
||||
secondaryWidthsToCheck.push_back(40);
|
||||
if (m_wifiPhy->GetChannelWidth() > 80)
|
||||
{
|
||||
secondaryWidthsToCheck.push_back(80);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto secondaryWidth : secondaryWidthsToCheck)
|
||||
{
|
||||
auto channelType = secondaryChannels.at(secondaryWidth);
|
||||
ccaThreshold = GetCcaThreshold(ppdu, channelType);
|
||||
delayUntilCcaEnd = GetDelayUntilCcaEnd(ccaThreshold, GetSecondaryBand(secondaryWidth));
|
||||
if (delayUntilCcaEnd.IsStrictlyPositive())
|
||||
{
|
||||
return std::make_pair(delayUntilCcaEnd, channelType);
|
||||
}
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
return vhtSecondaryChannels;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -267,7 +267,7 @@ class VhtPhy : public HtPhy
|
||||
PhyFieldRxStatus DoEndReceiveField(WifiPpduField field, Ptr<Event> event) override;
|
||||
bool IsAllConfigSupported(WifiPpduField field, Ptr<const WifiPpdu> ppdu) const override;
|
||||
uint32_t GetMaxPsduSize() const override;
|
||||
CcaIndication GetCcaIndication(const Ptr<const WifiPpdu> ppdu) override;
|
||||
const std::map<MHz_u, WifiChannelListType>& GetCcaSecondaryChannels() const override;
|
||||
|
||||
/**
|
||||
* End receiving the SIG-A or SIG-B, perform VHT-specific actions, and
|
||||
|
||||
Reference in New Issue
Block a user