1 #pragma once 2 3 #include "data_interface.hpp" 4 5 #include <stdint.h> 6 7 #include <phosphor-logging/log.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 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 /** 164 * @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. 228 */ 229 const std::chrono::milliseconds _defaultSendRetryDelay{1000}; 230 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}; 242 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}; 248 }; 249 250 } // namespace pels 251 } // namespace openpower 252