blob: a857c7f4e3cc33101dc48a69386a01cc1da0fd7b [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>
8
Tom Joseph86d17b42017-02-15 14:45:01 +05309namespace sol
10{
11
Tom Josephfbcac2e2017-03-14 18:15:07 +053012/** @struct Outbound
13 *
14 * Operation/Status in an outbound SOL payload format(BMC to Remote Console).
15 */
16struct Outbound
17{
18#if BYTE_ORDER == LITTLE_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070019 uint8_t testMode : 2; //!< Not supported.
20 uint8_t breakDetected : 1; //!< Not supported.
21 uint8_t transmitOverrun : 1; //!< Not supported.
22 uint8_t SOLDeactivating : 1; //!< 0 : SOL is active, 1 : SOL deactivated.
23 uint8_t charUnavailable : 1; //!< 0 : Available, 1 : Unavailable.
24 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
25 uint8_t reserved : 1; //!< Reserved.
Tom Josephfbcac2e2017-03-14 18:15:07 +053026#endif
27
28#if BYTE_ORDER == BIG_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070029 uint8_t reserved : 1; //!< Reserved.
30 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
31 uint8_t charUnavailable : 1; //!< 0 : Available, 1 : Unavailable.
32 uint8_t SOLDeactivating : 1; //!< 0 : SOL is active, 1 : SOL deactivated.
33 uint8_t transmitOverrun : 1; //!< Not supported.
34 uint8_t breakDetected : 1; //!< Not supported.
35 uint8_t testMode : 2; //!< Not supported.
Tom Josephfbcac2e2017-03-14 18:15:07 +053036#endif
37} __attribute__((packed));
38
39/** @struct Inbound
40 *
41 * Operation/Status in an Inbound SOL Payload format(Remote Console to BMC).
42 */
43struct Inbound
44{
45#if BYTE_ORDER == LITTLE_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070046 uint8_t flushOut : 1; //!< Not supported.
47 uint8_t flushIn : 1; //!< Not supported.
48 uint8_t dcd : 1; //!< Not supported.
49 uint8_t cts : 1; //!< Not supported.
50 uint8_t generateBreak : 1; //!< Not supported.
51 uint8_t ring : 1; //!< Not supported.
52 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
53 uint8_t reserved : 1; //!< Reserved.
Tom Josephfbcac2e2017-03-14 18:15:07 +053054#endif
55
56#if BYTE_ORDER == BIG_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070057 uint8_t reserved : 1; //!< Reserved.
58 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
59 uint8_t ring : 1; //!< Not supported.
60 uint8_t generateBreak : 1; //!< Not supported.
61 uint8_t cts : 1; //!< Not supported.
62 uint8_t dcd : 1; //!< Not supported.
63 uint8_t flushIn : 1; //!< Not supported.
64 uint8_t flushOut : 1; //!< Not supported.
Tom Josephfbcac2e2017-03-14 18:15:07 +053065#endif
66} __attribute__((packed));
67
68/** @struct Payload
69 *
70 * SOL Payload Data Format.The following fields make up the SOL payload in an
71 * RMCP+ packet, followed by the console character data.
72 */
73struct Payload
74{
Vernon Mauery9e801a22018-10-12 13:20:49 -070075 uint8_t packetSeqNum; //!< Packet sequence number
76 uint8_t packetAckSeqNum; //!< Packet ACK/NACK sequence number
77 uint8_t acceptedCharCount; //!< Accepted character count
Tom Josephfbcac2e2017-03-14 18:15:07 +053078 union
79 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070080 uint8_t operation; //!< Operation/Status
81 struct Outbound outOperation; //!< BMC to Remote Console
82 struct Inbound inOperation; //!< Remote Console to BMC
Tom Josephfbcac2e2017-03-14 18:15:07 +053083 };
84} __attribute__((packed));
85
Tom Joseph86d17b42017-02-15 14:45:01 +053086namespace internal
87{
88
89/** @struct SequenceNumbers
90 *
91 * SOL sequence numbers. At the session level, SOL Payloads share the session
92 * sequence numbers for authenticated and unauthenticated packets with other
93 * packets under the IPMI session. At the payload level, SOL packets include
94 * their own message sequence numbers that are used for tracking missing and
95 * retried SOL messages. The sequence numbers must be non-zero. Retried
96 * packets use the same sequence number as the first packet.
97 */
98struct SequenceNumbers
99{
100 static constexpr uint8_t MAX_SOL_SEQUENCE_NUMBER = 0x10;
101
102 /** @brief Get the SOL sequence number.
103 *
104 * @param[in] inbound - true for inbound sequence number and false for
105 * outbound sequence number
106 *
107 * @return sequence number
108 */
109 auto get(bool inbound = true) const
110 {
111 return inbound ? in : out;
112 }
113
114 /** @brief Increment the inbound SOL sequence number. */
115 void incInboundSeqNum()
116 {
117 if ((++in) == MAX_SOL_SEQUENCE_NUMBER)
118 {
119 in = 1;
120 }
121 }
122
123 /** @brief Increment the outbound SOL sequence number.
124 *
125 * @return outbound sequence number to populate the SOL payload.
126 */
127 auto incOutboundSeqNum()
128 {
129 if ((++out) == MAX_SOL_SEQUENCE_NUMBER)
130 {
131 out = 1;
132 }
133
134 return out;
135 }
136
Vernon Mauery9e801a22018-10-12 13:20:49 -0700137 private:
138 uint8_t in = 1; //!< Inbound sequence number.
139 uint8_t out = 0; //!< Outbound sequence number, since the first
140 //!< operation is increment, it is initialised to 0
Tom Joseph86d17b42017-02-15 14:45:01 +0530141};
142
143} // namespace internal
144
145/** @class Context
146 *
147 * Context keeps the state of the SOL session. The information needed to
148 * maintain the state of the SOL is part of this class. This class provides
149 * interfaces to handle incoming SOL payload, send response and send outbound
150 * SOL payload.
151 */
Yong Lia3de8a82020-05-09 10:04:11 +0800152class Context : public std::enable_shared_from_this<Context>
Tom Joseph86d17b42017-02-15 14:45:01 +0530153{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700154 public:
Vernon Mauery6f353e82018-11-09 08:43:24 -0800155 Context() = delete;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700156 ~Context() = default;
157 Context(const Context&) = delete;
158 Context& operator=(const Context&) = delete;
Vernon Mauery6f353e82018-11-09 08:43:24 -0800159 Context(Context&&) = delete;
160 Context& operator=(Context&&) = delete;
Tom Joseph86d17b42017-02-15 14:45:01 +0530161
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800162 /** @brief Context Factory
163 *
164 * This is called by the SOL Manager when a SOL payload instance is
165 * started for the activate payload command. Its purpose is to be able
166 * to perform post-creation tasks on the object without changing the
167 * code flow
168 *
169 * @param[in] io - boost::asio io context for event scheduling.
170 * @param[in] maxRetryCount - Retry count max value.
171 * @param[in] sendThreshold - Character send threshold.
172 * @param[in] instance - SOL payload instance.
173 * @param[in] sessionID - BMC session ID.
174 */
175 static std::shared_ptr<Context>
176 makeContext(std::shared_ptr<boost::asio::io_context> io,
177 uint8_t maxRetryCount, uint8_t sendThreshold,
178 uint8_t instance, session::SessionID sessionID);
179
Vernon Mauery9e801a22018-10-12 13:20:49 -0700180 /** @brief Context Constructor.
181 *
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800182 * This should only be used by the Context factory makeContext
183 * or the accumulate timer will not be initialized properly
Vernon Mauery9e801a22018-10-12 13:20:49 -0700184 *
Vernon Mauery6f353e82018-11-09 08:43:24 -0800185 * @param[in] io - boost::asio io context for event scheduling.
Vernon Mauery9e801a22018-10-12 13:20:49 -0700186 * @param[in] maxRetryCount - Retry count max value.
187 * @param[in] sendThreshold - Character send threshold.
188 * @param[in] instance - SOL payload instance.
189 * @param[in] sessionID - BMC session ID.
190 */
Vernon Mauery6f353e82018-11-09 08:43:24 -0800191 Context(std::shared_ptr<boost::asio::io_context> io, uint8_t maxRetryCount,
192 uint8_t sendThreshold, uint8_t instance,
193 session::SessionID sessionID);
Tom Joseph86d17b42017-02-15 14:45:01 +0530194
Vernon Mauery9e801a22018-10-12 13:20:49 -0700195 static constexpr auto clear = true;
196 static constexpr auto noClear = false;
Tom Joseph86d17b42017-02-15 14:45:01 +0530197
Vernon Mauery6f353e82018-11-09 08:43:24 -0800198 /** @brief accumulate timer */
199 boost::asio::steady_timer accumulateTimer;
200
201 /** @brief retry timer */
202 boost::asio::steady_timer retryTimer;
203
Vernon Mauery9e801a22018-10-12 13:20:49 -0700204 /** @brief Retry count max value. */
205 const uint8_t maxRetryCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530206
Vernon Mauery9e801a22018-10-12 13:20:49 -0700207 /** @brief Retry counter. */
208 uint8_t retryCounter = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530209
Vernon Mauery9e801a22018-10-12 13:20:49 -0700210 /** @brief Character send threshold. */
211 const uint8_t sendThreshold = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530212
Vernon Mauery9e801a22018-10-12 13:20:49 -0700213 /** @brief SOL payload instance. */
214 const uint8_t payloadInstance = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530215
Vernon Mauery9e801a22018-10-12 13:20:49 -0700216 /** @brief Session ID. */
217 const session::SessionID sessionID = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530218
Vernon Mauery6f353e82018-11-09 08:43:24 -0800219 /** @brief session pointer
220 */
221 std::shared_ptr<session::Session> session;
222
223 /** @brief enable/disable accumulate timer
224 *
225 * The timeout interval is managed by the SOL Manager;
226 * this function only enables or disable the timer
227 *
228 * @param[in] enable - enable(true) or disable(false) accumulation timer
229 */
230 void enableAccumulateTimer(bool enable);
231
232 /** @brief enable/disable retry timer
233 *
234 * The timeout interval is managed by the SOL Manager;
235 * this function only enables or disable the timer
236 *
237 * @param[in] enable - enable(true) or disable(false) retry timer
238 */
239 void enableRetryTimer(bool enable);
240
Vernon Mauery9e801a22018-10-12 13:20:49 -0700241 /** @brief Process the Inbound SOL payload.
242 *
243 * The SOL payload from the remote console is processed and the
244 * acknowledgment handling is done.
245 *
246 * @param[in] seqNum - Packet sequence number.
247 * @param[in] ackSeqNum - Packet ACK/NACK sequence number.
248 * @param[in] count - Accepted character count.
249 * @param[in] operation - ACK is false, NACK is true
250 * @param[in] input - Incoming SOL character data.
251 */
252 void processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, uint8_t count,
253 bool status, const std::vector<uint8_t>& input);
Tom Joseph86d17b42017-02-15 14:45:01 +0530254
Vernon Mauery9e801a22018-10-12 13:20:49 -0700255 /** @brief Send the outbound SOL payload.
256 *
257 * @return zero on success and negative value if condition for sending
258 * the payload fails.
259 */
260 int sendOutboundPayload();
Tom Joseph86d17b42017-02-15 14:45:01 +0530261
Vernon Mauery9e801a22018-10-12 13:20:49 -0700262 /** @brief Resend the SOL payload.
263 *
264 * @param[in] clear - if true then send the payload and clear the
265 * cached payload, if false only send the payload.
266 */
267 void resendPayload(bool clear);
Tom Joseph86d17b42017-02-15 14:45:01 +0530268
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800269 /** @brief accumlate timer handler called by timer */
270 void charAccTimerHandler();
271
272 /** @brief retry timer handler called by timer */
273 void retryTimerHandler();
274
Vernon Mauery9e801a22018-10-12 13:20:49 -0700275 private:
276 /** @brief Expected character count.
277 *
278 * Expected Sequence number and expected character count is set before
279 * sending the SOL payload. The check is done against these values when
280 * an incoming SOL payload is received.
281 */
282 size_t expectedCharCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530283
Vernon Mauery9e801a22018-10-12 13:20:49 -0700284 /** @brief Inbound and Outbound sequence numbers. */
285 internal::SequenceNumbers seqNums;
Tom Joseph86d17b42017-02-15 14:45:01 +0530286
Vernon Mauery9e801a22018-10-12 13:20:49 -0700287 /** @brief Copy of the last sent SOL payload.
288 *
289 * A copy of the SOL payload is kept here, so that when a retry needs
290 * to be attempted the payload is sent again.
291 */
292 std::vector<uint8_t> payloadCache;
Tom Joseph86d17b42017-02-15 14:45:01 +0530293
Vernon Mauery9e801a22018-10-12 13:20:49 -0700294 /**
295 * @brief Send Response for Incoming SOL payload.
296 *
297 * @param[in] ackSeqNum - Packet ACK/NACK Sequence Number.
298 * @param[in] count - Accepted Character Count.
299 * @param[in] ack - Set ACK/NACK in the Operation.
300 */
301 void prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack);
Tom Joseph86d17b42017-02-15 14:45:01 +0530302
Vernon Mauery9e801a22018-10-12 13:20:49 -0700303 /** @brief Send the outgoing SOL payload.
304 *
305 * @param[in] out - buffer containing the SOL payload.
306 */
307 void sendPayload(const std::vector<uint8_t>& out) const;
Tom Joseph86d17b42017-02-15 14:45:01 +0530308};
309
310} // namespace sol