pldmtool/softoff: Use InstanceId APIs from libpldm
The af-mctp transport does not broadcast the PLDM messages between the
MCTP socket instances. Pldmtool/softoff have to handle get/free
instanceId instead of depending on the pldmd. Update pldmtool/softoff
to use get/free instanceId APIs in libpldm.
Tested.
1. Call more than 32 pldmtool commands to make sure the allocated
InstanceId are free correctly.
2. Repeat calling softoff more than 32 times. Make sure the functional
should work normally.
Signed-off-by: Dung Cao <dung@os.amperecomputing.com>
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
Change-Id: I7cda124694d95d00c37f4993e22cfe33a980d364
diff --git a/softoff/softoff.cpp b/softoff/softoff.cpp
index be78933..f80e048 100644
--- a/softoff/softoff.cpp
+++ b/softoff/softoff.cpp
@@ -1,5 +1,6 @@
#include "softoff.hpp"
+#include "common/instance_id.hpp"
#include "common/utils.hpp"
#include <libpldm/entity.h>
@@ -294,26 +295,8 @@
uint8_t instanceID;
mctpEID = pldm::utils::readHostEID();
-
- // Get instanceID
- try
- {
- auto& bus = pldm::utils::DBusHandler::getBus();
- auto method = bus.new_method_call(
- "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
- "xyz.openbmc_project.PLDM.Requester", "GetInstanceId");
- method.append(mctpEID);
-
- auto ResponseMsg = bus.call(method, dbusTimeout);
-
- ResponseMsg.read(instanceID);
- }
- catch (const sdbusplus::exception_t& e)
- {
- error("PLDM soft off: Error get instanceID,ERROR={ERR_EXCEP}",
- "ERR_EXCEP", e.what());
- return PLDM_ERROR;
- }
+ // TODO: fix mapping to work around OpenBMC ecosystem deficiencies
+ pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEID);
std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(effecterID) +
sizeof(effecterCount) +
@@ -322,10 +305,13 @@
auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
set_effecter_state_field stateField{
PLDM_REQUEST_SET, PLDM_SW_TERM_GRACEFUL_SHUTDOWN_REQUESTED};
+ pldm::InstanceIdDb instanceIdDb;
+ instanceID = instanceIdDb.next(pldmTID);
auto rc = encode_set_state_effecter_states_req(
instanceID, effecterID, effecterCount, &stateField, request);
if (rc != PLDM_SUCCESS)
{
+ instanceIdDb.free(pldmTID, instanceID);
error("Message encode failure. PLDM error code = {RC}", "RC", lg2::hex,
static_cast<int>(rc));
return PLDM_ERROR;
@@ -341,9 +327,10 @@
// Add a timer to the event loop, default 30s.
auto timerCallback =
- [=, this](Timer& /*source*/, Timer::TimePoint /*time*/) {
+ [=, this](Timer& /*source*/, Timer::TimePoint /*time*/) mutable {
if (!responseReceived)
{
+ instanceIdDb.free(pldmTID, instanceID);
error(
"PLDM soft off: ERROR! Can't get the response for the PLDM request msg. Time out! Exit the pldm-softpoweroff");
exit(-1);
@@ -354,7 +341,7 @@
std::chrono::seconds{1}, std::move(timerCallback));
// Add a callback to handle EPOLLIN on fd
- auto callback = [=, this](IO& io, int fd, uint32_t revents) {
+ auto callback = [=, this](IO& io, int fd, uint32_t revents) mutable {
if (!(revents & EPOLLIN))
{
return;
@@ -362,6 +349,7 @@
uint8_t* responseMsg = nullptr;
size_t responseMsgSize{};
+ pldm_tid_t srcTID = pldmTID;
auto rc = pldm_recv(mctpEID, fd, request->hdr.instance_id, &responseMsg,
&responseMsgSize);
@@ -379,6 +367,18 @@
// sent out
io.set_enabled(Enabled::Off);
auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get());
+
+ if (srcTID != pldmTID ||
+ !pldm_msg_hdr_correlate_response(&request->hdr, &response->hdr))
+ {
+ /* This isn't the response we were looking for */
+ return;
+ }
+
+ /* We have the right response, release the instance ID and process */
+ io.set_enabled(Enabled::Off);
+ instanceIdDb.free(pldmTID, instanceID);
+
if (response->payload[0] != PLDM_SUCCESS)
{
error("Getting the wrong response. PLDM RC = {RC}", "RC",
@@ -415,6 +415,7 @@
rc = pldm_send(mctpEID, fd, requestMsg.data(), requestMsg.size());
if (0 > rc)
{
+ instanceIdDb.free(pldmTID, instanceID);
error(
"Failed to send message/receive response. RC = {RC}, errno = {ERR}",
"RC", static_cast<int>(rc), "ERR", errno);
@@ -430,6 +431,7 @@
}
catch (const sdeventplus::SdEventError& e)
{
+ instanceIdDb.free(pldmTID, instanceID);
error(
"PLDM host soft off: Failure in processing request.ERROR= {ERR_EXCEP}",
"ERR_EXCEP", e.what());