| #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); |
| } |