PLDM: Handling modified PDRs

This commit handles the PDRs which are modified.
This also prevents the looping of host PDRs when we get
the modified PDR in between the PDR exchange. With this
change we will fetch only the modified PDRs and not all
the PDRs again.

Change-Id: If674f23ce83f44853c74139c9d3c4e5aea05259a
Signed-off-by: Pavithra Barithaya <pavithra.b@ibm.com>
diff --git a/host-bmc/host_pdr_handler.cpp b/host-bmc/host_pdr_handler.cpp
index 0cc8a1a..75d3e61 100644
--- a/host-bmc/host_pdr_handler.cpp
+++ b/host-bmc/host_pdr_handler.cpp
@@ -123,7 +123,16 @@
 void HostPDRHandler::fetchPDR(PDRRecordHandles&& recordHandles)
 {
     pdrRecordHandles.clear();
-    pdrRecordHandles = std::move(recordHandles);
+    modifiedPDRRecordHandles.clear();
+
+    if (isHostPdrModified)
+    {
+        modifiedPDRRecordHandles = std::move(recordHandles);
+    }
+    else
+    {
+        pdrRecordHandles = std::move(recordHandles);
+    }
 
     // Defer the actual fetch of PDRs from the host (by queuing the call on the
     // main event loop). That way, we can respond to the platform event msg from
@@ -146,13 +155,16 @@
                                     PLDM_GET_PDR_REQ_BYTES);
     auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
     uint32_t recordHandle{};
-    if (!nextRecordHandle)
+    if (!nextRecordHandle && (!modifiedPDRRecordHandles.empty()) &&
+        isHostPdrModified)
     {
-        if (!pdrRecordHandles.empty())
-        {
-            recordHandle = pdrRecordHandles.front();
-            pdrRecordHandles.pop_front();
-        }
+        recordHandle = modifiedPDRRecordHandles.front();
+        modifiedPDRRecordHandles.pop_front();
+    }
+    else if (!nextRecordHandle && (!pdrRecordHandles.empty()))
+    {
+        recordHandle = pdrRecordHandles.front();
+        pdrRecordHandles.pop_front();
     }
     else
     {
@@ -551,10 +563,19 @@
     }
     else
     {
-        deferredFetchPDREvent = std::make_unique<sdeventplus::source::Defer>(
-            event,
-            std::bind(std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
-                      this, nextRecordHandle, std::placeholders::_1));
+        if (modifiedPDRRecordHandles.empty() && isHostPdrModified)
+        {
+            isHostPdrModified = false;
+        }
+        else
+        {
+            deferredFetchPDREvent =
+                std::make_unique<sdeventplus::source::Defer>(
+                    event,
+                    std::bind(
+                        std::mem_fn((&HostPDRHandler::_processFetchPDREvent)),
+                        this, nextRecordHandle, std::placeholders::_1));
+        }
     }
 }
 
@@ -576,6 +597,11 @@
         nextRecordHandle = this->pdrRecordHandles.front();
         this->pdrRecordHandles.pop_front();
     }
+    if (isHostPdrModified && (!this->modifiedPDRRecordHandles.empty()))
+    {
+        nextRecordHandle = this->modifiedPDRRecordHandles.front();
+        this->modifiedPDRRecordHandles.pop_front();
+    }
     this->getHostPDR(nextRecordHandle);
 }
 
diff --git a/host-bmc/host_pdr_handler.hpp b/host-bmc/host_pdr_handler.hpp
index 694bcdd..6d33f5a 100644
--- a/host-bmc/host_pdr_handler.hpp
+++ b/host-bmc/host_pdr_handler.hpp
@@ -20,7 +20,6 @@
 
 namespace pldm
 {
-
 using EntityType = uint16_t;
 // vector which would hold the PDR record handle data returned by
 // pldmPDRRepositoryChgEvent event data
@@ -159,6 +158,11 @@
      */
     void setHostSensorState(const PDRList& stateSensorPDRs);
 
+    /** @brief whether we received PLDM_RECORDS_MODIFIED event data operation
+     *  from host
+     */
+    bool isHostPdrModified = false;
+
     /** @brief check whether Host is running when pldmd starts
      */
     bool isHostUp();
@@ -244,6 +248,10 @@
     /** @brief maps an entity type to parent pldm_entity from the BMC's entity
      *  association tree
      */
+
+    /** @brief list of PDR record handles modified pointing to host PDRs */
+    PDRRecordHandles modifiedPDRRecordHandles;
+
     std::map<EntityType, pldm_entity> parents;
     /** @brief D-Bus property changed signal match */
     std::unique_ptr<sdbusplus::bus::match_t> hostOffMatch;
diff --git a/libpldmresponder/platform.cpp b/libpldmresponder/platform.cpp
index 4728bb6..8dce111 100644
--- a/libpldmresponder/platform.cpp
+++ b/libpldmresponder/platform.cpp
@@ -515,8 +515,14 @@
                 return rc;
             }
 
-            if (eventDataOperation == PLDM_RECORDS_ADDED)
+            if (eventDataOperation == PLDM_RECORDS_ADDED ||
+                eventDataOperation == PLDM_RECORDS_MODIFIED)
             {
+                if (eventDataOperation == PLDM_RECORDS_MODIFIED)
+                {
+                    hostPDRHandler->isHostPdrModified = true;
+                }
+
                 rc = getPDRRecordHandles(
                     reinterpret_cast<const ChangeEntry*>(changeRecordData +
                                                          dataOffset),
@@ -530,11 +536,6 @@
                 }
             }
 
-            if (eventDataOperation == PLDM_RECORDS_MODIFIED)
-            {
-                return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
-            }
-
             changeRecordData +=
                 dataOffset + (numberOfChangeEntries * sizeof(ChangeEntry));
             changeRecordDataSize -=