blob: b907af4847b744c988783f79c30fe903af122b31 [file] [log] [blame]
Matt Spinler5c350fd2019-12-12 13:53:53 -06001#pragma once
2
3#include "host_interface.hpp"
4
Patrick Williams49bcbe92024-06-26 23:06:54 -05005#include <libpldm/instance-id.h>
Matt Spinler5c350fd2019-12-12 13:53:53 -06006#include <libpldm/pldm.h>
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -05007#include <libpldm/transport.h>
8#include <libpldm/transport/mctp-demux.h>
Matt Spinler5c350fd2019-12-12 13:53:53 -06009
Matt Spinler5c350fd2019-12-12 13:53:53 -060010#include <sdeventplus/clock.hpp>
11#include <sdeventplus/source/io.hpp>
12#include <sdeventplus/utility/timer.hpp>
13
Patrick Williams2544b412022-10-04 08:41:06 -050014#include <chrono>
15#include <memory>
16
Matt Spinler5c350fd2019-12-12 13:53:53 -060017namespace openpower::pels
18{
19
20/**
21 * @class PLDMInterface
22 *
23 * This class handles sending the 'new file available' PLDM
24 * command to the host to notify it of a new PEL's ID and size.
25 *
26 * The command response is asynchronous.
27 */
28class PLDMInterface : public HostInterface
29{
30 public:
31 PLDMInterface() = delete;
32 PLDMInterface(const PLDMInterface&) = default;
33 PLDMInterface& operator=(const PLDMInterface&) = default;
34 PLDMInterface(PLDMInterface&&) = default;
35 PLDMInterface& operator=(PLDMInterface&&) = default;
36
37 /**
38 * @brief Constructor
39 *
40 * @param[in] event - The sd_event object pointer
41 * @param[in] dataIface - The DataInterface object
42 */
43 PLDMInterface(sd_event* event, DataInterfaceBase& dataIface) :
44 HostInterface(event, dataIface),
45 _receiveTimer(
46 event,
47 std::bind(std::mem_fn(&PLDMInterface::receiveTimerExpired), this))
48 {
Patrick Williams49bcbe92024-06-26 23:06:54 -050049 pldm_instance_db_init_default(&_pldm_idb);
Matt Spinler2843ba22020-03-03 16:36:32 -060050
Matt Spinler5c350fd2019-12-12 13:53:53 -060051 readEID();
52 }
53
54 /**
55 * @brief Destructor
56 */
57 ~PLDMInterface();
58
59 /**
60 * @brief Kicks off the send of the 'new file available' command
61 * to send up the ID and size of the new PEL.
62 *
Matt Spinler2843ba22020-03-03 16:36:32 -060063 * It starts by issuing the async D-Bus method call to read the
64 * instance ID.
65 *
Matt Spinler5c350fd2019-12-12 13:53:53 -060066 * @param[in] id - The PEL ID
67 * @param[in] size - The PEL size in bytes
68 *
69 * @return CmdStatus - the success/fail status of the send
70 */
71 CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) override;
72
73 /**
74 * @brief Cancels waiting for a command response
Matt Spinler2843ba22020-03-03 16:36:32 -060075 *
76 * This will clear the instance ID so the next command
77 * will request a new one.
Matt Spinler5c350fd2019-12-12 13:53:53 -060078 */
79 void cancelCmd() override;
80
Matt Spinler2843ba22020-03-03 16:36:32 -060081 /**
82 * @brief Cleans up so that a new command is ready to be sent.
83 *
84 * Does not clear the instance ID.
85 */
86 void cleanupCmd();
87
Matt Spinler5c350fd2019-12-12 13:53:53 -060088 private:
89 /**
90 * @brief The asynchronous callback for getting the response
91 * of the 'new file available' command.
92 *
93 * Calls the response callback that is registered.
94 *
95 * @param[in] io - The event source object
96 * @param[in] fd - The FD used
97 * @param[in] revents - The event bits
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -050098 * @param[in] transport - The transport data pointer
Matt Spinler5c350fd2019-12-12 13:53:53 -060099 */
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -0500100 void receive(sdeventplus::source::IO& io, int fd, uint32_t revents,
101 pldm_transport* transport) override;
Matt Spinler5c350fd2019-12-12 13:53:53 -0600102
103 /**
104 * @brief Function called when the receive timer expires.
105 *
106 * This is considered a failure and so will invoke the
107 * registered response callback function with a failure
108 * indication.
109 */
110 void receiveTimerExpired();
111
112 /**
113 * @brief Configures the sdeventplus::source::IO object to
114 * call receive() on EPOLLIN activity on the PLDM FD
115 * which is used for command responses.
116 */
117 void registerReceiveCallback();
118
119 /**
120 * @brief Reads the MCTP endpoint ID out of a file
121 */
122 void readEID();
123
124 /**
125 * @brief Opens the PLDM file descriptor
126 */
127 void open();
128
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -0500129 /** @brief Opens the MCTP socket for sending and receiving messages.
130 *
131 */
132 int openMctpDemuxTransport();
133
Matt Spinler5c350fd2019-12-12 13:53:53 -0600134 /**
Matt Spinler5c350fd2019-12-12 13:53:53 -0600135 * @brief Encodes and sends the PLDM 'new file available' cmd
Matt Spinler5c350fd2019-12-12 13:53:53 -0600136 */
Matt Spinler2843ba22020-03-03 16:36:32 -0600137 void doSend();
Matt Spinler5c350fd2019-12-12 13:53:53 -0600138
139 /**
140 * @brief Closes the PLDM file descriptor
141 */
142 void closeFD();
143
144 /**
Matt Spinler2843ba22020-03-03 16:36:32 -0600145 * @brief Kicks off the send of the 'new file available' command
146 * to send the ID and size of a PEL after the instance ID
147 * has been retrieved.
148 */
149 void startCommand();
150
151 /**
Patrick Williams49bcbe92024-06-26 23:06:54 -0500152 * @brief Allocates the instance id.
153 */
154 void allocIID();
155
156 /**
157 * @brief Frees the instance id.
158 */
159 void freeIID();
160
161 /**
Matt Spinler5c350fd2019-12-12 13:53:53 -0600162 * @brief The MCTP endpoint ID
163 */
164 mctp_eid_t _eid;
165
166 /**
167 * @brief The PLDM instance ID of the current command
Matt Spinler2843ba22020-03-03 16:36:32 -0600168 *
169 * A new ID will be used for every command.
170 *
171 * If there are command failures, the same instance ID can be
172 * used on retries only if the host didn't respond.
Matt Spinler5c350fd2019-12-12 13:53:53 -0600173 */
Patrick Williams49bcbe92024-06-26 23:06:54 -0500174 std::optional<pldm_instance_id_t> _instanceID;
Matt Spinler5c350fd2019-12-12 13:53:53 -0600175
176 /**
177 * @brief The PLDM command file descriptor for the current command
178 */
179 int _fd = -1;
180
181 /**
182 * @brief The event object for handling callbacks on the PLDM FD
183 */
184 std::unique_ptr<sdeventplus::source::IO> _source;
185
186 /**
187 * @brief A timer to only allow a certain amount of time for the
188 * async PLDM receive before it is considered a failure.
189 */
190 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _receiveTimer;
191
192 /**
193 * @brief The command timeout value
194 */
195 const std::chrono::milliseconds _receiveTimeout{10000};
Matt Spinler2843ba22020-03-03 16:36:32 -0600196
197 /**
Patrick Williams49bcbe92024-06-26 23:06:54 -0500198 * @brief The libpldm instance ID database.
Matt Spinler2843ba22020-03-03 16:36:32 -0600199 */
Patrick Williams49bcbe92024-06-26 23:06:54 -0500200 pldm_instance_db* _pldm_idb = nullptr;
Matt Spinler2843ba22020-03-03 16:36:32 -0600201
202 /**
203 * @brief The ID of the PEL to notify the host of.
204 */
205 uint32_t _pelID = 0;
206
207 /**
208 * @brief The size of the PEL to notify the host of.
209 */
210 uint32_t _pelSize = 0;
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -0500211
212 /**
213 * @brief pldm transport instance.
214 */
215 pldm_transport* pldmTransport = nullptr;
216
217 pldm_transport_mctp_demux* mctpDemux = nullptr;
Matt Spinler5c350fd2019-12-12 13:53:53 -0600218};
219
220} // namespace openpower::pels