wifi: Make HT Operation IE optional in mgt frames

This commit is contained in:
Stefano Avallone
2022-07-12 19:08:44 +02:00
parent 0f95f8b606
commit 2610957d0a
6 changed files with 106 additions and 155 deletions

View File

@@ -669,88 +669,87 @@ HtOperation
ApWifiMac::GetHtOperation (void) const
{
NS_LOG_FUNCTION (this);
NS_ASSERT (GetHtSupported ());
HtOperation operation;
if (GetHtSupported ())
operation.SetPrimaryChannel (GetWifiPhy ()->GetPrimaryChannelNumber (20));
operation.SetRifsMode (false);
operation.SetNonGfHtStasPresent (true);
if (GetWifiPhy ()->GetChannelWidth () > 20)
{
operation.SetHtSupported (1);
operation.SetPrimaryChannel (GetWifiPhy ()->GetPrimaryChannelNumber (20));
operation.SetRifsMode (false);
operation.SetNonGfHtStasPresent (true);
if (GetWifiPhy ()->GetChannelWidth () > 20)
{
operation.SetSecondaryChannelOffset (1);
operation.SetStaChannelWidth (1);
}
if (m_numNonHtStations == 0)
{
operation.SetHtProtection (NO_PROTECTION);
}
else
{
operation.SetHtProtection (MIXED_MODE_PROTECTION);
}
uint64_t maxSupportedRate = 0; //in bit/s
for (const auto & mcs : GetWifiPhy ()->GetMcsList (WIFI_MOD_CLASS_HT))
{
uint8_t nss = (mcs.GetMcsValue () / 8) + 1;
NS_ASSERT (nss > 0 && nss < 5);
uint64_t dataRate = mcs.GetDataRate (GetWifiPhy ()->GetChannelWidth (), GetHtConfiguration ()->GetShortGuardIntervalSupported () ? 400 : 800, nss);
if (dataRate > maxSupportedRate)
{
maxSupportedRate = dataRate;
NS_LOG_DEBUG ("Updating maxSupportedRate to " << maxSupportedRate);
}
}
uint8_t maxSpatialStream = GetWifiPhy ()->GetMaxSupportedTxSpatialStreams ();
auto mcsList = GetWifiPhy ()->GetMcsList (WIFI_MOD_CLASS_HT);
uint8_t nMcs = mcsList.size ();
for (const auto& sta : GetLink (SINGLE_LINK_OP_ID).staList)
{
if (GetWifiRemoteStationManager ()->GetHtSupported (sta.second))
{
uint64_t maxSupportedRateByHtSta = 0; //in bit/s
auto itMcs = mcsList.begin ();
for (uint8_t j = 0; j < (std::min (nMcs, GetWifiRemoteStationManager ()->GetNMcsSupported (sta.second))); j++)
{
WifiMode mcs = *itMcs++;
uint8_t nss = (mcs.GetMcsValue () / 8) + 1;
NS_ASSERT (nss > 0 && nss < 5);
uint64_t dataRate = mcs.GetDataRate (GetWifiRemoteStationManager ()->GetChannelWidthSupported (sta.second),
GetWifiRemoteStationManager ()->GetShortGuardIntervalSupported (sta.second) ? 400 : 800, nss);
if (dataRate > maxSupportedRateByHtSta)
{
maxSupportedRateByHtSta = dataRate;
}
}
if (maxSupportedRateByHtSta < maxSupportedRate)
{
maxSupportedRate = maxSupportedRateByHtSta;
}
if (GetWifiRemoteStationManager ()->GetNMcsSupported (sta.second) < nMcs)
{
nMcs = GetWifiRemoteStationManager ()->GetNMcsSupported (sta.second);
}
if (GetWifiRemoteStationManager ()->GetNumberOfSupportedStreams (sta.second) < maxSpatialStream)
{
maxSpatialStream = GetWifiRemoteStationManager ()->GetNumberOfSupportedStreams (sta.second);
}
}
}
operation.SetRxHighestSupportedDataRate (static_cast<uint16_t> (maxSupportedRate / 1e6)); //in Mbit/s
operation.SetTxMcsSetDefined (nMcs > 0);
operation.SetTxMaxNSpatialStreams (maxSpatialStream);
//To be filled in once supported
operation.SetObssNonHtStasPresent (0);
operation.SetDualBeacon (0);
operation.SetDualCtsProtection (0);
operation.SetStbcBeacon (0);
operation.SetLSigTxopProtectionFullSupport (0);
operation.SetPcoActive (0);
operation.SetPhase (0);
operation.SetRxMcsBitmask (0);
operation.SetTxRxMcsSetUnequal (0);
operation.SetTxUnequalModulation (0);
operation.SetSecondaryChannelOffset (1);
operation.SetStaChannelWidth (1);
}
if (m_numNonHtStations == 0)
{
operation.SetHtProtection (NO_PROTECTION);
}
else
{
operation.SetHtProtection (MIXED_MODE_PROTECTION);
}
uint64_t maxSupportedRate = 0; //in bit/s
for (const auto & mcs : GetWifiPhy ()->GetMcsList (WIFI_MOD_CLASS_HT))
{
uint8_t nss = (mcs.GetMcsValue () / 8) + 1;
NS_ASSERT (nss > 0 && nss < 5);
uint64_t dataRate = mcs.GetDataRate (GetWifiPhy ()->GetChannelWidth (), GetHtConfiguration ()->GetShortGuardIntervalSupported () ? 400 : 800, nss);
if (dataRate > maxSupportedRate)
{
maxSupportedRate = dataRate;
NS_LOG_DEBUG ("Updating maxSupportedRate to " << maxSupportedRate);
}
}
uint8_t maxSpatialStream = GetWifiPhy ()->GetMaxSupportedTxSpatialStreams ();
auto mcsList = GetWifiPhy ()->GetMcsList (WIFI_MOD_CLASS_HT);
uint8_t nMcs = mcsList.size ();
for (const auto& sta : GetLink (SINGLE_LINK_OP_ID).staList)
{
if (GetWifiRemoteStationManager ()->GetHtSupported (sta.second))
{
uint64_t maxSupportedRateByHtSta = 0; //in bit/s
auto itMcs = mcsList.begin ();
for (uint8_t j = 0; j < (std::min (nMcs, GetWifiRemoteStationManager ()->GetNMcsSupported (sta.second))); j++)
{
WifiMode mcs = *itMcs++;
uint8_t nss = (mcs.GetMcsValue () / 8) + 1;
NS_ASSERT (nss > 0 && nss < 5);
uint64_t dataRate = mcs.GetDataRate (GetWifiRemoteStationManager ()->GetChannelWidthSupported (sta.second),
GetWifiRemoteStationManager ()->GetShortGuardIntervalSupported (sta.second) ? 400 : 800, nss);
if (dataRate > maxSupportedRateByHtSta)
{
maxSupportedRateByHtSta = dataRate;
}
}
if (maxSupportedRateByHtSta < maxSupportedRate)
{
maxSupportedRate = maxSupportedRateByHtSta;
}
if (GetWifiRemoteStationManager ()->GetNMcsSupported (sta.second) < nMcs)
{
nMcs = GetWifiRemoteStationManager ()->GetNMcsSupported (sta.second);
}
if (GetWifiRemoteStationManager ()->GetNumberOfSupportedStreams (sta.second) < maxSpatialStream)
{
maxSpatialStream = GetWifiRemoteStationManager ()->GetNumberOfSupportedStreams (sta.second);
}
}
}
operation.SetRxHighestSupportedDataRate (static_cast<uint16_t> (maxSupportedRate / 1e6)); //in Mbit/s
operation.SetTxMcsSetDefined (nMcs > 0);
operation.SetTxMaxNSpatialStreams (maxSpatialStream);
//To be filled in once supported
operation.SetObssNonHtStasPresent (0);
operation.SetDualBeacon (0);
operation.SetDualCtsProtection (0);
operation.SetStbcBeacon (0);
operation.SetLSigTxopProtectionFullSupport (0);
operation.SetPcoActive (0);
operation.SetPhase (0);
operation.SetRxMcsBitmask (0);
operation.SetTxRxMcsSetUnequal (0);
operation.SetTxUnequalModulation (0);
return operation;
}

