Rashmica Gupta | 1ed5f7a | 2023-05-22 13:56:42 +1000 | [diff] [blame] | 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(pldm_tid_t tid, const void* tx, |
| 155 | size_t txLen, void*& rx, |
| 156 | size_t& rxLen) |
| 157 | { |
| 158 | return pldm_transport_send_recv_msg(transport, tid, tx, txLen, &rx, &rxLen); |
| 159 | } |