Normalize fru record set and PDRs from Remote terminus

When Remote terminus sends the entity association PDR to BMC, BMC will
generate a new container Id and put it into Remote terminus entity
association PDR, and then add it to BMC entity association tree.

As the container Id in the corresponding Remote terminus fru record
set PDR and state sensor/effecter PDR has not been updated, when we
get a fru record set PDR or state sensor/effecter PDR, we will check the
entity association tree, pick up the changed container Id and update
the fru record and add to our PDR repo.

As per the Spec DSP 0248, Section 11.8 - <Designing Association PDRs for Monitoring and Control>,
https://www.dmtf.org/sites/default/files/standards/documents/DSP0248_1.0.1.pdf

1) Identify the physical entities and assign them Entity Identification Information values:
a) Identify the topmost physical container entities and give them the containerID for "system".
b) Assign each remaining physical entity a different containerID value using whatever approach works best for the implementation. (For example, containerID values could be assigned sequentially starting from 1, or 1000 if it necessary to have a value that is more readily distinguishable as a being a containerID.)

2) Create Entity Association PDRs for the physical-to-physical containment associations.

3) Create the Sensor PDR, Effecter PDR, or other PDRs that are associated with the physical entities, and set the Entity Identification Information based on the containment PDRs that were created earlier.

4) Create the PDRs for any logical entities and set the containerID value for the containing entity to the containerID for the appropriate physical container entities.

5) Create the Sensor PDR, Effecter PDR, or other PDRs that reference those logical entities.

We are following this principal in our change for Normalization of the PDRs from the remote Terminus.

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I48cab631ab4a50a8ba654c114792993cb5f418a7
diff --git a/host-bmc/host_pdr_handler.cpp b/host-bmc/host_pdr_handler.cpp
index 8317cf0..7dbd4e5 100644
--- a/host-bmc/host_pdr_handler.cpp
+++ b/host-bmc/host_pdr_handler.cpp
@@ -17,6 +17,7 @@
 #include <sdeventplus/source/time.hpp>
 
 #include <fstream>
+#include <type_traits>
 
 PHOSPHOR_LOG2_USING;
 
@@ -51,6 +52,38 @@
     return TERMINUS_HANDLE;
 }
 
+template <typename T>
+void updateContainerId(pldm_entity_association_tree* entityTree,
+                       std::vector<uint8_t>& pdr)
+{
+    T* t = nullptr;
+    if (entityTree == nullptr)
+    {
+        return;
+    }
+    if (std::is_same<T, pldm_pdr_fru_record_set>::value)
+    {
+        t = (T*)(pdr.data() + sizeof(pldm_pdr_hdr));
+    }
+    else
+    {
+        t = (T*)(pdr.data());
+    }
+    if (t == nullptr)
+    {
+        return;
+    }
+
+    pldm_entity entity{t->entity_type, t->entity_instance, t->container_id};
+    auto node = pldm_entity_association_tree_find_with_locality(entityTree,
+                                                                &entity, true);
+    if (node)
+    {
+        pldm_entity e = pldm_entity_extract(node);
+        t->container_id = e.entity_container_id;
+    }
+}
+
 HostPDRHandler::HostPDRHandler(
     int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, pldm_pdr* repo,
     const std::string& eventsJsonsDir, pldm_entity_association_tree* entityTree,
@@ -523,24 +556,29 @@
                 {
                     pdrTerminusHandle =
                         extractTerminusHandle<pldm_state_sensor_pdr>(pdr);
+                    updateContainerId<pldm_state_sensor_pdr>(entityTree, pdr);
                     stateSensorPDRs.emplace_back(pdr);
                 }
                 else if (pdrHdr->type == PLDM_PDR_FRU_RECORD_SET)
                 {
                     pdrTerminusHandle =
                         extractTerminusHandle<pldm_pdr_fru_record_set>(pdr);
+                    updateContainerId<pldm_pdr_fru_record_set>(entityTree, pdr);
                     fruRecordSetPDRs.emplace_back(pdr);
                 }
                 else if (pdrHdr->type == PLDM_STATE_EFFECTER_PDR)
                 {
                     pdrTerminusHandle =
                         extractTerminusHandle<pldm_state_effecter_pdr>(pdr);
+                    updateContainerId<pldm_state_effecter_pdr>(entityTree, pdr);
                 }
                 else if (pdrHdr->type == PLDM_NUMERIC_EFFECTER_PDR)
                 {
                     pdrTerminusHandle =
                         extractTerminusHandle<pldm_numeric_effecter_value_pdr>(
                             pdr);
+                    updateContainerId<pldm_numeric_effecter_value_pdr>(
+                        entityTree, pdr);
                 }
                 // if the TLPDR is invalid update the repo accordingly
                 if (!tlValid)