Skip to content

Commit

Permalink
Move to libpldm APIs for Allocating Instance IDs and change Transport…
Browse files Browse the repository at this point in the history
… APIs

Replace the current APIs with libpldm APIs for allocating instance IDs
directly.  This eliminates the need for remote D-Bus calls to the pldm
daemon.

Replace pldm transport APIs with libpldm pldm_transport APIs. This
change migrates the application off the deprecated "requester" APIs in
libpldm. Since we currently lack the infrastructure to obtain the
correct TIDs, use the EID as the TID in the EID-to-TID mapping to
maintain the current functionality.

Change-Id: I348d54d9b5db47ef706cf7935e01ab8e7a55a594
Signed-off-by: Lakshmi Yadlapati <[email protected]>
  • Loading branch information
Lakshmi-y committed Jul 18, 2024
1 parent 33e4191 commit b116fb3
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 95 deletions.
27 changes: 24 additions & 3 deletions dump/pldm_oem_cmds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ using namespace phosphor::logging;

constexpr auto eidPath = "/usr/share/pldm/host_eid";
constexpr mctp_eid_t defaultEIDValue = 9;
PLDMInstanceManager instanceManager;

using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
Expand Down Expand Up @@ -73,11 +74,13 @@ void newFileAvailable(uint32_t dumpId, pldm_fileio_file_type pldmDumpType,
pldmInstanceId, dumpId, static_cast<uint16_t>(pldmDumpType),
dumpSize, newFileAvailReqMsg.size())
.c_str());

int retCode = encode_new_file_req(
pldmInstanceId, pldmDumpType, dumpId, dumpSize,
reinterpret_cast<pldm_msg*>(newFileAvailReqMsg.data()));
if (retCode != PLDM_SUCCESS)
{
freePLDMInstanceID(pldmInstanceId, mctpEndPointId);
log<level::ERR>(
fmt::format(
"Failed to encode pldm New file req for new dump available "
Expand All @@ -88,12 +91,27 @@ void newFileAvailable(uint32_t dumpId, pldm_fileio_file_type pldmDumpType,
"Acknowledging new file request failed due to encoding error"));
}

internal::CustomFd pldmFd(openPLDM());
retCode = openPLDM(mctpEndPointId);
if (retCode < 0)
{
freePLDMInstanceID(pldmInstanceId, mctpEndPointId);
log<level::ERR>(fmt::format("Failed to openPLDM for new dump available "
"dumpId({}), pldmDumpType({}),rc({})",
dumpId, static_cast<uint16_t>(pldmDumpType),
retCode)
.c_str());
elog<NotAllowed>(Reason(
"Acknowledging new file request failed due to openPLDM error"));
}

retCode = pldm_send(mctpEndPointId, pldmFd(), newFileAvailReqMsg.data(),
newFileAvailReqMsg.size());
pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEndPointId);
retCode = pldm_transport_send_msg(pldmTransport, pldmTID,
newFileAvailReqMsg.data(),
newFileAvailReqMsg.size());
if (retCode != PLDM_REQUESTER_SUCCESS)
{
freePLDMInstanceID(pldmInstanceId, mctpEndPointId);
pldmClose();
auto errorNumber = errno;
log<level::ERR>(
fmt::format(
Expand All @@ -106,5 +124,8 @@ void newFileAvailable(uint32_t dumpId, pldm_fileio_file_type pldmDumpType,
elog<NotAllowed>(Reason("New file available via pldm is not "
"allowed due to new file request send failed"));
}
freePLDMInstanceID(pldmInstanceId, mctpEndPointId);
pldmClose();
}

} // namespace openpower::dump::pldm
185 changes: 133 additions & 52 deletions dump/pldm_utils.cpp
Original file line number Diff line number Diff line change
@@ -1,93 +1,174 @@
// SPDX-License-Identifier: Apache-2.0

#include "pldm_utils.hpp"

#include "xyz/openbmc_project/Common/error.hpp"

#include <fmt/core.h>
#include <libpldm/base.h>
#include <libpldm/pldm.h>
#include <libpldm/transport.h>
#include <libpldm/transport/mctp-demux.h>
#include <poll.h>

#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>

namespace openpower::dump::pldm
{

using namespace phosphor::logging;
namespace internal
using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;

pldm_instance_db* pldmInstanceIdDb = nullptr;
pldm_transport* pldmTransport = nullptr;
pldm_transport_mctp_demux* mctpDemux = nullptr;

PLDMInstanceManager::PLDMInstanceManager()
{
std::string getService(sdbusplus::bus::bus& bus, const std::string& path,
const std::string& interface)
initPLDMInstanceIdDb();
}

PLDMInstanceManager::~PLDMInstanceManager()
{
using namespace phosphor::logging;
constexpr auto objectMapperName = "xyz.openbmc_project.ObjectMapper";
constexpr auto objectMapperPath = "/xyz/openbmc_project/object_mapper";
destroyPLDMInstanceIdDb();
}

auto method = bus.new_method_call(objectMapperName, objectMapperPath,
objectMapperName, "GetObject");
void initPLDMInstanceIdDb()
{
auto rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
if (rc)
{
log<level::ERR>(
std::format("Error calling pldm_instance_db_init_default RC{}", rc)
.c_str());
elog<NotAllowed>(
Reason("Required host dump action via pldm is not allowed due "
"to initPLDMInstanceIdDb failed"));
}
}

method.append(path);
method.append(std::vector<std::string>({interface}));
void destroyPLDMInstanceIdDb()
{
auto rc = pldm_instance_db_destroy(pldmInstanceIdDb);
if (rc)
{
log<level::ERR>(
std::format("pldm_instance_db_destroy failed RC{}", rc).c_str());
}
}

std::vector<std::pair<std::string, std::vector<std::string>>> response;
pldm_instance_id_t getPLDMInstanceID(uint8_t tid)
{
pldm_instance_id_t instanceID = 0;

try
auto rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &instanceID);
if (rc == -EAGAIN)
{
auto reply = bus.call(method);
reply.read(response);
if (response.empty())
{
log<level::ERR>(fmt::format("Error in mapper response for getting "
"service name, PATH({}), INTERFACE({})",
path, interface)
.c_str());
return std::string{};
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &instanceID);
}
catch (const sdbusplus::exception::exception& e)

if (rc)
{
log<level::ERR>(fmt::format("Error in mapper method call, "
"errormsg({}), PATH({}), INTERFACE({})",
e.what(), path, interface)
.c_str());
return std::string{};
log<level::ERR>(
std::format(
"getPLDMInstanceID: Failed to alloc ID for TID {}. RC{}", tid,
rc)
.c_str());
elog<NotAllowed>(
Reason("Failure in communicating with libpldm service, "
"service may not be running"));
}
return response[0].first;
log<level::INFO>(
std::format("got tid {} and set instanceID to {}", tid, instanceID)
.c_str());

return instanceID;
}
} // namespace internal

