summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Joseph <tomjoseph@in.ibm.com>2017-03-14 18:15:07 +0530
committerPatrick Williams <patrick@stwcx.xyz>2017-04-24 11:22:15 -0500
commitfbcac2e7e71d907543963c27a212575289de22b9 (patch)
tree23dd885c1cf580b47952353e7c0ca70335c12cdd
parent4ff14b59a16a2ecd99c77236db0b47c60c5a1a05 (diff)
downloadphosphor-net-ipmid-fbcac2e7e71d907543963c27a212575289de22b9.tar.gz
phosphor-net-ipmid-fbcac2e7e71d907543963c27a212575289de22b9.zip
Implement API to handle inbound SOL Payload
Change-Id: I4bcb98568d84ba384ac11b7777d936c7d5fc124e Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
-rw-r--r--Makefile.am3
-rw-r--r--sol/sol_context.cpp123
-rw-r--r--sol/sol_context.hpp74
3 files changed, 199 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 6843a7e..35e5353 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,7 +45,8 @@ netipmid_SOURCES = \
sol/sol_context.hpp \
sol/sol_manager.hpp \
sd_event_loop.cpp \
- sol/sol_manager.cpp
+ sol/sol_manager.cpp \
+ sol/sol_context.cpp
netipmid_CPPFLAGS = -DNET_IPMID_LIB_PATH=\"/usr/lib/net-ipmid/\"
netipmid_LDFLAGS = $(SYSTEMD_LIBS) $(CRYPTO_LIBS) $(libmapper_LIBS) $(PHOSPHOR_LOGGING_LIBS) $(LIBADD_DLOPEN) -export-dynamic
diff --git a/sol/sol_context.cpp b/sol/sol_context.cpp
new file mode 100644
index 0000000..b81281b
--- /dev/null
+++ b/sol/sol_context.cpp
@@ -0,0 +1,123 @@
+#include <phosphor-logging/log.hpp>
+#include "main.hpp"
+#include "sd_event_loop.hpp"
+#include "sol_context.hpp"
+#include "sol_manager.hpp"
+
+namespace sol
+{
+
+using namespace phosphor::logging;
+
+void Context::processInboundPayload(uint8_t seqNum,
+ uint8_t ackSeqNum,
+ uint8_t count,
+ bool status,
+ const Buffer& input)
+{
+ uint8_t respAckSeqNum = 0;
+ uint8_t acceptedCount = 0;
+ auto ack = false;
+
+ /*
+ * Check if the Inbound sequence number is same as the expected one.
+ * If the Packet Sequence Number is 0, it is an ACK-Only packet. Multiple
+ * outstanding sequence numbers are not supported in this version of the SOL
+ * specification. Retried packets use the same sequence number as the first
+ * packet.
+ */
+ if(seqNum && (seqNum != seqNums.get(true)))
+ {
+ log<level::INFO>("Out of sequence SOL packet - packet is dropped");
+ return;
+ }
+
+ /*
+ * Check if the expected ACK/NACK sequence number is same as the
+ * ACK/NACK sequence number in the packet. If packet ACK/NACK sequence
+ * number is 0, then it is an informational packet. No request packet being
+ * ACK'd or NACK'd.
+ */
+ if (ackSeqNum && (ackSeqNum != seqNums.get(false)))
+ {
+ log<level::INFO>("Out of sequence ack number - SOL packet is dropped");
+ return;
+ }
+
+ /*
+ * Retry the SOL payload packet in the following conditions:
+ *
+ * a) NACK in Operation/Status
+ * b) Accepted Character Count does not match with the sent out SOL payload
+ * c) Non-zero Packet ACK/NACK Sequence Number
+ */
+ if (status || ((count != expectedCharCount) && ackSeqNum))
+ {
+ resendPayload(noClear);
+ std::get<eventloop::EventLoop&>(singletonPool).switchTimer
+ (payloadInstance, eventloop::Timers::RETRY, false);
+ std::get<eventloop::EventLoop&>(singletonPool).switchTimer
+ (payloadInstance, eventloop::Timers::RETRY, true);
+ return;
+ }
+ /*
+ * Clear the sent data once the acknowledgment sequence number matches
+ * and the expected character count matches.
+ */
+ else if ((count == expectedCharCount) && ackSeqNum)
+ {
+ // Clear the Host Console Buffer
+ std::get<sol::Manager&>(singletonPool).dataBuffer.erase(count);
+
+ // Once it is acknowledged stop the retry interval timer
+ std::get<eventloop::EventLoop&>(singletonPool).switchTimer(
+ payloadInstance, eventloop::Timers::RETRY, false);
+
+ retryCounter = maxRetryCount;
+ expectedCharCount = 0;
+ payloadCache.clear();
+ }
+
+ // Write character data to the Host Console
+ if (!input.empty() && seqNum)
+ {
+ auto rc = std::get<sol::Manager&>(singletonPool).writeConsoleSocket(
+ input);
+ if (rc)
+ {
+ log<level::ERR>("Writing to console socket descriptor failed");
+ ack = true;
+ }
+ else
+ {
+ respAckSeqNum = seqNum;
+ ack = false;
+ acceptedCount = input.size();
+ }
+ }
+
+ if (seqNum != 0)
+ {
+ seqNums.incInboundSeqNum();
+ prepareResponse(respAckSeqNum, acceptedCount, ack);
+ }
+ else
+ {
+ std::get<eventloop::EventLoop&>(singletonPool).switchTimer
+ (payloadInstance, eventloop::Timers::ACCUMULATE, true);
+ }
+}
+
+void Context::prepareResponse(uint8_t ackSeqNum,
+ uint8_t count,
+ bool ack)
+{
+
+}
+
+void Context::resendPayload(bool clear)
+{
+
+}
+
+} // namespace sol
diff --git a/sol/sol_context.hpp b/sol/sol_context.hpp
index 81ad19b..9de88c9 100644
--- a/sol/sol_context.hpp
+++ b/sol/sol_context.hpp
@@ -6,6 +6,80 @@
namespace sol
{
+/** @struct Outbound
+ *
+ * Operation/Status in an outbound SOL payload format(BMC to Remote Console).
+ */
+struct Outbound
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t testMode: 2; //!< Not supported.
+ uint8_t breakDetected: 1; //!< Not supported.
+ uint8_t transmitOverrun: 1; //!< Not supported.
+ uint8_t SOLDeactivating: 1; //!< 0 : SOL is active, 1 : SOL deactivated.
+ uint8_t charUnavailable: 1; //!< 0 : Available, 1 : Unavailable.
+ uint8_t ack: 1; //!< 0 : ACK, 1 : NACK.
+ uint8_t reserved: 1; //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved: 1; //!< Reserved.
+ uint8_t ack: 1; //!< 0 : ACK, 1 : NACK.
+ uint8_t charUnavailable: 1; //!< 0 : Available, 1 : Unavailable.
+ uint8_t SOLDeactivating: 1; //!< 0 : SOL is active, 1 : SOL deactivated.
+ uint8_t transmitOverrun: 1; //!< Not supported.
+ uint8_t breakDetected: 1; //!< Not supported.
+ uint8_t testMode: 2; //!< Not supported.
+#endif
+} __attribute__((packed));
+
+/** @struct Inbound
+ *
+ * Operation/Status in an Inbound SOL Payload format(Remote Console to BMC).
+ */
+struct Inbound
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+ uint8_t flushOut: 1; //!< Not supported.
+ uint8_t flushIn: 1; //!< Not supported.
+ uint8_t dcd: 1; //!< Not supported.
+ uint8_t cts: 1; //!< Not supported.
+ uint8_t generateBreak: 1; //!< Not supported.
+ uint8_t ring: 1; //!< Not supported.
+ uint8_t ack: 1; //!< 0 : ACK, 1 : NACK.
+ uint8_t reserved: 1; //!< Reserved.
+#endif
+
+#if BYTE_ORDER == BIG_ENDIAN
+ uint8_t reserved: 1; //!< Reserved.
+ uint8_t ack: 1; //!< 0 : ACK, 1 : NACK.
+ uint8_t ring: 1; //!< Not supported.
+ uint8_t generateBreak: 1; //!< Not supported.
+ uint8_t cts: 1; //!< Not supported.
+ uint8_t dcd: 1; //!< Not supported.
+ uint8_t flushIn: 1; //!< Not supported.
+ uint8_t flushOut: 1; //!< Not supported.
+#endif
+} __attribute__((packed));
+
+/** @struct Payload
+ *
+ * SOL Payload Data Format.The following fields make up the SOL payload in an
+ * RMCP+ packet, followed by the console character data.
+ */
+struct Payload
+{
+ uint8_t packetSeqNum; //!< Packet sequence number
+ uint8_t packetAckSeqNum; //!< Packet ACK/NACK sequence number
+ uint8_t acceptedCharCount; //!< Accepted character count
+ union
+ {
+ uint8_t operation; //!<Operation/Status
+ struct Outbound outOperation; //!<BMC to Remote Console
+ struct Inbound inOperation; //!<Remote Console to BMC
+ };
+} __attribute__((packed));
+
namespace internal
{
OpenPOWER on IntegriCloud