pdr: Add pldm_entity_association_tree_delete_node() API
This API deletes the specific entity node from the entity
association tree. We must handle the parent children and sibling
relationship before we delete the node from the entity association
tree.
Change-Id: I326adba8316a15c6af0696cdd9bdf2be7e592452
Signed-off-by: Pavithra Barithaya <pavithrabarithaya07@gmail.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 36ca07f..23a058e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@
- pdr: Add pldm_pdr_delete_by_effecter_id() API
- platform: Add encode req for GetPDRRepositoryInfo
- pdr: Add pldm_pdr_delete_by_sensor_id() API
+- pdr: Add pldm_entity_association_tree_delete_node() API
- oem: ibm: Add boot side rename state set and enum
diff --git a/include/libpldm/pdr.h b/include/libpldm/pdr.h
index 25faf6f..8370ba2 100644
--- a/include/libpldm/pdr.h
+++ b/include/libpldm/pdr.h
@@ -696,6 +696,18 @@
pldm_pdr *repo, pldm_entity *entity, bool is_remote,
uint32_t *pdr_record_handle);
+/** @brief deletes a node and it's children from the entity association tree
+ * @param[in] tree - opaque pointer acting as a handle to the tree
+ * @param[in] entity - the pldm entity to be deleted
+ * Note - The values passed in entity must be in host-endianness.
+ *
+ * @return 0 on success, returns -EINVAL if the arguments are invalid and if
+ * the entity passed is invalid or NULL, or -ENOENT if the @param entity is
+ * not found in @param tree.
+ */
+int pldm_entity_association_tree_delete_node(pldm_entity_association_tree *tree,
+ const pldm_entity *entity);
+
/** @brief removes a PLDM PDR record if it matches given record set identifier
* @param[in] repo - opaque pointer acting as a PDR repo handle
* @param[in] fru_rsi - FRU record set identifier
diff --git a/src/dsp/pdr.c b/src/dsp/pdr.c
index 69229d5..f8873b1 100644
--- a/src/dsp/pdr.c
+++ b/src/dsp/pdr.c
@@ -2346,3 +2346,44 @@
}
return rc;
}
+
+LIBPLDM_ABI_TESTING
+int pldm_entity_association_tree_delete_node(pldm_entity_association_tree *tree,
+ const pldm_entity *entity)
+{
+ if (!tree || !entity) {
+ return -EINVAL;
+ }
+ pldm_entity_node *node = NULL;
+ pldm_find_entity_ref_in_tree(tree, *entity, &node);
+ if (!node) {
+ return -ENOENT;
+ }
+
+ pldm_entity_node *parent = NULL;
+ pldm_find_entity_ref_in_tree(tree, node->parent, &parent);
+ if (!parent) {
+ return -ENOENT;
+ }
+
+ pldm_entity_node *curr = parent->first_child;
+ pldm_entity_node *prev = NULL;
+ while (curr != NULL) {
+ if (pldm_entity_cmp(entity, &curr->entity)) {
+ if (curr == parent->first_child) {
+ parent->first_child = curr->next_sibling;
+ } else {
+ if (prev) {
+ prev->next_sibling = curr->next_sibling;
+ }
+ }
+ curr->next_sibling = NULL;
+
+ entity_association_tree_destroy(node);
+ break;
+ }
+ prev = curr;
+ curr = curr->next_sibling;
+ }
+ return 0;
+}
diff --git a/tests/dsp/pdr.cpp b/tests/dsp/pdr.cpp
index 0d19de2..9c48215 100644
--- a/tests/dsp/pdr.cpp
+++ b/tests/dsp/pdr.cpp
@@ -7,6 +7,7 @@
#include <cstdint>
#include <cstdlib>
#include <cstring>
+#include <memory>
#include <vector>
#include <gtest/gtest.h>
@@ -2589,3 +2590,71 @@
pldm_pdr_destroy(repo);
}
#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(EntityAssociationPDR, testDeleteNode)
+{
+ std::unique_ptr<pldm_entity, decltype(&free)> entities(
+ (pldm_entity*)malloc(sizeof(pldm_entity) * 4), &free);
+ ASSERT_NE(entities, nullptr);
+
+ entities.get()[0].entity_type = 1;
+
+ entities.get()[1].entity_type = 2;
+ entities.get()[1].entity_instance_num = 1;
+ entities.get()[1].entity_container_id = 2;
+
+ entities.get()[2].entity_type = 3;
+ entities.get()[2].entity_instance_num = 1;
+ entities.get()[2].entity_container_id = 2;
+
+ entities.get()[3].entity_type = 4;
+ entities.get()[3].entity_instance_num = 1;
+ entities.get()[3].entity_container_id = 2;
+
+ auto tree = pldm_entity_association_tree_init();
+ ASSERT_NE(tree, nullptr);
+
+ auto l1 = pldm_entity_association_tree_add_entity(
+ tree, &entities.get()[0], 0xffff, nullptr,
+ PLDM_ENTITY_ASSOCIAION_LOGICAL, false, true, 0xffff);
+ ASSERT_NE(l1, nullptr);
+
+ auto l2 = pldm_entity_association_tree_add_entity(
+ tree, &entities.get()[1], 0xffff, l1, PLDM_ENTITY_ASSOCIAION_PHYSICAL,
+ false, false, 0xffff);
+ ASSERT_NE(l2, nullptr);
+
+ auto l3 = pldm_entity_association_tree_add_entity(
+ tree, &entities.get()[2], 0xffff, l1, PLDM_ENTITY_ASSOCIAION_PHYSICAL,
+ false, true, 0xffff);
+ ASSERT_NE(l3, nullptr);
+
+ auto l4 = pldm_entity_association_tree_add_entity(
+ tree, &entities.get()[3], 0xffff, l1, PLDM_ENTITY_ASSOCIAION_PHYSICAL,
+ false, true, 0xffff);
+ ASSERT_NE(l4, nullptr);
+
+ EXPECT_EQ(pldm_entity_get_num_children(l1, PLDM_ENTITY_ASSOCIAION_PHYSICAL),
+ 3);
+
+ pldm_entity entity{};
+ entity.entity_type = 4;
+ entity.entity_instance_num = 1;
+ entity.entity_container_id = 2;
+
+ pldm_entity_association_tree_delete_node(tree, &entity);
+ EXPECT_EQ(pldm_entity_get_num_children(l1, PLDM_ENTITY_ASSOCIAION_PHYSICAL),
+ 2);
+
+ entity.entity_type = 3;
+ entity.entity_instance_num = 1;
+ entity.entity_container_id = 2;
+
+ pldm_entity_association_tree_delete_node(tree, &entity);
+ EXPECT_EQ(pldm_entity_get_num_children(l1, PLDM_ENTITY_ASSOCIAION_PHYSICAL),
+ 1);
+
+ pldm_entity_association_tree_destroy(tree);
+}
+#endif