diff --git a/CHANGES.md b/CHANGES.md index ab6535100..4ecb3b5de 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ This file is a best-effort approach to solving this issue; we will do our best b ### Changes to existing API * (lr-wpan) Debloat MAC PD-DATA.indication and reduce packet copies. +* (zigbee) Added group table ### Changes to build system diff --git a/src/zigbee/CMakeLists.txt b/src/zigbee/CMakeLists.txt index 860966ff1..8f1f588b3 100644 --- a/src/zigbee/CMakeLists.txt +++ b/src/zigbee/CMakeLists.txt @@ -6,6 +6,7 @@ build_lib( model/zigbee-aps-header.cc model/zigbee-aps-tables.cc model/zigbee-aps.cc + model/zigbee-group-table.cc model/zigbee-nwk-fields.cc model/zigbee-nwk.cc model/zigbee-stack.cc @@ -18,6 +19,7 @@ build_lib( model/zigbee-aps-header.h model/zigbee-aps-tables.h model/zigbee-aps.h + model/zigbee-group-table.h model/zigbee-nwk-fields.h model/zigbee-nwk.h model/zigbee-stack.h diff --git a/src/zigbee/model/zigbee-group-table.cc b/src/zigbee/model/zigbee-group-table.cc new file mode 100644 index 000000000..f30210cbc --- /dev/null +++ b/src/zigbee/model/zigbee-group-table.cc @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2025 Tokushima University, Japan + * + * SPDX-License-Identifier: GPL-2.0-only + * + * Author: + * Alberto Gallegos Ramonet + */ + +#include "zigbee-group-table.h" + +#include "ns3/log.h" + +namespace ns3 +{ +namespace zigbee +{ + +NS_LOG_COMPONENT_DEFINE("ZigbeeGroupTable"); + +ZigbeeGroupTable::ZigbeeGroupTable() = default; + +ZigbeeGroupTable::~ZigbeeGroupTable() = default; + +bool +ZigbeeGroupTable::AddEntry(uint16_t groupId, uint8_t endPoint) +{ + NS_LOG_FUNCTION(this << groupId << static_cast(endPoint)); + + if (m_groupTable.size() == MAX_GROUP_ID_ENTRIES) + { + NS_LOG_WARN("Group table is full, cannot add group ID " << groupId); + return false; // too many groups + } + + // Check the group entry existence, if it does not exist, create it. + auto& group = m_groupTable[groupId]; + if (group[endPoint]) + { + NS_LOG_INFO("Endpoint " << static_cast(endPoint) << " already exists in group " + << groupId); + return false; // endPoint already in group + } + + NS_LOG_INFO("Adding endpoint " << static_cast(endPoint) << " to group " << groupId); + group.set(endPoint); + return true; +} + +bool +ZigbeeGroupTable::RemoveEntry(uint16_t groupId, uint8_t endPoint) +{ + NS_LOG_FUNCTION(this << groupId << static_cast(endPoint)); + + auto group = m_groupTable.find(groupId); + auto endPoints = group->second; + + if (group == m_groupTable.end()) + { + NS_LOG_WARN("Group ID " << groupId << " does not exist, cannot remove endpoint " + << static_cast(endPoint)); + return false; // group doesn't exist + } + + if (!endPoints[endPoint]) + { + NS_LOG_WARN("Endpoint " << static_cast(endPoint) << " not found in group " + << groupId); + return false; // endpoint not in this group + } + else + { + endPoints.reset(endPoint); // Turn bit in bitset off (0) + NS_LOG_INFO("Removed endpoint " << static_cast(endPoint) << " from group " + << groupId); + + if (endPoints.none()) + { + m_groupTable.erase(group); // remove group if no endpoints left + } + return true; // endpoint removed successfully + } +} + +bool +ZigbeeGroupTable::RemoveMembership(uint8_t endPoint) +{ + NS_LOG_FUNCTION(this << static_cast(endPoint)); + + bool removed = false; + for (auto group = m_groupTable.begin(); group != m_groupTable.end(); ++group) + { + if (group->second[endPoint]) + { + group->second.reset(endPoint); // Turn bit in bitset off (0) + NS_LOG_INFO("Removed endpoint " << static_cast(endPoint) << " from group " + << group->first); + + if (group->second.none()) + { + m_groupTable.erase(group); // remove group if no endpoints left + } + removed = true; // endpoint removed successfully + } + } + return removed; +} + +bool +ZigbeeGroupTable::IsGroupMember(uint16_t groupId) const +{ + return m_groupTable.find(groupId) != m_groupTable.end(); +} + +bool +ZigbeeGroupTable::LookUpEndPoints(uint16_t groupId, std::vector& endPoints) const +{ + bool hasEndPoints = false; + auto group = m_groupTable.find(groupId); + + if (group == m_groupTable.end()) + { + NS_LOG_WARN("Group ID " << groupId << " does not exist, cannot look up endpoints"); + return false; // group doesn't exist + } + + for (auto endpoint = 0; endpoint < MAX_ENDPOINT_ENTRIES; ++endpoint) + { + if (group->second[endpoint]) + { + endPoints.push_back(endpoint); + hasEndPoints = true; + } + } + return hasEndPoints; +} + +} // namespace zigbee +} // namespace ns3 diff --git a/src/zigbee/model/zigbee-group-table.h b/src/zigbee/model/zigbee-group-table.h new file mode 100644 index 000000000..54e9402b6 --- /dev/null +++ b/src/zigbee/model/zigbee-group-table.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2025 Tokushima University, Japan + * + * SPDX-License-Identifier: GPL-2.0-only + * + * Author: + * Alberto Gallegos Ramonet + */ + +#ifndef ZIGBEE_GROUP_TABLE_H +#define ZIGBEE_GROUP_TABLE_H + +#include "ns3/simple-ref-count.h" + +#include +#include + +namespace ns3 +{ +namespace zigbee +{ + +/** + * @ingroup zigbee + * The Zigbee Group Table + * Zigbee Specification r22.1.0, Section 2.2.8.3 and 3.6.6.1 + * The group table is a special table that is accessible by both the + * Zigbee NWK and APS layers. It is used to store group IDs and associated endpoints. + * The group table is used in GroupCasting operations (A type of multicast in Zigbee). + * In this implementation, the group table is represented as a map where the key is the group ID + * and the value is a bitset representing the endpoints associated with that group ID. + * Each bit in the bitset corresponds to an endpoint, where the index of the bit represents the + * endpoint number. + */ +class ZigbeeGroupTable : public SimpleRefCount +{ + public: + /** + * Constructor for Zigbee group table. + */ + ZigbeeGroupTable(); + + /** + * Destructor for Zigbee group table. + */ + ~ZigbeeGroupTable(); + + /** + * Add a group ID and its related endpoint. If the group ID already exists, + * the endpoint is added to the existing group ID entry. + * + * @param groupId The group ID to add. + * @param endPoint The endpoint to associate with the group ID. + * @return True if the entry was added successfully or the endpoint is already a member of the + * group, false if the table is full. + */ + bool AddEntry(uint16_t groupId, uint8_t endPoint); + + /** + * Remove endpoint from a group. If the endpoint is the last one + * associated with the group ID, the group ID entry is removed. + * + * @param groupId The group ID of the group to remove the endpoint from. + * @param endPoint The endpoint to remove from the group ID. + * @return True if the entry was removed successfully, false if the group does not exist, or the + * endpoint is not a member of the group. + */ + bool RemoveEntry(uint16_t groupId, uint8_t endPoint); + + /** + * Remove the endPoint from all groups. + * + * @param endPoint The endpoint to remove from all groups. If the removed endpoint is the last + * one associated with the group ID, the group ID entry is also removed. + * @return True if the endpoint was remmoved from at least one group, false if the endpoint was + * not found in any group. + * + */ + bool RemoveMembership(uint8_t endPoint); + + /** + * Indicates whether the group ID exists in the group table. + * + * @param groupId The group ID to query. + * @return True if the group ID exists, false otherwise. + */ + bool IsGroupMember(uint16_t groupId) const; + + /** + * Look up the endpoints associated with a given group ID. + * + * @param groupId The group ID to look up. + * @param endPoints A vector to store the endpoints associated with the group ID. + * @return True if the group ID was found and endpoints were retrieved, false otherwise. + */ + bool LookUpEndPoints(uint16_t groupId, std::vector& endPoints) const; + + private: + static constexpr int MAX_GROUP_ID_ENTRIES{256}; //!< The maximum amount of group ID + //!< entries allowed in the table. + static constexpr int MAX_ENDPOINT_ENTRIES{256}; //!< The maximum amount of endpoints + //!< allowed per group id entry. + std::unordered_map> + m_groupTable; //!< The group table object +}; + +} // namespace zigbee +} // namespace ns3 + +#endif /* ZIGBEE_GROUP_TABLE_H */