blob: 9de88c93739fc2d65f50618216e6a85a0f434154 [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
16 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.
23#endif
24
25#if BYTE_ORDER == BIG_ENDIAN
26 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.
33#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
43 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.
51#endif
52
53#if BYTE_ORDER == BIG_ENDIAN
54 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.
62#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{
72 uint8_t packetSeqNum; //!< Packet sequence number
73 uint8_t packetAckSeqNum; //!< Packet ACK/NACK sequence number
74 uint8_t acceptedCharCount; //!< Accepted character count
75 union
76 {
77 uint8_t operation; //!<Operation/Status
78 struct Outbound outOperation; //!<BMC to Remote Console
79 struct Inbound inOperation; //!<Remote Console to BMC
80 };
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
134 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
138};
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{
151 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;
158
159 /** @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,
170 uint8_t sendThreshold,
171 uint8_t instance,
172 session::SessionID sessionID):
173 maxRetryCount(maxRetryCount),
174 retryCounter(maxRetryCount),
175 sendThreshold(sendThreshold),
176 payloadInstance(instance),
177 sessionID(sessionID) {}
178
179 static constexpr auto clear = true;
180 static constexpr auto noClear = false;
181
182 /** @brief Retry count max value. */
183 const uint8_t maxRetryCount = 0;
184
185 /** @brief Retry counter. */
186 uint8_t retryCounter = 0;
187
188 /** @brief Character send threshold. */
189 const uint8_t sendThreshold = 0;
190
191 /** @brief SOL payload instance. */
192 const uint8_t payloadInstance = 0;
193
194 /** @brief Session ID. */
195 const session::SessionID sessionID = 0;
196
197 /** @brief Process the Inbound SOL payload.
198 *
199 * The SOL payload from the remote console is processed and the
200 * acknowledgment handling is done.
201 *
202 * @param[in] seqNum - Packet sequence number.
203 * @param[in] ackSeqNum - Packet ACK/NACK sequence number.
204 * @param[in] count - Accepted character count.
205 * @param[in] operation - ACK is false, NACK is true
206 * @param[in] input - Incoming SOL character data.
207 */
208 void processInboundPayload(uint8_t seqNum,
209 uint8_t ackSeqNum,
210 uint8_t count,
211 bool status,
212 const Buffer& input);
213
214 /** @brief Send the outbound SOL payload.
215 *
216 * @return zero on success and negative value if condition for sending
217 * the payload fails.
218 */
219 int sendOutboundPayload();
220
221 /** @brief Resend the SOL payload.
222 *
223 * @param[in] clear - if true then send the payload and clear the
224 * cached payload, if false only send the payload.
225 */
226 void resendPayload(bool clear);
227
228 private:
229 /** @brief Expected character count.
230 *
231 * Expected Sequence number and expected character count is set before
232 * sending the SOL payload. The check is done against these values when
233 * an incoming SOL payload is received.
234 */
235 size_t expectedCharCount = 0;
236
237 /** @brief Inbound and Outbound sequence numbers. */
238 internal::SequenceNumbers seqNums;
239
240 /** @brief Copy of the last sent SOL payload.
241 *
242 * A copy of the SOL payload is kept here, so that when a retry needs
243 * to be attempted the payload is sent again.
244 */
245 Buffer payloadCache;
246
247 /**
248 * @brief Send Response for Incoming SOL payload.
249 *
250 * @param[in] ackSeqNum - Packet ACK/NACK Sequence Number.
251 * @param[in] count - Accepted Character Count.
252 * @param[in] ack - Set ACK/NACK in the Operation.
253 */
254 void prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack);
255
256 /** @brief Send the outgoing SOL payload.
257 *
258 * @param[in] out - buffer containing the SOL payload.
259 */
260 void sendPayload(const Buffer& out) const;
261};
262
263} // namespace sol