Move to libpldm instance id APIs
libpldm provides APIs for allocating instance IDs directly, which
eliminates the need for remote dbus calls to the pldm daemon. Refactor
the code to use these APIs and eliminate all the dbus operations.
Change-Id: Ie73a1abb30e12a40014b2d35209e6e90c38a148b
Signed-off-by: Pavithra Barithaya <pavithrabarithaya07@gmail.com>
diff --git a/util/dbus.cpp b/util/dbus.cpp
index ebbdf67..c1b8741 100644
--- a/util/dbus.cpp
+++ b/util/dbus.cpp
@@ -534,38 +534,6 @@
return true;
}
-/** @brief Get PLDM instance associated with endpoint */
-bool getPldmInstanceID(uint8_t& pldmInstanceID, uint8_t Eid)
-{
- constexpr auto service = "xyz.openbmc_project.PLDM";
- constexpr auto path = "/xyz/openbmc_project/pldm";
- constexpr auto interface = "xyz.openbmc_project.PLDM.Requester";
- constexpr auto function = "GetInstanceId";
-
- try
- {
- // create dbus method
- auto bus = sdbusplus::bus::new_default();
- sdbusplus::message_t method =
- bus.new_method_call(service, path, interface, function);
-
- // append endpoint ID
- method.append(Eid);
-
- // request PLDM instance ID
- auto reply = bus.call(method);
- reply.read(pldmInstanceID);
- }
- catch (const sdbusplus::exception_t& e)
- {
- trace::err("get PLDM instance exception");
- trace::err(e.what());
- return false;
- }
-
- return true;
-}
-
/** @brief Determine if power fault was detected */
bool powerFault()
{
diff --git a/util/dbus.hpp b/util/dbus.hpp
index 3dcca49..0a8ede5 100644
--- a/util/dbus.hpp
+++ b/util/dbus.hpp
@@ -198,16 +198,6 @@
uint16_t stateSetId);
/**
- * @brief Get PLDM instance ID associated with endpoint
- *
- * @param[out] pldmInstanceID - PLDM instance id
- * @param[in] Eid - MCTP enpoint ID
- *
- * @return True on success otherwise False
- */
-bool getPldmInstanceID(uint8_t& pldmInstanceID, uint8_t Eid);
-
-/**
* @brief Determine if power fault was detected
*
* @return true if power fault or unknown, false otherwise
diff --git a/util/pldm.cpp b/util/pldm.cpp
index c161e51..a86d440 100644
--- a/util/pldm.cpp
+++ b/util/pldm.cpp
@@ -3,12 +3,103 @@
#include <libpldm/pldm.h>
#include <util/dbus.hpp>
+#include <util/pldm.hpp>
#include <util/trace.hpp>
namespace util
{
namespace pldm
{
+
+class PLDMInstanceManager
+{
+ public:
+ // Singleton access method
+ static PLDMInstanceManager& getInstance()
+ {
+ static PLDMInstanceManager instance;
+ return instance;
+ }
+
+ bool getPldmInstanceID(uint8_t& pldmInstance, uint8_t tid);
+ void freePLDMInstanceID(pldm_instance_id_t instanceID, uint8_t tid);
+
+ private:
+ // Private constructor and destructor to prevent creating multiple instances
+ PLDMInstanceManager();
+ ~PLDMInstanceManager();
+
+ // Deleted copy constructor and assignment operator to prevent copying
+ PLDMInstanceManager(const PLDMInstanceManager&) = delete;
+ PLDMInstanceManager& operator=(const PLDMInstanceManager&) = delete;
+
+ // Private member for the instance database
+ pldm_instance_db* pldmInstanceIdDb;
+};
+
+PLDMInstanceManager::PLDMInstanceManager() : pldmInstanceIdDb(nullptr)
+{
+ // Initialize the database object directly in the constructor
+ auto rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
+ if (rc)
+ {
+ trace::err("Error calling pldm_instance_db_init_default, rc = %d",
+ (unsigned)rc);
+ }
+}
+
+PLDMInstanceManager::~PLDMInstanceManager()
+{
+ // Directly destroy the database object in the destructor
+ if (pldmInstanceIdDb)
+ {
+ auto rc = pldm_instance_db_destroy(pldmInstanceIdDb);
+ if (rc)
+ {
+ trace::err("pldm_instance_db_destroy failed rc = %d", (unsigned)rc);
+ }
+ }
+}
+
+// Get the PLDM instance ID for the given terminus ID
+bool PLDMInstanceManager::getPldmInstanceID(uint8_t& pldmInstance, uint8_t tid)
+{
+ pldm_instance_id_t id;
+ int rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &id);
+ if (rc == -EAGAIN)
+ {
+ std::this_thread::sleep_for(
+ std::chrono::milliseconds(100)); // Retry after 100ms
+ rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid,
+ &id); // Retry allocation
+ }
+
+ if (rc)
+ {
+ trace::err("getPldmInstanceId: Failed to alloc ID for TID = %d, RC= %d",
+ (unsigned)tid, (unsigned)rc);
+ return false;
+ }
+
+ pldmInstance = id; // Return the allocated instance ID
+ trace::inf("Got instanceId: %d, for PLDM TID: %d", (unsigned)pldmInstance,
+ (unsigned)tid);
+ return true;
+}
+
+// Free the PLDM instance ID associated with the terminus ID
+void PLDMInstanceManager::freePLDMInstanceID(pldm_instance_id_t instanceID,
+ uint8_t tid)
+{
+ int rc = pldm_instance_id_free(pldmInstanceIdDb, tid, instanceID);
+ if (rc)
+ {
+ trace::err(
+ "pldm_instance_id_free failed to free id=%d of TID=%d with rc= %d",
+ (unsigned)instanceID, (unsigned)tid, (unsigned)rc);
+ }
+}
+
/** @brief Send PLDM request
*
* @param[in] request - the request data
@@ -50,9 +141,11 @@
uint16_t effecterId, uint8_t effecterCount, uint8_t stateIdPos,
uint8_t stateSetValue, uint8_t mctpEid)
{
+ PLDMInstanceManager& manager = PLDMInstanceManager::getInstance();
+
// get pldm instance associated with the endpoint ID
uint8_t pldmInstanceID;
- if (!util::dbus::getPldmInstanceID(pldmInstanceID, mctpEid))
+ if (!manager.getPldmInstanceID(pldmInstanceID, mctpEid))
{
return std::vector<uint8_t>();
}
@@ -87,6 +180,7 @@
if (rc != PLDM_SUCCESS)
{
trace::err("encode set effecter states request failed");
+ manager.freePLDMInstanceID(pldmInstanceID, mctpEid);
request.clear();
}
@@ -293,6 +387,9 @@
if (!fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSbeInstance,
sbeSensorOffset))
{
+ PLDMInstanceManager& manager = PLDMInstanceManager::getInstance();
+ auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&request);
+ manager.freePLDMInstanceID(reqhdr->instance_id, hbrtMctpEid);
return false;
}
@@ -355,8 +452,13 @@
trace::err("send pldm request failed");
if (-1 != pldmFd)
{
+ trace::err("failed to connect to pldm");
close(pldmFd);
}
+ PLDMInstanceManager& manager = PLDMInstanceManager::getInstance();
+ auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&request);
+ manager.freePLDMInstanceID(reqhdr->instance_id, hbrtMctpEid);
+
return false;
}
@@ -386,6 +488,9 @@
trace::err("hreset timed out");
}
+ PLDMInstanceManager& manager = PLDMInstanceManager::getInstance();
+ auto reqhdr = reinterpret_cast<const pldm_msg_hdr*>(&request);
+ manager.freePLDMInstanceID(reqhdr->instance_id, hbrtMctpEid);
close(pldmFd); // close pldm socket
return hresetStatus == "success" ? true : false;
diff --git a/util/pldm.hpp b/util/pldm.hpp
index c5d4057..a5b1a4c 100644
--- a/util/pldm.hpp
+++ b/util/pldm.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <libpldm/instance-id.h>
+
namespace util
{
namespace pldm