using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
void freePLDMInstanceID(pldm_instance_id_t instanceID, uint8_t tid)
{
auto rc = pldm_instance_id_free(pldmInstanceIdDb, tid, instanceID);
if (rc)
{
log<level::ERR>(
std::format(
"freePLDMInstanceID: Failed to free ID {} for TID {}. RC{}",
instanceID, tid, rc)
.c_str());
}
}

int openPLDM()
int openPLDM(mctp_eid_t eid)
{
auto fd = pldm_open();
auto fd = -1;
if (pldmTransport)
{
log<level::ERR>("openPLDM: pldmTransport already setup!");
elog<NotAllowed>(
Reason("Required host dump action via pldm is not allowed because "
"pldmTransport already setup"));
return fd;
}
fd = openMctpDemuxTransport(eid);
if (fd < 0)
{
auto e = errno;
log<level::ERR>(fmt::format("pldm_open failed, errno({}), FD({})", e,
static_cast<int>(fd))
.c_str());
elog<NotAllowed>(Reason("Required host dump action via pldm is not "
"allowed due to pldm_open failed"));
log<level::ERR>(
fmt::format("openPLDM failed, errno({}), FD({})", e, fd).c_str());
elog<NotAllowed>(
Reason("Required host dump action via pldm is not allowed due "
"to openPLDM failed"));
}
return fd;
}

uint8_t getPLDMInstanceID(uint8_t eid)
int openMctpDemuxTransport(mctp_eid_t eid)
{
constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
constexpr auto pldm = "/xyz/openbmc_project/pldm";

auto bus = sdbusplus::bus::new_default();
auto service = internal::getService(bus, pldm, pldmRequester);
int rc = pldm_transport_mctp_demux_init(&mctpDemux);
if (rc)
{
log<level::ERR>(std::format("openMctpDemuxTransport: Failed to init "
"MCTP demux transport, errno={}/{}",
rc, strerror(rc))
.c_str());
return rc;
}

auto method = bus.new_method_call(service.c_str(), pldm, pldmRequester,
"GetInstanceId");
method.append(eid);
auto reply = bus.call(method);
rc = pldm_transport_mctp_demux_map_tid(mctpDemux, eid, eid);
if (rc)
{
log<level::ERR>(std::format("openMctpDemuxTransport: Failed to setup "
"tid to eid mapping, errno={}/{}",
errno, strerror(errno))
.c_str());
pldmClose();
return rc;
}
pldmTransport = pldm_transport_mctp_demux_core(mctpDemux);

uint8_t instanceID = 0;
reply.read(instanceID);
struct pollfd pollfd;
rc = pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd);
if (rc)
{
log<level::ERR>(
std::format(
"openMctpDemuxTransport: Failed to get pollfd , errno={}/{}",
errno, strerror(errno))
.c_str());
pldmClose();
return rc;
}
return pollfd.fd;
}

return instanceID;
void pldmClose()
{
pldm_transport_mctp_demux_destroy(mctpDemux);
mctpDemux = nullptr;
pldmTransport = nullptr;
}

} // namespace openpower::dump::pldm
Loading

0 comments on commit b116fb3

Please sign in to comment.