From a78720e57fe5045f1a0d32f82a21fd6dbb9b79d8 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Thu, 4 Nov 2021 13:46:12 +0000 Subject: [PATCH 1/2] Add NonSuccessCompletionCode exception info Some NM requests return additional information along with the non-success Completion Code. E.g. 0xC2 (get NM policy) returns the next valid policy ID for faster enumeration. Signed-off-by: Paul Fertser --- NodeManagerProxy.hpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/NodeManagerProxy.hpp b/NodeManagerProxy.hpp index 064aac4..57625e8 100644 --- a/NodeManagerProxy.hpp +++ b/NodeManagerProxy.hpp @@ -777,6 +777,11 @@ struct NonSuccessCompletionCode final : public sdbusplus::exception_t "xyz.openbmc_project.Common.Error.NonSuccessCompletionCode: The " "operation failed. Got non-success completion code."; + NonSuccessCompletionCode(uint8_t cc, const std::vector &resp) : + cc{cc}, resp{resp} + { + } + const char *name() const noexcept override { return errName; @@ -789,6 +794,19 @@ struct NonSuccessCompletionCode final : public sdbusplus::exception_t { return errWhat; }; + + uint8_t getCc(void) const + { + return cc; + } + const std::vector &getResp(void) const + { + return resp; + } + + private: + uint8_t cc; + std::vector resp; }; /** @@ -933,7 +951,7 @@ void ipmiSendReceive(std::shared_ptr conn, phosphor::logging::log( "error while sending IPMB request, wrong cc: ", phosphor::logging::entry("%d", cc)); - throw NonSuccessCompletionCode(); + throw NonSuccessCompletionCode(cc, dataReceived); } if (dataReceived.size() != sizeof(resp)) From e32052c2eceb4fafeeb604de52ab0abf1875cafa Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Fri, 5 Nov 2021 09:14:54 +0000 Subject: [PATCH 2/2] Enumerate existing policies on startup To ensure consistency between the set of policies used by NM and the set presented via D-Bus fetch all the existing policies on daemon startup and create the corresponding objects on the bus. Signed-off-by: Paul Fertser --- NodeManagerProxy.hpp | 135 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 11 deletions(-) diff --git a/NodeManagerProxy.hpp b/NodeManagerProxy.hpp index 57625e8..99503b1 100644 --- a/NodeManagerProxy.hpp +++ b/NodeManagerProxy.hpp @@ -1002,12 +1002,12 @@ class Policy static constexpr uint8_t dmtfPowerPolicyId = 254; static constexpr uint8_t dmtfPowerOemPolicyId = 255; - boost::container::flat_map triggerIdToName = { - {0, "AlwaysOn"}, - {1, "InletTemperature"}, - {2, "MissingReadingsTimeout"}, - {3, "TimeAfterHostReset"}, - {6, "GPIO"}}; + static const inline boost::container::flat_map + triggerIdToName = {{0, "AlwaysOn"}, + {1, "InletTemperature"}, + {2, "MissingReadingsTimeout"}, + {3, "TimeAfterHostReset"}, + {6, "GPIO"}}; uint8_t triggerIdFromName(const std::string &nameToBeFound) { @@ -1022,13 +1022,14 @@ class Policy return 255; } - std::string setOrUpdatePolicy(PolicyParams ¶ms) + std::string setOrUpdatePolicy(const PolicyParams ¶ms, + bool enableArg = false) { nmIpmiSetNmPolicyReq req = {0}; ipmiSetIntelIanaNumber(req.iana); req.domainId = domainId; - req.policyEnabled = 0x0; // Policy disabled during creation + req.policyEnabled = enableArg; req.policyId = getIdAsInt(); req.triggerType = triggerIdFromName(params.triggerType); req.configurationAction = 0x1; // Create or modify policy @@ -1048,6 +1049,7 @@ class Policy limit = params.limit; failureAction = params.limitException; correctionTime = params.correctionInMs; + enabled = enableArg; return dbusPath; } @@ -1438,8 +1440,117 @@ class Domain createCapabilitesInterface(server); createPolicyManagerInterface(server); createStatisticsInterface(server); + for (auto &&p : storedPolicies{*this}) + { + if (std::get<0>(p) != Policy::dmtfPowerOemPolicyId) + createOrUpdatePolicy(server, std::to_string(std::get<0>(p)), + std::get<1>(p), std::get<2>(p)); + } } + class storedPolicies + { + const Domain &domain; + + public: + storedPolicies(const Domain &domain) : domain{domain} + { + } + + class iterator + : public std::iterator> + { + const Domain &domain; + + uint8_t policyIdInt; + PolicyParams params; + bool enabled; + + void fetchPolicyParams(void) + { + nmIpmiGetNmPolicyReq req = {0}; + ipmiSetIntelIanaNumber(req.iana); + req.domainId = domain.id; + nmIpmiGetNmPolicyResp resp = {0}; + + while (policyIdInt != 0) + { + req.policyId = policyIdInt; + try + { + ipmiSendReceive( + domain.conn, ipmiGetNmPolicyNetFn, + ipmiGetNmPolicyLun, ipmiGetNmPolicyCmd, req, resp); + + enabled = resp.policyEnabled; + params.triggerType = + Policy::triggerIdToName.at(resp.triggerType); + params.powerCorrectionType = resp.cpuPowerCorrection; + params.policyStorage = resp.storageOption; + params.limit = resp.limit; + params.correctionInMs = resp.correctionTime; + params.triggerLimit = resp.triggerLimit; + params.statReportingPeriod = resp.statsPeriod; + params.limitException = + (resp.sendAlert << 1) | resp.shutdownSystem; + break; + } + catch (NonSuccessCompletionCode &e) + { + if (e.getCc() == 0x80) + { + // next valid policy ID + policyIdInt = e.getResp()[3]; + } + else + throw(e); + } + } + } + + public: + explicit iterator(uint8_t id, const Domain &domain) : + policyIdInt{id}, domain{domain} + { + fetchPolicyParams(); + } + iterator &operator++() + { + policyIdInt++; + fetchPolicyParams(); + return *this; + } + iterator operator++(int) + { + iterator retval = *this; + ++(*this); + return retval; + } + bool operator==(iterator other) const + { + return policyIdInt == other.policyIdInt; + } + bool operator!=(iterator other) const + { + return !(*this == other); + } + value_type operator*() const + { + return {policyIdInt, params, enabled}; + } + }; + iterator begin() const + { + return iterator{1, domain}; + } + iterator end() const + { + return iterator{0, domain}; + } + }; + private: uint8_t id; std::string dbusPath; @@ -1503,13 +1614,14 @@ class Domain std::string createOrUpdatePolicy(sdbusplus::asio::object_server &server, std::string policyId, - PolicyParams &policyParams) + const PolicyParams &policyParams, + bool enable = false) { for (auto &policy : policies) { if (policy->getId() == policyId) { - return policy->setOrUpdatePolicy(policyParams); + return policy->setOrUpdatePolicy(policyParams, enable); } } auto policyTmp = std::make_unique( @@ -1524,7 +1636,8 @@ class Domain } } }); - std::string policyPath = policyTmp->setOrUpdatePolicy(policyParams); + std::string policyPath = + policyTmp->setOrUpdatePolicy(policyParams, enable); policies.emplace_back(std::move(policyTmp)); return policyPath; }