1 #pragma once 2 3 #include "data_interface.hpp" 4 5 #include <stdint.h> 6 7 #include <phosphor-logging/lg2.hpp> 8 #include <sdeventplus/event.hpp> 9 #include <sdeventplus/source/io.hpp> 10 11 #include <chrono> 12 #include <functional> 13 14 namespace openpower 15 { 16 namespace pels 17 { 18 19 /** 20 * @brief Return codes from sending a command 21 */ 22 enum class CmdStatus 23 { 24 success, 25 failure 26 }; 27 28 /** 29 * @brief Return codes from the command response 30 */ 31 enum 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 */ 46 class 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) 64 {} 65 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 113 /** 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 126 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 /** 141 * @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 lg2::error( 156 "Host iface response callback threw an exception: {EX}", 157 "EX", e); 158 } 159 } 160 } 161 162 /** 163 * @brief Returns the event object in use 164 * 165 * @return sdeventplus::Event& - The event object 166 */ 167 sdeventplus::Event& getEvent() 168 { 169 return _event; 170 } 171 172 /** 173 * @brief Pure virtual function to cancel an in-progress command 174 * 175 * 'In progress' means after the send but before the receive 176 */ 177 virtual void cancelCmd() = 0; 178 179 /** 180 * @brief Says if the command is in progress (after send/before receive) 181 * 182 * @return bool - If command is in progress 183 */ 184 bool cmdInProgress() const 185 { 186 return _inProgress; 187 } 188 189 protected: 190 /** 191 * @brief Pure virtual function for implementing the asynchronous 192 * command response callback. 193 * 194 * @param[in] io - The sdeventplus IO object that the callback is 195 * invoked from. 196 * @param[in] fd - The file descriptor being used 197 * @param[in] revents - The event status bits 198 */ 199 virtual void receive(sdeventplus::source::IO& io, int fd, 200 uint32_t revents) = 0; 201 202 /** 203 * @brief An optional function to call on a successful command response. 204 */ 205 std::optional<ResponseFunction> _responseFunc; 206 207 /** 208 * @brief The sd_event wrapper object needed for response callbacks 209 */ 210 sdeventplus::Event _event; 211 212 /** 213 * @brief The DataInterface object 214 */ 215 DataInterfaceBase& _dataIface; 216 217 /** 218 * @brief Tracks status of after a command is sent and before the 219 * response is received. 220 */ 221 bool _inProgress = false; 222 223 private: 224 /** 225 * @brief The default amount of time to wait before retrying 226 * a failed send. 227 */ 228 const std::chrono::milliseconds _defaultSendRetryDelay{1000}; 229 230 /** 231 * @brief The default amount of time to wait 232 * before retrying after a failed receive. 233 */ 234 const std::chrono::milliseconds _defaultReceiveRetryDelay{1000}; 235 236 /** 237 * @brief The default amount of time to wait when the host said it 238 * was full before sending the PEL again. 239 */ 240 const std::chrono::milliseconds _defaultHostFullRetryDelay{60000}; 241 242 /** 243 * @brief The default amount of time to wait after the host is up 244 * before sending up the PELs. 245 */ 246 const std::chrono::milliseconds _defaultHostUpDelay{60000}; 247 }; 248 249 } // namespace pels 250 } // namespace openpower 251