blob: 220040beb2d33043e7248b3c06972979200f6ed0 [file] [log] [blame]
Tom Joseph86d17b42017-02-15 14:45:01 +05301#pragma once
2
3#include "console_buffer.hpp"
4#include "session.hpp"
5
6namespace sol
7{
8
Tom Josephfbcac2e2017-03-14 18:15:07 +05309/** @struct Outbound
10 *
11 * Operation/Status in an outbound SOL payload format(BMC to Remote Console).
12 */
13struct Outbound
14{
15#if BYTE_ORDER == LITTLE_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070016 uint8_t testMode : 2; //!< Not supported.
17 uint8_t breakDetected : 1; //!< Not supported.
18 uint8_t transmitOverrun : 1; //!< Not supported.
19 uint8_t SOLDeactivating : 1; //!< 0 : SOL is active, 1 : SOL deactivated.
20 uint8_t charUnavailable : 1; //!< 0 : Available, 1 : Unavailable.
21 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
22 uint8_t reserved : 1; //!< Reserved.
Tom Josephfbcac2e2017-03-14 18:15:07 +053023#endif
24
25#if BYTE_ORDER == BIG_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070026 uint8_t reserved : 1; //!< Reserved.
27 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
28 uint8_t charUnavailable : 1; //!< 0 : Available, 1 : Unavailable.
29 uint8_t SOLDeactivating : 1; //!< 0 : SOL is active, 1 : SOL deactivated.
30 uint8_t transmitOverrun : 1; //!< Not supported.
31 uint8_t breakDetected : 1; //!< Not supported.
32 uint8_t testMode : 2; //!< Not supported.
Tom Josephfbcac2e2017-03-14 18:15:07 +053033#endif
34} __attribute__((packed));
35
36/** @struct Inbound
37 *
38 * Operation/Status in an Inbound SOL Payload format(Remote Console to BMC).
39 */
40struct Inbound
41{
42#if BYTE_ORDER == LITTLE_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070043 uint8_t flushOut : 1; //!< Not supported.
44 uint8_t flushIn : 1; //!< Not supported.
45 uint8_t dcd : 1; //!< Not supported.
46 uint8_t cts : 1; //!< Not supported.
47 uint8_t generateBreak : 1; //!< Not supported.
48 uint8_t ring : 1; //!< Not supported.
49 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
50 uint8_t reserved : 1; //!< Reserved.
Tom Josephfbcac2e2017-03-14 18:15:07 +053051#endif
52
53#if BYTE_ORDER == BIG_ENDIAN
Vernon Mauery9e801a22018-10-12 13:20:49 -070054 uint8_t reserved : 1; //!< Reserved.
55 uint8_t ack : 1; //!< 0 : ACK, 1 : NACK.
56 uint8_t ring : 1; //!< Not supported.
57 uint8_t generateBreak : 1; //!< Not supported.
58 uint8_t cts : 1; //!< Not supported.
59 uint8_t dcd : 1; //!< Not supported.
60 uint8_t flushIn : 1; //!< Not supported.
61 uint8_t flushOut : 1; //!< Not supported.
Tom Josephfbcac2e2017-03-14 18:15:07 +053062#endif
63} __attribute__((packed));
64
65/** @struct Payload
66 *
67 * SOL Payload Data Format.The following fields make up the SOL payload in an
68 * RMCP+ packet, followed by the console character data.
69 */
70struct Payload
71{
Vernon Mauery9e801a22018-10-12 13:20:49 -070072 uint8_t packetSeqNum; //!< Packet sequence number
73 uint8_t packetAckSeqNum; //!< Packet ACK/NACK sequence number
74 uint8_t acceptedCharCount; //!< Accepted character count
Tom Josephfbcac2e2017-03-14 18:15:07 +053075 union
76 {
Vernon Mauery9e801a22018-10-12 13:20:49 -070077 uint8_t operation; //!< Operation/Status
78 struct Outbound outOperation; //!< BMC to Remote Console
79 struct Inbound inOperation; //!< Remote Console to BMC
Tom Josephfbcac2e2017-03-14 18:15:07 +053080 };
81} __attribute__((packed));
82
Tom Joseph86d17b42017-02-15 14:45:01 +053083namespace internal
84{
85
86/** @struct SequenceNumbers
87 *
88 * SOL sequence numbers. At the session level, SOL Payloads share the session
89 * sequence numbers for authenticated and unauthenticated packets with other
90 * packets under the IPMI session. At the payload level, SOL packets include
91 * their own message sequence numbers that are used for tracking missing and
92 * retried SOL messages. The sequence numbers must be non-zero. Retried
93 * packets use the same sequence number as the first packet.
94 */
95struct SequenceNumbers
96{
97 static constexpr uint8_t MAX_SOL_SEQUENCE_NUMBER = 0x10;
98
99 /** @brief Get the SOL sequence number.
100 *
101 * @param[in] inbound - true for inbound sequence number and false for
102 * outbound sequence number
103 *
104 * @return sequence number
105 */
106 auto get(bool inbound = true) const
107 {
108 return inbound ? in : out;
109 }
110
111 /** @brief Increment the inbound SOL sequence number. */
112 void incInboundSeqNum()
113 {
114 if ((++in) == MAX_SOL_SEQUENCE_NUMBER)
115 {
116 in = 1;
117 }
118 }
119
120 /** @brief Increment the outbound SOL sequence number.
121 *
122 * @return outbound sequence number to populate the SOL payload.
123 */
124 auto incOutboundSeqNum()
125 {
126 if ((++out) == MAX_SOL_SEQUENCE_NUMBER)
127 {
128 out = 1;
129 }
130
131 return out;
132 }
133
Vernon Mauery9e801a22018-10-12 13:20:49 -0700134 private:
135 uint8_t in = 1; //!< Inbound sequence number.
136 uint8_t out = 0; //!< Outbound sequence number, since the first
137 //!< operation is increment, it is initialised to 0
Tom Joseph86d17b42017-02-15 14:45:01 +0530138};
139
140} // namespace internal
141
142/** @class Context
143 *
144 * Context keeps the state of the SOL session. The information needed to
145 * maintain the state of the SOL is part of this class. This class provides
146 * interfaces to handle incoming SOL payload, send response and send outbound
147 * SOL payload.
148 */
149class Context
150{
Vernon Mauery9e801a22018-10-12 13:20:49 -0700151 public:
152 Context() = default;
153 ~Context() = default;
154 Context(const Context&) = delete;
155 Context& operator=(const Context&) = delete;
156 Context(Context&&) = default;
157 Context& operator=(Context&&) = default;
Tom Joseph86d17b42017-02-15 14:45:01 +0530158
Vernon Mauery9e801a22018-10-12 13:20:49 -0700159 /** @brief Context Constructor.
160 *
161 * This is issued by the SOL Manager when a SOL payload instance is
162 * started for the activate payload command.
163 *
164 * @param[in] maxRetryCount - Retry count max value.
165 * @param[in] sendThreshold - Character send threshold.
166 * @param[in] instance - SOL payload instance.
167 * @param[in] sessionID - BMC session ID.
168 */
169 Context(uint8_t maxRetryCount, uint8_t sendThreshold, uint8_t instance,
170 session::SessionID sessionID) :
171 maxRetryCount(maxRetryCount),
172 retryCounter(maxRetryCount), sendThreshold(sendThreshold),
173 payloadInstance(instance), sessionID(sessionID)
174 {
175 }
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 Mauery9e801a22018-10-12 13:20:49 -0700180 /** @brief Retry count max value. */
181 const uint8_t maxRetryCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530182
Vernon Mauery9e801a22018-10-12 13:20:49 -0700183 /** @brief Retry counter. */
184 uint8_t retryCounter = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530185
Vernon Mauery9e801a22018-10-12 13:20:49 -0700186 /** @brief Character send threshold. */
187 const uint8_t sendThreshold = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530188
Vernon Mauery9e801a22018-10-12 13:20:49 -0700189 /** @brief SOL payload instance. */
190 const uint8_t payloadInstance = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530191
Vernon Mauery9e801a22018-10-12 13:20:49 -0700192 /** @brief Session ID. */
193 const session::SessionID sessionID = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530194
Vernon Mauery9e801a22018-10-12 13:20:49 -0700195 /** @brief Process the Inbound SOL payload.
196 *
197 * The SOL payload from the remote console is processed and the
198 * acknowledgment handling is done.
199 *
200 * @param[in] seqNum - Packet sequence number.
201 * @param[in] ackSeqNum - Packet ACK/NACK sequence number.
202 * @param[in] count - Accepted character count.
203 * @param[in] operation - ACK is false, NACK is true
204 * @param[in] input - Incoming SOL character data.
205 */
206 void processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, uint8_t count,
207 bool status, const std::vector<uint8_t>& input);
Tom Joseph86d17b42017-02-15 14:45:01 +0530208
Vernon Mauery9e801a22018-10-12 13:20:49 -0700209 /** @brief Send the outbound SOL payload.
210 *
211 * @return zero on success and negative value if condition for sending
212 * the payload fails.
213 */
214 int sendOutboundPayload();
Tom Joseph86d17b42017-02-15 14:45:01 +0530215
Vernon Mauery9e801a22018-10-12 13:20:49 -0700216 /** @brief Resend the SOL payload.
217 *
218 * @param[in] clear - if true then send the payload and clear the
219 * cached payload, if false only send the payload.
220 */
221 void resendPayload(bool clear);
Tom Joseph86d17b42017-02-15 14:45:01 +0530222
Vernon Mauery9e801a22018-10-12 13:20:49 -0700223 private:
224 /** @brief Expected character count.
225 *
226 * Expected Sequence number and expected character count is set before
227 * sending the SOL payload. The check is done against these values when
228 * an incoming SOL payload is received.
229 */
230 size_t expectedCharCount = 0;
Tom Joseph86d17b42017-02-15 14:45:01 +0530231
Vernon Mauery9e801a22018-10-12 13:20:49 -0700232 /** @brief Inbound and Outbound sequence numbers. */
233 internal::SequenceNumbers seqNums;
Tom Joseph86d17b42017-02-15 14:45:01 +0530234
Vernon Mauery9e801a22018-10-12 13:20:49 -0700235 /** @brief Copy of the last sent SOL payload.
236 *
237 * A copy of the SOL payload is kept here, so that when a retry needs
238 * to be attempted the payload is sent again.
239 */
240 std::vector<uint8_t> payloadCache;
Tom Joseph86d17b42017-02-15 14:45:01 +0530241
Vernon Mauery9e801a22018-10-12 13:20:49 -0700242 /**
243 * @brief Send Response for Incoming SOL payload.
244 *
245 * @param[in] ackSeqNum - Packet ACK/NACK Sequence Number.
246 * @param[in] count - Accepted Character Count.
247 * @param[in] ack - Set ACK/NACK in the Operation.
248 */
249 void prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack);
Tom Joseph86d17b42017-02-15 14:45:01 +0530250
Vernon Mauery9e801a22018-10-12 13:20:49 -0700251 /** @brief Send the outgoing SOL payload.
252 *
253 * @param[in] out - buffer containing the SOL payload.
254 */
255 void sendPayload(const std::vector<uint8_t>& out) const;
Tom Joseph86d17b42017-02-15 14:45:01 +0530256};
257
258} // namespace sol