blob: 34a0076b6fa14fe1a65506002720a0a0668ceeb6 [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>
George Liubc8958f2022-07-04 09:29:49 +08008
Andrew Geissler9d9b7632020-05-17 09:18:05 -05009#include <cstddef>
Vernon Mauery6f353e82018-11-09 08:43:24 -080010
Tom Joseph86d17b42017-02-15 14:45:01 +053011namespace sol
12{
13
Tom Josephfbcac2e2017-03-14 18:15:07 +053014/** @struct Outbound
15 *
16 * Operation/Status in an outbound SOL payload format(BMC to Remote Console).
17 */
18struct Outbound
19{
20#if BYTE_ORDER == LITTLE_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070021 uint8_t testMode : 2; //!< Not supported.
22 uint8_t breakDetected : 1; //!< Not supported.
23 uint8_t transmitOverrun : 1; //!< Not supported.
24 uint8_t SOLDeactivating : 1; //!< 0 : SOL is active, 1 : SOL deactivated.
25 uint8_t charUnavailable : 1; //!< 0 : Available, 1 : Unavailable.
26 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
27 uint8_t reserved : 1; //!< Reserved.
Tom Josephfbcac2e2017-03-14 18:15:07 +053028#endif
29
30#if BYTE_ORDER == BIG_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070031 uint8_t reserved : 1; //!< Reserved.
32 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
33 uint8_t charUnavailable : 1; //!< 0 : Available, 1 : Unavailable.
34 uint8_t SOLDeactivating : 1; //!< 0 : SOL is active, 1 : SOL deactivated.
35 uint8_t transmitOverrun : 1; //!< Not supported.
36 uint8_t breakDetected : 1; //!< Not supported.
37 uint8_t testMode : 2; //!< Not supported.
Tom Josephfbcac2e2017-03-14 18:15:07 +053038#endif
39} __attribute__((packed));
40
41/** @struct Inbound
42 *
43 * Operation/Status in an Inbound SOL Payload format(Remote Console to BMC).
44 */
45struct Inbound
46{
47#if BYTE_ORDER == LITTLE_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070048 uint8_t flushOut : 1; //!< Not supported.
49 uint8_t flushIn : 1; //!< Not supported.
50 uint8_t dcd : 1; //!< Not supported.
51 uint8_t cts : 1; //!< Not supported.
52 uint8_t generateBreak : 1; //!< Not supported.
53 uint8_t ring : 1; //!< Not supported.
54 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
55 uint8_t reserved : 1; //!< Reserved.
Tom Josephfbcac2e2017-03-14 18:15:07 +053056#endif
57
58#if BYTE_ORDER == BIG_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070059 uint8_t reserved : 1; //!< Reserved.
60 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
61 uint8_t ring : 1; //!< Not supported.
62 uint8_t generateBreak : 1; //!< Not supported.
63 uint8_t cts : 1; //!< Not supported.
64 uint8_t dcd : 1; //!< Not supported.
65 uint8_t flushIn : 1; //!< Not supported.
66 uint8_t flushOut : 1; //!< Not supported.
Tom Josephfbcac2e2017-03-14 18:15:07 +053067#endif
68} __attribute__((packed));
69
70/** @struct Payload
71 *
72 * SOL Payload Data Format.The following fields make up the SOL payload in an
73 * RMCP+ packet, followed by the console character data.
74 */
75struct Payload
76{
Vernon Mauery9e801a22018-10-12 13:20:49 -070077 uint8_t packetSeqNum; //!< Packet sequence number
78 uint8_t packetAckSeqNum; //!< Packet ACK/NACK sequence number
79 uint8_t acceptedCharCount; //!< Accepted character count
Tom Josephfbcac2e2017-03-14 18:15:07 +053080 union
81 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070082 uint8_t operation; //!< Operation/Status
83 struct Outbound outOperation; //!< BMC to Remote Console
84 struct Inbound inOperation; //!< Remote Console to BMC
Tom Josephfbcac2e2017-03-14 18:15:07 +053085 };
86} __attribute__((packed));
87
Tom Joseph86d17b42017-02-15 14:45:01 +053088namespace internal
89{
90
91/** @struct SequenceNumbers
92 *
93 * SOL sequence numbers. At the session level, SOL Payloads share the session
94 * sequence numbers for authenticated and unauthenticated packets with other
95 * packets under the IPMI session. At the payload level, SOL packets include
96 * their own message sequence numbers that are used for tracking missing and
97 * retried SOL messages. The sequence numbers must be non-zero. Retried
98 * packets use the same sequence number as the first packet.
99 */
100struct SequenceNumbers
101{
102 static constexpr uint8_t MAX_SOL_SEQUENCE_NUMBER = 0x10;
103
104 /** @brief Get the SOL sequence number.
105 *
106 * @param[in] inbound - true for inbound sequence number and false for
107 * outbound sequence number
108 *
109 * @return sequence number
110 */
111 auto get(bool inbound = true) const
112 {
113 return inbound ? in : out;
114 }
115
116 /** @brief Increment the inbound SOL sequence number. */
117 void incInboundSeqNum()
118 {
119 if ((++in) == MAX_SOL_SEQUENCE_NUMBER)
120 {
121 in = 1;
122 }
123 }
124
125 /** @brief Increment the outbound SOL sequence number.
126 *
127 * @return outbound sequence number to populate the SOL payload.
128 */
129 auto incOutboundSeqNum()
130 {
131 if ((++out) == MAX_SOL_SEQUENCE_NUMBER)
132 {
133 out = 1;
134 }
135
136 return out;
137 }
138
Vernon Mauery9e801a22018-10-12 13:20:49 -0700139 private:
140 uint8_t in = 1; //!< Inbound sequence number.
141 uint8_t out = 0; //!< Outbound sequence number, since the first
142 //!< operation is increment, it is initialised to 0
Tom Joseph86d17b42017-02-15 14:45:01 +0530143};
144
145} // namespace internal
146
147/** @class Context
148 *
149 * Context keeps the state of the SOL session. The information needed to
150 * maintain the state of the SOL is part of this class. This class provides
151 * interfaces to handle incoming SOL payload, send response and send outbound
152 * SOL payload.
153 */
Yong Lia3de8a82020-05-09 10:04:11 +0800154class Context : public std::enable_shared_from_this<Context>
Tom Joseph86d17b42017-02-15 14:45:01 +0530155{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700156 public:
Vernon Mauery6f353e82018-11-09 08:43:24 -0800157 Context() = delete;
Vernon Mauery9e801a22018-10-12 13:20:49 -0700158 ~Context() = default;
159 Context(const Context&) = delete;
160 Context& operator=(const Context&) = delete;
Vernon Mauery6f353e82018-11-09 08:43:24 -0800161 Context(Context&&) = delete;
162 Context& operator=(Context&&) = delete;
Tom Joseph86d17b42017-02-15 14:45:01 +0530163
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800164 /** @brief Context Factory
165 *
166 * This is called by the SOL Manager when a SOL payload instance is
167 * started for the activate payload command. Its purpose is to be able
168 * to perform post-creation tasks on the object without changing the
169 * code flow
170 *
171 * @param[in] io - boost::asio io context for event scheduling.
172 * @param[in] maxRetryCount - Retry count max value.
173 * @param[in] sendThreshold - Character send threshold.
174 * @param[in] instance - SOL payload instance.
175 * @param[in] sessionID - BMC session ID.
176 */
177 static std::shared_ptr<Context>
178 makeContext(std::shared_ptr<boost::asio::io_context> io,
179 uint8_t maxRetryCount, uint8_t sendThreshold,
180 uint8_t instance, session::SessionID sessionID);
181
Vernon Mauery9e801a22018-10-12 13:20:49 -0700182 /** @brief Context Constructor.
183 *
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800184 * This should only be used by the Context factory makeContext
185 * or the accumulate timer will not be initialized properly
Vernon Mauery9e801a22018-10-12 13:20:49 -0700186 *
Vernon Mauery6f353e82018-11-09 08:43:24 -0800187 * @param[in] io - boost::asio io context for event scheduling.
Vernon Mauery9e801a22018-10-12 13:20:49 -0700188 * @param[in] maxRetryCount - Retry count max value.
189 * @param[in] sendThreshold - Character send threshold.
190 * @param[in] instance - SOL payload instance.
191 * @param[in] sessionID - BMC session ID.
192 */
Vernon Mauery6f353e82018-11-09 08:43:24 -0800193 Context(std::shared_ptr<boost::asio::io_context> io, uint8_t maxRetryCount,
194 uint8_t sendThreshold, uint8_t instance,
195 session::SessionID sessionID);
Tom Joseph86d17b42017-02-15 14:45:01 +0530196
Vernon Mauery9e801a22018-10-12 13:20:49 -0700197 static constexpr auto clear = true;
198 static constexpr auto noClear = false;
Tom Joseph86d17b42017-02-15 14:45:01 +0530199
Vernon Mauery6f353e82018-11-09 08:43:24 -0800200 /** @brief accumulate timer */
201 boost::asio::steady_timer accumulateTimer;
202
203 /** @brief retry timer */
204 boost::asio::steady_timer retryTimer;
205
Vernon Mauery9e801a22018-10-12 13:20:49 -0700206 /** @brief Retry count max value. */
207 const uint8_t maxRetryCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530208
Vernon Mauery9e801a22018-10-12 13:20:49 -0700209 /** @brief Retry counter. */
210 uint8_t retryCounter = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530211
Vernon Mauery9e801a22018-10-12 13:20:49 -0700212 /** @brief Character send threshold. */
213 const uint8_t sendThreshold = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530214
Vernon Mauery9e801a22018-10-12 13:20:49 -0700215 /** @brief SOL payload instance. */
216 const uint8_t payloadInstance = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530217
Vernon Mauery9e801a22018-10-12 13:20:49 -0700218 /** @brief Session ID. */
219 const session::SessionID sessionID = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530220
Vernon Mauery6f353e82018-11-09 08:43:24 -0800221 /** @brief session pointer
222 */
223 std::shared_ptr<session::Session> session;
224
225 /** @brief enable/disable accumulate timer
226 *
227 * The timeout interval is managed by the SOL Manager;
228 * this function only enables or disable the timer
229 *
230 * @param[in] enable - enable(true) or disable(false) accumulation timer
231 */
232 void enableAccumulateTimer(bool enable);
233
234 /** @brief enable/disable retry timer
235 *
236 * The timeout interval is managed by the SOL Manager;
237 * this function only enables or disable the timer
238 *
239 * @param[in] enable - enable(true) or disable(false) retry timer
240 */
241 void enableRetryTimer(bool enable);
242
Vernon Mauery9e801a22018-10-12 13:20:49 -0700243 /** @brief Process the Inbound SOL payload.
244 *
245 * The SOL payload from the remote console is processed and the
246 * acknowledgment handling is done.
247 *
248 * @param[in] seqNum - Packet sequence number.
249 * @param[in] ackSeqNum - Packet ACK/NACK sequence number.
250 * @param[in] count - Accepted character count.
251 * @param[in] operation - ACK is false, NACK is true
252 * @param[in] input - Incoming SOL character data.
253 */
254 void processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, uint8_t count,
255 bool status, const std::vector<uint8_t>& input);
Tom Joseph86d17b42017-02-15 14:45:01 +0530256
Vernon Mauery9e801a22018-10-12 13:20:49 -0700257 /** @brief Send the outbound SOL payload.
258 *
259 * @return zero on success and negative value if condition for sending
260 * the payload fails.
261 */
262 int sendOutboundPayload();
Tom Joseph86d17b42017-02-15 14:45:01 +0530263
Vernon Mauery9e801a22018-10-12 13:20:49 -0700264 /** @brief Resend the SOL payload.
265 *
266 * @param[in] clear - if true then send the payload and clear the
267 * cached payload, if false only send the payload.
268 */
269 void resendPayload(bool clear);
Tom Joseph86d17b42017-02-15 14:45:01 +0530270
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800271 /** @brief accumlate timer handler called by timer */
272 void charAccTimerHandler();
273
274 /** @brief retry timer handler called by timer */
275 void retryTimerHandler();
276
Vernon Mauery9e801a22018-10-12 13:20:49 -0700277 private:
278 /** @brief Expected character count.
279 *
280 * Expected Sequence number and expected character count is set before
281 * sending the SOL payload. The check is done against these values when
282 * an incoming SOL payload is received.
283 */
284 size_t expectedCharCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530285
Vernon Mauery9e801a22018-10-12 13:20:49 -0700286 /** @brief Inbound and Outbound sequence numbers. */
287 internal::SequenceNumbers seqNums;
Tom Joseph86d17b42017-02-15 14:45:01 +0530288
Vernon Mauery9e801a22018-10-12 13:20:49 -0700289 /** @brief Copy of the last sent SOL payload.
290 *
291 * A copy of the SOL payload is kept here, so that when a retry needs
292 * to be attempted the payload is sent again.
293 */
294 std::vector<uint8_t> payloadCache;
Tom Joseph86d17b42017-02-15 14:45:01 +0530295
Vernon Mauery9e801a22018-10-12 13:20:49 -0700296 /**
297 * @brief Send Response for Incoming SOL payload.
298 *
299 * @param[in] ackSeqNum - Packet ACK/NACK Sequence Number.
300 * @param[in] count - Accepted Character Count.
301 * @param[in] ack - Set ACK/NACK in the Operation.
302 */
303 void prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack);
Tom Joseph86d17b42017-02-15 14:45:01 +0530304
Vernon Mauery9e801a22018-10-12 13:20:49 -0700305 /** @brief Send the outgoing SOL payload.
306 *
307 * @param[in] out - buffer containing the SOL payload.
308 */
309 void sendPayload(const std::vector<uint8_t>& out) const;
Tom Joseph86d17b42017-02-15 14:45:01 +0530310};
311
312} // namespace sol