1 #pragma once
2 
3 #include "data_interface.hpp"
4 
5 #include <stdint.h>
6 
7 #include <chrono>
8 #include <functional>
9 #include <sdeventplus/event.hpp>
10 #include <sdeventplus/source/io.hpp>
11 
12 namespace openpower
13 {
14 namespace pels
15 {
16 
17 /**
18  * @brief Return codes from sending a command
19  */
20 enum class CmdStatus
21 {
22     success,
23     failure
24 };
25 
26 /**
27  * @brief Return codes from the command response
28  */
29 enum class ResponseStatus
30 {
31     success,
32     failure
33 };
34 
35 /**
36  * @class HostInterface
37  *
38  * An abstract base class for sending the 'New PEL available' command
39  * to the host.  Used so that the PLDM interfaces can be mocked for
40  * testing the HostNotifier code.  The response to this command is
41  * asynchronous, with the intent that other code registers a callback
42  * function to run when the response is received.
43  */
44 class HostInterface
45 {
46   public:
47     HostInterface() = delete;
48     virtual ~HostInterface() = default;
49     HostInterface(const HostInterface&) = default;
50     HostInterface& operator=(const HostInterface&) = default;
51     HostInterface(HostInterface&&) = default;
52     HostInterface& operator=(HostInterface&&) = default;
53 
54     /**
55      * @brief Constructor
56      *
57      * @param[in] event - The sd_event object pointer
58      * @param[in] dataIface - The DataInterface object
59      */
60     HostInterface(sd_event* event, DataInterfaceBase& dataIface) :
61         _event(event), _dataIface(dataIface)
62     {
63     }
64 
65     /**
66      * @brief Pure virtual function for sending the 'new PEL available'
67      *        asynchronous command to the host.
68      *
69      * @param[in] id - The ID of the new PEL
70      * @param[in] size - The size of the new PEL
71      *
72      * @return CmdStatus - If the send was successful or not
73      */
74     virtual CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) = 0;
75 
76     /**
77      * @brief Returns the amount of time to wait before retrying after
78      *        a failed send command.
79      *
80      * @return milliseconds - The amount of time to wait
81      */
82     virtual std::chrono::milliseconds getSendRetryDelay() const
83     {
84         return _defaultSendRetryDelay;
85     }
86 
87     /**
88      * @brief Returns the amount of time to wait before retrying after
89      *        a command receive.
90      *
91      * @return milliseconds - The amount of time to wait
92      */
93     virtual std::chrono::milliseconds getReceiveRetryDelay() const
94     {
95         return _defaultReceiveRetryDelay;
96     }
97 
98     /**
99      * @brief Returns the amount of time to wait before retrying if the
100      *        host firmware's PEL storage was full and it can't store
101      *        any more logs until it is freed up somehow.
102      *
103      * In this class to help with mocking.
104      *
105      * @return milliseconds - The amount of time to wait
106      */
107     virtual std::chrono::milliseconds getHostFullRetryDelay() const
108     {
109         return _defaultHostFullRetryDelay;
110     }
111 
112     using ResponseFunction = std::function<void(ResponseStatus)>;
113 
114     /**
115      * @brief Sets the function to call on the command receive.
116      *
117      * The success/failure status is passed to the function.
118      *
119      * @param[in] func - The callback function
120      */
121     void setResponseFunction(ResponseFunction func)
122     {
123         _responseFunc = std::move(func);
124     }
125 
126     /**
127      * @brief Returns the event object in use
128      *
129      * @return sdeventplus::Event& - The event object
130      */
131     sdeventplus::Event& getEvent()
132     {
133         return _event;
134     }
135 
136     /**
137      * @brief Pure virtual function to cancel an in-progress command
138      *
139      * 'In progress' means after the send but before the receive
140      */
141     virtual void cancelCmd() = 0;
142 
143     /**
144      * @brief Says if the command is in progress (after send/before receive)
145      *
146      * @return bool - If command is in progress
147      */
148     bool cmdInProgress() const
149     {
150         return _inProgress;
151     }
152 
153   protected:
154     /**
155      * @brief Pure virtual function for implementing the asynchronous
156      *        command response callback.
157      *
158      * @param[in] io - The sdeventplus IO object that the callback is
159      *                 invoked from.
160      * @param[in] fd - The file descriptor being used
161      * @param[in] revents - The event status bits
162      */
163     virtual void receive(sdeventplus::source::IO& io, int fd,
164                          uint32_t revents) = 0;
165 
166     /**
167      * @brief An optional function to call on a successful command response.
168      */
169     std::optional<ResponseFunction> _responseFunc;
170 
171     /**
172      * @brief The sd_event wrapper object needed for response callbacks
173      */
174     sdeventplus::Event _event;
175 
176     /**
177      * @brief The DataInterface object
178      */
179     DataInterfaceBase& _dataIface;
180 
181     /**
182      * @brief Tracks status of after a command is sent and before the
183      *        response is received.
184      */
185     bool _inProgress = false;
186 
187   private:
188     /**
189      * @brief The default amount of time to wait before retrying
190      *        a failed send.
191      *
192      * It is this value for the case where all instance IDs are used
193      * and it takes this long in the PLDM daemon for them to reset.
194      */
195     const std::chrono::milliseconds _defaultSendRetryDelay{6000};
196 
197     /**
198      * @brief The default amount of time to wait
199      *        before retrying after a failed receive.
200      */
201     const std::chrono::milliseconds _defaultReceiveRetryDelay{1000};
202 
203     /**
204      * @brief The default amount of time to wait when the host said it
205      *        was full before sending the PEL again.
206      */
207     const std::chrono::milliseconds _defaultHostFullRetryDelay{60000};
208 };
209 
210 } // namespace pels
211 } // namespace openpower
212