zigbee: Add group table

This commit is contained in:
Alberto Gallegos Ramonet
2025-07-09 14:22:04 +09:00
parent f3f1fc2c49
commit 9231d8bf04
4 changed files with 252 additions and 0 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,139 @@
/*
* Copyright (c) 2025 Tokushima University, Japan
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Author:
* Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
*/
#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<uint16_t>(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<uint16_t>(endPoint) << " already exists in group "
<< groupId);
return false; // endPoint already in group
}
NS_LOG_INFO("Adding endpoint " << static_cast<uint16_t>(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<uint16_t>(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<uint16_t>(endPoint));
return false; // group doesn't exist
}
if (!endPoints[endPoint])
{
NS_LOG_WARN("Endpoint " << static_cast<uint16_t>(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<uint16_t>(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<uint16_t>(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<uint16_t>(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<uint8_t>& 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

View File

@@ -0,0 +1,110 @@
/*
* Copyright (c) 2025 Tokushima University, Japan
*
* SPDX-License-Identifier: GPL-2.0-only
*
* Author:
* Alberto Gallegos Ramonet <alramonet@is.tokushima-u.ac.jp>
*/
#ifndef ZIGBEE_GROUP_TABLE_H
#define ZIGBEE_GROUP_TABLE_H
#include "ns3/simple-ref-count.h"
#include <bitset>
#include <unordered_map>
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<ZigbeeGroupTable>
{
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<uint8_t>& 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<uint16_t, std::bitset<MAX_ENDPOINT_ENTRIES>>
m_groupTable; //!< The group table object
};
} // namespace zigbee
} // namespace ns3
#endif /* ZIGBEE_GROUP_TABLE_H */