From e4b7d7c4cceb7391e8ef82281f2c2c1eb5cee1f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deronne?= Date: Sat, 25 Nov 2017 16:19:45 +0100 Subject: [PATCH] wifi: Introduce HeOperation in 802.11ax management frames --- src/wifi/model/ap-wifi-mac.cc | 18 +++ src/wifi/model/ap-wifi-mac.h | 7 +- src/wifi/model/he-operation.cc | 187 ++++++++++++++++++++++ src/wifi/model/he-operation.h | 149 +++++++++++++++++ src/wifi/model/mgt-headers.cc | 36 ++++- src/wifi/model/mgt-headers.h | 29 +++- src/wifi/model/sta-wifi-mac.cc | 2 + src/wifi/model/wifi-information-element.h | 1 + src/wifi/wscript | 2 + 9 files changed, 427 insertions(+), 4 deletions(-) create mode 100644 src/wifi/model/he-operation.cc create mode 100644 src/wifi/model/he-operation.h diff --git a/src/wifi/model/ap-wifi-mac.cc b/src/wifi/model/ap-wifi-mac.cc index 21a05bd58..58833f392 100644 --- a/src/wifi/model/ap-wifi-mac.cc +++ b/src/wifi/model/ap-wifi-mac.cc @@ -641,7 +641,22 @@ ApWifiMac::GetVhtOperation (void) const } operation.SetMaxVhtMcsPerNss (nss, maxMcs); } + } + return operation; +} +HeOperation +ApWifiMac::GetHeOperation (void) const +{ + NS_LOG_FUNCTION (this); + HeOperation operation; + if (m_heSupported) + { + operation.SetHeSupported (1); + for (uint8_t nss = 1; nss <= m_phy->GetMaxSupportedRxSpatialStreams (); nss++) + { + operation.SetMaxHeMcsPerNss (nss, 11); //TBD: hardcode to 11 for now since we assume all MCS values are supported + } } return operation; } @@ -691,6 +706,7 @@ ApWifiMac::SendProbeResp (Mac48Address to) if (m_heSupported) { probe.SetHeCapabilities (GetHeCapabilities ()); + probe.SetHeOperation (GetHeOperation ()); } packet->AddHeader (probe); @@ -749,6 +765,7 @@ ApWifiMac::SendAssocResp (Mac48Address to, bool success) if (m_heSupported) { assoc.SetHeCapabilities (GetHeCapabilities ()); + assoc.SetHeOperation (GetHeOperation ()); } packet->AddHeader (assoc); @@ -804,6 +821,7 @@ ApWifiMac::SendOneBeacon (void) if (m_heSupported) { beacon.SetHeCapabilities (GetHeCapabilities ()); + beacon.SetHeOperation (GetHeOperation ()); } packet->AddHeader (beacon); diff --git a/src/wifi/model/ap-wifi-mac.h b/src/wifi/model/ap-wifi-mac.h index a853fb44a..028b9c8d2 100644 --- a/src/wifi/model/ap-wifi-mac.h +++ b/src/wifi/model/ap-wifi-mac.h @@ -25,7 +25,6 @@ #include "regular-wifi-mac.h" #include "capability-information.h" -#include "ht-operation.h" #include "supported-rates.h" #include "dsss-parameter-set.h" #include "erp-information.h" @@ -241,6 +240,12 @@ private: * \return the VHT operation that we support */ VhtOperation GetVhtOperation (void) const; + /** + * Return the HE operation of the current AP. + * + * \return the HE operation that we support + */ + HeOperation GetHeOperation (void) const; /** * Return an instance of SupportedRates that contains all rates that we support * including HT rates. diff --git a/src/wifi/model/he-operation.cc b/src/wifi/model/he-operation.cc new file mode 100644 index 000000000..b6c0bae15 --- /dev/null +++ b/src/wifi/model/he-operation.cc @@ -0,0 +1,187 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 Sébastien Deronne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Sébastien Deronne + */ + +#include "he-operation.h" + +namespace ns3 { + +HeOperation::HeOperation () + : m_bsssColor (0), + m_defaultPEDuration (0), + m_twtRequired (0), + m_heDurationBasedRtsThreshold (0), + m_partialBsssColor (0), + m_maxBssidIndicator (0), + m_txBssidIndicator (0), + m_bsssColorDisabled (0), + m_dualBeacon (0), + m_basicHeMcsAndNssSet (0), + m_heSupported (0) +{ +} + +WifiInformationElementId +HeOperation::ElementId () const +{ + return IE_HE_OPERATION; +} + +void +HeOperation::SetHeSupported (uint8_t hesupported) +{ + m_heSupported = hesupported; +} + +uint8_t +HeOperation::GetInformationFieldSize () const +{ + //we should not be here if he is not supported + NS_ASSERT (m_heSupported > 0); + return 10; +} + +void +HeOperation::SetHeOperationParameters (uint32_t ctrl) +{ + m_bsssColor = ctrl & 0x3f; + m_defaultPEDuration = (ctrl >> 6) & 0x07; + m_twtRequired = (ctrl >> 9) & 0x01; + m_heDurationBasedRtsThreshold = (ctrl >> 10) & 0x03ff; + m_partialBsssColor = (ctrl >> 20) & 0x01; + m_maxBssidIndicator = (ctrl >> 21) & 0xff; + m_txBssidIndicator = (ctrl >> 29) & 0x01; + m_bsssColorDisabled = (ctrl >> 30) & 0x01; + m_dualBeacon = (ctrl >> 31) & 0x01; +} + +uint32_t +HeOperation::GetHeOperationParameters () const +{ + uint32_t val = 0; + val |= m_bsssColor & 0x3f; + val |= (m_defaultPEDuration & 0x07) << 6; + val |= (m_twtRequired & 0x01) << 9; + val |= (m_heDurationBasedRtsThreshold & 0x03ff) << 10; + val |= (m_partialBsssColor & 0x01) << 20; + val |= (m_maxBssidIndicator & 0xff) << 21; + val |= (m_txBssidIndicator & 0x01) << 29; + val |= (m_bsssColorDisabled & 0x01) << 30; + val |= (m_dualBeacon & 0x01) << 31; + return val; +} + +void +HeOperation::SetMaxHeMcsPerNss (uint8_t nss, uint8_t maxHeMcs) +{ + NS_ASSERT ((maxHeMcs >= 7 && maxHeMcs <= 11) && (nss >= 1 && nss <= 8)); + m_basicHeMcsAndNssSet |= (((maxHeMcs - 7) & 0x07) << ((nss - 1) * 3)); +} + +uint32_t +HeOperation::GetBasicHeMcsAndNssSet (void) const +{ + return m_basicHeMcsAndNssSet; +} + +Buffer::Iterator +HeOperation::Serialize (Buffer::Iterator i) const +{ + if (m_heSupported < 1) + { + return i; + } + return WifiInformationElement::Serialize (i); +} + +uint16_t +HeOperation::GetSerializedSize () const +{ + if (m_heSupported < 1) + { + return 0; + } + return WifiInformationElement::GetSerializedSize (); +} + +void +HeOperation::SerializeInformationField (Buffer::Iterator start) const +{ + if (m_heSupported == 1) + { + //write the corresponding value for each bit + start.WriteHtolsbU32 (GetHeOperationParameters ()); + uint32_t mcsset = GetBasicHeMcsAndNssSet (); + start.WriteU16 (mcsset & 0xffff); + start.WriteU8 ((mcsset >> 16) & 0xff); + start.WriteU16 (0); //todo: VHT Operation Information + start.WriteU8 (0); //todo: VHT Operation Information + } +} + +uint8_t +HeOperation::DeserializeInformationField (Buffer::Iterator start, uint8_t length) +{ + Buffer::Iterator i = start; + uint32_t heOperationParameters = i.ReadLsbtohU32 (); + uint16_t mcsset_1 = i.ReadU16 (); + uint8_t mcsset_2 = i.ReadU8 (); + i.ReadU16 (); //todo: VHT Operation Information + i.ReadU8 (); //todo: VHT Operation Information + SetHeOperationParameters (heOperationParameters); + m_basicHeMcsAndNssSet |= mcsset_1 & 0xffff; + m_basicHeMcsAndNssSet |= (mcsset_2 & 0xff) << 16; + return length; +} + +ATTRIBUTE_HELPER_CPP (HeOperation); + +/** + * output stream output operator + * + * \param os output stream + * \param HeOperation the HE operation + * + * \returns output stream + */ +std::ostream & +operator << (std::ostream &os, const HeOperation &HeOperation) +{ + os << HeOperation.GetHeOperationParameters () << "|" + << HeOperation.GetBasicHeMcsAndNssSet (); + return os; +} + +/** + * input stream input operator + * + * \param is input stream + * \param HeOperation the HE operation + * + * \returns input stream + */ +std::istream &operator >> (std::istream &is, HeOperation &HeOperation) +{ + uint32_t c1; + is >> c1; + HeOperation.SetHeOperationParameters (c1); + return is; +} + +} //namespace ns3 diff --git a/src/wifi/model/he-operation.h b/src/wifi/model/he-operation.h new file mode 100644 index 000000000..b422d6801 --- /dev/null +++ b/src/wifi/model/he-operation.h @@ -0,0 +1,149 @@ +/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2017 Sébastien Deronne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Sébastien Deronne + */ + +#ifndef HE_OPERATION_H +#define HE_OPERATION_H + +#include "wifi-information-element.h" + +namespace ns3 { + +/** + * \brief The HE Operation Information Element + * \ingroup wifi + * + * This class knows how to serialise and deserialise + * the HE Operation Information Element + * + * \see attribute_HeOperation + */ +class HeOperation : public WifiInformationElement +{ +public: + HeOperation (); + /** + * Set the HE supported information element. + * + * \param hesupported the HE supported information element + */ + void SetHeSupported (uint8_t hesupported); + + /** + * Set the HE Operation Parameters field in the HE Operation information element. + * + * \param ctrl the HE Operation Parameters field in the HE Operation information element + */ + void SetHeOperationParameters (uint32_t ctrl); + /** + * Set the Basic HE-MCS and NSS field in the HE Operation information element + * by specifying the tuple (nss, maxMcs). + * + * \param nss the NSS + * \param maxHeMcs the maximum supported HE-MCS value corresponding to that NSS + */ + void SetMaxHeMcsPerNss (uint8_t nss, uint8_t maxHeMcs); + + /** + * Return the HE Operation Parameters field in the HE Operation information element. + * + * \return the HE Operation Parameters field in the HE Operation information element + */ + uint32_t GetHeOperationParameters (void) const; + /** + * Return the Basic HE-MCS And Nss field in the HE Operation information element. + * + * \return the Basic HE-MCS And Nss field in the HE Operation information element + */ + uint32_t GetBasicHeMcsAndNssSet (void) const; + + /** + * Return the element ID. + * + * \returns the element ID + */ + WifiInformationElementId ElementId () const; + /** + * Return the information field size. + * + * \returns the information field size + */ + uint8_t GetInformationFieldSize () const; + /** + * Serialize the information field. + * + * \param start the information field iterator + */ + void SerializeInformationField (Buffer::Iterator start) const; + /** + * Deserialize the information field. + * + * \param start the iterator + * \param length the length + * \returns the information field size + */ + uint8_t DeserializeInformationField (Buffer::Iterator start, uint8_t length); + /** + * This information element is a bit special in that it is only + * included if the STA is a HE STA. To support this we + * override the Serialize and GetSerializedSize methods of + * WifiInformationElement. + * + * \param start + * + * \return an iterator + */ + Buffer::Iterator Serialize (Buffer::Iterator start) const; + /** + * Return the serialized size of this HE Operations IE. + * + * \return the serialized size of this HE Operations IE + */ + uint16_t GetSerializedSize () const; + + +private: + //HE Operation Parameters fields + uint8_t m_bsssColor; //!< BSS color + uint8_t m_defaultPEDuration; //!< default PE duration + uint8_t m_twtRequired; //!< TWT required + uint16_t m_heDurationBasedRtsThreshold; //!< HE duration based RTS threshold + uint8_t m_partialBsssColor; //!< partial BSS color + uint8_t m_maxBssidIndicator; //!< max BSSID indicator + uint8_t m_txBssidIndicator; //!< TX BSSID indicator + uint8_t m_bsssColorDisabled; //!< BSS color disabled + uint8_t m_dualBeacon; //!< BSS color disabled + + //Basic HE-MCS and NSS Set + uint32_t m_basicHeMcsAndNssSet; ///< basic HE MCS NSS set + + //TODO: VHT Operation Information subfields not defined in the standard yet. + + /// This is used to decide whether this element should be added to the frame or not + uint8_t m_heSupported; +}; + +std::ostream &operator << (std::ostream &os, const HeOperation &HeOperation); +std::istream &operator >> (std::istream &is, HeOperation &HeOperation); + +ATTRIBUTE_HELPER_HEADER (HeOperation); + +} //namespace ns3 + +#endif /* HE_OPERATION_H */ diff --git a/src/wifi/model/mgt-headers.cc b/src/wifi/model/mgt-headers.cc index 1c8517197..00a3ba366 100644 --- a/src/wifi/model/mgt-headers.cc +++ b/src/wifi/model/mgt-headers.cc @@ -271,6 +271,18 @@ MgtProbeResponseHeader::GetHeCapabilities (void) const return m_heCapability; } +void +MgtProbeResponseHeader::SetHeOperation (HeOperation heoperation) +{ + m_heOperation = heoperation; +} + +HeOperation +MgtProbeResponseHeader::GetHeOperation (void) const +{ + return m_heOperation; +} + void MgtProbeResponseHeader::SetSsid (Ssid ssid) { @@ -360,6 +372,7 @@ MgtProbeResponseHeader::GetSerializedSize (void) const size += m_vhtCapability.GetSerializedSize (); size += m_vhtOperation.GetSerializedSize (); size += m_heCapability.GetSerializedSize (); + size += m_heOperation.GetSerializedSize (); return size; } @@ -373,7 +386,8 @@ MgtProbeResponseHeader::Print (std::ostream &os) const << "HT Operation=" << m_htOperation << " , " << "VHT Capabilities=" << m_vhtCapability << " , " << "VHT Operation=" << m_vhtOperation << " , " - << "HE Capabilities=" << m_heCapability; + << "HE Capabilities=" << m_heCapability << " , " + << "HE Operation=" << m_heOperation; } void @@ -403,6 +417,7 @@ MgtProbeResponseHeader::Serialize (Buffer::Iterator start) const i = m_vhtCapability.Serialize (i); i = m_vhtOperation.Serialize (i); i = m_heCapability.Serialize (i); + i = m_heOperation.Serialize (i); } uint32_t @@ -424,6 +439,7 @@ MgtProbeResponseHeader::Deserialize (Buffer::Iterator start) i = m_vhtCapability.DeserializeIfPresent (i); i = m_vhtOperation.DeserializeIfPresent (i); i = m_heCapability.DeserializeIfPresent (i); + i = m_heOperation.DeserializeIfPresent (i); return i.GetDistanceFrom (start); } @@ -729,6 +745,18 @@ MgtAssocResponseHeader::GetHeCapabilities (void) const return m_heCapability; } +void +MgtAssocResponseHeader::SetHeOperation (HeOperation heoperation) +{ + m_heOperation = heoperation; +} + +HeOperation +MgtAssocResponseHeader::GetHeOperation (void) const +{ + return m_heOperation; +} + void MgtAssocResponseHeader::SetErpInformation (ErpInformation erpInformation) { @@ -786,6 +814,7 @@ MgtAssocResponseHeader::GetSerializedSize (void) const size += m_vhtCapability.GetSerializedSize (); size += m_vhtOperation.GetSerializedSize (); size += m_heCapability.GetSerializedSize (); + size += m_heOperation.GetSerializedSize (); return size; } @@ -799,7 +828,8 @@ MgtAssocResponseHeader::Print (std::ostream &os) const << "HT Operation=" << m_htOperation << " , " << "VHT Capabilities=" << m_vhtCapability << " , " << "VHT Operation=" << m_vhtOperation << " , " - << "HE Capabilities=" << m_heCapability; + << "HE Capabilities=" << m_heCapability << " , " + << "HE Operation=" << m_heOperation; } void @@ -818,6 +848,7 @@ MgtAssocResponseHeader::Serialize (Buffer::Iterator start) const i = m_vhtCapability.Serialize (i); i = m_vhtOperation.Serialize (i); i = m_heCapability.Serialize (i); + i = m_heOperation.Serialize (i); } uint32_t @@ -836,6 +867,7 @@ MgtAssocResponseHeader::Deserialize (Buffer::Iterator start) i = m_vhtCapability.DeserializeIfPresent (i); i = m_vhtOperation.DeserializeIfPresent (i); i = m_heCapability.DeserializeIfPresent (i); + i = m_heOperation.DeserializeIfPresent (i); return i.GetDistanceFrom (start); } diff --git a/src/wifi/model/mgt-headers.h b/src/wifi/model/mgt-headers.h index 6a247f574..79829067a 100644 --- a/src/wifi/model/mgt-headers.h +++ b/src/wifi/model/mgt-headers.h @@ -35,6 +35,7 @@ #include "erp-information.h" #include "edca-parameter-set.h" #include "he-capabilities.h" +#include "he-operation.h" namespace ns3 { @@ -214,6 +215,12 @@ public: * \return HE capabilities */ HeCapabilities GetHeCapabilities (void) const; + /** + * Return the HE operation. + * + * \return HE operation + */ + HeOperation GetHeOperation (void) const; /** * Return the ERP information. * @@ -286,6 +293,12 @@ public: * \param hecapabilities HE capabilities */ void SetHeCapabilities (HeCapabilities hecapabilities); + /** + * Set the HE operation. + * + * \param heoperation HE operation + */ + void SetHeOperation (HeOperation heoperation); /** * Register this type. @@ -311,6 +324,7 @@ private: ErpInformation m_erpInformation; //!< ERP information EdcaParameterSet m_edcaParameterSet; //!< EDCA Parameter Set HeCapabilities m_heCapability; //!< HE capabilities + HeOperation m_heOperation; //!< HE operation }; @@ -475,6 +489,12 @@ public: * \return HE capabilities */ HeCapabilities GetHeCapabilities (void) const; + /** + * Return the HE operation. + * + * \return HE operation + */ + HeOperation GetHeOperation (void) const; /** * Return the ERP information. * @@ -523,6 +543,12 @@ public: * \param hecapabilities HE capabilities */ void SetHeCapabilities (HeCapabilities hecapabilities); + /** + * Set the HE operation. + * + * \param heoperation HE operation + */ + void SetHeOperation (HeOperation heoperation); /** * Set the Service Set Identifier (SSID). * @@ -589,7 +615,8 @@ private: HtOperation m_htOperation; //!< HT operation VhtCapabilities m_vhtCapability; //!< VHT capabilities VhtOperation m_vhtOperation; //!< VHT operation - HeCapabilities m_heCapability; //!< HE capabilities + HeCapabilities m_heCapability; //!< HE capabilities + HeOperation m_heOperation; //!< HE operation ErpInformation m_erpInformation; //!< ERP information EdcaParameterSet m_edcaParameterSet; //!< EDCA Parameter Set }; diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index 48b4c19e0..fb838e4f5 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -590,6 +590,7 @@ StaWifiMac::Receive (Ptr packet, const WifiMacHeader *hdr) HeCapabilities heCapabilities = beacon.GetHeCapabilities (); //todo: once we support non constant rate managers, we should add checks here whether HE is supported by the peer m_stationManager->AddStationHeCapabilities (hdr->GetAddr2 (), heCapabilities); + HeOperation heOperation = beacon.GetHeOperation (); for (uint32_t i = 0; i < m_phy->GetNMcs (); i++) { WifiMode mcs = m_phy->GetMcs (i); @@ -806,6 +807,7 @@ StaWifiMac::Receive (Ptr packet, const WifiMacHeader *hdr) HeCapabilities hecapabilities = assocResp.GetHeCapabilities (); //todo: once we support non constant rate managers, we should add checks here whether HE is supported by the peer m_stationManager->AddStationHeCapabilities (hdr->GetAddr2 (), hecapabilities); + HeOperation heOperation = assocResp.GetHeOperation (); } for (uint32_t i = 0; i < m_phy->GetNModes (); i++) { diff --git a/src/wifi/model/wifi-information-element.h b/src/wifi/model/wifi-information-element.h index d370c2dc2..10e6e2a12 100644 --- a/src/wifi/model/wifi-information-element.h +++ b/src/wifi/model/wifi-information-element.h @@ -187,6 +187,7 @@ typedef uint8_t WifiInformationElementId; #define IE_VENDOR_SPECIFIC ((WifiInformationElementId)221) // 222 to 255 are reserved #define IE_HE_CAPABILITIES ((WifiInformationElementId)255) //todo: not defined yet in the standard! +#define IE_HE_OPERATION ((WifiInformationElementId)255) //todo: not defined yet in the standard! /** diff --git a/src/wifi/wscript b/src/wifi/wscript index 0fd62d1b0..eb5436d11 100644 --- a/src/wifi/wscript +++ b/src/wifi/wscript @@ -85,6 +85,7 @@ def build(bld): 'model/he-capabilities.cc', 'model/frame-capture-model.cc', 'model/simple-frame-capture-model.cc', + 'model/he-operation.cc', 'helper/wifi-radio-energy-model-helper.cc', 'helper/vht-wifi-mac-helper.cc', 'helper/ht-wifi-mac-helper.cc', @@ -196,6 +197,7 @@ def build(bld): 'model/frame-capture-model.h', 'model/simple-frame-capture-model.h', 'model/qos-blocked-destinations.h', + 'model/he-operation.h', 'helper/wifi-radio-energy-model-helper.h', 'helper/vht-wifi-mac-helper.h', 'helper/ht-wifi-mac-helper.h',