zigbee: Add group table
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
139
src/zigbee/model/zigbee-group-table.cc
Normal file
139
src/zigbee/model/zigbee-group-table.cc
Normal 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
|
||||
110
src/zigbee/model/zigbee-group-table.h
Normal file
110
src/zigbee/model/zigbee-group-table.h
Normal 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 */
|
||||
Reference in New Issue
Block a user