blob: d9924151f22ecb10bd40e051c428b7d2ae34d749 [file] [log] [blame]
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +10001#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
11struct pldm_transport* transport_impl_init(TransportImpl& impl, pollfd& pollfd);
12void transport_impl_destroy(TransportImpl& impl);
13
14static constexpr uint8_t MCTP_EID_VALID_MIN = 8;
15static 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
103struct 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
114void 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
123PldmTransport::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
132PldmTransport::~PldmTransport()
133{
134 transport_impl_destroy(impl);
135}
136
137int PldmTransport::getEventSource() const
138{
139 return pfd.fd;
140}
141
142pldm_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
148pldm_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
154pldm_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}