diff --git a/src/wifi/CMakeLists.txt b/src/wifi/CMakeLists.txt index c00f5cd70..592155c34 100644 --- a/src/wifi/CMakeLists.txt +++ b/src/wifi/CMakeLists.txt @@ -29,6 +29,7 @@ set(source_files model/eht/eht-configuration.cc model/eht/eht-frame-exchange-manager.cc model/eht/eht-operation.cc + model/eht/tid-to-link-mapping-element.cc model/eht/eht-phy.cc model/eht/eht-ppdu.cc model/eht/multi-link-element.cc @@ -177,6 +178,7 @@ set(header_files model/eht/eht-configuration.h model/eht/eht-frame-exchange-manager.h model/eht/eht-operation.h + model/eht/tid-to-link-mapping-element.h model/eht/eht-phy.h model/eht/eht-ppdu.h model/eht/multi-link-element.h diff --git a/src/wifi/model/eht/tid-to-link-mapping-element.cc b/src/wifi/model/eht/tid-to-link-mapping-element.cc new file mode 100644 index 000000000..9a8feb6ab --- /dev/null +++ b/src/wifi/model/eht/tid-to-link-mapping-element.cc @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2022 + * + * 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: Sharan Naribole + */ + +#include +#include + +namespace ns3 +{ + +uint16_t +TidToLinkMapping::Control::GetSubfieldSize() const +{ + // IEEE 802.11be D2.0 Figure 9-1002an + NS_ASSERT_MSG(defaultMapping != presenceBitmap.has_value(), + "Presence bitmap not expected if default mapping is set"); + auto size = WIFI_TID_TO_LINK_MAPPING_CONTROL_BASIC_SIZE_B; + if (defaultMapping) + { + return size; + } + return size + WIFI_LINK_MAPPING_PRESENCE_IND_SIZE_B; +} + +void +TidToLinkMapping::Control::Serialize(Buffer::Iterator& start) const +{ + uint8_t val = static_cast(direction); + val |= ((defaultMapping ? 1 : 0) << 2); + start.WriteU8(val); + NS_ASSERT_MSG(defaultMapping != presenceBitmap.has_value(), + "Presence bitmap not expected if default mapping is set"); + if (presenceBitmap.has_value()) + { + start.WriteU8(presenceBitmap.value()); + } +} + +uint16_t +TidToLinkMapping::Control::Deserialize(Buffer::Iterator start) +{ + auto i = start; + uint8_t count = 0; + auto val = i.ReadU8(); + count++; + + direction = static_cast(val & 0x03); + defaultMapping = (((val >> 2) & 0x01) == 1); + if (defaultMapping) + { + return count; + } + presenceBitmap = i.ReadU8(); + return ++count; +} + +WifiInformationElementId +TidToLinkMapping::ElementId() const +{ + return IE_EXTENSION; +} + +WifiInformationElementId +TidToLinkMapping::ElementIdExt() const +{ + return IE_EXT_TID_TO_LINK_MAPPING_ELEMENT; +} + +void +TidToLinkMapping::SetLinkMappingOfTid(uint8_t tid, std::list linkIds) +{ + NS_ABORT_MSG_IF(tid > 7, "Invalid tid: " << +tid); + NS_ABORT_MSG_IF(m_control.defaultMapping, + "Per-TID link mapping not expected if default mapping is set"); + + // derive link mapping for the given TID + uint16_t linkMapping = 0; + + for (const auto& linkId : linkIds) + { + linkMapping |= (1 << linkId); + } + + m_linkMapping[tid] = linkMapping; + + if (!m_control.presenceBitmap.has_value()) + { + m_control.presenceBitmap = 0; + } + *m_control.presenceBitmap |= (1 << tid); +} + +std::list +TidToLinkMapping::GetLinkMappingOfTid(uint8_t tid) const +{ + auto it = m_linkMapping.find(tid); + + if (it == m_linkMapping.end()) + { + return {}; + } + + std::list linkIds; + for (uint8_t linkId = 0; linkId < 15; linkId++) + { + if (((it->second >> linkId) & 0x0001) == 1) + { + linkIds.push_back(linkId); + } + } + + return linkIds; +} + +uint16_t +TidToLinkMapping::GetInformationFieldSize() const +{ + // IEEE 802.11be D2.0 9.4.2.314 TID-To-Link Mapping element + uint16_t ret = WIFI_IE_ELEMENT_ID_EXT_SIZE; // Element ID Extension + ret += m_control.GetSubfieldSize(); + NS_ASSERT_MSG(m_linkMapping.empty() == m_control.defaultMapping, + "Per-TID link mapping not expected if default mapping is set"); + ret += WIFI_LINK_MAPPING_PER_TID_SIZE_B * (m_linkMapping.size()); + return ret; +} + +void +TidToLinkMapping::SerializeInformationField(Buffer::Iterator start) const +{ + // IEEE 802.11be D2.0 9.4.2.314 TID-To-Link Mapping element + m_control.Serialize(start); + NS_ASSERT_MSG(m_linkMapping.empty() == m_control.defaultMapping, + "Per-TID link mapping not expected if default mapping is set"); + + for (const auto& [tid, linkMapping] : m_linkMapping) + { + start.WriteHtolsbU16(linkMapping); + } +} + +uint16_t +TidToLinkMapping::DeserializeInformationField(Buffer::Iterator start, uint16_t length) +{ + auto i = start; + uint16_t count = 0; + auto nCtrlOctets = m_control.Deserialize(i); + NS_ASSERT_MSG(nCtrlOctets <= length, "Tid-to-Link Mapping deserialize error"); + i.Next(nCtrlOctets); + count += nCtrlOctets; + m_linkMapping.clear(); + if (m_control.presenceBitmap.has_value()) + { + NS_ABORT_MSG_IF(m_control.defaultMapping, + "Default mapping should not be set when presence bitmap is present"); + const auto presenceBitmap = m_control.presenceBitmap.value(); + for (uint8_t tid = 0; tid < 8; tid++) + { + if (((presenceBitmap >> tid) & 0x01) == 1) + { + m_linkMapping[tid] = i.ReadLsbtohU16(); + count += 2; + } + } + } + + NS_ABORT_MSG_IF(count != length, + "TID-to-Link Mapping Length (" << +length + << ") differs " + "from actual number of bytes read (" + << +count << ")"); + return count; +} + +} // namespace ns3 diff --git a/src/wifi/model/eht/tid-to-link-mapping-element.h b/src/wifi/model/eht/tid-to-link-mapping-element.h new file mode 100644 index 000000000..3a34cb893 --- /dev/null +++ b/src/wifi/model/eht/tid-to-link-mapping-element.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2022 + * + * 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: Sharan Naribole + */ + +#ifndef TID_TO_LINK_MAPPING_H +#define TID_TO_LINK_MAPPING_H + +#include + +#include +#include +#include +#include + +namespace ns3 +{ + +/** + * TID-to-Link Mapping Control Direction + * IEEE 802.11be D2.0 Figure 9-1002an + */ +enum class TidLinkMapDir : uint8_t +{ + DOWNLINK = 0, + UPLINK = 1, + BOTH_DIRECTIONS = 2, +}; + +/// whether to enforce the default link mapping +constexpr auto DEFAULT_WIFI_TID_LINK_MAPPING{true}; +/// default value for the Direction subfield of the TID-To-Link Control field +constexpr auto DEFAULT_WIFI_TID_LINK_MAP_DIR{TidLinkMapDir::BOTH_DIRECTIONS}; +/// size in bytes of the Link Mapping Of TID n field (IEEE 802.11be D2.0 9.4.2.314) +constexpr uint16_t WIFI_LINK_MAPPING_PER_TID_SIZE_B = 2; +/// size in bytes of the TID-To-Link Control field with default link mapping +constexpr uint16_t WIFI_TID_TO_LINK_MAPPING_CONTROL_BASIC_SIZE_B = + 1; // IEEE 802.11be D2.0 9.4.2.314 +/// size in bytes of the Link Mapping Presence Indicator field (IEEE 802.11be D2.0 9.4.2.314) +constexpr uint16_t WIFI_LINK_MAPPING_PRESENCE_IND_SIZE_B = 1; + +/** + * \brief TID-to-Link Mapping Information Element + * \ingroup wifi + * + * This class serializes and deserializes + * the TID-to-Link Mapping element + * IEEE 802.11be D2.0 9.4.2.314 + * + */ +class TidToLinkMapping : public WifiInformationElement +{ + public: + /** + * TID-to-Link Mapping Control subfield + * IEEE 802.11be D2.0 Figure 9-1002an + */ + struct Control + { + TidLinkMapDir direction{DEFAULT_WIFI_TID_LINK_MAP_DIR}; ///< Direction + bool defaultMapping{DEFAULT_WIFI_TID_LINK_MAPPING}; ///< Default link mapping + std::optional presenceBitmap; ///< Link Mapping Presence Indicator + + /// \return Serialized size of TID-to-Link Mapping Control in octets + uint16_t GetSubfieldSize() const; + + /** + * Serialize the TID-to-Link Mapping Control subfield + * + * \param start iterator pointing to where the subfield should be written to + */ + void Serialize(Buffer::Iterator& start) const; + /** + * Deserialize the TID-to-Link Mapping Control subfield + * + * \param start iterator pointing to where the subfield should be read from + * \return the number of octets read + */ + uint16_t Deserialize(Buffer::Iterator start); + }; + + WifiInformationElementId ElementId() const override; + WifiInformationElementId ElementIdExt() const override; + + /** + * Set the Link Mapping field of the given TID such that the given TID is mapped + * to the links associated with the given link IDs. + * + * \param tid the given TID + * \param linkIds the IDs of the links which the given TID is mapped to + */ + void SetLinkMappingOfTid(uint8_t tid, std::list linkIds); + /** + * Get the Link Mapping field of the given TID. + * + * \param tid the given TID + * \return the IDs of the links which the given TID is mapped to + */ + std::list GetLinkMappingOfTid(uint8_t tid) const; + + TidToLinkMapping::Control m_control; ///< TID-to-link Mapping Control + std::map m_linkMapping; ///< TID-indexed Link Mapping + + private: + uint16_t GetInformationFieldSize() const override; + void SerializeInformationField(Buffer::Iterator start) const override; + uint16_t DeserializeInformationField(Buffer::Iterator start, uint16_t length) override; +}; + +} // namespace ns3 + +#endif /* TID_TO_LINK_MAPPING_H */ diff --git a/src/wifi/model/wifi-information-element.h b/src/wifi/model/wifi-information-element.h index 7ffd19c37..0ea914db0 100644 --- a/src/wifi/model/wifi-information-element.h +++ b/src/wifi/model/wifi-information-element.h @@ -236,6 +236,7 @@ typedef uint8_t WifiInformationElementId; #define IE_EXT_EHT_OPERATION ((WifiInformationElementId)106) #define IE_EXT_MULTI_LINK_ELEMENT ((WifiInformationElementId)107) #define IE_EXT_EHT_CAPABILITIES ((WifiInformationElementId)108) +#define IE_EXT_TID_TO_LINK_MAPPING_ELEMENT ((WifiInformationElementId)109) /** * \brief Information element, as defined in 802.11-2007 standard