summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLei YU <mine260309@gmail.com>2017-02-27 14:30:35 +0800
committerLei YU <mine260309@gmail.com>2017-10-16 20:40:04 +0800
commit91910e604cf5d779da2da1241a38f155017e3bfe (patch)
treeac0ceb0c853ba5bd6ad588b7c0e6ee805a249649
parenta5003ceb4425ebd4b2f71d3478027e8fa75d4860 (diff)
downloadphosphor-time-manager-91910e604cf5d779da2da1241a38f155017e3bfe.tar.gz
phosphor-time-manager-91910e604cf5d779da2da1241a38f155017e3bfe.zip
Remove unused legacy files
Change-Id: Ieb667636963722d54dba93850dd0e3396e1e83c1 Signed-off-by: Lei YU <mine260309@gmail.com>
-rw-r--r--time-config.cpp726
-rw-r--r--time-config.hpp345
-rw-r--r--time-manager.cpp838
-rw-r--r--time-manager.hpp306
-rw-r--r--time-register.c25
-rw-r--r--time-register.hpp17
6 files changed, 0 insertions, 2257 deletions
diff --git a/time-config.cpp b/time-config.cpp
deleted file mode 100644
index 416ffc9..0000000
--- a/time-config.cpp
+++ /dev/null
@@ -1,726 +0,0 @@
-#include <cstdlib>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <mapper.h>
-#include <cassert>
-#include <cctype>
-#include <algorithm>
-#include <phosphor-logging/log.hpp>
-#include <phosphor-logging/elog-errors.hpp>
-#include <xyz/openbmc_project/Common/error.hpp>
-#include "time-manager.hpp"
-
-using namespace phosphor::logging;
-using namespace sdbusplus::xyz::openbmc_project::Common::Error;
-
-std::map<std::string, TimeConfig::FUNCTOR> TimeConfig::iv_TimeParams = {
- // TODO via openbmc/openbmc#668 - openbmc/openbmc#1770 is still work in
- // progress at the time of writing this, so the use_dhcp_ntp is still using
- // the old org.openbmc settings interfaces. The whole of time manager is
- // anyway being rewritten to use new xyz.openbmc_project interfaces; as part
- // of that switching to new setting interfaces is also covered.
- { "use_dhcp_ntp", std::make_tuple(&TimeConfig::getSystemSettings,
- &TimeConfig::updateNetworkSettings)
- }
-};
-
-namespace internal
-{
-namespace setting
-{
-
-/** @brief Convert d-bus enum string to native string. For eg, convert
- * "xyz.openbmc_project.Time.Owner.Split" to "SPLIT".
- *
- * @param[in] value - setting enum string
- *
- * @return converted string
- */
-inline auto dbusToNative(std::string&& value)
-{
- auto setting = std::move(value);
- auto index = setting.find_last_of('.') + 1;
- setting = setting.substr(index, setting.length() - index);
- std::transform(setting.begin(), setting.end(), setting.begin(),
- [](unsigned char c){ return std::toupper(c); });
- return setting;
-}
-
-} // namespace setting
-} // namespace internal
-
-TimeConfig::TimeConfig() :
- iv_dbus(nullptr),
- iv_CurrTimeMode(timeModes::MANUAL),
- iv_RequestedTimeMode(timeModes::MANUAL),
- iv_CurrTimeOwner(timeOwners::BOTH),
- iv_RequestedTimeOwner(timeOwners::BOTH),
- iv_CurrDhcpNtp("yes"),
- iv_SettingChangeAllowed(false),
- iv_SplitModeChanged(false)
-{
- // Not really having anything to do here.
-}
-
-// Given a mode string, returns it's equivalent mode enum
-TimeConfig::timeModes TimeConfig::getTimeMode(const char* timeMode)
-{
- // We are forcing the values to be in specific case and range
- if (!strcmp(timeMode,"NTP"))
- {
- return timeModes::NTP;
- }
- else
- {
- return timeModes::MANUAL;
- }
-}
-
-// Accepts a timeMode enum and returns it's string value
-const char* TimeConfig::modeStr(TimeConfig::timeModes timeMode)
-{
- switch(timeMode)
- {
- case timeModes::NTP:
- {
- return "NTP";
- }
- case timeModes::MANUAL:
- {
- return "MANUAL";
- }
- }
-
- assert(false);
- return nullptr;
-}
-
-// Given a owner string, returns it's equivalent owner enum
-TimeConfig::timeOwners TimeConfig::getTimeOwner(const char* timeOwner)
-{
- if (!strcmp(timeOwner,"BMC"))
- {
- return timeOwners::BMC;
- }
- else if (!strcmp(timeOwner,"HOST"))
- {
- return timeOwners::HOST;
- }
- else if (!strcmp(timeOwner,"SPLIT"))
- {
- return timeOwners::SPLIT;
- }
- else
- {
- return timeOwners::BOTH;
- }
-}
-
-// Accepts a timeOwner enum and returns it's string value
-const char* TimeConfig::ownerStr(timeOwners timeOwner)
-{
- switch(timeOwner)
- {
- case timeOwners::BMC:
- {
- return "BMC";
- }
- case timeOwners::HOST:
- {
- return "HOST";
- }
- case timeOwners::SPLIT:
- {
- return "SPLIT";
- }
- case timeOwners::BOTH:
- {
- return "BOTH";
- }
- }
-
- assert(false);
- return nullptr;
-}
-
-// Returns the busname that hosts objPath
-std::unique_ptr<char> TimeConfig::getProvider(const char* objPath)
-{
- char *provider = nullptr;
- mapper_get_service(iv_dbus, objPath, &provider);
- return std::unique_ptr<char>(provider);
-}
-
-// Accepts a settings name and returns its value.
-// for the variant of type 'string' now.
-std::string TimeConfig::getSystemSettings(const char* key)
-{
- constexpr auto settingsObj = "/org/openbmc/settings/host0";
- constexpr auto propertyIntf = "org.freedesktop.DBus.Properties";
- constexpr auto hostIntf = "org.openbmc.settings.Host";
-
- const char* value = nullptr;
- std::string settingsVal {};
- sd_bus_message* reply = nullptr;
-
- std::cout <<"Getting System Settings: " << key << std::endl;
-
- // Get the provider from object mapper
- auto settingsProvider = getProvider(settingsObj);
- if (!settingsProvider)
- {
- std::cerr << "Error Getting service for Settings" << std::endl;
- return value;
- }
-
- auto r = sd_bus_call_method(iv_dbus,
- settingsProvider.get(),
- settingsObj,
- propertyIntf,
- "Get",
- nullptr,
- &reply,
- "ss",
- hostIntf,
- key);
- if (r < 0)
- {
- std::cerr <<"Error" << strerror(-r)
- <<" reading system settings" << std::endl;
- goto finish;
- }
-
- r = sd_bus_message_read(reply, "v", "s", &value);
- if (r < 0)
- {
- std::cerr <<"Error " << strerror(-r)
- <<" parsing settings data" << std::endl;
- }
-finish:
- if (value)
- {
- settingsVal.assign(value);
- }
- reply = sd_bus_message_unref(reply);
- return settingsVal;
-}
-
-// Reads value from /org/openbmc/control/power0
-// This signature on purpose to plug into time parameter map
-std::string TimeConfig::getPowerSetting(const char* key)
-{
- constexpr auto powerObj = "/org/openbmc/control/power0";
- constexpr auto powerIntf = "org.openbmc.control.Power";
- constexpr auto propertyIntf = "org.freedesktop.DBus.Properties";
-
- int value = -1;
- std::string powerValue {};
- sd_bus_message* reply = nullptr;
-
- std::cout <<"Reading Power Control key: " << key << std::endl;
-
- // Get the provider from object mapper
- auto powerProvider = getProvider(powerObj);
- if (!powerProvider)
- {
- std::cerr <<" Error getting provider for Power Settings" << std::endl;
- return powerValue;
- }
-
- auto r = sd_bus_call_method(iv_dbus,
- powerProvider.get(),
- powerObj,
- propertyIntf,
- "Get",
- nullptr,
- &reply,
- "ss",
- powerIntf,
- key);
- if (r < 0)
- {
- std::cerr <<"Error " << strerror(-r)
- << "reading: " << key << std::endl;
- goto finish;
- }
-
- r = sd_bus_message_read(reply, "v", "i", &value);
- if (r < 0)
- {
- std::cerr <<"Error " << strerror(-r)
- <<" parsing " << key << "value" << std::endl;
- // For maintenance
- goto finish;
- }
-finish:
- if (value != -1)
- {
- powerValue = std::to_string(value);
- }
- reply = sd_bus_message_unref(reply);
- return powerValue;
-}
-
-// Updates .network file with UseNtp=
-int TimeConfig::updateNetworkSettings(const std::string& useDhcpNtp)
-{
- constexpr auto networkObj = "/org/openbmc/NetworkManager/Interface";
- constexpr auto networkIntf = "org.openbmc.NetworkManager";
-
- std::cout << "use_dhcp_ntp = " << useDhcpNtp.c_str() << std::endl;
-
- // If what we have already is what it is, then just return.
- if (iv_CurrDhcpNtp == useDhcpNtp)
- {
- return 0;
- }
-
- // Get the provider from object mapper
- auto networkProvider = getProvider(networkObj);
- if (!networkProvider)
- {
- return -1;
- }
-
- auto r = sd_bus_call_method(iv_dbus,
- networkProvider.get(),
- networkObj,
- networkIntf,
- "UpdateUseNtpField",
- nullptr,
- nullptr,
- "s",
- useDhcpNtp.c_str());
- if (r < 0)
- {
- std::cerr <<"Error " << strerror(-r)
- << " updating UseNtp" << std::endl;
- }
- else
- {
- std::cout <<"Successfully updated UseNtp=["
- << useDhcpNtp << "]" << std::endl;
-
- r = writeData(cv_DhcpNtpFile, useDhcpNtp);
- }
-
- return 0;
-}
-
-// Reads the values from 'settingsd' and applies:
-// 1) Time Mode
-// 2) time Owner
-// 3) UseNTP setting
-// 4) Pgood
-int TimeConfig::processInitialSettings(sd_bus* dbus)
-{
- // First call from TimeManager to config manager
- iv_dbus = dbus;
-
- auto timeOwnerFunctor = std::make_tuple(&TimeConfig::getTimeOwnerSetting,
- &TimeConfig::updateTimeOwner);
- iv_TimeParams.emplace(settings.timeOwner, std::move(timeOwnerFunctor));
- auto timeSyncFunctor = std::make_tuple(
- &TimeConfig::getTimeSyncMethodSetting,
- &TimeConfig::updateTimeMode);
- iv_TimeParams.emplace(settings.timeSyncMethod, std::move(timeSyncFunctor));
-
- using namespace sdbusplus::bus::match::rules;
- sdbusplus::bus::bus bus(iv_dbus);
-
- settingsMatches.emplace_back(
- bus,
- propertiesChanged(settings.timeOwner, settings::timeOwnerIntf),
- std::bind(std::mem_fn(&TimeConfig::settingsChanged),
- this, std::placeholders::_1));
-
- settingsMatches.emplace_back(
- bus,
- propertiesChanged(settings.timeSyncMethod, settings::timeSyncIntf),
- std::bind(std::mem_fn(&TimeConfig::settingsChanged),
- this, std::placeholders::_1));
-
- // Read saved info like Who was the owner , what was the mode,
- // what was the use_dhcp_ntp setting before etc..
- auto r = readPersistentData();
- if (r < 0)
- {
- std::cerr << "Error reading the data saved in flash."
- << std::endl;
- return r;
- }
-
- // Now read whats in settings and apply if allowed.
- for (auto& iter : iv_TimeParams)
- {
- // Get the settings value for various keys.
- auto reader = std::get<READER>(iter.second);
- auto value = (this->*reader)(iter.first.c_str());
- if (!value.empty())
- {
- // Get the value for the key and validate.
- auto updater = std::get<UPDATER>(iter.second);
- auto r = (this->*updater)(value);
- if (r < 0)
- {
- std::cerr << "Error setting up initial keys" << std::endl;
- return r;
- }
- }
- else
- {
- std::cerr << "key " << iter.first
- <<" has no value: " << std::endl;
- return -1;
- }
- }
-
- // Now that we have taken care of consuming, push this as well
- // so that we can use the same map for handling pgood change too.
- auto readerUpdater = std::make_tuple(&TimeConfig::getPowerSetting,
- &TimeConfig::processPgoodChange);
- iv_TimeParams.emplace("pgood", readerUpdater);
-
- return 0;
-}
-
-// This is called by Property Change handler on the event of
-// receiving notification on property value change.
-int TimeConfig::updatePropertyVal(const char* key, const std::string& value)
-{
- auto iter = iv_TimeParams.find(key);
- if (iter != iv_TimeParams.end())
- {
- auto updater = std::get<UPDATER>(iter->second);
- return (this->*updater)(value);
- }
- // Coming here indicates that we never had a matching key.
- return -1;
-}
-
-// Called by sd_event when Properties are changed in Control/power0
-// Interested in change to 'pgood'
-int TimeConfig::processPgoodChange(const std::string& newPgood)
-{
- // Indicating that we are safe to apply any changes
- if (!newPgood.compare("0"))
- {
- iv_SettingChangeAllowed = true;
- std::cout <<"Changing time settings allowed now" << std::endl;
- }
- else
- {
- iv_SettingChangeAllowed = false;
- std::cout <<"Changing time settings is *deferred* now" << std::endl;
- }
-
- // if we have had users that changed the time settings
- // when we were not ready yet, do it now.
- if (iv_RequestedTimeOwner != iv_CurrTimeOwner)
- {
- auto r = updateTimeOwner(ownerStr(iv_RequestedTimeOwner));
- if (r < 0)
- {
- std::cerr << "Error updating new time owner" << std::endl;
- return r;
- }
- std::cout << "New Owner is : "
- << ownerStr(iv_RequestedTimeOwner) << std::endl;
- }
-
- if (iv_RequestedTimeMode != iv_CurrTimeMode)
- {
- auto r = updateTimeMode(modeStr(iv_RequestedTimeMode));
- if (r < 0)
- {
- std::cerr << "Error updating new time mode" << std::endl;
- return r;
- }
- std::cout <<"New Mode is : "
- << modeStr(iv_RequestedTimeMode) << std::endl;
- }
- return 0;
-}
-
-// Manipulates time owner if the system setting allows it
-int TimeConfig::updateTimeMode(const std::string& newModeStr)
-{
- auto r = 0;
- iv_RequestedTimeMode = getTimeMode(newModeStr.c_str());
-
- std::cout <<"Requested_Mode: " << newModeStr
- << " Current_Mode: " << modeStr(iv_CurrTimeMode)
- << std::endl;
-
- if (iv_RequestedTimeMode == iv_CurrTimeMode)
- {
- std::cout << "Mode is already set to : "
- << newModeStr << std::endl;
- return 0;
- }
-
- // Also, if the time owner is HOST, then we should not allow NTP.
- // However, it may so happen that there are 2 pending requests, one for
- // changing to NTP and other for changing owner to something not HOST.
- // So check if there is a pending timeOwner change and if so, allow NTP
- // if the current is HOST and requested is non HOST.
- if (iv_CurrTimeOwner == timeOwners::HOST &&
- iv_RequestedTimeOwner == timeOwners::HOST &&
- iv_RequestedTimeMode == timeModes::NTP)
- {
- std::cout <<"Can not set mode to NTP with HOST as owner"
- << std::endl;
- return 0;
- }
-
- if (iv_SettingChangeAllowed)
- {
- r = modifyNtpSettings(iv_RequestedTimeMode);
- if (r < 0)
- {
- std::cerr << "Error changing TimeMode settings"
- << std::endl;
- }
- else
- {
- iv_CurrTimeMode = iv_RequestedTimeMode;
- }
- std::cout << "Current_Mode changed to: "
- << newModeStr << " :: " << modeStr(iv_CurrTimeMode) << std::endl;
-
- // Need this when we either restart or come back from reset
- r = writeData(cv_TimeModeFile, modeStr(iv_CurrTimeMode));
- }
- else
- {
- std::cout <<"Deferring update until system state allows it"
- << std::endl;
- }
- return r;
-}
-
-// Manipulates time owner if the system setting allows it
-int TimeConfig::updateTimeOwner(const std::string& newOwnerStr)
-{
- int r = 0;
- iv_RequestedTimeOwner = getTimeOwner(newOwnerStr.c_str());
-
- // Needed when owner changes to HOST
- std::string manualMode = "Manual";
-
- // Needed by time manager to do some house keeping
- iv_SplitModeChanged = false;
-
- if (iv_RequestedTimeOwner == iv_CurrTimeOwner)
- {
- std::cout <<"Owner is already set to : "
- << newOwnerStr << std::endl;
- return 0;
- }
-
- std::cout <<"Requested_Owner: " << newOwnerStr
- << " Current_Owner: " << ownerStr(iv_CurrTimeOwner)
- << std::endl;
-
- if (iv_SettingChangeAllowed)
- {
- // If we are transitioning from SPLIT to something else,
- // reset the host offset.
- if (iv_CurrTimeOwner == timeOwners::SPLIT &&
- iv_RequestedTimeOwner != timeOwners::SPLIT)
- {
- // Needed by time manager to do some house keeping
- iv_SplitModeChanged = true;
- }
- iv_CurrTimeOwner = iv_RequestedTimeOwner;
- std::cout << "Current_Owner is now: "
- << newOwnerStr << std::endl;
-
- // HOST and NTP are exclusive
- if (iv_CurrTimeOwner == timeOwners::HOST)
- {
- std::cout <<"Forcing the mode to MANUAL" << std::endl;
- r = updateTimeMode(manualMode);
- if (r < 0)
- {
- std::cerr << "Error forcing the mode to MANUAL" << std::endl;
- return r;
- }
- }
- // Need this when we either restart or come back from reset
- r = writeData(cv_TimeOwnerFile, ownerStr(iv_CurrTimeOwner));
- }
- else
- {
- std::cout <<"Deferring update until system state allows it"
- << std::endl;
- }
-
- return r;
-}
-
-// Accepts the time mode and makes necessary changes to timedate1
-int TimeConfig::modifyNtpSettings(const timeModes& newTimeMode)
-{
- auto ntpChangeOp = 0;
-
- // Pass '1' -or- '0' to SetNTP method indicating Enable/Disable
- ntpChangeOp = (newTimeMode == timeModes::NTP) ? 1 : 0;
-
- std::cout <<"Applying NTP setting..." << std::endl;
-
- auto r = sd_bus_call_method(iv_dbus,
- "org.freedesktop.timedate1",
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "SetNTP",
- nullptr,
- nullptr, // timedate1 does not return response
- "bb",
- ntpChangeOp, // '1' means Enable
- 0); // '0' meaning no policy-kit
- if (r < 0)
- {
- std::cerr <<"Error: " << strerror(-r)
- << "changing time Mode" << std::endl;
- }
- else
- {
- std::cout << "SUCCESS. NTP setting is now: " <<
- ((ntpChangeOp) ? "Enabled" : "Disabled");
-
- // TODO : https://github.com/openbmc/phosphor-time-manager/issues/1
- if (ntpChangeOp)
- {
- r = system("systemctl restart systemd-timesyncd &");
- }
- else
- {
- r = system("systemctl stop systemd-timesyncd &");
- }
- }
- return r;
-}
-
-// Reads all the saved data from the last run
-int TimeConfig::readPersistentData()
-{
- // If we are coming back from a reset reload, then need to
- // read what was the last successful Mode and Owner.
- auto savedTimeMode = readData<std::string>(cv_TimeModeFile);
- if (!savedTimeMode.empty())
- {
- iv_CurrTimeMode = getTimeMode(savedTimeMode.c_str());
- std::cout <<"Last known time_mode: "
- << savedTimeMode.c_str() << std::endl;
- }
-
- auto savedTimeOwner = readData<std::string>(cv_TimeOwnerFile);
- if (!savedTimeOwner.empty())
- {
- iv_CurrTimeOwner = getTimeOwner(savedTimeOwner.c_str());
- std::cout <<"Last known time_owner: "
- << savedTimeOwner.c_str() << std::endl;
- }
-
- auto savedDhcpNtp = readData<std::string>(cv_DhcpNtpFile);
- if (!savedDhcpNtp.empty())
- {
- iv_CurrDhcpNtp = savedDhcpNtp;
- std::cout <<"Last known use_dhcp_ntp: "
- << iv_CurrDhcpNtp.c_str() << std::endl;
- }
- else
- {
- // This seems to be the first time.
- std::cerr <<"Empty DhcpNtp string" << std::endl;
- iv_CurrDhcpNtp = "yes";
- }
-
- // Doing this here to make sure 'pgood' is read and handled
- // first before anything.
- auto pgood = getPowerSetting("pgood");
- if (!pgood.compare("0"))
- {
- std::cout << "Changing settings *allowed* now" << std::endl;
- iv_SettingChangeAllowed = true;
- }
- return 0;
-}
-
-std::string TimeConfig::getTimeOwnerSetting(const char* path)
-{
- sdbusplus::bus::bus bus{iv_dbus};
- auto method = bus.new_method_call(
- settings.service(settings.timeOwner,
- settings::timeOwnerIntf).c_str(),
- path,
- "org.freedesktop.DBus.Properties",
- "Get");
- method.append(settings::timeOwnerIntf, "TimeOwner");
- auto reply = bus.call(method);
- if (reply.is_method_error())
- {
- log<level::ERR>("Error in TimeOwner Get");
- elog<InternalFailure>();
- }
-
- sdbusplus::message::variant<std::string> result;
- reply.read(result);
- // TODO via openbmc/openbmc#668 - because the old org.openbmc settings
- // interfaces defined the time settings as strings, the code in this file
- // is based around that fact. We use enums in the new settings interfaces,
- // so code in this file can be changed to work with enums instead. That's
- // being covered by the time manager rework (#668). For now, converting the
- // settings to the string format that this object expects it to be.
- // For eg, convert "xyz.openbmc_project.Time.Owner.Split" to "SPLIT".
- auto setting = result.get<std::string>();
- return internal::setting::dbusToNative(std::move(setting));
-}
-
-std::string TimeConfig::getTimeSyncMethodSetting(const char* path)
-{
- sdbusplus::bus::bus bus{iv_dbus};
- auto method = bus.new_method_call(
- settings.service(settings.timeSyncMethod,
- settings::timeSyncIntf).c_str(),
- path,
- "org.freedesktop.DBus.Properties",
- "Get");
- method.append(settings::timeSyncIntf, "TimeSyncMethod");
- auto reply = bus.call(method);
- if (reply.is_method_error())
- {
- log<level::ERR>("Error in TimeSyncMethod Get");
- elog<InternalFailure>();
- }
-
- sdbusplus::message::variant<std::string> result;
- reply.read(result);
- auto setting = result.get<std::string>();
- return internal::setting::dbusToNative(std::move(setting));
-}
-
-int TimeConfig::settingsChanged(sdbusplus::message::message& msg)
-{
- using Interface = std::string;
- using Property = std::string;
- using Value = std::string;
- using Properties = std::map<Property, sdbusplus::message::variant<Value>>;
-
- Interface interface;
- Properties properties;
-
- msg.read(interface, properties);
-
- auto path = msg.get_path();
- for(const auto& p : properties)
- {
- auto setting = p.second.get<std::string>();
- updatePropertyVal(path,
- internal::setting::dbusToNative(std::move(setting)));
- }
-
- return 0;
-}
diff --git a/time-config.hpp b/time-config.hpp
deleted file mode 100644
index 257ab30..0000000
--- a/time-config.hpp
+++ /dev/null
@@ -1,345 +0,0 @@
-#include <map>
-#include <systemd/sd-bus.h>
-#include <sdbusplus/bus/match.hpp>
-#include "settings.hpp"
-
-/** @class TimeConfig
- * @brief Maintains various time modes and time owners.
- */
-class TimeConfig
-{
-public:
- /** @brief Supported time modes
- * NTP Time sourced by Network Time Server
- * MANUAL User of the system need to set the time
- */
- enum class timeModes
- {
- NTP,
- MANUAL
- };
-
- /** @brief Supported time owners
- * BMC Time source may be NTP or MANUAL but it has to be set natively
- * on the BMC. Meaning, host can not set the time. What it also
- * means is that when BMC gets IPMI_SET_SEL_TIME, then its ignored.
- * similarly, when BMC gets IPMI_GET_SEL_TIME, then the BMC's time
- * is returned.
- *
- * HOST Its only IPMI_SEL_SEL_TIME that will set the time on BMC.
- * Meaning, IPMI_GET_SEL_TIME and request to get BMC time will
- * result in same value.
- *
- * SPLIT Both BMC and HOST will maintain their individual clocks but then
- * the time information is stored in BMC. BMC can have either NTP
- * or MANUAL as it's source of time and will set the time directly
- * on the BMC. When IPMI_SET_SEL_TIME is received, then the delta
- * between that and BMC's time is calculated and is stored.
- * When BMC reads the time, the current time is returned.
- * When IPMI_GET_SEL_TIME is received, BMC's time is retrieved and
- * then the delta offset is factored in prior to returning.
- *
- * BOTH: BMC's time is set with whoever that sets the time. Similarly,
- * BMC's time is returned to whoever that asks the time.
- */
- enum class timeOwners
- {
- BMC,
- HOST,
- SPLIT,
- BOTH
- };
-
- // Do not have a usecase of copying this object so disable
- TimeConfig();
- ~TimeConfig() = default;
- TimeConfig(const TimeConfig&) = delete;
- TimeConfig& operator=(const TimeConfig&) = delete;
- TimeConfig(TimeConfig&&) = delete;
- TimeConfig& operator=(TimeConfig&&) = delete;
-
- inline auto getCurrTimeMode() const
- {
- return iv_CurrTimeMode;
- }
-
- inline auto getCurrTimeOwner() const
- {
- return iv_CurrTimeOwner;
- }
-
- inline auto getRequestedTimeMode() const
- {
- return iv_RequestedTimeMode;
- }
-
- inline auto getRequestedTimeOwner() const
- {
- return iv_RequestedTimeOwner;
- }
-
- inline auto isSplitModeChanged() const
- {
- return iv_SplitModeChanged;
- }
-
- inline void updateSplitModeFlag(const bool& value)
- {
- iv_SplitModeChanged = value;
- }
-
- inline sd_bus* getDbus() const
- {
- return iv_dbus;
- }
-
- /** brief Generic file reader used to read time mode,
- * time owner, host time, host offset and useDhcpNtp
- *
- * @param[in] filename - Name of file where data is preserved.
- * @return - File content
- */
- template <typename T>
- T readData(const char* fileName)
- {
- T data = T();
- if(std::ifstream(fileName))
- {
- std::ifstream file(fileName, std::ios::in);
- file >> data;
- file.close();
- }
- return data;
- }
-
- /** @brief Generic file writer used to write time mode,
- * time owner, host time, host offset and useDhcpNtp
- *
- * @param[in] filename - Name of file where data is preserved.
- * @param[in] data - Data to be written to file
- * @return - 0 for now. But will be changed to raising
- * - Exception
- */
- template <typename T>
- auto writeData(const char* fileName, T&& data)
- {
- std::ofstream file(fileName, std::ios::out);
- file << data;
- file.close();
- return 0;
- }
-
- /** @brief Reads saved data and populates below properties
- * - Current Time Mode
- * - Current Time Owner
- * - Whether to use NTP settings given by DHCP
- * - Last known host offset
- *
- * @param[in] dbus - Handler to sd_bus used by time manager
- *
- * @return - < 0 for failure and others for success
- */
- int processInitialSettings(sd_bus* dbus);
-
- /** @brief Accepts time mode string, returns the equivalent enum
- *
- * @param[in] timeModeStr - Current Time Mode in string
- *
- * @return - Equivalent ENUM
- * - Input : "NTP", Output: timeModes::NTP
- */
- static timeModes getTimeMode(const char* timeModeStr);
-
- /** @brief Accepts timeMode enum and returns it's string equivalent
- *
- * @param[in] timeMode - Current Time Mode Enum
- *
- * @return - Equivalent string
- * - Input : timeModes::NTP, Output : "NTP"
- */
- static const char* modeStr(const timeModes timeMode);
-
- /** @brief Accepts timeOwner string and returns it's equivalent enum
- *
- * @param[in] timeOwnerStr - Current Time Owner in string
- *
- * @return - Equivalent ENUM
- * - Input : "BMC", output : timeOwners::BMC
- */
- static timeOwners getTimeOwner(const char* timeOwnerStr);
-
- /** @brief Accepts timeOwner enum and returns it's string equivalent
- *
- * @param[in] timeOwner - Current Time Mode Enum
- *
- * @return - Equivalent string
- * - Input : timeOwners::BMC, Output : "BMC"
- */
- static const char* ownerStr(const timeOwners timeOwner);
-
- /** @brief Gets called when the settings property changes.
- * Walks the map and then applies the changes
- *
- * @param[in] key - Name of the property
- * @param[in] value - Value
- *
- * @return - < 0 on failure, success otherwise
- */
- int updatePropertyVal(const char* key, const std::string& value);
-
- // Acts on the time property changes / reads initial property
- using READER = std::string (TimeConfig::*) (const char*);
- using UPDATER = int (TimeConfig::*) (const std::string&);
- using FUNCTOR = std::tuple<READER, UPDATER>;
-
- // Most of this is statically constructed and PGOOD is added later.
- static std::map<std::string, FUNCTOR> iv_TimeParams;
-
- /** @brief Callback to handle change in a setting
- *
- * @param[in] msg - sdbusplus dbusmessage
- *
- * @return 0 on success, < 0 on failure.
- */
- int settingsChanged(sdbusplus::message::message& msg);
-
-private:
- // Bus initialised by manager on a call to process initial settings
- sd_bus *iv_dbus;
-
- /** @brief 'Requested' is what is asked by user in settings
- * 'Current' is what the TimeManager is really using since its not
- * possible to apply the mode and owner as and when the user updates
- * Settings. They are only applied when the system power is off.
- */
- timeModes iv_CurrTimeMode;
- timeModes iv_RequestedTimeMode;
-
- timeOwners iv_CurrTimeOwner;
- timeOwners iv_RequestedTimeOwner;
-
- /** @brief One of the entry in .network file indicates whether the
- * systemd-timesyncd should use the NTP server list that are sent by DHCP
- * server or not. If the value is 'yes', then NTP server list sent by DHCP
- * are used. else entries that are configured statically with NTP= are used
- */
- std::string iv_CurrDhcpNtp;
-
- /** @brief Dictated by state of pgood. When the pgood value is 'zero', then
- * its an indication that we are okay to apply any pending Mode / Owner
- * values. Meaning, Current will be updated with what is in Requested.
- */
- bool iv_SettingChangeAllowed;
-
- // Needed to nudge Time Manager to reset offset
- bool iv_SplitModeChanged;
-
- /** @brief Settings objects of intereset */
- settings::Objects settings;
-
- /** @brief sbdbusplus match objects */
- std::vector<sdbusplus::bus::match_t> settingsMatches;
-
- static constexpr auto cv_TimeModeFile = "/var/lib/obmc/saved_timeMode";
- static constexpr auto cv_TimeOwnerFile = "/var/lib/obmc/saved_timeOwner";
- static constexpr auto cv_DhcpNtpFile = "/var/lib/obmc/saved_dhcpNtp";
-
- /** @brief Wrapper that looks up in the mapper service for a given
- * object path and returns the service name
- *
- * @param[in] objpath - dbus object path
- *
- * @return - unique_ptr holding service name.
- * - Caller needs to validate if its populated
- */
- std::unique_ptr<char> getProvider(const char* objPath);
-
- /** @brief Helper function for processInitialSettings.
- * Reads saved data and populates below properties. Only the values are
- * read from the file system. but it will not take the action on those.
- * Actions on these are taken by processInitialSettings
- *
- * - Current Time Mode
- * - Current Time Owner
- * - Whether to use NTP settings given by DHCP
- * - Current Pgood state
- *
- * @return - < 0 for failure and success on others
- */
- int readPersistentData();
-
- /** @brief Updates the 'ntp' field in systemd/timedate1,
- * which enables / disables NTP syncing
- *
- * @param[in] newTimeMode - Time Mode Enum
- *
- * @return - < 0 on failure and success on others
- */
- int modifyNtpSettings(const timeModes& newTimeMode);
-
- /** @brief Accepts system setting parameter and returns its value
- *
- * @param[in] key - Name of the property
- *
- * @return - Value as string
- */
- std::string getSystemSettings(const char* key);
-
- /** @brief Returns the time owner setting
- *
- * @param[in] path - Time owner setting object path
- *
- * @return - Value as string
- */
- std::string getTimeOwnerSetting(const char* path);
-
- /** @brief Returns the time sync method setting
- *
- * @param[in] path - Time sync method setting object path
- *
- * @return - Value as string
- */
- std::string getTimeSyncMethodSetting(const char* path);
-
- /** @brief Reads the data hosted by /org/openbmc/control/power0
- *
- * @param[in] key - Name of the property
- *
- * @return - Value as string
- */
- std::string getPowerSetting(const char* key);
-
- /** @brief Accepts Mode string and applies only if conditions allow it.
- *
- * @param[in] newModeStr - Requested Time Mode
- *
- * @return - < 0 on failure, success otherwise
- */
- int updateTimeMode(const std::string& newModeStr);
-
- /** @brief Accepts Ownere string and applies only if conditions allow it.
- *
- * @param[in] newOwnerStr - Requested Time Owner
- *
- * @return - < 0 on failure, success otherwise
- */
-
- int updateTimeOwner(const std::string& newownerStr);
-
- /** @brief Updates .network file with UseNtp= provided by NetworkManager
- *
- * @param[in] useDhcpNtp - will be 'yes' or 'no'
- *
- * @return - < 0 on failure, success otherwise
- */
- int updateNetworkSettings(const std::string& useDhcpNtp);
-
- /** @brief Accepts current pgood value and then updates any pending mode
- * or owner requests
- *
- * @param[in] useDhcpNtp - will be 'yes' or 'no'
- *
- * @return - < 0 on failure, success otherwise
- */
- int processPgoodChange(const std::string& newPgood);
-};
diff --git a/time-manager.cpp b/time-manager.cpp
deleted file mode 100644
index d0e7113..0000000
--- a/time-manager.cpp
+++ /dev/null
@@ -1,838 +0,0 @@
-#define _XOPEN_SOURCE
-#include <chrono>
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-#include <array>
-#include <unistd.h>
-#include <assert.h>
-#include <sys/timerfd.h>
-#include <systemd/sd-event.h>
-#include <systemd/sd-bus.h>
-#include <systemd/sd-daemon.h>
-#include "time-register.hpp"
-#include "time-manager.hpp"
-
-// Neeed to do this since its not exported outside of the kernel.
-// Refer : https://gist.github.com/lethean/446cea944b7441228298
-#ifndef TFD_TIMER_CANCEL_ON_SET
-#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
-#endif
-
-// Needed to make sure timerfd does not misfire eventhough we set CANCEL_ON_SET
-#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)
-
-// Used in time-register.c
-extern sd_bus_vtable timeServicesVtable[];
-
-Time::Time(const TimeConfig& timeConfig) : config(timeConfig)
-{
- // Nothing to do here
-}
-
-BmcTime::BmcTime(const TimeConfig& timeConfig) : Time(timeConfig)
-{
- // Nothing to do here
-}
-
-HostTime::HostTime(const TimeConfig& timeConfig,
- const std::chrono::microseconds& hostOffset)
- : Time(timeConfig),
- iv_Offset(hostOffset)
-{
- // Nothing to do here
-}
-
-TimeManager::TimeManager() :
- iv_HostOffset(std::chrono::microseconds(0)),
- iv_UptimeUsec(std::chrono::microseconds(0)),
- iv_EventSource(nullptr),
- iv_Event(nullptr)
-{
- assert(setupTimeManager() >= 0);
-}
-
-// Needed to be standalone extern "C" to register
-// as a callback routine with sd_bus_vtable
-int GetTime(sd_bus_message* m, void* userdata,
- sd_bus_error* retError)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- return tmgr->getTime(m, userdata, retError);
-}
-
-int SetTime(sd_bus_message* m, void* userdata,
- sd_bus_error* retError)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- return tmgr->setTime(m, userdata, retError);
-}
-
-// Property reader
-int getCurrTimeModeProperty(sd_bus* bus, const char* path,
- const char* interface, const char* property,
- sd_bus_message* m, void* userdata,
- sd_bus_error* error)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- return sd_bus_message_append(m, "s",
- TimeConfig::modeStr(tmgr->config.getCurrTimeMode()));
-}
-
-int getCurrTimeOwnerProperty(sd_bus* bus, const char* path,
- const char* interface, const char* property,
- sd_bus_message* m, void* userdata,
- sd_bus_error* error)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- return sd_bus_message_append(m, "s",
- TimeConfig::ownerStr(tmgr->config.getCurrTimeOwner()));
-}
-
-int getReqTimeModeProperty(sd_bus* bus, const char* path,
- const char* interface, const char* property,
- sd_bus_message* m, void* userdata,
- sd_bus_error* error)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- return sd_bus_message_append(m, "s",
- TimeConfig::modeStr(tmgr->config.getRequestedTimeMode()));
-}
-
-int getReqTimeOwnerProperty(sd_bus* bus, const char* path,
- const char* interface, const char* property,
- sd_bus_message* m, void* userdata,
- sd_bus_error* error)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- return sd_bus_message_append(m, "s",
- TimeConfig::ownerStr(tmgr->config.getRequestedTimeOwner()));
-}
-
-int TimeManager::getTime(sd_bus_message* m, void* userdata,
- sd_bus_error* retError)
-{
- const char* target = nullptr;
-
- // Extract the target and call respective GetTime
- auto r = sd_bus_message_read(m, "s", &target);
- if (r < 0)
- {
- std::cerr << "Error:" << strerror(-r)
- <<" reading user time" << std::endl;
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_IO_ERROR, "Error reading input");
-
- return sd_bus_reply_method_error(m, retError);
- }
-
- if (!strcasecmp(target, "bmc"))
- {
- auto time = BmcTime(config);
- return time.getTime(m, retError);
- }
- else if (!strcasecmp(target, "host"))
- {
- auto time = HostTime(config, iv_HostOffset);
- return time.getTime(m, retError);
- }
- else
- {
- std::cerr << "Error:" << strerror(-r)
- <<" Invalid Target" << std::endl;
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_IO_ERROR, "Valid targets are BMC or HOST");
-
- return sd_bus_reply_method_error(m, retError);
- }
-}
-
-int TimeManager::setTime(sd_bus_message* m, void* userdata,
- sd_bus_error* retError)
-{
- const char* target = nullptr;
- auto r = sd_bus_message_read(m, "s", &target);
- if (r < 0)
- {
- std::cerr << "Error:" << strerror(-r)
- <<" reading user time" << std::endl;
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_IO_ERROR, "Error reading input");
-
- return sd_bus_reply_method_error(m, retError);
- }
-
- if (!strcasecmp(target, "bmc"))
- {
- auto time = BmcTime(config);
- auto r = time.setTime(m, retError);
- if (r < 0)
- {
- // This would have the error populated
- return sd_bus_reply_method_error(m, retError);
- }
- }
- else if (!strcasecmp(target, "host"))
- {
- auto time = HostTime(config, iv_HostOffset);
-
- auto r = time.setTime(m, retError);
- if (r < 0)
- {
- // This would have the error populated
- return sd_bus_reply_method_error(m, retError);
- }
-
- if (config.getCurrTimeOwner() == TimeConfig::timeOwners::SPLIT)
- {
- iv_HostOffset = time.getChangedOffset();
- r = config.writeData(cv_HostOffsetFile, iv_HostOffset.count());
- if (r < 0)
- {
- // probably does not make sense to crash on these..
- // The next NTP sync will set things right.
- std::cerr << "Error saving host_offset: "
- << iv_HostOffset.count() << std::endl;
- }
- }
- }
- return sd_bus_reply_method_return(m, "i", 0);
-}
-
-int Time::setTimeOfDay(const std::chrono::microseconds& timeOfDayUsec,
- sd_bus_error *retError)
-{
- // These 2 are for bypassing some policy
- // checking in the timedate1 service
- auto relative = false;
- auto interactive = false;
-
- return sd_bus_call_method(config.getDbus(),
- "org.freedesktop.timedate1",
- "/org/freedesktop/timedate1",
- "org.freedesktop.timedate1",
- "SetTime",
- retError,
- nullptr, // timedate1 does not return response
- "xbb",
- (int64_t)timeOfDayUsec.count(), //newTimeUsec,
- relative, // Time in absolute seconds since epoch
- interactive); // bypass polkit checks
-}
-
-// Common routine for BMC and HOST Get Time operations
-std::chrono::microseconds Time::getBaseTime()
-{
- auto currBmcTime = std::chrono::system_clock::now();
- return std::chrono::duration_cast<std::chrono::microseconds>
- (currBmcTime.time_since_epoch());
-}
-
-// Accepts the time in microseconds and converts to Human readable format.
-std::string Time::convertToStr(const std::chrono::microseconds& timeInUsec)
-{
- using namespace std::chrono;
-
- // Convert this to number of seconds;
- auto timeInSec = duration_cast<seconds>(microseconds(timeInUsec));
- auto time_T = static_cast<std::time_t>(timeInSec.count());
-
- std::ostringstream timeFormat {};
- timeFormat << std::put_time(std::gmtime(&time_T), "%c %Z");
-
- auto timeStr = timeFormat.str();
- std::cout << timeStr.c_str() << std::endl;
- return timeStr;
-}
-
-// Reads timeofday and returns time string
-// and also number of microseconds.
-// Ex : Tue Aug 16 22:49:43 2016
-int BmcTime::getTime(sd_bus_message *m, sd_bus_error *retError)
-{
- std::cout << "Request to get BMC time: ";
-
- // Get BMC time
- auto timeInUsec = getBaseTime();
- auto timeStr = convertToStr(timeInUsec);
- return sd_bus_reply_method_return(
- m, "sx", timeStr.c_str(), (uint64_t)timeInUsec.count());
-}
-
-// Designated to be called by IPMI_GET_SEL time from host
-int HostTime::getTime(sd_bus_message *m, sd_bus_error *retError)
-{
- using namespace std::chrono;
-
- std::cout << "Request to get HOST time" << std::endl;
-
- // Get BMC time and add Host's offset
- // Referencing the iv_hostOffset of TimeManager object
- auto timeInUsec = getBaseTime();
- auto hostTime = timeInUsec.count() + iv_Offset.count();
-
- auto timeStr = convertToStr(duration_cast<microseconds>
- (microseconds(hostTime)));
-
- std::cout << " Host_time_str: [ " << timeStr
- << " ] host_time usec: [ " << hostTime
- << " ] host_offset: [ " << iv_Offset.count()
- << " ] " << std::endl;
-
- return sd_bus_reply_method_return(m, "sx", timeStr.c_str(),
- (uint64_t)hostTime);
- return 0;
-}
-
-// Gets the time string and verifies if it conforms to format %Y-%m-%d %H:%M:%S
-// and then sets the BMC time. If the input time string does not conform to the
-// format, an error message is returned.
-int BmcTime::setTime(sd_bus_message *m, sd_bus_error *retError)
-{
- tm userTm {};
- const char* userTimeStr = nullptr;
-
- std::cout << "Request to set BMC time" << std::endl;
-
- std::cout << "Curr_Mode: " << TimeConfig::modeStr(config.getCurrTimeMode())
- << " Curr_Owner: " << TimeConfig::ownerStr(config.getCurrTimeOwner())
- << std::endl;
-
- if(config.getCurrTimeOwner() == TimeConfig::timeOwners::HOST)
- {
- std::cerr << "Can not set time. Owner is HOST" << std::endl;
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_FAILED, "Current owner is HOST");
-
- return -1;
- }
-
- auto r = sd_bus_message_read(m, "s", &userTimeStr);
- if (r < 0)
- {
- std::cerr << "Error:" << strerror(-r)
- <<" reading user time" << std::endl;
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_IO_ERROR, "Error reading input");
- return r;
- }
-
- std::cout <<" BMC TIME : " << userTimeStr << std::endl;
-
- // Convert the time string into tm structure
- std::istringstream timeString {};
- timeString.str(userTimeStr);
- timeString >> std::get_time(&userTm, "%Y-%m-%d %H:%M:%S");
- if (timeString.fail())
- {
- std::cerr << "Error: Incorrect time format" << std::endl;
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_INVALID_ARGS, "Incorrect time format");
- return -1;
- }
-
- // Convert the time structure into number of
- // seconds maintained in GMT. Followed the same that is in
- // systemd/timedate1
- auto timeOfDay = timegm(&userTm);
- if (timeOfDay < 0)
- {
- std::cerr <<"Error converting tm to seconds" << std::endl;
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_FAILED, "Error converting tm to seconds");
- return -1;
- }
-
- // Set REALTIME and also update hwclock
- auto timeInUsec = std::chrono::microseconds(
- std::chrono::seconds(timeOfDay));
- return setTimeOfDay(timeInUsec, retError);
-}
-
-// Gets the time string from IPMI ( which is currently in seconds since epoch )
-// and then sets the BMC time / adjusts the offset depending on current owner
-// policy.
-int HostTime::setTime(sd_bus_message *m, sd_bus_error *retError)
-{
- using namespace std::chrono;
-
- std::cout << "Request to SET Host time" << std::endl;
-
- std::cout << "Curr_Mode: " << TimeConfig::modeStr(config.getCurrTimeMode())
- << "Curr_Owner: " << TimeConfig::ownerStr(config.getCurrTimeOwner())
- << "host_offset: " << iv_Offset.count() << std::endl;
-
- if (config.getCurrTimeOwner() == TimeConfig::timeOwners::BMC)
- {
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_FAILED, "Current Owner is BMC");
- return -1;
- }
-
- const char* newHostTime = nullptr;
- auto r = sd_bus_message_read(m, "s", &newHostTime);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- << "reading host time" << std::endl;
- *retError = SD_BUS_ERROR_MAKE_CONST(
- SD_BUS_ERROR_IO_ERROR, "Error reading input");
- return -1;
- }
-
- // We need to convert the string input to decimal.
- auto hostTimeSec = std::stol(std::string(newHostTime));
-
- // And then to microseconds
- auto hostTimeUsec = duration_cast<microseconds>(seconds(hostTimeSec));
- std::cout << "setHostTime: HostTimeInUSec: "
- << hostTimeUsec.count() << std::endl;
-
- if (config.getCurrTimeOwner() == TimeConfig::timeOwners::SPLIT)
- {
- // Adjust the host offset
- auto bmcTimeUsec = duration_cast<microseconds>
- (system_clock::now().time_since_epoch());
-
- // We are not doing any time settings in BMC
- std::cout << "Updated: host_time: [ " << hostTimeUsec.count()
- << " ] host_offset: [ " << iv_Offset.count()
- << " ] " << std::endl;
-
- // Communicate the offset back to manager to update needed.
- changedOffset = hostTimeUsec - bmcTimeUsec;
-
- return 0;
- }
-
- // We are okay to update time in as long as BMC is not the owner
- return setTimeOfDay(hostTimeUsec, retError);
-}
-
-// Gets called into by sd_event on an activity seen on sd_bus
-int TimeManager::processSdBusMessage(sd_event_source* es, int fd,
- uint32_t revents, void* userdata)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- auto r = sd_bus_process(tmgr->getTimeBus(), nullptr);
- if (r < 0)
- {
- std::cerr <<"Error: " << strerror(-r)
- <<" processing sd_bus message:" << std::endl;
- }
- return r;
-}
-
-// Gets called into by sd_event on any time SET event
-int TimeManager::processTimeChange(sd_event_source* es, int fd,
- uint32_t revents, void* userdata)
-{
- using namespace std::chrono;
- std::cout << "BMC time changed" << std::endl;
-
- auto tmgr = static_cast<TimeManager*>(userdata);
-
- std::array<char, 64> time {};
-
- // We are not interested in the data here. Need to read time again .
- // So read until there is something here in the FD
- while (read(fd, time.data(), time.max_size()) > 0);
-
- std::cout <<" Curr_Mode: " << TimeConfig::modeStr(tmgr->config.getCurrTimeMode())
- << " Curr_Owner : " << TimeConfig::ownerStr(tmgr->config.getCurrTimeOwner())
- << " Host_Offset: " << tmgr->getHostOffset().count() << std::endl;
-
- // Read the current BMC time and adjust the
- // host time offset if the mode is SPLIT
- if (tmgr->config.getCurrTimeOwner() == TimeConfig::timeOwners::SPLIT)
- {
- // Delta between REAL and Monotonic.
- auto uptimeUsec = duration_cast<microseconds>
- (system_clock::now().time_since_epoch() -
- steady_clock::now().time_since_epoch());
-
- auto deltaTimeUsec = uptimeUsec - tmgr->getUptimeUsec();
-
- // If the BMC time goes backwards, then - of - will handle that.
- auto newHostOffset = tmgr->getHostOffset() - deltaTimeUsec;
- tmgr->updateHostOffset(newHostOffset);
-
- std::cout << " UPDATED HOST_OFFSET: "
- << tmgr->getHostOffset().count() << std::endl;
- tmgr->updateUptimeUsec(uptimeUsec);
-
- // Persist this
- auto r = tmgr->config.writeData(TimeManager::cv_HostOffsetFile,
- tmgr->getHostOffset().count());
- if (r < 0)
- {
- std::cerr << "Error saving host_offset: "
- << tmgr->getHostOffset().count() << std::endl;
- return r;
- }
- std::cout << " Updated: Host_Offset: "
- << tmgr->getHostOffset().count() << std::endl;
- }
- return 0;
-}
-
-// Resets iv_HostOffset. Needed when we move away from SPLIT.
-int TimeManager::resetHostOffset()
-{
- iv_HostOffset = std::chrono::microseconds(0);
- auto r = config.writeData(cv_HostOffsetFile, iv_HostOffset.count());
- config.updateSplitModeFlag(false);
- return r;
-}
-
-// Called by sd_event when Pgood is changed in Power
-int TimeManager::processPgoodChange(sd_bus_message* m, void* userdata,
- sd_bus_error* retError)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- const char* key = nullptr;
-
- auto newPgood = -1;
- auto r = 0;
-
- std::cout <<" PGOOD has changed.." << std::endl;
-
- // input data is "sa{sv}as" and we are just interested in a{sv}
- r = sd_bus_message_skip(m, "s");
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r) <<
- "skipping interface name in data" << std::endl;
- return r;
- }
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<"entering the dictionary" << std::endl;
- return r;
- }
-
- while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY,
- "sv")) > 0)
- {
- r = sd_bus_message_read(m, "s", &key);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<" reading the key from dict" << std::endl;
- // Can not continue here since the next
- // enter would result in error anyway
- return r;
- }
-
- if (!strcmp(key, "pgood"))
- {
- r = sd_bus_message_read(m, "v", "i", &newPgood);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- << "reading pgood" << std::endl;
- return r;
- }
- r = tmgr->config.updatePropertyVal(key, std::to_string(newPgood));
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- << "processing pgood" << std::endl;
- return r;
- }
- }
- else
- {
- sd_bus_message_skip(m, "v");
- }
- }
- return 0;
-}
-
-// Called by sd_event when Properties are changed in settingsd.
-// Interested in changes to 'timeMode', 'timeOwner' and 'use_dhcp_ntp'
-int TimeManager::processPropertyChange(sd_bus_message* m, void* userdata,
- sd_bus_error* retError)
-{
- auto tmgr = static_cast<TimeManager*>(userdata);
- const char* key = nullptr;
- const char* value = nullptr;
- auto r = 0;
-
- std::cout <<" User Settings have changed.." << std::endl;
-
- // input data is "sa{sv}as" and we are just interested in a{sv}
- r = sd_bus_message_skip(m, "s");
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r) <<
- "skipping interface name in data" << std::endl;
- goto finish;
- }
-
- r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<"entering the dictionary" << std::endl;
- goto finish;
- }
-
- while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY,
- "sv")) > 0)
- {
- r = sd_bus_message_read(m, "s", &key);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<" reading the key from dict" << std::endl;
- // Can not continue here since the next
- // enter would result in error anyway
- goto finish;
- }
-
- if (!strcmp(key, "use_dhcp_ntp"))
- {
- r = sd_bus_message_read(m, "v", "s", &value);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<"reading use_dhcp_ntp" << std::endl;
- goto finish;
- }
- r = tmgr->config.updatePropertyVal(key, value);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- << "processing dhcp_ntp" << std::endl;
- goto finish;
- }
- }
- else
- {
- sd_bus_message_skip(m, "v");
- }
- }
-finish:
- return r;
-}
-
-// Sets up callback handlers for activities on :
-// 1) user request on SD_BUS
-// 2) Time change
-// 3) Settings change
-// 4) System state change;
-int TimeManager::registerCallbackHandlers()
-{
- constexpr auto WATCH_SETTING_CHANGE =
- "type='signal',interface='org.freedesktop.DBus.Properties',"
- "path='/org/openbmc/settings/host0',member='PropertiesChanged'";
-
- constexpr auto WATCH_PGOOD_CHANGE =
- "type='signal',interface='org.freedesktop.DBus.Properties',"
- "path='/org/openbmc/control/power0',member='PropertiesChanged'";
-
- // Extract the descriptor out of sd_bus construct.
- auto sdBusFd = sd_bus_get_fd(iv_TimeBus);
-
- auto r = sd_event_add_io(iv_Event, &iv_EventSource, sdBusFd, EPOLLIN,
- processSdBusMessage, this);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<" adding sd_bus_message handler" << std::endl;
- return r;
- }
-
- // Choose the MAX time that is possible to aviod mis fires.
- itimerspec maxTime {};
- maxTime.it_value.tv_sec = TIME_T_MAX;
-
- auto timeFd = timerfd_create(CLOCK_REALTIME, 0);
- if (timeFd < 0)
- {
- std::cerr << "Errorno: " << errno << " creating timerfd" << std::endl;
- return -1;
- }
-
- r = timerfd_settime(timeFd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
- &maxTime, nullptr);
- if (r)
- {
- std::cerr << "Errorno: " << errno << "Setting timerfd" << std::endl;
- return -1;
- }
-
- // Wake me up *only* if someone SETS the time
- r = sd_event_add_io(iv_Event, &iv_EventSource, timeFd, EPOLLIN,
- processTimeChange, this);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- << "adding time_change handler" << std::endl;
- return r;
- }
-
- // Watch for property changes in settingsd
- r = sd_bus_add_match(iv_TimeBus, NULL, WATCH_SETTING_CHANGE,
- processPropertyChange, this);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<" adding property change listener" << std::endl;
- return r;
- }
-
- // Watch for state change. Only reliable one to count on is
- // state of [pgood]. value of [1] meaning host is powering on / powered
- // on. [0] means powered off.
- r = sd_bus_add_match(iv_TimeBus, NULL, WATCH_PGOOD_CHANGE,
- processPgoodChange, this);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- << " adding pgood change listener" << std::endl;
- }
- return r;
-}
-
-int TimeManager::setupTimeManager()
-{
- auto r = sd_bus_default_system(&iv_TimeBus);
- if (r < 0)
- {
- std::cerr << "Error" << strerror(-r)
- <<" connecting to system bus" << std::endl;
- goto finish;
- }
-
- r = sd_bus_add_object_manager(iv_TimeBus, NULL, cv_ObjPath);
- if (r < 0)
- {
- std::cerr << "Error" << strerror(-r)
- <<" adding object manager" << std::endl;
- goto finish;
- }
-
- std::cout <<"Registering dbus methods" << std::endl;
- r = sd_bus_add_object_vtable(iv_TimeBus,
- NULL,
- cv_ObjPath,
- cv_BusName,
- timeServicesVtable,
- this);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<" adding timer services vtable" << std::endl;
- goto finish;
- }
-
- // create a sd_event object and add handlers
- r = sd_event_default(&iv_Event);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- <<"creating an sd_event" << std::endl;
- goto finish;
- }
-
- // Handlers called by sd_event when an activity
- // is observed in event loop
- r = registerCallbackHandlers();
- if (r < 0)
- {
- std::cerr << "Error setting up callback handlers" << std::endl;
- goto finish;
- }
-
- // Need to do this here since TimeConfig may update the necessary owners
- r = config.processInitialSettings(iv_TimeBus);
- if (r < 0)
- {
- std::cerr << "Error setting up configuration params" << std::endl;
- goto finish;
- }
-
- // Read saved values from previous run
- r = readPersistentData();
- if (r < 0)
- {
- std::cerr << "Error reading persistent data" << std::endl;
- goto finish;
- }
-
- // Claim the bus
- r = sd_bus_request_name(iv_TimeBus, cv_BusName, 0);
- if (r < 0)
- {
- std::cerr << "Error: " << strerror(-r)
- << "acquiring service name" << std::endl;
- goto finish;
- }
-finish:
- if (r < 0)
- {
- iv_EventSource = sd_event_source_unref(iv_EventSource);
- iv_Event = sd_event_unref(iv_Event);
- }
- return r;
-}
-
-int TimeManager::readPersistentData()
-{
- using namespace std::chrono;
-
- // Get current host_offset
- // When we reach here, TimeConfig would have been populated and would have
- // applied the owner to SPLIT *if* the system allowed it. So check if we
- // moved away from SPLIT and if so, make offset:0
- if (config.isSplitModeChanged())
- {
- iv_HostOffset = microseconds(0);
- auto r = config.writeData(cv_HostOffsetFile, iv_HostOffset.count());
- if (r < 0)
- {
- std::cerr <<" Error saving offset to file" << std::endl;
- return r;
- }
- }
- else
- {
- auto hostTimeOffset = config.readData<long long int>(cv_HostOffsetFile);
- iv_HostOffset = microseconds(hostTimeOffset);
- std::cout <<"Last known host_offset:" << hostTimeOffset << std::endl;
- }
-
- //How long was the FSP up prior to 'this' start
- iv_UptimeUsec = duration_cast<microseconds>
- (system_clock::now().time_since_epoch() -
- steady_clock::now().time_since_epoch());
- if (iv_UptimeUsec.count() < 0)
- {
- std::cerr <<"Error reading uptime" << std::endl;
- return -1;
- }
- std::cout <<"Initial Uptime Usec: "
- << iv_UptimeUsec.count() << std::endl;
- return 0;
-}
-
-// Forever loop
-int TimeManager::waitForClientRequest()
-{
- return sd_event_loop(iv_Event);
-}
-
-int main(int argc, char* argv[])
-{
- auto tmgr = std::make_unique<TimeManager>();
-
- // Wait for the work
- auto r = tmgr->waitForClientRequest();
-
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
diff --git a/time-manager.hpp b/time-manager.hpp
deleted file mode 100644
index 23560a4..0000000
--- a/time-manager.hpp
+++ /dev/null
@@ -1,306 +0,0 @@
-#include <systemd/sd-bus.h>
-#include <fstream>
-#include <string>
-#include <chrono>
-#include "time-config.hpp"
-
-/** @class Time
- * @brief Base class catering to common data needed by implementations
- */
-class Time
-{
-public:
- /** @brief Takes time in microseconds and uses systemd/timedated
- * to set the system time
- *
- * @param[in] timeOfDayUsec - Time value in microseconds
- * @param[out] retError - Error message on failure
- * @return - Status of time set operation
- * @error - Error message populated
- */
- int setTimeOfDay(const std::chrono::microseconds& timeOfDayUsec,
- sd_bus_error *retError);
-
- /** @brief Reads BMC time
- *
- * @param[in] - None
- * @return - time read in microseconds
- */
- std::chrono::microseconds getBaseTime();
-
- /** @brief Converts microseconds to human readable time value
- *
- * @param[in] timeInUsec - Time value in microseconds
- * @return - Time converted to human readable format
- */
- std::string convertToStr(const std::chrono::microseconds& timeInUsec);
-
- /** @brief Reference to config information due to need of policy data */
- const TimeConfig& config;
-
- /** Needed to access configuration variables */
- Time(const TimeConfig&);
-
-private:
- Time();
-};
-
-/** @class BmcTime
- * @brief Provides time Set and time Get operations for BMC target
- */
-class BmcTime: public Time
-{
-public:
- /** @brief Called when the time is to be read on BMC
- *
- * @param[in] m - sd_bus message.
- * @param[out] retError - Error reporting structure
- * @return - On no error, time read which is specified in
- * microseonds and also in human readable format.
- *
- * - On error, retError populated
- */
- int getTime(sd_bus_message* m, sd_bus_error* retError);
-
- /** @brief Called when the time is to be set on BMC
- *
- * @param[in] m - sd_bus message encapsulating time string
- * @param[out] retError - Error reporting structure
- * @return - On no error, 0, -1 otherwise or retError thrown
- */
- int setTime(sd_bus_message* m, sd_bus_error* retError);
-
- /** @brief constructor */
- BmcTime(const TimeConfig&);
-
-private:
- BmcTime();
-};
-
-/** @class HostTime
- * @brief Provides time Set and time Get operations for BMC target
- */
-class HostTime: public Time
-{
-public:
- /** @brief Called when IPMI_GET_SEL_TIME is called
- *
- * @param[in] m - sd_bus message.
- * @param[out] retError - Error reporting structure
- * @return - On no error, time read which is specified in
- * microseonds and also in human readable format.
- *
- * - On error, retError populated
- */
- int getTime(sd_bus_message*, sd_bus_error*);
-
- /** @brief Called when the IPMI_SET_SEL_TIME is called
- *
- * @param[in] m - sd_bus message encapsulating time in seconds
- * @param[out] retError - Error reporting structure
- * @return - On no error, 0, -1 otherwise or retError thrown
- */
- int setTime(sd_bus_message*, sd_bus_error*);
-
- /** @brief constructor */
- HostTime(const TimeConfig&, const std::chrono::microseconds&);
-
- /** @brief When the owner is SPLIT, the delta between HOST's time and BMC's
- * time needs to be saved and this function returns current delta.
- *
- * @param[in] - None
- * @return - offset in microseconds
- */
- inline std::chrono::microseconds getChangedOffset() const
- {
- return changedOffset;
- }
-
- /** @brief Reference to host's offset in case of SPLIT owner */
- const std::chrono::microseconds& iv_Offset;
-
-private:
- HostTime();
-
- /** @brief The delta offset of Host and BMC time */
- std::chrono::microseconds changedOffset;
-};
-
-/** @class TimeManager
- * @brief Caters to client requests with Set and Get time and configuration
- * changes
- */
-class TimeManager
-{
-public:
- // Do not have a usecase of copying this object so disable
- TimeManager();
- ~TimeManager() = default;
- TimeManager(const TimeManager&) = delete;
- TimeManager& operator=(const TimeManager&) = delete;
- TimeManager(TimeManager&&) = delete;
- TimeManager& operator=(TimeManager&&) = delete;
-
- // Maintains *all* the config that is needed for TimeManager.
- TimeConfig config;
-
- /** @brief Callback handlers invoked by dbus on GetTime client requests
- *
- * @param[in] m - sd_bus message encapsulating the time target
- * @param[in] userdata - context that is filled while registering this
- * @param[out] retError - Error reporting mechanism
- *
- * @return - On no error, time in microseconds and human
- * readable string. retError otherwise.
- */
- int getTime(sd_bus_message* m, void* userdata, sd_bus_error* retError);
-
- /** @brief Callback handlers invoked by dbus on SetTime client requests
- *
- * @param[in] m - sd_bus message encapsulating the time target and
- * time value either in string or in seconds.
- * @param[in] userdata - client context that is filled while registering
- * @param[out] retError - Error reporting mechanism
- *
- * @return - On no error, time in microseconds and human
- * readable string. retError otherwise.
- */
- int setTime(sd_bus_message* m, void* userdata, sd_bus_error* retError);
-
- /** @brief sd_event callback handlers on the requests coming in dbus
- * These are actually GetTime and SetTime requests
- *
- * @param[in] es - Event Structure
- * @param[in] fd - file descriptor that had 'read' activity
- * @param[in] revents - generic linux style return event
- * @param[in] userdata - Client context filled while registering
- *
- * @return - 0 for success, failure otherwise.
- */
- static int processSdBusMessage(sd_event_source* es, int fd,
- uint32_t revents, void* userdata);
-
- /** @brief sd_event callback handler called whenever there is a
- * time change event indicated by timerfd expiring. This happens
- * whenever the time is set on BMC by any source.
- *
- * @param[in] es - Event Structure
- * @param[in] fd - file descriptor that had 'read' activity
- * @param[in] revents - generic linux style return event
- * @param[in] userdata - Client context filled while registering
- *
- * @return - 0 for success, failure otherwise.
- */
- static int processTimeChange(sd_event_source* es, int fd,
- uint32_t revents, void* userdata);
-
- /** @brief sd_event callback handler called whenever a settings
- * property is changed.
- * This gets called into whenever "time_mode", "time_owner",
- * "use_dhcp_ntp" properties are changed
- *
- * @param[in] es - Event Structure
- * @param[in] fd - file descriptor that had 'read' activity
- * @param[in] revents - generic linux style return event
- * @param[in] userdata - Client context filled while registering
- *
- * @return - 0 for success, failure otherwise.
- */
- static int processPropertyChange(sd_bus_message*,
- void*,sd_bus_error*);
-
- /** @brief sd_event callback handler called whenever Pgood property is
- * changed
- *
- * @param[in] es - Event Structure
- * @param[in] fd - file descriptor that had 'read' activity
- * @param[in] revents - generic linux style return event
- * @param[in] userdata - Client context filled while registering
- *
- * @return - 0 for success, failure otherwise.
- */
- static int processPgoodChange(sd_bus_message*,
- void*,sd_bus_error*);
-
- /** @brief registers callsback handlers for sd_event loop
- *
- * @param[in] - None
- * @return - 0 if everything goes well, -1 otherwise
- */
- int registerCallbackHandlers();
-
- /** @brief Makes the Delta between Host and BMC time as 'ZERO'. This
- * essentially only means that time owner was SPLIT before
- * and now changed to something else.
- *
- * @param[in] - None
- * @return - 0 if everything goes well, -1 otherwise.
- */
- int resetHostOffset();
-
- /** @brief Reads what was the last delta offset stored in file
- *
- * @param[in] - None
- * @return - 0 if everything goes well, -1 otherwise.
- */
- int readPersistentData();
-
- /** @brief waits on sd_events loop for client requests
- *
- * @param[in] - None
- * @return - 0 if everything goes well, -1 otherwise.
- */
- int waitForClientRequest();
-
- inline auto getHostOffset() const
- {
- return iv_HostOffset;
- }
-
- inline auto updateHostOffset(const std::chrono::microseconds& newOffset)
- {
- iv_HostOffset = newOffset;
- }
-
- inline auto getUptimeUsec() const
- {
- return iv_UptimeUsec;
- }
-
- inline auto updateUptimeUsec(const std::chrono::microseconds& newUpTime)
- {
- iv_UptimeUsec = newUpTime;
- }
-
- inline sd_bus* getTimeBus() const
- {
- return iv_TimeBus;
- }
-
-private:
- // What was the last known host offset.
- std::chrono::microseconds iv_HostOffset;
-
- // How long was the BMC up for prior to this boot
- std::chrono::microseconds iv_UptimeUsec;
-
- // Used for registering sd_bus callback handlers.
- sd_event_source* iv_EventSource;
- sd_event* iv_Event;
- sd_bus* iv_TimeBus;
-
- // Dbus communication enablers.
- static constexpr auto cv_BusName = "org.openbmc.TimeManager";
- static constexpr auto cv_ObjPath = "/org/openbmc/TimeManager";
- static constexpr auto cv_IntfName = "org.openbmc.TimeManager";
-
- // Store the offset in File System. Read back when TimeManager starts.
- static constexpr auto cv_HostOffsetFile = "/var/lib/obmc/saved_host_offset";
-
- /** @brief Sets up internal data structures and callback handler at startup
- *
- * @param[in] - None
- * @return - 0 if everything goes well, -1 otherwise
- */
- int setupTimeManager(void);
-};
diff --git a/time-register.c b/time-register.c
deleted file mode 100644
index cdc1dd2..0000000
--- a/time-register.c
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <systemd/sd-bus.h>
-#include "time-register.hpp"
-#include <sys/timerfd.h>
-#include <errno.h>
-#include <stdio.h>
-
-/* Function pointer of APIs exposed via Dbus */
-//const sd_bus_vtable timeServicesVtable[] =
-const sd_bus_vtable timeServicesVtable [] =
-{
- SD_BUS_VTABLE_START(0),
- SD_BUS_PROPERTY("curr_time_mode", "s", getCurrTimeModeProperty, 0,
- SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("curr_time_owner", "s", getCurrTimeOwnerProperty, 0,
- SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("requested_time_mode", "s", getReqTimeModeProperty, 0,
- SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("requested_time_owner", "s", getReqTimeOwnerProperty, 0,
- SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_METHOD("GetTime", "s", "sx", &GetTime,
- SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("SetTime", "ss", "i", &SetTime,
- SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_VTABLE_END,
-};
diff --git a/time-register.hpp b/time-register.hpp
deleted file mode 100644
index bf776d3..0000000
--- a/time-register.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <systemd/sd-bus.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-int getCurrTimeModeProperty(sd_bus*, const char*, const char*, const char*,
- sd_bus_message*, void*, sd_bus_error*);
-int getCurrTimeOwnerProperty(sd_bus*, const char*, const char*, const char*,
- sd_bus_message*, void*, sd_bus_error*);
-int getReqTimeModeProperty(sd_bus*, const char*, const char*, const char*,
- sd_bus_message*, void*, sd_bus_error*);
-int getReqTimeOwnerProperty(sd_bus*, const char*, const char*, const char*,
- sd_bus_message*, void*, sd_bus_error*);
-int GetTime(sd_bus_message*, void*, sd_bus_error*);
-int SetTime(sd_bus_message*, void*, sd_bus_error*);
-#ifdef __cplusplus
-};
-#endif
OpenPOWER on IntegriCloud