summaryrefslogtreecommitdiffstats
path: root/extensions/openpower-pels/host_interface.hpp
blob: 94c984a9e8bf5e391e3ed9a8247cd1b2b5045493 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#pragma once

#include "data_interface.hpp"

#include <stdint.h>

#include <chrono>
#include <functional>
#include <sdeventplus/event.hpp>
#include <sdeventplus/source/io.hpp>

namespace openpower
{
namespace pels
{

/**
 * @brief Return codes from sending a command
 */
enum class CmdStatus
{
    success,
    failure
};

/**
 * @brief Return codes from the command response
 */
enum class ResponseStatus
{
    success,
    failure
};

/**
 * @class HostInterface
 *
 * An abstract base class for sending the 'New PEL available' command
 * to the host.  Used so that the PLDM interfaces can be mocked for
 * testing the HostNotifier code.  The response to this command is
 * asynchronous, with the intent that other code registers a callback
 * function to run when the response is received.
 */
class HostInterface
{
  public:
    HostInterface() = delete;
    virtual ~HostInterface() = default;
    HostInterface(const HostInterface&) = default;
    HostInterface& operator=(const HostInterface&) = default;
    HostInterface(HostInterface&&) = default;
    HostInterface& operator=(HostInterface&&) = default;

    /**
     * @brief Constructor
     *
     * @param[in] event - The sd_event object pointer
     * @param[in] dataIface - The DataInterface object
     */
    HostInterface(sd_event* event, DataInterfaceBase& dataIface) :
        _event(event), _dataIface(dataIface)
    {
    }

    /**
     * @brief Pure virtual function for sending the 'new PEL available'
     *        asynchronous command to the host.
     *
     * @param[in] id - The ID of the new PEL
     * @param[in] size - The size of the new PEL
     *
     * @return CmdStatus - If the send was successful or not
     */
    virtual CmdStatus sendNewLogCmd(uint32_t id, uint32_t size) = 0;

    /**
     * @brief Returns the amount of time to wait before retrying after
     *        a failed send command.
     *
     * @return milliseconds - The amount of time to wait
     */
    virtual std::chrono::milliseconds getSendRetryDelay() const
    {
        return _defaultSendRetryDelay;
    }

    /**
     * @brief Returns the amount of time to wait before retrying after
     *        a command receive.
     *
     * @return milliseconds - The amount of time to wait
     */
    virtual std::chrono::milliseconds getReceiveRetryDelay() const
    {
        return _defaultReceiveRetryDelay;
    }

    /**
     * @brief Returns the amount of time to wait before retrying if the
     *        host firmware's PEL storage was full and it can't store
     *        any more logs until it is freed up somehow.
     *
     * In this class to help with mocking.
     *
     * @return milliseconds - The amount of time to wait
     */
    virtual std::chrono::milliseconds getHostFullRetryDelay() const
    {
        return _defaultHostFullRetryDelay;
    }

    using ResponseFunction = std::function<void(ResponseStatus)>;

    /**
     * @brief Sets the function to call on the command receive.
     *
     * The success/failure status is passed to the function.
     *
     * @param[in] func - The callback function
     */
    void setResponseFunction(ResponseFunction func)
    {
        _responseFunc = std::move(func);
    }

    /**
     * @brief Returns the event object in use
     *
     * @return sdeventplus::Event& - The event object
     */
    sdeventplus::Event& getEvent()
    {
        return _event;
    }

    /**
     * @brief Pure virtual function to cancel an in-progress command
     *
     * 'In progress' means after the send but before the receive
     */
    virtual void cancelCmd() = 0;

    /**
     * @brief Says if the command is in progress (after send/before receive)
     *
     * @return bool - If command is in progress
     */
    bool cmdInProgress() const
    {
        return _inProgress;
    }

  protected:
    /**
     * @brief Pure virtual function for implementing the asynchronous
     *        command response callback.
     *
     * @param[in] io - The sdeventplus IO object that the callback is
     *                 invoked from.
     * @param[in] fd - The file descriptor being used
     * @param[in] revents - The event status bits
     */
    virtual void receive(sdeventplus::source::IO& io, int fd,
                         uint32_t revents) = 0;

    /**
     * @brief An optional function to call on a successful command response.
     */
    std::optional<ResponseFunction> _responseFunc;

    /**
     * @brief The sd_event wrapper object needed for response callbacks
     */
    sdeventplus::Event _event;

    /**
     * @brief The DataInterface object
     */
    DataInterfaceBase& _dataIface;

    /**
     * @brief Tracks status of after a command is sent and before the
     *        response is received.
     */
    bool _inProgress = false;

  private:
    /**
     * @brief The default amount of time to wait before retrying
     *        a failed send.
     *
     * It is this value for the case where all instance IDs are used
     * and it takes this long in the PLDM daemon for them to reset.
     */
    const std::chrono::milliseconds _defaultSendRetryDelay{6000};

    /**
     * @brief The default amount of time to wait
     *        before retrying after a failed receive.
     */
    const std::chrono::milliseconds _defaultReceiveRetryDelay{1000};

    /**
     * @brief The default amount of time to wait when the host said it
     *        was full before sending the PEL again.
     */
    const std::chrono::milliseconds _defaultHostFullRetryDelay{60000};
};

} // namespace pels
} // namespace openpower
OpenPOWER on IntegriCloud