diff options
| author | Vernon Mauery <vernon.mauery@linux.intel.com> | 2018-11-09 08:43:24 -0800 |
|---|---|---|
| committer | Vernon Mauery <vernon.mauery@linux.intel.com> | 2019-02-01 13:01:18 -0800 |
| commit | 6f353e868d6fef90e35ef13da7c7ae912becb97a (patch) | |
| tree | 1c6f6ab825c931cdd1d31e97eaa462b49c6f964b /sol | |
| parent | 7e4a651799df95e44b4c99825adf18a8ef878f52 (diff) | |
| download | phosphor-net-ipmid-6f353e868d6fef90e35ef13da7c7ae912becb97a.tar.gz phosphor-net-ipmid-6f353e868d6fef90e35ef13da7c7ae912becb97a.zip | |
netipmid: move sol timers to asio
The IPMI SOL console was using sd_event-based timers directly (without
any abstraction). This moves to a much higher level abstraction that is
very easy to use: asio timers.
Change-Id: Id5df76a1918cdfae420e01884d664234810b7abd
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Diffstat (limited to 'sol')
| -rw-r--r-- | sol/sol_context.cpp | 133 | ||||
| -rw-r--r-- | sol/sol_context.hpp | 54 | ||||
| -rw-r--r-- | sol/sol_manager.cpp | 12 |
3 files changed, 154 insertions, 45 deletions
diff --git a/sol/sol_context.cpp b/sol/sol_context.cpp index fffb66f..215f725 100644 --- a/sol/sol_context.cpp +++ b/sol/sol_context.cpp @@ -8,9 +8,62 @@ namespace sol { - using namespace phosphor::logging; +Context::Context(std::shared_ptr<boost::asio::io_context> io, + uint8_t maxRetryCount, uint8_t sendThreshold, uint8_t instance, + session::SessionID sessionID) : + accumulateTimer(*io), + retryTimer(*io), maxRetryCount(maxRetryCount), retryCounter(maxRetryCount), + sendThreshold(sendThreshold), payloadInstance(instance), + sessionID(sessionID) +{ + session = std::get<session::Manager&>(singletonPool).getSession(sessionID); + enableAccumulateTimer(true); +} + +void Context::enableAccumulateTimer(bool enable) +{ + // fetch the timeout from the SOL manager + std::chrono::microseconds interval = + std::get<sol::Manager&>(singletonPool).accumulateInterval; + if (enable) + { + accumulateTimer.expires_after(interval); + accumulateTimer.async_wait([this](const boost::system::error_code& ec) { + if (!ec) + { + charAccTimerHandler(); + } + }); + } + else + { + accumulateTimer.cancel(); + } +} + +void Context::enableRetryTimer(bool enable) +{ + if (enable) + { + // fetch the timeout from the SOL manager + std::chrono::microseconds interval = + std::get<sol::Manager&>(singletonPool).retryInterval; + retryTimer.expires_after(interval); + retryTimer.async_wait([this](const boost::system::error_code& ec) { + if (!ec) + { + retryTimerHandler(); + } + }); + } + else + { + retryTimer.cancel(); + } +} + void Context::processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, uint8_t count, bool status, const std::vector<uint8_t>& input) @@ -54,10 +107,8 @@ void Context::processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, 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); + enableRetryTimer(false); + enableRetryTimer(true); return; } /* @@ -70,8 +121,7 @@ void Context::processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, 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); + enableRetryTimer(false); retryCounter = maxRetryCount; expectedCharCount = 0; @@ -111,8 +161,7 @@ void Context::processInboundPayload(uint8_t seqNum, uint8_t ackSeqNum, } else { - std::get<eventloop::EventLoop&>(singletonPool) - .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, true); + enableAccumulateTimer(true); } } @@ -123,8 +172,7 @@ void Context::prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack) /* Sent a ACK only response */ if (payloadCache.size() != 0 || (bufferSize < sendThreshold)) { - std::get<eventloop::EventLoop&>(singletonPool) - .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, true); + enableAccumulateTimer(true); std::vector<uint8_t> outPayload(sizeof(Payload)); auto response = reinterpret_cast<Payload*>(outPayload.data()); @@ -148,10 +196,8 @@ void Context::prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack) std::copy_n(handle, readSize, payloadCache.data() + sizeof(Payload)); expectedCharCount = readSize; - std::get<eventloop::EventLoop&>(singletonPool) - .switchTimer(payloadInstance, eventloop::Timers::RETRY, true); - std::get<eventloop::EventLoop&>(singletonPool) - .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, false); + enableRetryTimer(true); + enableAccumulateTimer(false); sendPayload(payloadCache); } @@ -160,8 +206,7 @@ int Context::sendOutboundPayload() { if (payloadCache.size() != 0) { - std::get<eventloop::EventLoop&>(singletonPool) - .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, true); + enableAccumulateTimer(true); return -1; } @@ -179,10 +224,8 @@ int Context::sendOutboundPayload() std::copy_n(handle, readSize, payloadCache.data() + sizeof(Payload)); expectedCharCount = readSize; - std::get<eventloop::EventLoop&>(singletonPool) - .switchTimer(payloadInstance, eventloop::Timers::RETRY, true); - std::get<eventloop::EventLoop&>(singletonPool) - .switchTimer(payloadInstance, eventloop::Timers::ACCUMULATE, false); + enableRetryTimer(true); + enableAccumulateTimer(false); sendPayload(payloadCache); @@ -204,12 +247,54 @@ void Context::resendPayload(bool clear) void Context::sendPayload(const std::vector<uint8_t>& out) const { - auto session = - std::get<session::Manager&>(singletonPool).getSession(sessionID); - message::Handler msgHandler(session->channelPtr, sessionID); msgHandler.sendSOLPayload(out); } +void Context::charAccTimerHandler() +{ + auto bufferSize = std::get<sol::Manager&>(singletonPool).dataBuffer.size(); + + try + { + if (bufferSize > 0) + { + int rc = sendOutboundPayload(); + if (rc == 0) + { + return; + } + } + enableAccumulateTimer(true); + } + catch (std::exception& e) + { + log<level::ERR>(e.what()); + } +} + +void Context::retryTimerHandler() +{ + try + { + if (retryCounter) + { + --retryCounter; + enableRetryTimer(true); + resendPayload(sol::Context::noClear); + } + else + { + retryCounter = maxRetryCount; + resendPayload(sol::Context::clear); + enableRetryTimer(false); + enableAccumulateTimer(true); + } + } + catch (std::exception& e) + { + log<level::ERR>(e.what()); + } +} } // namespace sol diff --git a/sol/sol_context.hpp b/sol/sol_context.hpp index 220040b..8d0fc87 100644 --- a/sol/sol_context.hpp +++ b/sol/sol_context.hpp @@ -3,6 +3,9 @@ #include "console_buffer.hpp" #include "session.hpp" +#include <boost/asio/io_context.hpp> +#include <boost/asio/steady_timer.hpp> + namespace sol { @@ -149,34 +152,37 @@ struct SequenceNumbers class Context { public: - Context() = default; + Context() = delete; ~Context() = default; Context(const Context&) = delete; Context& operator=(const Context&) = delete; - Context(Context&&) = default; - Context& operator=(Context&&) = default; + Context(Context&&) = delete; + Context& operator=(Context&&) = delete; /** @brief Context Constructor. * * This is issued by the SOL Manager when a SOL payload instance is * started for the activate payload command. * + * @param[in] io - boost::asio io context for event scheduling. * @param[in] maxRetryCount - Retry count max value. * @param[in] sendThreshold - Character send threshold. * @param[in] instance - SOL payload instance. * @param[in] sessionID - BMC session ID. */ - Context(uint8_t maxRetryCount, uint8_t sendThreshold, uint8_t instance, - session::SessionID sessionID) : - maxRetryCount(maxRetryCount), - retryCounter(maxRetryCount), sendThreshold(sendThreshold), - payloadInstance(instance), sessionID(sessionID) - { - } + Context(std::shared_ptr<boost::asio::io_context> io, uint8_t maxRetryCount, + uint8_t sendThreshold, uint8_t instance, + session::SessionID sessionID); static constexpr auto clear = true; static constexpr auto noClear = false; + /** @brief accumulate timer */ + boost::asio::steady_timer accumulateTimer; + + /** @brief retry timer */ + boost::asio::steady_timer retryTimer; + /** @brief Retry count max value. */ const uint8_t maxRetryCount = 0; @@ -192,6 +198,28 @@ class Context /** @brief Session ID. */ const session::SessionID sessionID = 0; + /** @brief session pointer + */ + std::shared_ptr<session::Session> session; + + /** @brief enable/disable accumulate timer + * + * The timeout interval is managed by the SOL Manager; + * this function only enables or disable the timer + * + * @param[in] enable - enable(true) or disable(false) accumulation timer + */ + void enableAccumulateTimer(bool enable); + + /** @brief enable/disable retry timer + * + * The timeout interval is managed by the SOL Manager; + * this function only enables or disable the timer + * + * @param[in] enable - enable(true) or disable(false) retry timer + */ + void enableRetryTimer(bool enable); + /** @brief Process the Inbound SOL payload. * * The SOL payload from the remote console is processed and the @@ -253,6 +281,12 @@ class Context * @param[in] out - buffer containing the SOL payload. */ void sendPayload(const std::vector<uint8_t>& out) const; + + /** @brief accumlate timer handler called by timer */ + void charAccTimerHandler(); + + /** @brief retry timer handler called by timer */ + void retryTimerHandler(); }; } // namespace sol diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp index fc0efe9..2046fe4 100644 --- a/sol/sol_manager.cpp +++ b/sol/sol_manager.cpp @@ -102,16 +102,9 @@ void Manager::startPayloadInstance(uint8_t payloadInstance, } // Create the SOL Context data for payload instance - auto context = std::make_unique<Context>(retryCount, sendThreshold, + auto context = std::make_unique<Context>(io, retryCount, sendThreshold, payloadInstance, sessionID); - std::get<eventloop::EventLoop&>(singletonPool) - .startSOLPayloadInstance( - payloadInstance, - std::chrono::duration_cast<eventloop::IntervalType>( - accumulateInterval), - std::chrono::duration_cast<eventloop::IntervalType>(retryInterval)); - payloadMap.emplace(payloadInstance, std::move(context)); } @@ -125,9 +118,6 @@ void Manager::stopPayloadInstance(uint8_t payloadInstance) payloadMap.erase(iter); - std::get<eventloop::EventLoop&>(singletonPool) - .stopSOLPayloadInstance(payloadInstance); - if (payloadMap.empty()) { stopHostConsole(); |

