blob: ee818f304da2c6127e7ed791d7b8d9d8e669d7e2 [file] [log] [blame]
Matt Spinler99196682019-12-11 11:23:20 -06001#pragma once
2
3#include "data_interface.hpp"
4
5#include <stdint.h>
6
Matt Spinlera44efe42020-03-03 10:30:16 -06007#include <phosphor-logging/log.hpp>
Matt Spinler99196682019-12-11 11:23:20 -06008#include <sdeventplus/event.hpp>
9#include <sdeventplus/source/io.hpp>
10
Patrick Williams2544b412022-10-04 08:41:06 -050011#include <chrono>
12#include <functional>
13
Matt Spinler99196682019-12-11 11:23:20 -060014namespace openpower
15{
16namespace pels
17{
18
19/**
20 * @brief Return codes from sending a command
21 */
22enum class CmdStatus
23{
24 success,
25 failure
26};
27
28/**
29 * @brief Return codes from the command response
30 */
31enum class ResponseStatus
32{
33 success,
34 failure
35};
36
37/**
38 * @class HostInterface
39 *
40 * An abstract base class for sending the 'New PEL available' command
41 * to the host. Used so that the PLDM interfaces can be mocked for
42 * testing the HostNotifier code. The response to this command is
43 * asynchronous, with the intent that other code registers a callback
44 * function to run when the response is received.
45 */
46class HostInterface
47{
48 public:
49 HostInterface() = delete;
50 virtual ~HostInterface() = default;
51 HostInterface(const HostInterface&) = default;
52 HostInterface& operator=(const HostInterface&) = default;
53 HostInterface(HostInterface&&) = default;
54 HostInterface& operator=(HostInterface&&) = default;
55
56 /**
57 * @brief Constructor
58 *
59 * @param[in] event - The sd_event object pointer
60 * @param[in] dataIface - The DataInterface object
61 */
62 HostInterface(sd_event* event, DataInterfaceBase& dataIface) :
63 _event(event), _dataIface(dataIface)
Patrick Williams2544b412022-10-04 08:41:06 -050064 {}
Matt Spinler99196682019-12-11 11:23:20 -060065
66 /**
67 * @brief Pure virtual function for sending the 'new PEL available'
68 * asynchronous command to the host.
69 *
70 * @param[in] id - The ID of the new PEL
71 * @param[in] size - The size of the new PEL
72 *
73 * @return CmdStatus - If the send was successful or not
74 */
75 virtual CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) = 0;
76
77 /**
78 * @brief Returns the amount of time to wait before retrying after
79 * a failed send command.
80 *
81 * @return milliseconds - The amount of time to wait
82 */
83 virtual std::chrono::milliseconds getSendRetryDelay() const
84 {
85 return _defaultSendRetryDelay;
86 }
87
88 /**
89 * @brief Returns the amount of time to wait before retrying after
90 * a command receive.
91 *
92 * @return milliseconds - The amount of time to wait
93 */
94 virtual std::chrono::milliseconds getReceiveRetryDelay() const
95 {
96 return _defaultReceiveRetryDelay;
97 }
98
99 /**
100 * @brief Returns the amount of time to wait before retrying if the
101 * host firmware's PEL storage was full and it can't store
102 * any more logs until it is freed up somehow.
103 *
104 * In this class to help with mocking.
105 *
106 * @return milliseconds - The amount of time to wait
107 */
108 virtual std::chrono::milliseconds getHostFullRetryDelay() const
109 {
110 return _defaultHostFullRetryDelay;
111 }
112
Matt Spinlere5f75082022-01-24 16:09:51 -0600113 /**
114 * @brief Returns the amount of time to wait after the host is up
115 * before sending commands.
116 *
117 * In this class to help with mocking.
118 *
119 * @return milliseconds - The amount of time to wait
120 */
121 virtual std::chrono::milliseconds getHostUpDelay() const
122 {
123 return _defaultHostUpDelay;
124 }
125
Matt Spinler99196682019-12-11 11:23:20 -0600126 using ResponseFunction = std::function<void(ResponseStatus)>;
127
128 /**
129 * @brief Sets the function to call on the command receive.
130 *
131 * The success/failure status is passed to the function.
132 *
133 * @param[in] func - The callback function
134 */
135 void setResponseFunction(ResponseFunction func)
136 {
137 _responseFunc = std::move(func);
138 }
139
140 /**
Matt Spinlera44efe42020-03-03 10:30:16 -0600141 * @brief Call the response function
142 *
143 * @param[in] status - The status given to the function
144 */
145 void callResponseFunc(ResponseStatus status)
146 {
147 if (_responseFunc)
148 {
149 try
150 {
151 (*_responseFunc)(status);
152 }
153 catch (const std::exception& e)
154 {
155 using namespace phosphor::logging;
156 log<level::ERR>(
157 "Host iface response callback threw an exception",
158 entry("ERROR=%s", e.what()));
159 }
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
199 */
200 virtual void receive(sdeventplus::source::IO& io, int fd,
201 uint32_t revents) = 0;
202
203 /**
204 * @brief An optional function to call on a successful command response.
205 */
206 std::optional<ResponseFunction> _responseFunc;
207
208 /**
209 * @brief The sd_event wrapper object needed for response callbacks
210 */
211 sdeventplus::Event _event;
212
213 /**
214 * @brief The DataInterface object
215 */
216 DataInterfaceBase& _dataIface;
217
218 /**
219 * @brief Tracks status of after a command is sent and before the
220 * response is received.
221 */
222 bool _inProgress = false;
223
224 private:
225 /**
226 * @brief The default amount of time to wait before retrying
227 * a failed send.
Matt Spinler99196682019-12-11 11:23:20 -0600228 */
Matt Spinler3a4243a2020-03-03 16:51:08 -0600229 const std::chrono::milliseconds _defaultSendRetryDelay{1000};
Matt Spinler99196682019-12-11 11:23:20 -0600230
231 /**
232 * @brief The default amount of time to wait
233 * before retrying after a failed receive.
234 */
235 const std::chrono::milliseconds _defaultReceiveRetryDelay{1000};
236
237 /**
238 * @brief The default amount of time to wait when the host said it
239 * was full before sending the PEL again.
240 */
241 const std::chrono::milliseconds _defaultHostFullRetryDelay{60000};
Matt Spinlere5f75082022-01-24 16:09:51 -0600242
243 /**
244 * @brief The default amount of time to wait after the host is up
245 * before sending up the PELs.
246 */
247 const std::chrono::milliseconds _defaultHostUpDelay{60000};
Matt Spinler99196682019-12-11 11:23:20 -0600248};
249
250} // namespace pels
251} // namespace openpower