blob: 857b1fca12b89d3bf8b9cc8709a711aea7995017 [file] [log] [blame]
Matt Spinler99196682019-12-11 11:23:20 -06001#pragma once
2
3#include "data_interface.hpp"
4
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -05005#include <libpldm/transport.h>
Matt Spinler99196682019-12-11 11:23:20 -06006#include <stdint.h>
7
Matt Spinler1b418862023-06-29 12:37:41 -05008#include <phosphor-logging/lg2.hpp>
Matt Spinler99196682019-12-11 11:23:20 -06009#include <sdeventplus/event.hpp>
10#include <sdeventplus/source/io.hpp>
11
Patrick Williams2544b412022-10-04 08:41:06 -050012#include <chrono>
13#include <functional>
14
Matt Spinler99196682019-12-11 11:23:20 -060015namespace openpower
16{
17namespace pels
18{
19
20/**
21 * @brief Return codes from sending a command
22 */
23enum class CmdStatus
24{
25 success,
26 failure
27};
28
29/**
30 * @brief Return codes from the command response
31 */
32enum class ResponseStatus
33{
34 success,
35 failure
36};
37
38/**
39 * @class HostInterface
40 *
41 * An abstract base class for sending the 'New PEL available' command
42 * to the host. Used so that the PLDM interfaces can be mocked for
43 * testing the HostNotifier code. The response to this command is
44 * asynchronous, with the intent that other code registers a callback
45 * function to run when the response is received.
46 */
47class HostInterface
48{
49 public:
50 HostInterface() = delete;
51 virtual ~HostInterface() = default;
52 HostInterface(const HostInterface&) = default;
53 HostInterface& operator=(const HostInterface&) = default;
54 HostInterface(HostInterface&&) = default;
55 HostInterface& operator=(HostInterface&&) = default;
56
57 /**
58 * @brief Constructor
59 *
60 * @param[in] event - The sd_event object pointer
61 * @param[in] dataIface - The DataInterface object
62 */
63 HostInterface(sd_event* event, DataInterfaceBase& dataIface) :
64 _event(event), _dataIface(dataIface)
Patrick Williams2544b412022-10-04 08:41:06 -050065 {}
Matt Spinler99196682019-12-11 11:23:20 -060066
67 /**
68 * @brief Pure virtual function for sending the 'new PEL available'
69 * asynchronous command to the host.
70 *
71 * @param[in] id - The ID of the new PEL
72 * @param[in] size - The size of the new PEL
73 *
74 * @return CmdStatus - If the send was successful or not
75 */
76 virtual CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) = 0;
77
78 /**
79 * @brief Returns the amount of time to wait before retrying after
80 * a failed send command.
81 *
82 * @return milliseconds - The amount of time to wait
83 */
84 virtual std::chrono::milliseconds getSendRetryDelay() const
85 {
86 return _defaultSendRetryDelay;
87 }
88
89 /**
90 * @brief Returns the amount of time to wait before retrying after
91 * a command receive.
92 *
93 * @return milliseconds - The amount of time to wait
94 */
95 virtual std::chrono::milliseconds getReceiveRetryDelay() const
96 {
97 return _defaultReceiveRetryDelay;
98 }
99
100 /**
101 * @brief Returns the amount of time to wait before retrying if the
102 * host firmware's PEL storage was full and it can't store
103 * any more logs until it is freed up somehow.
104 *
105 * In this class to help with mocking.
106 *
107 * @return milliseconds - The amount of time to wait
108 */
109 virtual std::chrono::milliseconds getHostFullRetryDelay() const
110 {
111 return _defaultHostFullRetryDelay;
112 }
113
Matt Spinlere5f75082022-01-24 16:09:51 -0600114 /**
115 * @brief Returns the amount of time to wait after the host is up
116 * before sending commands.
117 *
118 * In this class to help with mocking.
119 *
120 * @return milliseconds - The amount of time to wait
121 */
122 virtual std::chrono::milliseconds getHostUpDelay() const
123 {
124 return _defaultHostUpDelay;
125 }
126
Matt Spinler99196682019-12-11 11:23:20 -0600127 using ResponseFunction = std::function<void(ResponseStatus)>;
128
129 /**
130 * @brief Sets the function to call on the command receive.
131 *
132 * The success/failure status is passed to the function.
133 *
134 * @param[in] func - The callback function
135 */
136 void setResponseFunction(ResponseFunction func)
137 {
138 _responseFunc = std::move(func);
139 }
140
141 /**
Matt Spinlera44efe42020-03-03 10:30:16 -0600142 * @brief Call the response function
143 *
144 * @param[in] status - The status given to the function
145 */
146 void callResponseFunc(ResponseStatus status)
147 {
148 if (_responseFunc)
149 {
150 try
151 {
152 (*_responseFunc)(status);
153 }
154 catch (const std::exception& e)
155 {
Matt Spinler1b418862023-06-29 12:37:41 -0500156 lg2::error(
157 "Host iface response callback threw an exception: {EX}",
158 "EX", e);
Matt Spinlera44efe42020-03-03 10:30:16 -0600159 }
160 }
161 }
162
163 /**
Matt Spinler99196682019-12-11 11:23:20 -0600164 * @brief Returns the event object in use
165 *
166 * @return sdeventplus::Event& - The event object
167 */
168 sdeventplus::Event& getEvent()
169 {
170 return _event;
171 }
172
173 /**
174 * @brief Pure virtual function to cancel an in-progress command
175 *
176 * 'In progress' means after the send but before the receive
177 */
178 virtual void cancelCmd() = 0;
179
180 /**
181 * @brief Says if the command is in progress (after send/before receive)
182 *
183 * @return bool - If command is in progress
184 */
185 bool cmdInProgress() const
186 {
187 return _inProgress;
188 }
189
190 protected:
191 /**
192 * @brief Pure virtual function for implementing the asynchronous
193 * command response callback.
194 *
195 * @param[in] io - The sdeventplus IO object that the callback is
196 * invoked from.
197 * @param[in] fd - The file descriptor being used
198 * @param[in] revents - The event status bits
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -0500199 * @param[in] transport - The transport data pointer
Matt Spinler99196682019-12-11 11:23:20 -0600200 */
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -0500201 virtual void receive(sdeventplus::source::IO& io, int fd, uint32_t revents,
202 pldm_transport* transport) = 0;
Matt Spinler99196682019-12-11 11:23:20 -0600203
204 /**
205 * @brief An optional function to call on a successful command response.
206 */
207 std::optional<ResponseFunction> _responseFunc;
208
209 /**
210 * @brief The sd_event wrapper object needed for response callbacks
211 */
212 sdeventplus::Event _event;
213
214 /**
215 * @brief The DataInterface object
216 */
217 DataInterfaceBase& _dataIface;
218
219 /**
220 * @brief Tracks status of after a command is sent and before the
221 * response is received.
222 */
223 bool _inProgress = false;
224
225 private:
226 /**
227 * @brief The default amount of time to wait before retrying
228 * a failed send.
Matt Spinler99196682019-12-11 11:23:20 -0600229 */
Matt Spinler3a4243a2020-03-03 16:51:08 -0600230 const std::chrono::milliseconds _defaultSendRetryDelay{1000};
Matt Spinler99196682019-12-11 11:23:20 -0600231
232 /**
233 * @brief The default amount of time to wait
234 * before retrying after a failed receive.
235 */
236 const std::chrono::milliseconds _defaultReceiveRetryDelay{1000};
237
238 /**
239 * @brief The default amount of time to wait when the host said it
240 * was full before sending the PEL again.
241 */
242 const std::chrono::milliseconds _defaultHostFullRetryDelay{60000};
Matt Spinlere5f75082022-01-24 16:09:51 -0600243
244 /**
245 * @brief The default amount of time to wait after the host is up
246 * before sending up the PELs.
247 */
248 const std::chrono::milliseconds _defaultHostUpDelay{60000};
Matt Spinler99196682019-12-11 11:23:20 -0600249};
250
251} // namespace pels
252} // namespace openpower