xref: /openbmc/pldm/common/transport.cpp (revision 16c2a0a0)
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*
pldm_transport_impl_mctp_demux_init(TransportImpl & impl,pollfd & pollfd)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*
pldm_transport_impl_af_mctp_init(TransportImpl & impl,pollfd & pollfd)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 
transport_impl_init(TransportImpl & impl,pollfd & pollfd)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 
transport_impl_destroy(TransportImpl & impl)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 
PldmTransport()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 
~PldmTransport()132 PldmTransport::~PldmTransport()
133 {
134     transport_impl_destroy(impl);
135 }
136 
getEventSource() const137 int PldmTransport::getEventSource() const
138 {
139     return pfd.fd;
140 }
141 
sendMsg(pldm_tid_t tid,const void * tx,size_t len)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 
recvMsg(pldm_tid_t & tid,void * & rx,size_t & len)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 
sendRecvMsg(pldm_tid_t tid,const void * tx,size_t txLen,void * & rx,size_t & rxLen)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