blob: 8d0fc87369e42442617bf62c464449a55471ab36 [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 */
152class Context
153{
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 Mauery9e801a22018-10-12 13:20:49 -0700162 /** @brief Context Constructor.
163 *
164 * This is issued by the SOL Manager when a SOL payload instance is
165 * started for the activate payload command.
166 *
Vernon Mauery6f353e82018-11-09 08:43:24 -0800167 * @param[in] io - boost::asio io context for event scheduling.
Vernon Mauery9e801a22018-10-12 13:20:49 -0700168 * @param[in] maxRetryCount - Retry count max value.
169 * @param[in] sendThreshold - Character send threshold.
170 * @param[in] instance - SOL payload instance.
171 * @param[in] sessionID - BMC session ID.
172 */
Vernon Mauery6f353e82018-11-09 08:43:24 -0800173 Context(std::shared_ptr<boost::asio::io_context> io, uint8_t maxRetryCount,
174 uint8_t sendThreshold, uint8_t instance,
175 session::SessionID sessionID);
Tom Joseph86d17b42017-02-15 14:45:01 +0530176
Vernon Mauery9e801a22018-10-12 13:20:49 -0700177 static constexpr auto clear = true;
178 static constexpr auto noClear = false;
Tom Joseph86d17b42017-02-15 14:45:01 +0530179
Vernon Mauery6f353e82018-11-09 08:43:24 -0800180 /** @brief accumulate timer */
181 boost::asio::steady_timer accumulateTimer;
182
183 /** @brief retry timer */
184 boost::asio::steady_timer retryTimer;
185
Vernon Mauery9e801a22018-10-12 13:20:49 -0700186 /** @brief Retry count max value. */
187 const uint8_t maxRetryCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530188
Vernon Mauery9e801a22018-10-12 13:20:49 -0700189 /** @brief Retry counter. */
190 uint8_t retryCounter = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530191
Vernon Mauery9e801a22018-10-12 13:20:49 -0700192 /** @brief Character send threshold. */
193 const uint8_t sendThreshold = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530194
Vernon Mauery9e801a22018-10-12 13:20:49 -0700195 /** @brief SOL payload instance. */
196 const uint8_t payloadInstance = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530197
Vernon Mauery9e801a22018-10-12 13:20:49 -0700198 /** @brief Session ID. */
199 const session::SessionID sessionID = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530200
Vernon Mauery6f353e82018-11-09 08:43:24 -0800201 /** @brief session pointer
202 */
203 std::shared_ptr<session::Session> session;
204
205 /** @brief enable/disable accumulate timer
206 *
207 * The timeout interval is managed by the SOL Manager;
208 * this function only enables or disable the timer
209 *
210 * @param[in] enable - enable(true) or disable(false) accumulation timer
211 */
212 void enableAccumulateTimer(bool enable);
213
214 /** @brief enable/disable retry timer
215 *
216 * The timeout interval is managed by the SOL Manager;
217 * this function only enables or disable the timer
218 *
219 * @param[in] enable - enable(true) or disable(false) retry timer
220 */
221 void enableRetryTimer(bool enable);
222
Vernon Mauery9e801a22018-10-12 13:20:49 -0700223 /** @brief Process the Inbound SOL payload.
224 *
225 * The SOL payload from the remote console is processed and the
226 * acknowledgment handling is done.
227 *
228 * @param[in] seqNum - Packet sequence number.
229 * @param[in] ackSeqNum - Packet ACK/NACK sequence number.
230 * @param[in] count - Accepted character count.
231 * @param[in] operation - ACK is false, NACK is true
232 * @param[in] input - Incoming SOL character data.
233 */
234 void processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, uint8_t count,
235 bool status, const std::vector<uint8_t>& input);
Tom Joseph86d17b42017-02-15 14:45:01 +0530236
Vernon Mauery9e801a22018-10-12 13:20:49 -0700237 /** @brief Send the outbound SOL payload.
238 *
239 * @return zero on success and negative value if condition for sending
240 * the payload fails.
241 */
242 int sendOutboundPayload();
Tom Joseph86d17b42017-02-15 14:45:01 +0530243
Vernon Mauery9e801a22018-10-12 13:20:49 -0700244 /** @brief Resend the SOL payload.
245 *
246 * @param[in] clear - if true then send the payload and clear the
247 * cached payload, if false only send the payload.
248 */
249 void resendPayload(bool clear);
Tom Joseph86d17b42017-02-15 14:45:01 +0530250
Vernon Mauery9e801a22018-10-12 13:20:49 -0700251 private:
252 /** @brief Expected character count.
253 *
254 * Expected Sequence number and expected character count is set before
255 * sending the SOL payload. The check is done against these values when
256 * an incoming SOL payload is received.
257 */
258 size_t expectedCharCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530259
Vernon Mauery9e801a22018-10-12 13:20:49 -0700260 /** @brief Inbound and Outbound sequence numbers. */
261 internal::SequenceNumbers seqNums;
Tom Joseph86d17b42017-02-15 14:45:01 +0530262
Vernon Mauery9e801a22018-10-12 13:20:49 -0700263 /** @brief Copy of the last sent SOL payload.
264 *
265 * A copy of the SOL payload is kept here, so that when a retry needs
266 * to be attempted the payload is sent again.
267 */
268 std::vector<uint8_t> payloadCache;
Tom Joseph86d17b42017-02-15 14:45:01 +0530269
Vernon Mauery9e801a22018-10-12 13:20:49 -0700270 /**
271 * @brief Send Response for Incoming SOL payload.
272 *
273 * @param[in] ackSeqNum - Packet ACK/NACK Sequence Number.
274 * @param[in] count - Accepted Character Count.
275 * @param[in] ack - Set ACK/NACK in the Operation.
276 */
277 void prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack);
Tom Joseph86d17b42017-02-15 14:45:01 +0530278
Vernon Mauery9e801a22018-10-12 13:20:49 -0700279 /** @brief Send the outgoing SOL payload.
280 *
281 * @param[in] out - buffer containing the SOL payload.
282 */
283 void sendPayload(const std::vector<uint8_t>& out) const;
Vernon Mauery6f353e82018-11-09 08:43:24 -0800284
285 /** @brief accumlate timer handler called by timer */
286 void charAccTimerHandler();
287
288 /** @brief retry timer handler called by timer */
289 void retryTimerHandler();
Tom Joseph86d17b42017-02-15 14:45:01 +0530290};
291
292} // namespace sol