blob: d9924151f22ecb10bd40e051c428b7d2ae34d749 [file] [log] [blame]
#include "common/transport.hpp"
#include <libpldm/transport.h>
#include <libpldm/transport/af-mctp.h>
#include <libpldm/transport/mctp-demux.h>
#include <algorithm>
#include <ranges>
#include <system_error>
struct pldm_transport* transport_impl_init(TransportImpl& impl, pollfd& pollfd);
void transport_impl_destroy(TransportImpl& impl);
static constexpr uint8_t MCTP_EID_VALID_MIN = 8;
static constexpr uint8_t MCTP_EID_VALID_MAX = 255;
/*
* Currently the OpenBMC ecosystem assumes TID == EID. Pre-populate the TID
* mappings over the EID space excluding the Null (0), Reserved (1 to 7),
* Broadcast EIDs (255) defined by Section 8.2 Special endpoint IDs in DSP0236
* v1.3.1. Further, by Section 8.1.1 SetTID command (0x01) in DSP0240 v1.1.0,
* the TIDs 0x00 and 0xff are also reserved. These overlap with the reserved
* EIDs so no additional filtering is required.
*
* Further, pldmtool and pldmd are two separate processes. They are opening two
* different sockets, but with the mctp-demux-daemon, the response messages are
* broadcasted to all sockets. When pldmd receives the response for a request
* issued by pldmtool, pldm_transport_mctp_demux_recv() may return with error
* PLDM_REQUESTER_RECV_FAIL if it fails to map the EID of the source endpoint to
* its TID. The EID to TID mappings of pldmtool and pldmd should be coherent to
* prevent the failure of pldm_transport_mctp_demux_recv().
*/
[[maybe_unused]] static struct pldm_transport*
pldm_transport_impl_mctp_demux_init(TransportImpl& impl, pollfd& pollfd)
{
impl.mctp_demux = nullptr;
pldm_transport_mctp_demux_init(&impl.mctp_demux);
if (!impl.mctp_demux)
{
return nullptr;
}
for (const auto eid :
std::views::iota(MCTP_EID_VALID_MIN, MCTP_EID_VALID_MAX))
{
int rc = pldm_transport_mctp_demux_map_tid(impl.mctp_demux, eid, eid);
if (rc)
{
pldm_transport_af_mctp_destroy(impl.af_mctp);
return nullptr;
}
}
pldm_transport* pldmTransport =
pldm_transport_mctp_demux_core(impl.mctp_demux);
if (pldmTransport != nullptr)
{
pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd);
}
return pldmTransport;
}
[[maybe_unused]] static struct pldm_transport*
pldm_transport_impl_af_mctp_init(TransportImpl& impl, pollfd& pollfd)
{
impl.af_mctp = nullptr;
pldm_transport_af_mctp_init(&impl.af_mctp);
if (!impl.af_mctp)
{
return nullptr;
}
for (const auto eid :
std::views::iota(MCTP_EID_VALID_MIN, MCTP_EID_VALID_MAX))
{
int rc = pldm_transport_af_mctp_map_tid(impl.af_mctp, eid, eid);
if (rc)
{
pldm_transport_af_mctp_destroy(impl.af_mctp);
return nullptr;
}
}
/* Listen for requests on any interface */
if (pldm_transport_af_mctp_bind(impl.af_mctp, nullptr, 0))
{
return nullptr;
}
pldm_transport* pldmTransport = pldm_transport_af_mctp_core(impl.af_mctp);
if (pldmTransport != nullptr)
{
pldm_transport_af_mctp_init_pollfd(pldmTransport, &pollfd);
}
return pldmTransport;
}
struct pldm_transport* transport_impl_init(TransportImpl& impl, pollfd& pollfd)
{
#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
return pldm_transport_impl_mctp_demux_init(impl, pollfd);
#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
return pldm_transport_impl_af_mctp_init(impl, pollfd);
#else
return nullptr;
#endif
}
void transport_impl_destroy(TransportImpl& impl)
{
#if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX)
pldm_transport_mctp_demux_destroy(impl.mctp_demux);
#elif defined(PLDM_TRANSPORT_WITH_AF_MCTP)
pldm_transport_af_mctp_destroy(impl.af_mctp);
#endif
}
PldmTransport::PldmTransport()
{
transport = transport_impl_init(impl, pfd);
if (!transport)
{
throw std::system_error(ENOMEM, std::generic_category());
}
}
PldmTransport::~PldmTransport()
{
transport_impl_destroy(impl);
}
int PldmTransport::getEventSource() const
{
return pfd.fd;
}
pldm_requester_rc_t PldmTransport::sendMsg(pldm_tid_t tid, const void* tx,
size_t len)
{
return pldm_transport_send_msg(transport, tid, tx, len);
}
pldm_requester_rc_t PldmTransport::recvMsg(pldm_tid_t& tid, void*& rx,
size_t& len)
{
return pldm_transport_recv_msg(transport, &tid, (void**)&rx, &len);
}
pldm_requester_rc_t PldmTransport::sendRecvMsg(pldm_tid_t tid, const void* tx,
size_t txLen, void*& rx,
size_t& rxLen)
{
return pldm_transport_send_recv_msg(transport, tid, tx, txLen, &rx, &rxLen);
}