diff options
author | Tom Joseph <tomjoseph@in.ibm.com> | 2017-03-14 18:15:07 +0530 |
---|---|---|
committer | Patrick Williams <patrick@stwcx.xyz> | 2017-04-24 11:22:15 -0500 |
commit | fbcac2e7e71d907543963c27a212575289de22b9 (patch) | |
tree | 23dd885c1cf580b47952353e7c0ca70335c12cdd | |
parent | 4ff14b59a16a2ecd99c77236db0b47c60c5a1a05 (diff) | |
download | phosphor-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.am | 3 | ||||
-rw-r--r-- | sol/sol_context.cpp | 123 | ||||
-rw-r--r-- | sol/sol_context.hpp | 74 |
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 { |