summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRatan Gupta <ratagupt@in.ibm.com>2018-03-12 16:21:37 +0530
committerRatan Gupta <ratagupt@in.ibm.com>2018-03-12 16:26:56 +0530
commit408013630a1ffded4fe035f1e39b8fcac85eccea (patch)
tree050f5d7077f65118a9b7ec634f5c57a747c34b9b
parent7e9e2ef68a1c53e022970d85566945d5bdc5a78e (diff)
downloadphosphor-net-ipmid-408013630a1ffded4fe035f1e39b8fcac85eccea.tar.gz
phosphor-net-ipmid-408013630a1ffded4fe035f1e39b8fcac85eccea.zip
SetLan: Define the global network timer
As timer is being referred in the provider library so it should be defined in per process(host-ipmid, net-ipmid) context. Defining the timer requires to pull the code of timer in this repository so adding the timer class. Change-Id: I4ea5f51fed03dd87d70868b0bc76ff1fb683931c Signed-off-by: Ratan Gupta <ratagupt@in.ibm.com>
-rw-r--r--Makefile.am3
-rw-r--r--main.cpp4
-rw-r--r--timer.cpp110
-rw-r--r--timer.hpp101
4 files changed, 217 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 33735fd..1d1a370 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -54,7 +54,8 @@ netipmid_SOURCES = \
sol_module.hpp \
sol_module.cpp \
settings.hpp \
- settings.cpp
+ settings.cpp \
+ timer.cpp
netipmid_CPPFLAGS = -DNET_IPMID_LIB_PATH=\"/usr/lib/net-ipmid/\"
diff --git a/main.cpp b/main.cpp
index ef4a349..c74b1c8 100644
--- a/main.cpp
+++ b/main.cpp
@@ -20,6 +20,7 @@
#include "provider_registration.hpp"
#include "socket_channel.hpp"
#include "sol_module.hpp"
+#include "timer.hpp"
// Tuple of Global Singletons
session::Manager manager;
@@ -32,6 +33,9 @@ std::tuple<session::Manager&, command::Table&, eventloop::EventLoop&,
sd_bus* bus = nullptr;
+// Global timer for network changes
+std::unique_ptr<phosphor::ipmi::Timer> networkTimer = nullptr;
+
FILE* ipmidbus = nullptr;
unsigned short g_sel_reserve = 0xFFFF;
sd_bus_slot* ipmid_slot = nullptr;
diff --git a/timer.cpp b/timer.cpp
new file mode 100644
index 0000000..06965de
--- /dev/null
+++ b/timer.cpp
@@ -0,0 +1,110 @@
+#include <chrono>
+#include <phosphor-logging/log.hpp>
+#include "timer.hpp"
+namespace phosphor
+{
+namespace ipmi
+{
+
+using namespace phosphor::logging;
+
+// Initializes the timer object
+void Timer::initialize()
+{
+ // This can not be called more than once.
+ if (eventSource)
+ {
+ throw std::runtime_error("Timer already initialized");
+ }
+
+ // Add infinite expiration time
+ auto r = sd_event_add_time(timeEvent, &eventSource,
+ CLOCK_MONOTONIC, // Time base
+ UINT64_MAX, // Expire time - way long time
+ 0, // Use default event accuracy
+ timeoutHandler, // Callback handler on timeout
+ this); // User data
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to set initial expiration time value",
+ entry("ERROR=%s", strerror(-r)));
+
+ throw std::runtime_error("Timer initialization failed");
+ }
+
+ // Disable the timer for now
+ r = setTimer(SD_EVENT_OFF);
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to disable timer",
+ entry("ERROR=%s", strerror(-r)));
+
+ throw std::runtime_error("Disabling the timer failed");
+ }
+ return;
+}
+
+/** @brief callback handler on timeout */
+int Timer::timeoutHandler(sd_event_source* eventSource,
+ uint64_t usec, void* userData)
+{
+ auto timer = static_cast<Timer*>(userData);
+ timer->expired = true;
+
+ log<level::INFO>("Timer expired");
+ // Call optional user call back function if available
+ if(timer->userCallBack)
+ {
+ timer->userCallBack();
+ }
+
+ sd_event_source_set_enabled(eventSource, SD_EVENT_OFF);
+ return 0;
+}
+
+// Gets the time from steady_clock
+std::chrono::microseconds Timer::getTime()
+{
+ using namespace std::chrono;
+ auto usec = steady_clock::now().time_since_epoch();
+ return duration_cast<microseconds>(usec);
+}
+
+// Enables or disables the timer
+int Timer::setTimer(int action)
+{
+ return sd_event_source_set_enabled(eventSource, action);
+}
+
+// Sets the time and arms the timer
+int Timer::startTimer(std::chrono::microseconds timeValue)
+{
+ // Disable the timer
+ setTimer(SD_EVENT_OFF);
+ expired = false;
+
+ // Get the current MONOTONIC time and add the delta
+ auto expireTime = getTime() + timeValue;
+
+ // Set the time
+ auto r = sd_event_source_set_time(eventSource, expireTime.count());
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to set timer",
+ entry("ERROR=%s", strerror(-r)));
+ return r;
+ }
+
+ // A ONESHOT timer means that when the timer goes off,
+ // its moves to disabled state.
+ r = setTimer(SD_EVENT_ONESHOT);
+ if (r < 0)
+ {
+ log<level::ERR>("Failure to start timer",
+ entry("ERROR=%s", strerror(-r)));
+ }
+ return r;
+}
+
+} // namespace ipmi
+} // namespace phosphor
diff --git a/timer.hpp b/timer.hpp
new file mode 100644
index 0000000..e39d85c
--- /dev/null
+++ b/timer.hpp
@@ -0,0 +1,101 @@
+#pragma once
+
+#include <chrono>
+#include <functional>
+#include <systemd/sd-event.h>
+namespace phosphor
+{
+namespace ipmi
+{
+
+/** @class Timer
+ * @brief Manages starting watchdog timers and handling timeouts
+ */
+class Timer
+{
+ public:
+ /** @brief Only need the default Timer */
+ Timer() = delete;
+ Timer(const Timer&) = delete;
+ Timer& operator=(const Timer&) = delete;
+ Timer(Timer&&) = delete;
+ Timer& operator=(Timer&&) = delete;
+
+ /** @brief Constructs timer object
+ *
+ * @param[in] events - sd_event pointer
+ * @param[in] funcCallBack - optional function callback for timer
+ * expirations
+ */
+ Timer(sd_event* events,
+ std::function<void()> userCallBack = nullptr)
+ : timeEvent(events), userCallBack(userCallBack)
+ {
+ // Initialize the timer
+ initialize();
+ }
+
+ ~Timer()
+ {
+ if (eventSource)
+ {
+ eventSource = sd_event_source_unref(eventSource);
+ }
+ }
+
+ inline auto isExpired() const
+ {
+ return expired;
+ }
+
+ /** @brief Starts the timer with specified expiration value.
+ * input is an offset from the current steady_clock
+ */
+ int startTimer(std::chrono::microseconds usec);
+
+ /** @brief Enables / disables the timer */
+ int setTimer(int action);
+
+ private:
+ /** @brief the sd_event structure */
+ sd_event* timeEvent = nullptr;
+
+ /** @brief Source of events */
+ sd_event_source* eventSource = nullptr;
+
+ /** @brief Returns if the associated timer is expired
+ *
+ * This is set to true when the timeoutHandler is called into
+ */
+ bool expired = true;
+
+ /** @brief Initializes the timer object with infinite
+ * expiration time and sets up the callback handler
+ *
+ * @return None.
+ *
+ * @error std::runtime exception thrown
+ */
+ void initialize();
+
+ /** @brief Callback function when timer goes off
+ *
+ * On getting the signal, initiate the hard power off request
+ *
+ * @param[in] eventSource - Source of the event
+ * @param[in] usec - time in micro seconds
+ * @param[in] userData - User data pointer
+ *
+ */
+ static int timeoutHandler(sd_event_source* eventSource,
+ uint64_t usec, void* userData);
+
+ /** @brief Gets the current time from steady clock */
+ static std::chrono::microseconds getTime();
+
+ /** @brief Optional function to call on timer expiration */
+ std::function<void()> userCallBack;
+};
+
+} // namespace ipmi
+} // namespace phosphor
OpenPOWER on IntegriCloud