xref: /openbmc/pldm/platform-mc/terminus_manager.hpp (revision fe2527954be36a3013dc6b8c8ff13ae649bb58a6)
1 #pragma once
2 
3 #include "config.h"
4 
5 #include "requester/handler.hpp"
6 #include "requester/mctp_endpoint_discovery.hpp"
7 #include "terminus.hpp"
8 
9 #include <libpldm/platform.h>
10 #include <libpldm/pldm.h>
11 
12 #include <limits>
13 #include <map>
14 #include <memory>
15 #include <optional>
16 #include <queue>
17 #include <utility>
18 #include <vector>
19 
20 namespace pldm
21 {
22 
23 enum class SupportedTransportLayer
24 {
25     MCTP
26 };
27 
28 namespace platform_mc
29 {
30 
31 /** @brief Size of TID Pool in pldmd */
32 constexpr size_t tidPoolSize = std::numeric_limits<pldm_tid_t>::max() + 1;
33 /** @brief Type definition for Requester request handler */
34 using RequesterHandler = requester::Handler<requester::Request>;
35 /** @brief Type definition for Terminus handler mapper */
36 using TerminiMapper = std::map<pldm_tid_t, std::shared_ptr<Terminus>>;
37 
38 class Manager;
39 /**
40  * @brief TerminusManager
41  *
42  * TerminusManager class to discover and initialize PLDM terminus.
43  */
44 class TerminusManager
45 {
46   public:
47     TerminusManager() = delete;
48     TerminusManager(const TerminusManager&) = delete;
49     TerminusManager(TerminusManager&&) = delete;
50     TerminusManager& operator=(const TerminusManager&) = delete;
51     TerminusManager& operator=(TerminusManager&&) = delete;
52     virtual ~TerminusManager() = default;
53 
TerminusManager(sdeventplus::Event & event,RequesterHandler & handler,pldm::InstanceIdDb & instanceIdDb,TerminiMapper & termini,Manager * manager,mctp_eid_t localEid)54     explicit TerminusManager(
55         sdeventplus::Event& event, RequesterHandler& handler,
56         pldm::InstanceIdDb& instanceIdDb, TerminiMapper& termini,
57         Manager* manager, mctp_eid_t localEid) :
58         handler(handler), instanceIdDb(instanceIdDb), termini(termini),
59         tidPool(tidPoolSize, false), manager(manager), localEid(localEid),
60         event(event)
61     {
62         // DSP0240 v1.1.0 table-8, special value: 0,0xFF = reserved
63         tidPool[0] = true;
64         tidPool[PLDM_TID_RESERVED] = true;
65     }
66 
67     /** @brief start a coroutine to discover terminus
68      *
69      *  @param[in] mctpInfos - list information of the MCTP endpoints
70      */
71     void discoverMctpTerminus(const MctpInfos& mctpInfos);
72 
73     /** @brief remove MCTP endpoints
74      *
75      *  @param[in] mctpInfos - list information of the MCTP endpoints
76      */
77     void removeMctpTerminus(const MctpInfos& mctpInfos);
78 
79     /** @brief Send request PLDM message to tid. The function will return when
80      *         received the response message from terminus. The function will
81      *         auto get the instanceID from libmctp and update to request
82      *         message.
83      *
84      *  @param[in] tid - Destination TID
85      *  @param[in] request - request PLDM message
86      *  @param[out] responseMsg - response PLDM message
87      *  @param[out] responseLen - length of response PLDM message
88      *  @return coroutine return_value - PLDM completion code
89      */
90     exec::task<int> sendRecvPldmMsg(pldm_tid_t tid, Request& request,
91                                     const pldm_msg** responseMsg,
92                                     size_t* responseLen);
93 
94     /** @brief Send request PLDM message to eid. The function will
95      *         return when received the response message from terminus.
96      *
97      *  @param[in] eid - Destination EID
98      *  @param[in] request - request PLDM message
99      *  @param[out] responseMsg - response PLDM message
100      *  @param[out] responseLen - length of response PLDM message
101      *  @return coroutine return_value - PLDM completion code
102      */
103     virtual exec::task<int> sendRecvPldmMsgOverMctp(
104         mctp_eid_t eid, Request& request, const pldm_msg** responseMsg,
105         size_t* responseLen);
106 
107     /** @brief member functions to map/unmap tid
108      */
109     std::optional<MctpInfo> toMctpInfo(const pldm_tid_t& tid);
110 
111     /** @brief Member functions to response the TID of specific MCTP interface
112      *
113      *  @param[in] mctpInfos - list information of the MCTP endpoints
114      *
115      *  @return tid - Terminus tid
116      */
117     std::optional<pldm_tid_t> toTid(const MctpInfo& mctpInfo) const;
118 
119     /** @brief Member functions to find the TID for MCTP interface. Response the
120      *         Terminus TID when mctpInfo is already in the data base. Response
121      *         new tid from pool when mctpInfo is new.
122      *
123      *  @param[in] mctpInfos - list information of the MCTP endpoints
124      *
125      *  @return tid - Terminus tid
126      */
127     std::optional<pldm_tid_t> mapTid(const MctpInfo& mctpInfo);
128 
129     /** @brief Member functions to store the mctp info and tid to terminus info
130      *         list.
131      *
132      *  @param[in] mctpInfos - list information of the MCTP endpoints
133      *  @param[in] tid - Destination TID
134      *
135      *  @return tid - Terminus tid
136      */
137     std::optional<pldm_tid_t> storeTerminusInfo(const MctpInfo& mctpInfo,
138                                                 pldm_tid_t tid);
139 
140     /** @brief Member functions to remove the TID from the transportLayer and
141      *         mctpInfo table
142      *
143      *  @param[in] tid - Destination TID
144      *
145      *  @return true/false - True when tid in the table otherwise return false
146      */
147     bool unmapTid(const pldm_tid_t& tid);
148 
149     /** @brief getter of local EID
150      *
151      *  @return uint8_t - local EID
152      */
getLocalEid()153     mctp_eid_t getLocalEid()
154     {
155         return localEid;
156     }
157 
158     /** @brief Helper function to invoke registered handlers for
159      *  updating the availability status of the MCTP endpoint
160      *
161      *  @param[in] mctpInfo - information of the target endpoint
162      *  @param[in] availability - new availability status
163      */
164     void updateMctpEndpointAvailability(const MctpInfo& mctpInfo,
165                                         Availability availability);
166 
167     /** @brief Construct MCTP Endpoint object path base on the MCTP endpoint
168      *  info
169      *
170      *  @param[in] mctpInfo - information of the target endpoint
171      */
172     std::string constructEndpointObjPath(const MctpInfo& mctpInfo);
173 
174     /** @brief Member functions to get the MCTP eid of active MCTP medium
175      *         interface of one terminus by terminus name
176      *
177      *  @param[in] terminusName - terminus name
178      *
179      *  @return option mctp_eid_t - the mctp eid or std::nullopt
180      */
181     std::optional<mctp_eid_t> getActiveEidByName(
182         const std::string& terminusName);
183 
184   private:
185     /** @brief Find the terminus object pointer in termini list.
186      *
187      *  @param[in] mctpInfos - list information of the MCTP endpoints
188      */
189     TerminiMapper::iterator findTerminusPtr(const MctpInfo& mctpInfo);
190 
191     /** @brief The coroutine task execute by discoverMctpTerminus()
192      *
193      *  @return coroutine return_value - PLDM completion code
194      */
195     exec::task<int> discoverMctpTerminusTask();
196 
197     /** @brief Initialize terminus and then instantiate terminus object to keeps
198      *         the data fetched from terminus
199      *
200      *  @param[in] mctpInfo - information of the MCTP endpoints
201      *  @return coroutine return_value - PLDM completion code
202      */
203     exec::task<int> initMctpTerminus(const MctpInfo& mctpInfo);
204 
205     /** @brief Send getTID PLDM command to destination EID and then return the
206      *         value of tid in reference parameter.
207      *
208      *  @param[in] eid - Destination EID
209      *  @param[out] tid - Terminus TID
210      *  @return coroutine return_value - PLDM completion code
211      */
212     exec::task<int> getTidOverMctp(mctp_eid_t eid, pldm_tid_t* tid);
213 
214     /** @brief Send setTID command to destination EID.
215      *
216      *  @param[in] eid - Destination EID
217      *  @param[in] tid - Destination TID
218      *  @return coroutine return_value - PLDM completion code
219      */
220     exec::task<int> setTidOverMctp(mctp_eid_t eid, pldm_tid_t tid);
221 
222     /** @brief Send getPLDMTypes command to destination TID and then return the
223      *         value of supportedTypes in reference parameter.
224      *
225      *  @param[in] tid - Destination TID
226      *  @param[out] supportedTypes - Supported Types returned from terminus
227      *  @return coroutine return_value - PLDM completion code
228      */
229     exec::task<int> getPLDMTypes(pldm_tid_t tid, uint64_t& supportedTypes);
230 
231     /** @brief Send getPLDMVersion command to destination TID and then return
232      *         the version of the PLDM supported type.
233      *
234      *  @param[in] tid - Destination TID
235      *  @param[in] type - PLDM Type
236      *  @param[out] version - PLDM Type version
237      *  @return coroutine return_value - PLDM completion code
238      */
239     exec::task<int> getPLDMVersion(pldm_tid_t tid, uint8_t type,
240                                    ver32_t* version);
241 
242     /** @brief Send getPLDMCommands command to destination TID and then return
243      *         the value of supportedCommands in reference parameter.
244      *
245      *  @param[in] tid - Destination TID
246      *  @param[in] type - PLDM Type
247      *  @param[in] version - PLDM Type version
248      *  @param[in] supportedCmds - Supported commands returned from terminus
249      *                             for specific type
250      *  @return coroutine return_value - PLDM completion code
251      */
252     exec::task<int> getPLDMCommands(pldm_tid_t tid, uint8_t type,
253                                     ver32_t version,
254                                     bitfield8_t* supportedCmds);
255 
256     /** @brief Reference to a Handler object that manages the request/response
257      *         logic.
258      */
259     RequesterHandler& handler;
260 
261     /** @brief Reference to the instanceID data base from libpldm */
262     pldm::InstanceIdDb& instanceIdDb;
263 
264     /** @brief Managed termini list */
265     TerminiMapper& termini;
266 
267     /** @brief tables for maintaining assigned TID */
268     std::vector<bool> tidPool;
269 
270     /** @brief Store the supported transport layers of specific TID */
271     std::map<pldm_tid_t, SupportedTransportLayer> transportLayerTable;
272 
273     /** @brief Store the supported MCTP interface info of specific TID */
274     std::map<pldm_tid_t, MctpInfo> mctpInfoTable;
275 
276     /** @brief A queue of MctpInfos to be discovered **/
277     std::queue<MctpInfos> queuedMctpInfos{};
278 
279     /** @brief coroutine handle of discoverTerminusTask */
280     std::optional<std::pair<exec::async_scope, std::optional<int>>>
281         discoverMctpTerminusTaskHandle{};
282 
283     /** @brief A Manager interface for calling the hook functions **/
284     Manager* manager;
285 
286     /** @brief local EID */
287     mctp_eid_t localEid;
288 
289     /** @brief MCTP Endpoint available status mapping */
290     std::map<MctpInfo, Availability> mctpInfoAvailTable;
291 
292     /** @brief reference of main event loop of pldmd, primarily used to schedule
293      *  work
294      */
295     sdeventplus::Event& event;
296 };
297 } // namespace platform_mc
298 } // namespace pldm
299