diff --git a/NodeManagerProxy.hpp b/NodeManagerProxy.hpp index 064aac4..99503b1 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)) @@ -984,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) { @@ -1004,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 @@ -1030,6 +1049,7 @@ class Policy limit = params.limit; failureAction = params.limitException; correctionTime = params.correctionInMs; + enabled = enableArg; return dbusPath; } @@ -1420,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; @@ -1485,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( @@ -1506,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; }