View File

@@ -48,8 +48,7 @@ HtOperation::HtOperation ()
m_txRxMcsSetUnequal (0),
m_txMaxNSpatialStreams (0),
m_txUnequalModulation (0),
m_reservedMcsSet3 (0),
m_htSupported (0)
m_reservedMcsSet3 (0)
{
for (uint8_t k = 0; k < MAX_SUPPORTED_MCS; k++)
{
@@ -63,17 +62,9 @@ HtOperation::ElementId () const
return IE_HT_OPERATION;
}
void
HtOperation::SetHtSupported (uint8_t htSupported)
{
m_htSupported = htSupported;
}
uint8_t
HtOperation::GetInformationFieldSize () const
{
//we should not be here if HT is not supported
NS_ASSERT (m_htSupported > 0);
return 22;
}
@@ -309,26 +300,6 @@ HtOperation::GetTxUnequalModulation (void) const
return m_txUnequalModulation;
}
Buffer::Iterator
HtOperation::Serialize (Buffer::Iterator i) const
{
if (m_htSupported < 1)
{
return i;
}
return WifiInformationElement::Serialize (i);
}
uint16_t
HtOperation::GetSerializedSize () const
{
if (m_htSupported < 1)
{
return 0;
}
return WifiInformationElement::GetSerializedSize ();
}
uint8_t
HtOperation::GetInformationSubset1 (void) const
{
@@ -458,16 +429,13 @@ HtOperation::GetBasicMcsSet2 (void) const
void
HtOperation::SerializeInformationField (Buffer::Iterator start) const
{
if (m_htSupported == 1)
{
//write the corresponding value for each bit
start.WriteU8 (GetPrimaryChannel ());
start.WriteU8 (GetInformationSubset1 ());
start.WriteU16 (GetInformationSubset2 ());
start.WriteU16 (GetInformationSubset3 ());
start.WriteHtolsbU64 (GetBasicMcsSet1 ());
start.WriteHtolsbU64 (GetBasicMcsSet2 ());
}
//write the corresponding value for each bit
start.WriteU8 (GetPrimaryChannel ());
start.WriteU8 (GetInformationSubset1 ());
start.WriteU16 (GetInformationSubset2 ());
start.WriteU16 (GetInformationSubset3 ());
start.WriteHtolsbU64 (GetBasicMcsSet1 ());
start.WriteHtolsbU64 (GetBasicMcsSet2 ());
}
uint8_t

View File

@@ -58,19 +58,6 @@ public:
void SerializeInformationField (Buffer::Iterator start) const override;
uint8_t DeserializeInformationField (Buffer::Iterator start,
uint8_t length) override;
/* This information element is a bit special in that it is only
included if the STA is an HT STA. To support this we
override the Serialize and GetSerializedSize methods of
WifiInformationElement. */
Buffer::Iterator Serialize (Buffer::Iterator start) const override;
uint16_t GetSerializedSize () const override;
/**
* Set the HT Supported.
*
* \param htSupported the HT Supported flag
*/
void SetHtSupported (uint8_t htSupported);
/**
* Set the Primary Channel field in the HT Operation information element.
@@ -404,9 +391,6 @@ private:
uint8_t m_txUnequalModulation; ///< transmit unequal modulation
uint32_t m_reservedMcsSet3; ///< reserved MCS set 3
uint8_t m_rxMcsBitmask[MAX_SUPPORTED_MCS]; ///< receive MCS bitmask
/// This is used to decide whether this element should be added to the frame or not
uint8_t m_htSupported;
};
/**

View File

@@ -340,7 +340,7 @@ MgtProbeResponseHeader::SetHtOperation (HtOperation&& htOperation)
m_htOperation = std::move (htOperation);
}
const HtOperation&
const std::optional<HtOperation>&
MgtProbeResponseHeader::GetHtOperation (void) const
{
return m_htOperation;
@@ -594,7 +594,7 @@ MgtProbeResponseHeader::GetSerializedSize (void) const
size += m_edcaParameterSet.GetSerializedSize ();
size += m_extendedCapability.GetSerializedSize ();
if (m_htCapability.has_value ()) size += m_htCapability->GetSerializedSize ();
size += m_htOperation.GetSerializedSize ();
if (m_htOperation.has_value ()) size += m_htOperation->GetSerializedSize ();
if (m_vhtCapability.has_value ()) size += m_vhtCapability->GetSerializedSize ();
size += m_vhtOperation.GetSerializedSize ();
if (m_heCapability.has_value ()) size += m_heCapability->GetSerializedSize ();
@@ -614,7 +614,7 @@ MgtProbeResponseHeader::Print (std::ostream &os) const
<< "ERP information=" << m_erpInformation << ", "
<< "Extended Capabilities=" << m_extendedCapability << " , ";
if (m_htCapability.has_value ()) os << "HT Capabilities=" << *m_htCapability << " , ";
os << "HT Operation=" << m_htOperation << " , ";
if (m_htOperation.has_value ()) os << "HT Operation=" << *m_htOperation << " , ";
if (m_vhtCapability.has_value ()) os << "VHT Capabilities=" << *m_vhtCapability << " , ";
os << "VHT Operation=" << m_vhtOperation << " , ";
if (m_heCapability.has_value ()) os << "HE Capabilities=" << *m_heCapability << " , ";
@@ -637,7 +637,7 @@ MgtProbeResponseHeader::Serialize (Buffer::Iterator start) const
i = m_edcaParameterSet.Serialize (i);
i = m_extendedCapability.Serialize (i);
if (m_htCapability.has_value ()) i = m_htCapability->Serialize (i);
i = m_htOperation.Serialize (i);
if (m_htOperation.has_value ()) i = m_htOperation->Serialize (i);
if (m_vhtCapability.has_value ()) i = m_vhtCapability->Serialize (i);
i = m_vhtOperation.Serialize (i);
if (m_heCapability.has_value ()) i = m_heCapability->Serialize (i);
@@ -664,7 +664,7 @@ MgtProbeResponseHeader::Deserialize (Buffer::Iterator start)
i = m_edcaParameterSet.DeserializeIfPresent (i);
i = m_extendedCapability.DeserializeIfPresent (i);
i = WifiInformationElement::DeserializeIfPresent (m_htCapability, i);
i = m_htOperation.DeserializeIfPresent (i);
i = WifiInformationElement::DeserializeIfPresent (m_htOperation, i);
i = WifiInformationElement::DeserializeIfPresent (m_vhtCapability, i);
i = m_vhtOperation.DeserializeIfPresent (i);
i = WifiInformationElement::DeserializeIfPresent (m_heCapability, i);
@@ -1356,7 +1356,7 @@ MgtAssocResponseHeader::SetHtOperation (HtOperation&& htOperation)
m_htOperation = std::move (htOperation);
}
const HtOperation&
const std::optional<HtOperation>&
MgtAssocResponseHeader::GetHtOperation (void) const
{
return m_htOperation;
@@ -1560,7 +1560,7 @@ MgtAssocResponseHeader::GetSerializedSize (void) const
size += m_edcaParameterSet.GetSerializedSize ();
size += m_extendedCapability.GetSerializedSize ();
if (m_htCapability.has_value ()) size += m_htCapability->GetSerializedSize ();
size += m_htOperation.GetSerializedSize ();
if (m_htOperation.has_value ()) size += m_htOperation->GetSerializedSize ();
if (m_vhtCapability.has_value ()) size += m_vhtCapability->GetSerializedSize ();
size += m_vhtOperation.GetSerializedSize ();
if (m_heCapability.has_value ()) size += m_heCapability->GetSerializedSize ();
@@ -1580,7 +1580,7 @@ MgtAssocResponseHeader::Print (std::ostream &os) const
<< "ERP information=" << m_erpInformation << ", "
<< "Extended Capabilities=" << m_extendedCapability << " , ";
if (m_htCapability.has_value ()) os << "HT Capabilities=" << *m_htCapability << " , ";
os << "HT Operation=" << m_htOperation << " , ";
if (m_htOperation.has_value ()) os << "HT Operation=" << *m_htOperation << " , ";
if (m_vhtCapability.has_value ()) os << "VHT Capabilities=" << *m_vhtCapability << " , ";
os << "VHT Operation=" << m_vhtOperation << " , ";
if (m_heCapability.has_value ()) os << "HE Capabilities=" << *m_heCapability << " , ";
@@ -1601,7 +1601,7 @@ MgtAssocResponseHeader::Serialize (Buffer::Iterator start) const
i = m_edcaParameterSet.Serialize (i);
i = m_extendedCapability.Serialize (i);
if (m_htCapability.has_value ()) i = m_htCapability->Serialize (i);
i = m_htOperation.Serialize (i);
if (m_htOperation.has_value ()) i = m_htOperation->Serialize (i);
if (m_vhtCapability.has_value ()) i = m_vhtCapability->Serialize (i);
i = m_vhtOperation.Serialize (i);
if (m_heCapability.has_value ()) i = m_heCapability->Serialize (i);
@@ -1624,7 +1624,7 @@ MgtAssocResponseHeader::Deserialize (Buffer::Iterator start)
i = m_edcaParameterSet.DeserializeIfPresent (i);
i = m_extendedCapability.DeserializeIfPresent (i);
i = WifiInformationElement::DeserializeIfPresent (m_htCapability, i);
i = m_htOperation.DeserializeIfPresent (i);
i = WifiInformationElement::DeserializeIfPresent (m_htOperation, i);
i = WifiInformationElement::DeserializeIfPresent (m_vhtCapability, i);
i = m_vhtOperation.DeserializeIfPresent (i);
i = WifiInformationElement::DeserializeIfPresent (m_heCapability, i);

View File

@@ -478,11 +478,11 @@ public:
*/
const std::optional<HtCapabilities>& GetHtCapabilities (void) const;
/**
* Return the HT operation.
* Return the HT operation, if present.
*
* \return HT operation
* \return HT operation, if present
*/
const HtOperation& GetHtOperation (void) const;
const std::optional<HtOperation>& GetHtOperation (void) const;
/**
* Return the VHT capabilities, if present.
*
@@ -715,7 +715,7 @@ private:
uint16_t m_aid; //!< AID
ExtendedCapabilities m_extendedCapability; //!< extended capabilities
std::optional<HtCapabilities> m_htCapability; //!< HT capabilities
HtOperation m_htOperation; //!< HT operation
std::optional<HtOperation> m_htOperation; //!< HT operation
std::optional<VhtCapabilities> m_vhtCapability; //!< VHT capabilities
VhtOperation m_vhtOperation; //!< VHT operation
ErpInformation m_erpInformation; //!< ERP information
@@ -932,11 +932,11 @@ public:
*/
const std::optional<HtCapabilities>& GetHtCapabilities (void) const;
/**
* Return the HT operation.
* Return the HT operation, if present.
*
* \return HT operation
* \return HT operation, if present
*/
const HtOperation& GetHtOperation (void) const;
const std::optional<HtOperation>& GetHtOperation (void) const;
/**
* Return the VHT capabilities, if present.
*
@@ -1197,7 +1197,7 @@ private:
DsssParameterSet m_dsssParameterSet; //!< DSSS Parameter Set
ExtendedCapabilities m_extendedCapability; //!< extended capabilities
std::optional<HtCapabilities> m_htCapability; //!< HT capabilities
HtOperation m_htOperation; //!< HT operation
std::optional<HtOperation> m_htOperation; //!< HT operation
std::optional<VhtCapabilities> m_vhtCapability; //!< VHT capabilities
VhtOperation m_vhtOperation; //!< VHT operation
std::optional<HeCapabilities> m_heCapability; //!< HE capabilities

View File

@@ -1715,8 +1715,8 @@ Bug2831TestCase::RxCallback (std::string context, Ptr<const Packet> p, RxPowerWa
{
MgtBeaconHeader beacon;
packet->RemoveHeader (beacon);
HtOperation htOperation = beacon.GetHtOperation ();
if (htOperation.GetStaChannelWidth () > 0)
const auto& htOperation = beacon.GetHtOperation ();
if (htOperation.has_value () && htOperation->GetStaChannelWidth () > 0)
{
m_countOperationalChannelWidth40++;
}