xref: /openbmc/pldm/platform-mc/manager.hpp (revision fe2527954be36a3013dc6b8c8ff13ae649bb58a6)
1 #pragma once
2 
3 #include "common/instance_id.hpp"
4 #include "common/types.hpp"
5 #include "event_manager.hpp"
6 #include "platform_manager.hpp"
7 #include "requester/handler.hpp"
8 #include "requester/mctp_endpoint_discovery.hpp"
9 #include "sensor_manager.hpp"
10 #include "terminus_manager.hpp"
11 
12 #include <libpldm/pldm.h>
13 
14 namespace pldm
15 {
16 namespace platform_mc
17 {
18 
19 using PollHandler = std::function<exec::task<int>(pldm_tid_t tid)>;
20 using PollHandlers = std::vector<PollHandler>;
21 
22 /**
23  * @brief Manager
24  *
25  * This class handles all the aspect of the PLDM Platform Monitoring and Control
26  * specification for the MCTP devices
27  */
28 class Manager : public pldm::MctpDiscoveryHandlerIntf
29 {
30   public:
31     Manager() = delete;
32     Manager(const Manager&) = delete;
33     Manager(Manager&&) = delete;
34     Manager& operator=(const Manager&) = delete;
35     Manager& operator=(Manager&&) = delete;
36     ~Manager() = default;
37 
Manager(sdeventplus::Event & event,RequesterHandler & handler,pldm::InstanceIdDb & instanceIdDb)38     explicit Manager(sdeventplus::Event& event, RequesterHandler& handler,
39                      pldm::InstanceIdDb& instanceIdDb) :
40         terminusManager(event, handler, instanceIdDb, termini, this,
41                         pldm::BmcMctpEid),
42         platformManager(terminusManager, termini, this),
43         sensorManager(event, terminusManager, termini, this),
44         eventManager(terminusManager, termini)
45     {}
46 
47     /** @brief Helper function to do the actions before discovering terminus
48      *
49      *  @return coroutine return_value - PLDM completion code
50      */
51     exec::task<int> beforeDiscoverTerminus();
52 
53     /** @brief Helper function to do the actions after discovering terminus
54      *
55      *  @return coroutine return_value - PLDM completion code
56      */
57     exec::task<int> afterDiscoverTerminus();
58 
59     /** @brief Helper function to invoke registered handlers for
60      *         the added MCTP endpoints
61      *
62      *  @param[in] mctpInfos - list information of the MCTP endpoints
63      */
handleMctpEndpoints(const MctpInfos & mctpInfos)64     void handleMctpEndpoints(const MctpInfos& mctpInfos)
65     {
66         terminusManager.discoverMctpTerminus(mctpInfos);
67     }
68 
69     /** @brief Helper function to invoke registered handlers for
70      *         the removed MCTP endpoints
71      *
72      *  @param[in] mctpInfos - list information of the MCTP endpoints
73      */
handleRemovedMctpEndpoints(const MctpInfos & mctpInfos)74     void handleRemovedMctpEndpoints(const MctpInfos& mctpInfos)
75     {
76         terminusManager.removeMctpTerminus(mctpInfos);
77     }
78 
79     /** @brief Helper function to invoke registered handlers for
80      *  updating the availability status of the MCTP endpoint
81      *
82      *  @param[in] mctpInfo - information of the target endpoint
83      *  @param[in] availability - new availability status
84      */
updateMctpEndpointAvailability(const MctpInfo & mctpInfo,Availability availability)85     void updateMctpEndpointAvailability(const MctpInfo& mctpInfo,
86                                         Availability availability)
87     {
88         /* Get TID of initialized terminus */
89         auto tid = terminusManager.toTid(mctpInfo);
90         if (tid)
91         {
92             if (availability)
93             {
94                 sensorManager.startSensorPollTimer(tid.value());
95             }
96             else
97             {
98                 sensorManager.disableTerminusSensors(tid.value());
99             }
100             updateAvailableState(tid.value(), availability);
101         }
102         terminusManager.updateMctpEndpointAvailability(mctpInfo, availability);
103     }
104 
105     /** @brief Helper function to start sensor polling of the terminus TID
106      */
startSensorPolling(pldm_tid_t tid)107     void startSensorPolling(pldm_tid_t tid)
108     {
109         sensorManager.startPolling(tid);
110     }
111 
112     /** @brief Helper function to set available state for pldm request (sensor
113      *         polling and event polling) of the terminus TID. The `false` state
114      *         will trigger stop flow in coroutine of sensor polling/event
115      *         polling task to stop.
116      */
updateAvailableState(pldm_tid_t tid,Availability state)117     void updateAvailableState(pldm_tid_t tid, Availability state)
118     {
119         if (termini.contains(tid))
120         {
121             sensorManager.updateAvailableState(tid, state);
122             eventManager.updateAvailableState(tid, state);
123         }
124     }
125 
126     /** @brief Helper function to stop sensor polling of the terminus TID
127      */
stopSensorPolling(pldm_tid_t tid)128     void stopSensorPolling(pldm_tid_t tid)
129     {
130         sensorManager.stopPolling(tid);
131     }
132 
133     /** @brief Sensor event handler function
134      *
135      *  @param[in] request - Event message
136      *  @param[in] payloadLength - Event message payload size
137      *  @param[in] tid - Terminus ID
138      *  @param[in] eventDataOffset - Event data offset
139      *
140      *  @return PLDM error code: PLDM_SUCCESS when there is no error in handling
141      *          the event
142      */
handleSensorEvent(const pldm_msg * request,size_t payloadLength,uint8_t,uint8_t tid,size_t eventDataOffset)143     int handleSensorEvent(const pldm_msg* request, size_t payloadLength,
144                           uint8_t /* formatVersion */, uint8_t tid,
145                           size_t eventDataOffset)
146     {
147         auto eventData = reinterpret_cast<const uint8_t*>(request->payload) +
148                          eventDataOffset;
149         auto eventDataSize = payloadLength - eventDataOffset;
150         eventManager.handlePlatformEvent(tid, PLDM_PLATFORM_EVENT_ID_NULL,
151                                          PLDM_SENSOR_EVENT, eventData,
152                                          eventDataSize);
153         return PLDM_SUCCESS;
154     }
155 
156     /** @brief CPER event handler function
157      *
158      *  @param[in] request - Event message
159      *  @param[in] payloadLength - Event message payload size
160      *  @param[in] tid - Terminus ID
161      *  @param[in] eventDataOffset - Event data offset
162      *
163      *  @return PLDM error code: PLDM_SUCCESS when there is no error in handling
164      *          the event
165      */
handleCperEvent(const pldm_msg * request,size_t payloadLength,uint8_t,uint8_t tid,size_t eventDataOffset)166     int handleCperEvent(const pldm_msg* request, size_t payloadLength,
167                         uint8_t /* formatVersion */, uint8_t tid,
168                         size_t eventDataOffset)
169     {
170         auto eventData =
171             const_cast<const uint8_t*>(request->payload) + eventDataOffset;
172         auto eventDataSize = payloadLength - eventDataOffset;
173         eventManager.handlePlatformEvent(tid, PLDM_PLATFORM_EVENT_ID_NULL,
174                                          PLDM_CPER_EVENT, eventData,
175                                          eventDataSize);
176         return PLDM_SUCCESS;
177     }
178 
179     /** @brief PLDM POLL event handler function
180      *
181      *  @param[in] request - Event message
182      *  @param[in] payloadLength - Event message payload size
183      *  @param[in] tid - Terminus ID
184      *  @param[in] eventDataOffset - Event data offset
185      *
186      *  @return PLDM error code: PLDM_SUCCESS when there is no error in handling
187      *          the event
188      */
handlePldmMessagePollEvent(const pldm_msg * request,size_t payloadLength,uint8_t,uint8_t tid,size_t eventDataOffset)189     int handlePldmMessagePollEvent(
190         const pldm_msg* request, size_t payloadLength,
191         uint8_t /* formatVersion */, uint8_t tid, size_t eventDataOffset)
192     {
193         auto eventData = reinterpret_cast<const uint8_t*>(request->payload) +
194                          eventDataOffset;
195         auto eventDataSize = payloadLength - eventDataOffset;
196         eventManager.handlePlatformEvent(tid, PLDM_PLATFORM_EVENT_ID_NULL,
197                                          PLDM_MESSAGE_POLL_EVENT, eventData,
198                                          eventDataSize);
199         return PLDM_SUCCESS;
200     }
201 
202     /** @brief The function to trigger the event polling
203      *
204      *  @param[in] tid - Terminus ID
205      *  @param[in] pollEventId - The source eventID from pldmMessagePollEvent
206      *  @param[in] pollDataTransferHandle - The dataTransferHandle from
207      *             pldmMessagePollEvent event
208      *  @return coroutine return_value - PLDM completion code
209      */
210     exec::task<int> pollForPlatformEvent(pldm_tid_t tid, uint16_t pollEventId,
211                                          uint32_t pollDataTransferHandle);
212 
213     /** @brief Handle Polled CPER event
214      *
215      *  @param[in] tid - tid where the event is from
216      *  @param[in] eventId - event Id
217      *  @param[in] eventData - event data
218      *  @param[in] eventDataSize - size of event data
219      *  @return PLDM completion code
220      */
handlePolledCperEvent(pldm_tid_t tid,uint16_t eventId,const uint8_t * eventData,size_t eventDataSize)221     int handlePolledCperEvent(pldm_tid_t tid, uint16_t eventId,
222                               const uint8_t* eventData, size_t eventDataSize)
223     {
224         return eventManager.handlePlatformEvent(tid, eventId, PLDM_CPER_EVENT,
225                                                 eventData, eventDataSize);
226     }
227 
228     /** @brief The helper function to allow register the handler function for
229      *         the polled event by PollForPlatformEventMessage
230      *
231      *  @param[in] eventClass - Event class
232      *  @param[in] handlerFunc - Event handler
233      *
234      */
registerPolledEventHandler(uint8_t eventClass,pldm::platform_mc::HandlerFuncs handlers)235     void registerPolledEventHandler(uint8_t eventClass,
236                                     pldm::platform_mc::HandlerFuncs handlers)
237     {
238         eventManager.registerPolledEventHandler(eventClass, handlers);
239     }
240 
241     /** @brief Register OEM flow to poll the PLDM Event use
242      *         PollForPlatformEventMessage command
243      *
244      *  @param[in] handler - Poll event handlerr
245      */
registerOEMPollMethod(PollHandler handler)246     void registerOEMPollMethod(PollHandler handler)
247     {
248         pollHandlers.push_back(std::move(handler));
249     }
250 
251     /** @brief OEM task to do OEM event polling
252      *
253      *  @param[in] tid - Destination TID
254      *  @return coroutine return_value - PLDM completion code
255      */
256     exec::task<int> oemPollForPlatformEvent(pldm_tid_t tid);
257 
258     /** @brief Get Active EIDs.
259      *
260      *  @param[in] addr - MCTP address of terminus
261      *  @param[in] terminiNames - MCTP terminus name
262      */
getActiveEidByName(const std::string & terminusName)263     std::optional<mctp_eid_t> getActiveEidByName(
264         const std::string& terminusName)
265     {
266         return terminusManager.getActiveEidByName(terminusName);
267     }
268 
269   private:
270     /** @brief List of discovered termini */
271     TerminiMapper termini{};
272 
273     /** @brief Terminus interface for calling the hook functions */
274     TerminusManager terminusManager;
275 
276     /** @brief Platform interface for calling the hook functions */
277     PlatformManager platformManager;
278 
279     /** @brief Store platform manager handler */
280     SensorManager sensorManager;
281 
282     /** @brief Store event manager handler */
283     EventManager eventManager;
284 
285     /** @brief map of PLDM event type to EventHandlers */
286     PollHandlers pollHandlers;
287 };
288 } // namespace platform_mc
289 } // namespace pldm
290