1 #include "common/transport.hpp" 2 3 #include <libpldm/transport.h> 4 #include <libpldm/transport/af-mctp.h> 5 #include <libpldm/transport/mctp-demux.h> 6 7 #include <algorithm> 8 #include <ranges> 9 #include <system_error> 10 11 struct pldm_transport* transport_impl_init(TransportImpl& impl, pollfd& pollfd); 12 void transport_impl_destroy(TransportImpl& impl); 13 14 static constexpr uint8_t MCTP_EID_VALID_MIN = 8; 15 static constexpr uint8_t MCTP_EID_VALID_MAX = 255; 16 17 /* 18 * Currently the OpenBMC ecosystem assumes TID == EID. Pre-populate the TID 19 * mappings over the EID space excluding the Null (0), Reserved (1 to 7), 20 * Broadcast EIDs (255) defined by Section 8.2 Special endpoint IDs in DSP0236 21 * v1.3.1. Further, by Section 8.1.1 SetTID command (0x01) in DSP0240 v1.1.0, 22 * the TIDs 0x00 and 0xff are also reserved. These overlap with the reserved 23 * EIDs so no additional filtering is required. 24 * 25 * Further, pldmtool and pldmd are two separate processes. They are opening two 26 * different sockets, but with the mctp-demux-daemon, the response messages are 27 * broadcasted to all sockets. When pldmd receives the response for a request 28 * issued by pldmtool, pldm_transport_mctp_demux_recv() may return with error 29 * PLDM_REQUESTER_RECV_FAIL if it fails to map the EID of the source endpoint to 30 * its TID. The EID to TID mappings of pldmtool and pldmd should be coherent to 31 * prevent the failure of pldm_transport_mctp_demux_recv(). 32 */ 33 34 [[maybe_unused]] static struct pldm_transport* 35 pldm_transport_impl_mctp_demux_init(TransportImpl& impl, pollfd& pollfd) 36 { 37 impl.mctp_demux = nullptr; 38 pldm_transport_mctp_demux_init(&impl.mctp_demux); 39 if (!impl.mctp_demux) 40 { 41 return nullptr; 42 } 43 44 for (const auto eid : 45 std::views::iota(MCTP_EID_VALID_MIN, MCTP_EID_VALID_MAX)) 46 { 47 int rc = pldm_transport_mctp_demux_map_tid(impl.mctp_demux, eid, eid); 48 if (rc) 49 { 50 pldm_transport_af_mctp_destroy(impl.af_mctp); 51 return nullptr; 52 } 53 } 54 55 pldm_transport* pldmTransport = 56 pldm_transport_mctp_demux_core(impl.mctp_demux); 57 58 if (pldmTransport != nullptr) 59 { 60 pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd); 61 } 62 63 return pldmTransport; 64 } 65 66 [[maybe_unused]] static struct pldm_transport* 67 pldm_transport_impl_af_mctp_init(TransportImpl& impl, pollfd& pollfd) 68 { 69 impl.af_mctp = nullptr; 70 pldm_transport_af_mctp_init(&impl.af_mctp); 71 if (!impl.af_mctp) 72 { 73 return nullptr; 74 } 75 76 for (const auto eid : 77 std::views::iota(MCTP_EID_VALID_MIN, MCTP_EID_VALID_MAX)) 78 { 79 int rc = pldm_transport_af_mctp_map_tid(impl.af_mctp, eid, eid); 80 if (rc) 81 { 82 pldm_transport_af_mctp_destroy(impl.af_mctp); 83 return nullptr; 84 } 85 } 86 87 /* Listen for requests on any interface */ 88 if (pldm_transport_af_mctp_bind(impl.af_mctp, nullptr, 0)) 89 { 90 return nullptr; 91 } 92 93 pldm_transport* pldmTransport = pldm_transport_af_mctp_core(impl.af_mctp); 94 95 if (pldmTransport != nullptr) 96 { 97 pldm_transport_af_mctp_init_pollfd(pldmTransport, &pollfd); 98 } 99 100 return pldmTransport; 101 } 102 103 struct pldm_transport* transport_impl_init(TransportImpl& impl, pollfd& pollfd) 104 { 105 #if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX) 106 return pldm_transport_impl_mctp_demux_init(impl, pollfd); 107 #elif defined(PLDM_TRANSPORT_WITH_AF_MCTP) 108 return pldm_transport_impl_af_mctp_init(impl, pollfd); 109 #else 110 return nullptr; 111 #endif 112 } 113 114 void transport_impl_destroy(TransportImpl& impl) 115 { 116 #if defined(PLDM_TRANSPORT_WITH_MCTP_DEMUX) 117 pldm_transport_mctp_demux_destroy(impl.mctp_demux); 118 #elif defined(PLDM_TRANSPORT_WITH_AF_MCTP) 119 pldm_transport_af_mctp_destroy(impl.af_mctp); 120 #endif 121 } 122 123 PldmTransport::PldmTransport() 124 { 125 transport = transport_impl_init(impl, pfd); 126 if (!transport) 127 { 128 throw std::system_error(ENOMEM, std::generic_category()); 129 } 130 } 131 132 PldmTransport::~PldmTransport() 133 { 134 transport_impl_destroy(impl); 135 } 136 137 int PldmTransport::getEventSource() const 138 { 139 return pfd.fd; 140 } 141 142 pldm_requester_rc_t PldmTransport::sendMsg(pldm_tid_t tid, const void* tx, 143 size_t len) 144 { 145 return pldm_transport_send_msg(transport, tid, tx, len); 146 } 147 148 pldm_requester_rc_t PldmTransport::recvMsg(pldm_tid_t& tid, void*& rx, 149 size_t& len) 150 { 151 return pldm_transport_recv_msg(transport, &tid, (void**)&rx, &len); 152 } 153 154 pldm_requester_rc_t PldmTransport::sendRecvMsg( 155 pldm_tid_t tid, const void* tx, size_t txLen, void*& rx, size_t& rxLen) 156 { 157 return pldm_transport_send_recv_msg(transport, tid, tx, txLen, &rx, &rxLen); 158 } 159