blob: a07189214bf5f7bdad3cb50f78fda973bdee3f00 [file] [log] [blame]
Tom Joseph86d17b42017-02-15 14:45:01 +05301#pragma once
2
3#include "console_buffer.hpp"
4#include "session.hpp"
5
Vernon Mauery6f353e82018-11-09 08:43:24 -08006#include <boost/asio/io_context.hpp>
7#include <boost/asio/steady_timer.hpp>
Andrew Geissler9d9b7632020-05-17 09:18:05 -05008#include <cstddef>
Vernon Mauery6f353e82018-11-09 08:43:24 -08009
Tom Joseph86d17b42017-02-15 14:45:01 +053010namespace sol
11{
12
Tom Josephfbcac2e2017-03-14 18:15:07 +053013/** @struct Outbound
14 *
15 * Operation/Status in an outbound SOL payload format(BMC to Remote Console).
16 */
17struct Outbound
18{
19#if BYTE_ORDER == LITTLE_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070020 uint8_t testMode : 2; //!< Not supported.
21 uint8_t breakDetected : 1; //!< Not supported.
22 uint8_t transmitOverrun : 1; //!< Not supported.
23 uint8_t SOLDeactivating : 1; //!< 0 : SOL is active, 1 : SOL deactivated.
24 uint8_t charUnavailable : 1; //!< 0 : Available, 1 : Unavailable.
25 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
26 uint8_t reserved : 1; //!< Reserved.
Tom Josephfbcac2e2017-03-14 18:15:07 +053027#endif
28
29#if BYTE_ORDER == BIG_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070030 uint8_t reserved : 1; //!< Reserved.
31 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
32 uint8_t charUnavailable : 1; //!< 0 : Available, 1 : Unavailable.
33 uint8_t SOLDeactivating : 1; //!< 0 : SOL is active, 1 : SOL deactivated.
34 uint8_t transmitOverrun : 1; //!< Not supported.
35 uint8_t breakDetected : 1; //!< Not supported.
36 uint8_t testMode : 2; //!< Not supported.
Tom Josephfbcac2e2017-03-14 18:15:07 +053037#endif
38} __attribute__((packed));
39
40/** @struct Inbound
41 *
42 * Operation/Status in an Inbound SOL Payload format(Remote Console to BMC).
43 */
44struct Inbound
45{
46#if BYTE_ORDER == LITTLE_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070047 uint8_t flushOut : 1; //!< Not supported.
48 uint8_t flushIn : 1; //!< Not supported.
49 uint8_t dcd : 1; //!< Not supported.
50 uint8_t cts : 1; //!< Not supported.
51 uint8_t generateBreak : 1; //!< Not supported.
52 uint8_t ring : 1; //!< Not supported.
53 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
54 uint8_t reserved : 1; //!< Reserved.
Tom Josephfbcac2e2017-03-14 18:15:07 +053055#endif
56
57#if BYTE_ORDER == BIG_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070058 uint8_t reserved : 1; //!< Reserved.
59 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
60 uint8_t ring : 1; //!< Not supported.
61 uint8_t generateBreak : 1; //!< Not supported.
62 uint8_t cts : 1; //!< Not supported.
63 uint8_t dcd : 1; //!< Not supported.
64 uint8_t flushIn : 1; //!< Not supported.
65 uint8_t flushOut : 1; //!< Not supported.
Tom Josephfbcac2e2017-03-14 18:15:07 +053066#endif
67} __attribute__((packed));
68
69/** @struct Payload
70 *
71 * SOL Payload Data Format.The following fields make up the SOL payload in an
72 * RMCP+ packet, followed by the console character data.
73 */
74struct Payload
75{
Vernon Mauery9e801a22018-10-12 13:20:49 -070076 uint8_t packetSeqNum; //!< Packet sequence number
77 uint8_t packetAckSeqNum; //!< Packet ACK/NACK sequence number
78 uint8_t acceptedCharCount; //!< Accepted character count
Tom Josephfbcac2e2017-03-14 18:15:07 +053079 union
80 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070081 uint8_t operation; //!< Operation/Status
82 struct Outbound outOperation; //!< BMC to Remote Console
83 struct Inbound inOperation; //!< Remote Console to BMC
Tom Josephfbcac2e2017-03-14 18:15:07 +053084 };
85} __attribute__((packed));
86
Tom Joseph86d17b42017-02-15 14:45:01 +053087namespace internal
88{
89
90/** @struct SequenceNumbers
91 *
92 * SOL sequence numbers. At the session level, SOL Payloads share the session
93 * sequence numbers for authenticated and unauthenticated packets with other
94 * packets under the IPMI session. At the payload level, SOL packets include
95 * their own message sequence numbers that are used for tracking missing and
96 * retried SOL messages. The sequence numbers must be non-zero. Retried
97 * packets use the same sequence number as the first packet.
98 */
99struct SequenceNumbers
100{
101 static constexpr uint8_t MAX_SOL_SEQUENCE_NUMBER = 0x10;
102
103 /** @brief Get the SOL sequence number.
104 *
105 * @param[in] inbound - true for inbound sequence number and false for
106 * outbound sequence number
107 *
108 * @return sequence number
109 */
110 auto get(bool inbound = true) const
111 {
112 return inbound ? in : out;
113 }
114
115 /** @brief Increment the inbound SOL sequence number. */
116 void incInboundSeqNum()
117 {
118 if ((++in) == MAX_SOL_SEQUENCE_NUMBER)
119 {
120 in = 1;
121 }
122 }
123
124 /** @brief Increment the outbound SOL sequence number.
125 *
126 * @return outbound sequence number to populate the SOL payload.
127 */
128 auto incOutboundSeqNum()
129 {
130 if ((++out) == MAX_SOL_SEQUENCE_NUMBER)
131 {
132 out = 1;
133 }
134
135 return out;
136 }
137
Vernon Mauery9e801a22018-10-12 13:20:49 -0700138 private:
139 uint8_t in = 1; //!< Inbound sequence number.
140 uint8_t out = 0; //!< Outbound sequence number, since the first
141 //!< operation is increment, it is initialised to 0
Tom Joseph86d17b42017-02-15 14:45:01 +0530142};
143
144} // namespace internal
145
146/** @class Context
147 *
148 * Context keeps the state of the SOL session. The information needed to
149 * maintain the state of the SOL is part of this class. This class provides
150 * interfaces to handle incoming SOL payload, send response and send outbound
151 * SOL payload.
152 */
Yong Lia3de8a82020-05-09 10:04:11 +0800153class Context : public std::enable_shared_from_this<Context>
Tom Joseph86d17b42017-02-15 14:45:01 +0530154{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700155 public:
Vernon Mauery6f353e82018-11-09 08:43:24 -0800156 Context() = delete;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700157 ~Context() = default;
158 Context(const Context&) = delete;
159 Context& operator=(const Context&) = delete;
Vernon Mauery6f353e82018-11-09 08:43:24 -0800160 Context(Context&&) = delete;
161 Context& operator=(Context&&) = delete;
Tom Joseph86d17b42017-02-15 14:45:01 +0530162
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800163 /** @brief Context Factory
164 *
165 * This is called by the SOL Manager when a SOL payload instance is
166 * started for the activate payload command. Its purpose is to be able
167 * to perform post-creation tasks on the object without changing the
168 * code flow
169 *
170 * @param[in] io - boost::asio io context for event scheduling.
171 * @param[in] maxRetryCount - Retry count max value.
172 * @param[in] sendThreshold - Character send threshold.
173 * @param[in] instance - SOL payload instance.
174 * @param[in] sessionID - BMC session ID.
175 */
176 static std::shared_ptr<Context>
177 makeContext(std::shared_ptr<boost::asio::io_context> io,
178 uint8_t maxRetryCount, uint8_t sendThreshold,
179 uint8_t instance, session::SessionID sessionID);
180
Vernon Mauery9e801a22018-10-12 13:20:49 -0700181 /** @brief Context Constructor.
182 *
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800183 * This should only be used by the Context factory makeContext
184 * or the accumulate timer will not be initialized properly
Vernon Mauery9e801a22018-10-12 13:20:49 -0700185 *
Vernon Mauery6f353e82018-11-09 08:43:24 -0800186 * @param[in] io - boost::asio io context for event scheduling.
Vernon Mauery9e801a22018-10-12 13:20:49 -0700187 * @param[in] maxRetryCount - Retry count max value.
188 * @param[in] sendThreshold - Character send threshold.
189 * @param[in] instance - SOL payload instance.
190 * @param[in] sessionID - BMC session ID.
191 */
Vernon Mauery6f353e82018-11-09 08:43:24 -0800192 Context(std::shared_ptr<boost::asio::io_context> io, uint8_t maxRetryCount,
193 uint8_t sendThreshold, uint8_t instance,
194 session::SessionID sessionID);
Tom Joseph86d17b42017-02-15 14:45:01 +0530195
Vernon Mauery9e801a22018-10-12 13:20:49 -0700196 static constexpr auto clear = true;
197 static constexpr auto noClear = false;
Tom Joseph86d17b42017-02-15 14:45:01 +0530198
Vernon Mauery6f353e82018-11-09 08:43:24 -0800199 /** @brief accumulate timer */
200 boost::asio::steady_timer accumulateTimer;
201
202 /** @brief retry timer */
203 boost::asio::steady_timer retryTimer;
204
Vernon Mauery9e801a22018-10-12 13:20:49 -0700205 /** @brief Retry count max value. */
206 const uint8_t maxRetryCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530207
Vernon Mauery9e801a22018-10-12 13:20:49 -0700208 /** @brief Retry counter. */
209 uint8_t retryCounter = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530210
Vernon Mauery9e801a22018-10-12 13:20:49 -0700211 /** @brief Character send threshold. */
212 const uint8_t sendThreshold = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530213
Vernon Mauery9e801a22018-10-12 13:20:49 -0700214 /** @brief SOL payload instance. */
215 const uint8_t payloadInstance = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530216
Vernon Mauery9e801a22018-10-12 13:20:49 -0700217 /** @brief Session ID. */
218 const session::SessionID sessionID = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530219
Vernon Mauery6f353e82018-11-09 08:43:24 -0800220 /** @brief session pointer
221 */
222 std::shared_ptr<session::Session> session;
223
224 /** @brief enable/disable accumulate timer
225 *
226 * The timeout interval is managed by the SOL Manager;
227 * this function only enables or disable the timer
228 *
229 * @param[in] enable - enable(true) or disable(false) accumulation timer
230 */
231 void enableAccumulateTimer(bool enable);
232
233 /** @brief enable/disable retry timer
234 *
235 * The timeout interval is managed by the SOL Manager;
236 * this function only enables or disable the timer
237 *
238 * @param[in] enable - enable(true) or disable(false) retry timer
239 */
240 void enableRetryTimer(bool enable);
241
Vernon Mauery9e801a22018-10-12 13:20:49 -0700242 /** @brief Process the Inbound SOL payload.
243 *
244 * The SOL payload from the remote console is processed and the
245 * acknowledgment handling is done.
246 *
247 * @param[in] seqNum - Packet sequence number.
248 * @param[in] ackSeqNum - Packet ACK/NACK sequence number.
249 * @param[in] count - Accepted character count.
250 * @param[in] operation - ACK is false, NACK is true
251 * @param[in] input - Incoming SOL character data.
252 */
253 void processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, uint8_t count,
254 bool status, const std::vector<uint8_t>& input);
Tom Joseph86d17b42017-02-15 14:45:01 +0530255
Vernon Mauery9e801a22018-10-12 13:20:49 -0700256 /** @brief Send the outbound SOL payload.
257 *
258 * @return zero on success and negative value if condition for sending
259 * the payload fails.
260 */
261 int sendOutboundPayload();
Tom Joseph86d17b42017-02-15 14:45:01 +0530262
Vernon Mauery9e801a22018-10-12 13:20:49 -0700263 /** @brief Resend the SOL payload.
264 *
265 * @param[in] clear - if true then send the payload and clear the
266 * cached payload, if false only send the payload.
267 */
268 void resendPayload(bool clear);
Tom Joseph86d17b42017-02-15 14:45:01 +0530269
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800270 /** @brief accumlate timer handler called by timer */
271 void charAccTimerHandler();
272
273 /** @brief retry timer handler called by timer */
274 void retryTimerHandler();
275
Vernon Mauery9e801a22018-10-12 13:20:49 -0700276 private:
277 /** @brief Expected character count.
278 *
279 * Expected Sequence number and expected character count is set before
280 * sending the SOL payload. The check is done against these values when
281 * an incoming SOL payload is received.
282 */
283 size_t expectedCharCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530284
Vernon Mauery9e801a22018-10-12 13:20:49 -0700285 /** @brief Inbound and Outbound sequence numbers. */
286 internal::SequenceNumbers seqNums;
Tom Joseph86d17b42017-02-15 14:45:01 +0530287
Vernon Mauery9e801a22018-10-12 13:20:49 -0700288 /** @brief Copy of the last sent SOL payload.
289 *
290 * A copy of the SOL payload is kept here, so that when a retry needs
291 * to be attempted the payload is sent again.
292 */
293 std::vector<uint8_t> payloadCache;
Tom Joseph86d17b42017-02-15 14:45:01 +0530294
Vernon Mauery9e801a22018-10-12 13:20:49 -0700295 /**
296 * @brief Send Response for Incoming SOL payload.
297 *
298 * @param[in] ackSeqNum - Packet ACK/NACK Sequence Number.
299 * @param[in] count - Accepted Character Count.
300 * @param[in] ack - Set ACK/NACK in the Operation.
301 */
302 void prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack);
Tom Joseph86d17b42017-02-15 14:45:01 +0530303
Vernon Mauery9e801a22018-10-12 13:20:49 -0700304 /** @brief Send the outgoing SOL payload.
305 *
306 * @param[in] out - buffer containing the SOL payload.
307 */
308 void sendPayload(const std::vector<uint8_t>& out) const;
Tom Joseph86d17b42017-02-15 14:45:01 +0530309};
310
311} // namespace sol