libpldm: pdr: add API to remove remote PDRs
Add an API that lets the caller delete all remote PDRs from the BMC's
PDR repository.
The PDR record handles are adjusted in order to
continue to remain sequential, by increments of 1, for the remaining
records.
Signed-off-by: Deepak Kodihalli <dkodihal@in.ibm.com>
Change-Id: Icf260f6335fc537dd7bb9a7d148d30ec4345636e
diff --git a/libpldm/pdr.c b/libpldm/pdr.c
index bfbf566..3aa9541 100644
--- a/libpldm/pdr.c
+++ b/libpldm/pdr.c
@@ -600,6 +600,53 @@
entity_association_pdr_add(tree->root, repo, is_remote);
}
+void pldm_pdr_remove_remote_pdrs(pldm_pdr *repo)
+{
+ assert(repo != NULL);
+ bool removed = false;
+
+ pldm_pdr_record *record = repo->first;
+ pldm_pdr_record *prev = NULL;
+ while (record != NULL) {
+ pldm_pdr_record *next = record->next;
+ if (record->is_remote == true) {
+ if (repo->first == record) {
+ repo->first = next;
+ } else {
+ prev->next = next;
+ }
+ if (repo->last == record) {
+ repo->last = prev;
+ }
+ if (record->data) {
+ free(record->data);
+ }
+ --repo->record_count;
+ repo->size -= record->size;
+ free(record);
+ removed = true;
+ } else {
+ prev = record;
+ }
+ record = next;
+ }
+
+ if (removed == true) {
+ record = repo->first;
+ uint32_t record_handle = 0;
+ while (record != NULL) {
+ record->record_handle = ++record_handle;
+ if (record->data != NULL) {
+ struct pldm_pdr_hdr *hdr =
+ (struct pldm_pdr_hdr *)(record->data);
+ hdr->record_handle =
+ htole32(record->record_handle);
+ }
+ record = record->next;
+ }
+ }
+}
+
void entity_association_tree_find(pldm_entity_node *node, pldm_entity *entity,
pldm_entity_node **out)
{
diff --git a/libpldm/pdr.h b/libpldm/pdr.h
index b85bed5..0489814 100644
--- a/libpldm/pdr.h
+++ b/libpldm/pdr.h
@@ -138,6 +138,12 @@
bool pldm_pdr_record_is_remote(const pldm_pdr_record *record);
+/** @brief Remove all PDR records that belong to a remote terminus
+ *
+ * @param[in] repo - opaque pointer acting as a PDR repo handle
+ */
+void pldm_pdr_remove_remote_pdrs(pldm_pdr *repo);
+
/* ======================= */
/* FRU Record Set PDR APIs */
/* ======================= */
diff --git a/libpldm/tests/libpldm_pdr_test.cpp b/libpldm/tests/libpldm_pdr_test.cpp
index 622ec32..c0fbe32 100644
--- a/libpldm/tests/libpldm_pdr_test.cpp
+++ b/libpldm/tests/libpldm_pdr_test.cpp
@@ -36,6 +36,176 @@
pldm_pdr_destroy(repo);
}
+TEST(PDRUpdate, testRemove)
+{
+ std::array<uint8_t, 10> data{};
+
+ auto repo = pldm_pdr_init();
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 0);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 0);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 0);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 2);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 6);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 3);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 5);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 3);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 5);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 2);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 3);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 5);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 2);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 3);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 1);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 3);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 2);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
+ pldm_pdr_destroy(repo);
+
+ repo = pldm_pdr_init();
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ pldm_pdr_remove_remote_pdrs(repo);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 2);
+ auto handle = pldm_pdr_add(repo, data.data(), data.size(), 0, false);
+ EXPECT_EQ(handle, 3);
+ handle = pldm_pdr_add(repo, data.data(), data.size(), 0, true);
+ EXPECT_EQ(handle, 4);
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 4);
+ pldm_pdr_destroy(repo);
+}
+
TEST(PDRAccess, testGet)
{
auto repo = pldm_pdr_init();