diff options
author | Jason M. Bills <jason.m.bills@linux.intel.com> | 2020-11-17 00:51:01 +0300 |
---|---|---|
committer | Jason M. Bills <jason.m.bills@linux.intel.com> | 2020-11-17 01:37:09 +0300 |
commit | 18576aaaa49bf249aef0b72dd12fc452fccb6aed (patch) | |
tree | e3f3d79d24a0e6966b33fbdbbbecfe3bb2932efb /meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb | |
parent | 989cbcf37fea988ef6b76b9bc1cc5774bacda2cf (diff) | |
download | openbmc-18576aaaa49bf249aef0b72dd12fc452fccb6aed.tar.xz |
Update to internal 0.74-155
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb')
13 files changed, 1022 insertions, 72 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-memory-leak.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-memory-leak.patch new file mode 100644 index 000000000..2c433b623 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-memory-leak.patch @@ -0,0 +1,124 @@ +From 8bb79ae9384e876b617663a7df4fc8a7a749219e Mon Sep 17 00:00:00 2001 +From: James Feist <james.feist@linux.intel.com> +Date: Mon, 28 Sep 2020 15:52:59 -0700 +Subject: [PATCH 1/1] Fix memory leak + +Downstream only fix to resolve leak. This makes the +socket lambda capture by weak_ptr so that it no longer +has ownership. + +Tested: Used script that creates leak, no more leak + +Signed-off-by: James Feist <james.feist@linux.intel.com> +--- + http/http_connection.h | 10 ++++++++-- + http/http_request.h | 2 +- + include/dump_offload.hpp | 9 +++++++-- + redfish-core/lib/event_service.hpp | 10 +++++++--- + redfish-core/lib/redfish_sessions.hpp | 12 +++++++----- + 5 files changed, 30 insertions(+), 13 deletions(-) + +diff --git a/http/http_connection.h b/http/http_connection.h +index 8db8108..4093e95 100644 +--- a/http/http_connection.h ++++ b/http/http_connection.h +@@ -531,8 +531,14 @@ class Connection : + + if (!isInvalidRequest) + { +- req->socket = [this, self = shared_from_this()]() -> Adaptor& { +- return self->socket(); ++ auto self = this->weak_from_this(); ++ req->socket = [self]() -> Adaptor* { ++ auto shared = self.lock(); ++ if (shared) ++ { ++ return &(shared->socket()); ++ } ++ return nullptr; + }; + + res.completeRequestHandler = [] {}; +diff --git a/http/http_request.h b/http/http_request.h +index 95f88c7..3313582 100644 +--- a/http/http_request.h ++++ b/http/http_request.h +@@ -36,7 +36,7 @@ struct Request + std::shared_ptr<crow::persistent_data::UserSession> session; + + std::string userRole{}; +- std::function<Adaptor&()> socket; ++ std::function<Adaptor*()> socket; + Request( + boost::beast::http::request<boost::beast::http::string_body>& reqIn) : + req(reqIn), +diff --git a/include/dump_offload.hpp b/include/dump_offload.hpp +index 1777dfe..a01fb32 100644 +--- a/include/dump_offload.hpp ++++ b/include/dump_offload.hpp +@@ -290,8 +290,13 @@ inline void handleDumpOffloadUrl(const crow::Request& req, crow::Response& res, + boost::asio::io_context* io_con = req.ioService; + + handler = std::make_shared<Handler>(media, *io_con, entryId); +- handler->stream = +- std::make_shared<crow::Request::Adaptor>(std::move(req.socket())); ++ handler->stream = nullptr; ++ auto socket = req.socket(); ++ if (socket) ++ { ++ handler->stream = ++ std::make_shared<crow::Request::Adaptor>(std::move(*socket)); ++ } + handler->connect(); + handler->waitForMessageOnSocket(); + } +diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp +index 351f689..40758e7 100644 +--- a/redfish-core/lib/event_service.hpp ++++ b/redfish-core/lib/event_service.hpp +@@ -551,9 +551,13 @@ class EventServiceSSE : public Node + } + } + } +- +- std::shared_ptr<crow::Request::Adaptor> sseConn = +- std::make_shared<crow::Request::Adaptor>(std::move(req.socket())); ++ auto socket = req.socket(); ++ std::shared_ptr<crow::Request::Adaptor> sseConn = nullptr; ++ if (socket) ++ { ++ sseConn = ++ std::make_shared<crow::Request::Adaptor>(std::move((*socket))); ++ } + std::shared_ptr<Subscription> subValue = + std::make_shared<Subscription>(sseConn); + +diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp +index 8080e6f..267f98a 100644 +--- a/redfish-core/lib/redfish_sessions.hpp ++++ b/redfish-core/lib/redfish_sessions.hpp +@@ -227,14 +227,16 @@ class SessionCollection : public Node + } + } + #endif +- ++ auto socket = req.socket(); ++ if (socket) ++ { + #ifdef BMCWEB_ENABLE_SSL +- clientIp = +- req.socket().next_layer().remote_endpoint().address().to_string(); ++ clientIp = ++ (*socket).next_layer().remote_endpoint().address().to_string(); + #else +- clientIp = req.socket().remote_endpoint().address().to_string(); ++ clientIp = (*socket).remote_endpoint().address().to_string(); + #endif +- ++ } + // User is authenticated - create session + std::shared_ptr<crow::persistent_data::UserSession> session = + crow::persistent_data::SessionStore::getInstance() +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch deleted file mode 100644 index 90905762b..000000000 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch +++ /dev/null @@ -1,33 +0,0 @@ -From f43d6ba7e32565a7881949070bd25cb13f50ebf7 Mon Sep 17 00:00:00 2001 -From: James Feist <james.feist@linux.intel.com> -Date: Thu, 27 Aug 2020 13:56:52 -0700 -Subject: [PATCH 1/1] Workaround: Fix memory leak - -Req caputures self not allowing the connection to -be freed. There is discussion in upstream about a -real fix, this should be kept downstream only. - -Tested: Sent 1000 connections, saw no VSZ increase - -Change-Id: I63440abbe0882ffe228395b5d3bc869f10048ddc -Signed-off-by: James Feist <james.feist@linux.intel.com> ---- - http/http_connection.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/http/http_connection.h b/http/http_connection.h -index 109a272..393c2e7 100644 ---- a/http/http_connection.h -+++ b/http/http_connection.h -@@ -422,6 +422,8 @@ class Connection : - { - adaptor.close(); - } -+ // HACK TO REMOVE MEMORY LEAK -+ req.reset(); - } - - void completeRequest() --- -2.17.1 - diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0027-EventService-Improvements-and-limitations.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0027-EventService-Improvements-and-limitations.patch new file mode 100644 index 000000000..23b8a429c --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0027-EventService-Improvements-and-limitations.patch @@ -0,0 +1,265 @@ +From 1a848063c3a90dd0910a33e8d5d01ef6fd48fdd6 Mon Sep 17 00:00:00 2001 +From: AppaRao Puli <apparao.puli@linux.intel.com> +Date: Fri, 2 Oct 2020 02:03:08 +0530 +Subject: [PATCH] EventService: Improvements and limitations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Below improvements are made for MetricReport event +format Types: + - To reduce load on D-Bus, removed “GetAll” D-Bus + method call. Use “PropertiesChanged” Signal + instead of “ReportUpdated” signal + - Optimize the getDateTime function call + - Set the sublimit of 2 for MetricReport subscriptions. + - Read ReportTimestamp from signal & fromat it. + +Tested: + - Stressed EventService along with Telemetry reports and + it works fine. + - Tried adding more than two MetricReport subscriptions + and it returns error as expected. + - Report timestamp works. + +Change-Id: I58773ea4e25eb0c792c2c43b7450ef52f01996fa +Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> +--- + http/utility.h | 14 ++- + redfish-core/include/event_service_manager.hpp | 116 +++++++++++++------------ + redfish-core/lib/event_service.hpp | 17 ++++ + 3 files changed, 83 insertions(+), 64 deletions(-) + +diff --git a/http/utility.h b/http/utility.h +index 8254091..666c13e 100644 +--- a/http/utility.h ++++ b/http/utility.h +@@ -775,18 +775,16 @@ inline void convertToLinks(std::string& s) + */ + inline std::string getDateTime(const std::time_t& time) + { +- std::array<char, 128> dateTime; +- std::string redfishDateTime("0000-00-00T00:00:00Z00:00"); ++ std::array<char, sizeof("0000-00-00T00:00:00+00:00\0")> dateTime; + +- if (std::strftime(dateTime.begin(), dateTime.size(), "%FT%T%z", +- std::localtime(&time))) ++ size_t sz = std::strftime(dateTime.begin(), dateTime.size(), "%FT%T+00:00", ++ std::gmtime(&time)); ++ if (sz == 0 || sz > dateTime.size()) + { +- // insert the colon required by the ISO 8601 standard +- redfishDateTime = std::string(dateTime.data()); +- redfishDateTime.insert(redfishDateTime.end() - 2, ':'); ++ return ""; + } + +- return redfishDateTime; ++ return std::string(dateTime.data(), sz); + } + + inline std::string dateTimeNow() +diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp +index 8397159..b503e2f 100644 +--- a/redfish-core/include/event_service_manager.hpp ++++ b/redfish-core/include/event_service_manager.hpp +@@ -40,6 +40,7 @@ namespace redfish + + using ReadingsObjType = + std::vector<std::tuple<std::string, std::string, double, int32_t>>; ++using ReadingsAndTimestamp = std::tuple<int32_t, ReadingsObjType>; + using EventServiceConfig = std::tuple<bool, uint32_t, uint32_t>; + + static constexpr const char* eventFormatType = "Event"; +@@ -1026,6 +1027,11 @@ class EventServiceManager + return count; + } + ++ size_t getMetricReportSubscriptionsCount() ++ { ++ return noOfMetricReportSubscribers; ++ } ++ + std::vector<std::string> getAllIDs() + { + std::vector<std::string> idList; +@@ -1294,8 +1300,8 @@ class EventServiceManager + + #endif + +- void getMetricReading(const std::string& service, +- const std::string& objPath, const std::string& intf) ++ void getMetricReading(const std::string& objPath, const int32_t& reportTs, ++ const ReadingsObjType& readings) + { + std::size_t found = objPath.find_last_of("/"); + if (found == std::string::npos) +@@ -1311,55 +1317,22 @@ class EventServiceManager + return; + } + +- crow::connections::systemBus->async_method_call( +- [idStr{std::move(idStr)}]( +- const boost::system::error_code ec, +- boost::container::flat_map< +- std::string, std::variant<int32_t, ReadingsObjType>>& +- resp) { +- if (ec) +- { +- BMCWEB_LOG_DEBUG +- << "D-Bus call failed to GetAll metric readings."; +- return; +- } +- +- const int32_t* timestampPtr = +- std::get_if<int32_t>(&resp["Timestamp"]); +- if (!timestampPtr) +- { +- BMCWEB_LOG_DEBUG << "Failed to Get timestamp."; +- return; +- } +- +- ReadingsObjType* readingsPtr = +- std::get_if<ReadingsObjType>(&resp["Readings"]); +- if (!readingsPtr) +- { +- BMCWEB_LOG_DEBUG << "Failed to Get Readings property."; +- return; +- } +- +- if (!readingsPtr->size()) +- { +- BMCWEB_LOG_DEBUG << "No metrics report to be transferred"; +- return; +- } ++ if (!readings.size()) ++ { ++ BMCWEB_LOG_DEBUG << "No metrics in report to be transferred"; ++ return; ++ } + +- for (const auto& it : +- EventServiceManager::getInstance().subscriptionsMap) +- { +- std::shared_ptr<Subscription> entry = it.second; +- if (entry->eventFormatType == metricReportFormatType) +- { +- entry->filterAndSendReports( +- idStr, crow::utility::getDateTime(*timestampPtr), +- *readingsPtr); +- } +- } +- }, +- service, objPath, "org.freedesktop.DBus.Properties", "GetAll", +- intf); ++ for (const auto& it : ++ EventServiceManager::getInstance().subscriptionsMap) ++ { ++ std::shared_ptr<Subscription> entry = it.second; ++ if (entry->eventFormatType == metricReportFormatType) ++ { ++ entry->filterAndSendReports( ++ idStr, crow::utility::getDateTime(reportTs), readings); ++ } ++ } + } + + void unregisterMetricReportSignal() +@@ -1382,22 +1355,53 @@ class EventServiceManager + + BMCWEB_LOG_DEBUG << "Metrics report signal - Register"; + std::string matchStr( +- "type='signal',member='ReportUpdate', " +- "interface='xyz.openbmc_project.MonitoringService.Report'"); ++ "type='signal',member='PropertiesChanged'," ++ "sender='xyz.openbmc_project.MonitoringService'," ++ "interface='org.freedesktop.DBus.Properties'," ++ "path_namespace='/xyz/openbmc_project/MonitoringService/Reports/" ++ "TelemetryService'," ++ "arg0='xyz.openbmc_project.MonitoringService.Report'"); + + matchTelemetryMonitor = std::make_shared<sdbusplus::bus::match::match>( + *crow::connections::systemBus, matchStr, + [this](sdbusplus::message::message& msg) { + if (msg.is_method_error()) + { +- BMCWEB_LOG_ERROR << "TelemetryMonitor Signal error"; ++ BMCWEB_LOG_ERROR << "Received error in monitor signal"; + return; + } + +- std::string service = msg.get_sender(); + std::string objPath = msg.get_path(); +- std::string intf = msg.get_interface(); +- getMetricReading(service, objPath, intf); ++ std::string intf; ++ std::vector< ++ std::pair<std::string, std::variant<ReadingsAndTimestamp>>> ++ msgData; ++ msg.read(intf, msgData); ++ ++ if (intf != "xyz.openbmc_project.MonitoringService.Report") ++ { ++ BMCWEB_LOG_ERROR ++ << "Received property from wrong interface"; ++ return; ++ } ++ ++ const ReadingsAndTimestamp* dataPtr = nullptr; ++ for (const auto& [key, var] : msgData) ++ { ++ if (key == "Readings") ++ { ++ dataPtr = std::get_if<ReadingsAndTimestamp>(&var); ++ break; ++ } ++ } ++ if (!dataPtr) ++ { ++ BMCWEB_LOG_ERROR << "Failed to get readings from signal"; ++ return; ++ } ++ ++ const auto& [timestamp, readings] = *dataPtr; ++ getMetricReading(objPath, timestamp, readings); + }); + } + +diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp +index 40758e7..c3addca 100644 +--- a/redfish-core/lib/event_service.hpp ++++ b/redfish-core/lib/event_service.hpp +@@ -28,6 +28,7 @@ static constexpr const std::array<const char*, 3> supportedRetryPolicies = { + + static constexpr const uint8_t maxNoOfSubscriptions = 20; + static constexpr const uint8_t maxNoOfSSESubscriptions = 10; ++static constexpr const uint8_t maxNoOfMetricReportSubscriptions = 2; + + class EventService : public Node + { +@@ -253,6 +254,22 @@ class EventDestinationCollection : public Node + } + } + ++ if (eventFormatType) ++ { ++ if (*eventFormatType == metricReportFormatType) ++ { ++ if (EventServiceManager::getInstance() ++ .getMetricReportSubscriptionsCount() >= ++ maxNoOfMetricReportSubscriptions) ++ { ++ BMCWEB_LOG_ERROR ++ << "Max metric report subscription limit reached"; ++ messages::eventSubscriptionLimitExceeded(asyncResp->res); ++ return; ++ } ++ } ++ } ++ + // Validate the URL using regex expression + // Format: <protocol>://<host>:<port>/<uri> + // protocol: http/https +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0028-EventService-Schedule-MetricReport-data-format.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0028-EventService-Schedule-MetricReport-data-format.patch new file mode 100644 index 000000000..7a58c3a98 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0028-EventService-Schedule-MetricReport-data-format.patch @@ -0,0 +1,58 @@ +From 4b586eba14826f19daf84c17bd6b8170ce7d6337 Mon Sep 17 00:00:00 2001 +From: AppaRao Puli <apparao.puli@linux.intel.com> +Date: Fri, 2 Oct 2020 16:18:04 +0530 +Subject: [PATCH] EventService: Schedule MetricReport data format + +Stress test with telemetric report data, bmcweb +slows down in responding to redfish requests. +Scheduling the MtericReport data filtering and +MetricReport formmating to place back of queue. + +Tested: + - Improved redfish request data procesing + +Change-Id: I3664bbaa3ee2d749310205b574f5d969574cf29a +Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> +--- + redfish-core/include/event_service_manager.hpp | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp +index b503e2f..b6b8b5a 100644 +--- a/redfish-core/include/event_service_manager.hpp ++++ b/redfish-core/include/event_service_manager.hpp +@@ -1323,16 +1323,21 @@ class EventServiceManager + return; + } + +- for (const auto& it : +- EventServiceManager::getInstance().subscriptionsMap) +- { +- std::shared_ptr<Subscription> entry = it.second; +- if (entry->eventFormatType == metricReportFormatType) +- { +- entry->filterAndSendReports( +- idStr, crow::utility::getDateTime(reportTs), readings); +- } +- } ++ boost::asio::post( ++ crow::connections::systemBus->get_io_context(), ++ [this, idStr, reportTs, readings] { ++ for (const auto& it : ++ EventServiceManager::getInstance().subscriptionsMap) ++ { ++ std::shared_ptr<Subscription> entry = it.second; ++ if (entry->eventFormatType == metricReportFormatType) ++ { ++ entry->filterAndSendReports( ++ idStr, crow::utility::getDateTime(reportTs), ++ readings); ++ } ++ } ++ }); + } + + void unregisterMetricReportSignal() +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0029-Added-Validation-on-MessageId-and-RegistryPrefix.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0029-Added-Validation-on-MessageId-and-RegistryPrefix.patch new file mode 100644 index 000000000..bee45d957 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0029-Added-Validation-on-MessageId-and-RegistryPrefix.patch @@ -0,0 +1,166 @@ +From 729f09fd4918fec4615d6cee898fbb7aaebd6751 Mon Sep 17 00:00:00 2001 +From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> +Date: Sat, 26 Sep 2020 03:45:41 +0530 +Subject: [PATCH] Added Validation on MessageId and RegistryPrefix + +Message ID's and Registry prefixes used to subscribe to an event +will be checked against allowed values. +Base registry prefix is removed, because there won't be any Redfish +events logged with Base registry prefix. +Corrected "Task" registry prefix to "TaskEvent". + +Tested: + - Validated POST action with different combinations of + Message id's and Registry Prefix. + - Redfish validator passed. + +Change-Id: Ie6dc0268ffaf03606395f9d78f19cfcb6f432120 +Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> +Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> +--- + redfish-core/include/event_service_manager.hpp | 48 +++++++++++++++++++------- + redfish-core/lib/event_service.hpp | 48 +++++++++++++++++++++++--- + 2 files changed, 80 insertions(+), 16 deletions(-) + +diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp +index b6b8b5a..afbf799 100644 +--- a/redfish-core/include/event_service_manager.hpp ++++ b/redfish-core/include/event_service_manager.hpp +@@ -18,6 +18,7 @@ + #include "registries.hpp" + #include "registries/base_message_registry.hpp" + #include "registries/openbmc_message_registry.hpp" ++#include "registries/task_event_message_registry.hpp" + + #include <sys/inotify.h> + #include <systemd/sd-journal.h> +@@ -68,6 +69,40 @@ using EventLogObjectsType = + + namespace message_registries + { ++static bool ++ isValidMessageId(const std::string& messageId, ++ const boost::beast::span<const MessageEntry>& registry) ++{ ++ boost::beast::span<const MessageEntry>::const_iterator messageIdIt = ++ std::find_if(registry.cbegin(), registry.cend(), ++ [&messageId](const MessageEntry& messageEntry) { ++ return !messageId.compare(messageEntry.first); ++ }); ++ if (messageIdIt != registry.cend()) ++ { ++ return true; ++ } ++ ++ return false; ++} ++ ++static const boost::beast::span<const MessageEntry> ++ getRegistryFromPrefix(const std::string& registryName) ++{ ++ if (std::string(task_event::header.registryPrefix) == registryName) ++ { ++ return boost::beast::span<const MessageEntry>(task_event::registry); ++ } ++ else if (std::string(openbmc::header.registryPrefix) == registryName) ++ { ++ return boost::beast::span<const MessageEntry>(openbmc::registry); ++ } ++ else if (std::string(base::header.registryPrefix) == registryName) ++ { ++ return boost::beast::span<const MessageEntry>(base::registry); ++ } ++ return boost::beast::span<const MessageEntry>(openbmc::registry); ++} + static const Message* + getMsgFromRegistry(const std::string& messageKey, + const boost::beast::span<const MessageEntry>& registry) +@@ -101,18 +136,7 @@ static const Message* formatMessage(const std::string_view& messageID) + std::string& messageKey = fields[3]; + + // Find the right registry and check it for the MessageKey +- if (std::string(base::header.registryPrefix) == registryName) +- { +- return getMsgFromRegistry( +- messageKey, boost::beast::span<const MessageEntry>(base::registry)); +- } +- if (std::string(openbmc::header.registryPrefix) == registryName) +- { +- return getMsgFromRegistry( +- messageKey, +- boost::beast::span<const MessageEntry>(openbmc::registry)); +- } +- return nullptr; ++ return getMsgFromRegistry(messageKey, getRegistryFromPrefix(registryName)); + } + } // namespace message_registries + +diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp +index c3addca..095b76d 100644 +--- a/redfish-core/lib/event_service.hpp ++++ b/redfish-core/lib/event_service.hpp +@@ -21,8 +21,8 @@ namespace redfish + + static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = { + eventFormatType, metricReportFormatType}; +-static constexpr const std::array<const char*, 3> supportedRegPrefixes = { +- "Base", "OpenBMC", "Task"}; ++static constexpr const std::array<const char*, 2> supportedRegPrefixes = { ++ "OpenBMC", "TaskEvent"}; + static constexpr const std::array<const char*, 3> supportedRetryPolicies = { + "TerminateAfterRetries", "SuspendRetries", "RetryForever"}; + +@@ -393,8 +393,48 @@ class EventDestinationCollection : public Node + + if (msgIds) + { +- // Do we need to loop-up MessageRegistry and validate +- // data for authenticity??? Not mandate, i believe. ++ std::vector<std::string> registryPrefix; ++ ++ // If no registry prefixes are mentioned, consider all supported ++ // prefixes ++ if (subValue->registryPrefixes.empty()) ++ { ++ registryPrefix.assign(supportedRegPrefixes.begin(), ++ supportedRegPrefixes.end()); ++ } ++ else ++ { ++ registryPrefix = subValue->registryPrefixes; ++ } ++ ++ for (const std::string& id : *msgIds) ++ { ++ bool validId = false; ++ ++ // Check for Message ID in each of the selected Registry ++ for (const std::string& it : registryPrefix) ++ { ++ const boost::beast::span< ++ const redfish::message_registries::MessageEntry>& ++ registry = ++ redfish::message_registries::getRegistryFromPrefix( ++ it); ++ ++ if (isValidMessageId(id, registry)) ++ { ++ validId = true; ++ break; ++ } ++ } ++ ++ if (!validId) ++ { ++ messages::propertyValueNotInList(asyncResp->res, id, ++ "MessageIds"); ++ return; ++ } ++ } ++ + subValue->registryMsgIds = *msgIds; + } + +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0030-Initialize-Event-Service-Config-on-bmcweb-restart.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0030-Initialize-Event-Service-Config-on-bmcweb-restart.patch new file mode 100644 index 000000000..60631bc3c --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0030-Initialize-Event-Service-Config-on-bmcweb-restart.patch @@ -0,0 +1,36 @@ +From 20f61051cc1dc68b5be2419a4ec0fdbfedf3466e Mon Sep 17 00:00:00 2001 +From: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> +Date: Wed, 7 Oct 2020 01:45:28 +0530 +Subject: [PATCH] Initialize Event Service Config on bmcweb restart + +Added instantiation of EventServiceManager Object in the +EventService constructor to initialize Event Service Config +and register the subscriptions from the config. + +Tested: + - Subscribed Events were successfully received on restart + of bmcweb Service as well as on reboot of bmc + +Change-Id: Ie2d446b49e172a057ba53e3d3692c40010fb88ff +Signed-off-by: P Dheeraj Srujan Kumar <p.dheeraj.srujan.kumar@intel.com> +--- + redfish-core/lib/event_service.hpp | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp +index 095b76d..7a29af5 100644 +--- a/redfish-core/lib/event_service.hpp ++++ b/redfish-core/lib/event_service.hpp +@@ -42,6 +42,9 @@ class EventService : public Node + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, + {boost::beast::http::verb::post, {{"ConfigureManager"}}}}; ++ ++ // Create EventServiceManager instance and initialize Config ++ EventServiceManager::getInstance(); + } + + private: +-- +2.17.1 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0031-get-on-crashdump-can-follow-redfish-privileges.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0031-get-on-crashdump-can-follow-redfish-privileges.patch new file mode 100644 index 000000000..0e12915a9 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0031-get-on-crashdump-can-follow-redfish-privileges.patch @@ -0,0 +1,140 @@ +From c2310caa0362eb01988a43a4b6114c52261628e0 Mon Sep 17 00:00:00 2001 +From: AppaRao Puli <apparao.puli@linux.intel.com> +Date: Thu, 8 Oct 2020 12:33:57 +0530 +Subject: [PATCH] get on crashdump can follow redfish privileges + +Get & Head on crashdump uri's are deviated from redfish privilege +registries(LogService), thinking of security concerns. But it can +also follow normal 'Login' privilege like other LogService URI's. +There is not security issue as 'Login' privilege means user is +already authenticated. + +Tested: + - Verified get & head on crashdump uri's with login + user and it works fine. + +Change-Id: Iab913b633aa2daf5ecfa111a631071c095fa29d5 +Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> +--- + redfish-core/lib/log_services.hpp | 48 +++++++++++++-------------------------- + 1 file changed, 16 insertions(+), 32 deletions(-) + +diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp +index 590243c..e6090e5 100644 +--- a/redfish-core/lib/log_services.hpp ++++ b/redfish-core/lib/log_services.hpp +@@ -2403,11 +2403,9 @@ class CrashdumpService : public Node + CrashdumpService(CrowApp& app) : + Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/") + { +- // Note: Deviated from redfish privilege registry for GET & HEAD +- // method for security reasons. + entityPrivileges = { +- {boost::beast::http::verb::get, {{"ConfigureComponents"}}}, +- {boost::beast::http::verb::head, {{"ConfigureComponents"}}}, ++ {boost::beast::http::verb::get, {{"Login"}}}, ++ {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, +@@ -2463,11 +2461,9 @@ class CrashdumpClear : public Node + Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/" + "LogService.ClearLog/") + { +- // Note: Deviated from redfish privilege registry for GET & HEAD +- // method for security reasons. + entityPrivileges = { +- {boost::beast::http::verb::get, {{"ConfigureComponents"}}}, +- {boost::beast::http::verb::head, {{"ConfigureComponents"}}}, ++ {boost::beast::http::verb::get, {{"Login"}}}, ++ {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, +@@ -2556,11 +2552,9 @@ class CrashdumpEntryCollection : public Node + CrashdumpEntryCollection(CrowApp& app) : + Node(app, "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/") + { +- // Note: Deviated from redfish privilege registry for GET & HEAD +- // method for security reasons. + entityPrivileges = { +- {boost::beast::http::verb::get, {{"ConfigureComponents"}}}, +- {boost::beast::http::verb::head, {{"ConfigureComponents"}}}, ++ {boost::beast::http::verb::get, {{"Login"}}}, ++ {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, +@@ -2643,11 +2637,9 @@ class CrashdumpEntry : public Node + "/redfish/v1/Systems/system/LogServices/Crashdump/Entries/<str>/", + std::string()) + { +- // Note: Deviated from redfish privilege registry for GET & HEAD +- // method for security reasons. + entityPrivileges = { +- {boost::beast::http::verb::get, {{"ConfigureComponents"}}}, +- {boost::beast::http::verb::head, {{"ConfigureComponents"}}}, ++ {boost::beast::http::verb::get, {{"Login"}}}, ++ {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, +@@ -2678,11 +2670,9 @@ class CrashdumpFile : public Node + "<str>/", + std::string(), std::string()) + { +- // Note: Deviated from redfish privilege registry for GET & HEAD +- // method for security reasons. + entityPrivileges = { +- {boost::beast::http::verb::get, {{"ConfigureComponents"}}}, +- {boost::beast::http::verb::head, {{"ConfigureComponents"}}}, ++ {boost::beast::http::verb::get, {{"Login"}}}, ++ {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureManager"}}}, + {boost::beast::http::verb::put, {{"ConfigureManager"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureManager"}}}, +@@ -2780,11 +2770,9 @@ class OnDemandCrashdump : public Node + "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/Oem/" + "Crashdump.OnDemand/") + { +- // Note: Deviated from redfish privilege registry for GET & HEAD +- // method for security reasons. + entityPrivileges = { +- {boost::beast::http::verb::get, {{"ConfigureComponents"}}}, +- {boost::beast::http::verb::head, {{"ConfigureComponents"}}}, ++ {boost::beast::http::verb::get, {{"Login"}}}, ++ {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, +@@ -2852,11 +2840,9 @@ class TelemetryCrashdump : public Node + "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/Oem/" + "Crashdump.Telemetry/") + { +- // Note: Deviated from redfish privilege registry for GET & HEAD +- // method for security reasons. + entityPrivileges = { +- {boost::beast::http::verb::get, {{"ConfigureComponents"}}}, +- {boost::beast::http::verb::head, {{"ConfigureComponents"}}}, ++ {boost::beast::http::verb::get, {{"Login"}}}, ++ {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, +@@ -2924,11 +2910,9 @@ class SendRawPECI : public Node + "/redfish/v1/Systems/system/LogServices/Crashdump/Actions/Oem/" + "Crashdump.SendRawPeci/") + { +- // Note: Deviated from redfish privilege registry for GET & HEAD +- // method for security reasons. + entityPrivileges = { +- {boost::beast::http::verb::get, {{"ConfigureComponents"}}}, +- {boost::beast::http::verb::head, {{"ConfigureComponents"}}}, ++ {boost::beast::http::verb::get, {{"Login"}}}, ++ {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0034-Avoid-using-deleted-Connection-in-Response.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0034-Avoid-using-deleted-Connection-in-Response.patch new file mode 100644 index 000000000..1d6239527 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0034-Avoid-using-deleted-Connection-in-Response.patch @@ -0,0 +1,42 @@ +From ab6152177b105625512c524f5c862acde260d72a Mon Sep 17 00:00:00 2001 +From: "Wludzik, Jozef" <jozef.wludzik@intel.com> +Date: Mon, 19 Oct 2020 13:07:45 +0200 +Subject: [PATCH] Avoid using deleted Connection in Response + +Connection is destroyed when completeRequestHandler is nulled. It +causes that memory is freed. When Response::end() is called and +connection is not alive, completeRequest() method removes last +shared_ptr reference by setting nullptr on completeRequestHandler +member of Response. In this moment code is executed on destroyed +object and can cause stack overflow. +Fixed it by moving a call to completeRequest method to Asio +executor in completeRequestHandler. + +Tested: + - Ran stress test that send a lot of GET and POST requests + without a bmcweb service crash + +Change-Id: Idcf6a06dac32e9eac08285b9b53a5e8afe36c955 +Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com> +--- + http/http_connection.h | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/http/http_connection.h b/http/http_connection.h +index 4093e95..59a134f 100644 +--- a/http/http_connection.h ++++ b/http/http_connection.h +@@ -557,7 +557,9 @@ class Connection : + { + needToCallAfterHandlers = true; + res.completeRequestHandler = [self(shared_from_this())] { +- self->completeRequest(); ++ boost::asio::post(self->adaptor.get_executor(), [self] { ++ self->completeRequest(); ++ }); + }; + if (req->isUpgrade() && + boost::iequals( +-- +2.16.6 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0035-EventService-Fix-hostname-resolve-issue.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0035-EventService-Fix-hostname-resolve-issue.patch new file mode 100644 index 000000000..372ff6801 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0035-EventService-Fix-hostname-resolve-issue.patch @@ -0,0 +1,137 @@ +From c3a63a9ff4103b215d85845b98ba51c039511713 Mon Sep 17 00:00:00 2001 +From: AppaRao Puli <apparao.puli@linux.intel.com> +Date: Fri, 16 Oct 2020 17:03:36 +0530 +Subject: [PATCH] EventService - Fix hostname resolve issue + +The hostname also accepted in EventService +as destination. When this hostname resolution +fails, causes the bmcweb crash. So avoid the +bmcweb crash by catching exception and control +goes to retry process like any other failure. + +Tested: + - No bmcweb crash observed when hostname resolve fails. + - Created subscription with invalid hostname and + verified the retry process. + - Created subscriptions with positive cases and all + works fine. + +Change-Id: I0adf6864911c4cf49a11110519c73556d87f3279 +Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com> +--- + http/http_client.hpp | 54 ++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 42 insertions(+), 12 deletions(-) + +diff --git a/http/http_client.hpp b/http/http_client.hpp +index 6d3d702..abccc84 100644 +--- a/http/http_client.hpp ++++ b/http/http_client.hpp +@@ -36,6 +36,9 @@ static constexpr unsigned int httpReadBodyLimit = 1024; + enum class ConnState + { + initialized, ++ resolveInProgress, ++ resolveFailed, ++ resolved, + connectInProgress, + connectFailed, + sslHandshakeInProgress, +@@ -52,6 +55,7 @@ enum class ConnState + class HttpClient : public std::enable_shared_from_this<HttpClient> + { + private: ++ boost::asio::ip::tcp::resolver resolver; + boost::asio::ssl::context ctx{boost::asio::ssl::context::tlsv12_client}; + boost::beast::tcp_stream conn; + std::optional<boost::beast::ssl_stream<boost::beast::tcp_stream&>> sslConn; +@@ -76,6 +80,32 @@ class HttpClient : public std::enable_shared_from_this<HttpClient> + bool runningTimer; + ConnState state; + ++ void doResolve() ++ { ++ BMCWEB_LOG_DEBUG << "Trying to resolve: " << host << ":" << port; ++ if (state == ConnState::resolveInProgress) ++ { ++ return; ++ } ++ state = ConnState::resolveInProgress; ++ // TODO: Use async_resolver. boost asio example ++ // code as is crashing with async_resolve(). ++ try ++ { ++ endpoint = resolver.resolve(host, port); ++ } ++ catch (const std::exception& e) ++ { ++ BMCWEB_LOG_ERROR << "Failed to resolve hostname: " << host << " - " ++ << e.what(); ++ state = ConnState::resolveFailed; ++ checkQueue(); ++ return; ++ } ++ state = ConnState::resolved; ++ checkQueue(); ++ } ++ + void doConnect() + { + if (useSsl) +@@ -348,6 +378,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient> + } + + if ((state == ConnState::connectFailed) || ++ (state == ConnState::resolveFailed) || + (state == ConnState::sendFailed) || + (state == ConnState::recvFailed)) + { +@@ -393,16 +424,21 @@ class HttpClient : public std::enable_shared_from_this<HttpClient> + { + switch (state) + { ++ case ConnState::initialized: ++ case ConnState::resolveFailed: ++ case ConnState::connectFailed: ++ doResolve(); ++ break; + case ConnState::connectInProgress: ++ case ConnState::resolveInProgress: + case ConnState::sslHandshakeInProgress: + case ConnState::sendInProgress: + case ConnState::suspended: + case ConnState::terminated: + // do nothing + break; +- case ConnState::initialized: + case ConnState::closed: +- case ConnState::connectFailed: ++ case ConnState::resolved: + case ConnState::sendFailed: + case ConnState::recvFailed: + { +@@ -428,18 +464,12 @@ class HttpClient : public std::enable_shared_from_this<HttpClient> + const std::string& destIP, const std::string& destPort, + const std::string& destUri, + const bool inUseSsl = true) : +- conn(ioc), +- timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri), +- useSsl(inUseSsl), retryCount(0), maxRetryAttempts(5), ++ resolver(ioc), ++ conn(ioc), timer(ioc), subId(id), host(destIP), port(destPort), ++ uri(destUri), useSsl(inUseSsl), retryCount(0), maxRetryAttempts(5), + retryPolicyAction("TerminateAfterRetries"), runningTimer(false), + state(ConnState::initialized) +- { +- boost::asio::ip::tcp::resolver resolver(ioc); +- // TODO: Use async_resolver. boost asio example +- // code as is crashing with async_resolve(). +- // It needs debug. +- endpoint = resolver.resolve(host, port); +- } ++ {} + + void sendData(const std::string& data) + { +-- +2.7.4 + diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch index 3850c8fa8..b30f874f6 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Redfish-TelemetryService-schema-implementation.patch @@ -1,4 +1,4 @@ -From 7820421433349df28bd393e8d610d1848af0f1c8 Mon Sep 17 00:00:00 2001 +From 505ae9c2e6af470cdddcac9bac0de98afe0cfe58 Mon Sep 17 00:00:00 2001 From: "Wludzik, Jozef" <jozef.wludzik@intel.com> Date: Mon, 27 Apr 2020 17:24:15 +0200 Subject: [PATCH 1/5] Redfish TelemetryService schema implementation @@ -30,11 +30,11 @@ Change-Id: Ie6b0b49f4ef5eeaef07d1209b6c349270c04d570 redfish-core/include/utils/json_utils.hpp | 101 +++++++++++++ redfish-core/include/utils/telemetry_utils.hpp | 100 +++++++++++++ redfish-core/include/utils/time_utils.hpp | 97 +++++++++++++ - redfish-core/lib/metric_report.hpp | 149 +++++++++++++++++++ + redfish-core/lib/metric_report.hpp | 164 +++++++++++++++++++++ redfish-core/lib/metric_report_definition.hpp | 193 +++++++++++++++++++++++++ redfish-core/lib/service_root.hpp | 2 + redfish-core/lib/telemetry_service.hpp | 92 ++++++++++++ - 9 files changed, 765 insertions(+) + 9 files changed, 780 insertions(+) create mode 100644 redfish-core/include/utils/telemetry_utils.hpp create mode 100644 redfish-core/include/utils/time_utils.hpp create mode 100644 redfish-core/lib/metric_report.hpp @@ -73,7 +73,7 @@ index e1360f7..3df88d8 100644 } // namespace utility } // namespace dbus diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index cc98e1a..3d4c117 100644 +index 2e568da..898f548 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp @@ -25,6 +25,8 @@ @@ -93,7 +93,7 @@ index cc98e1a..3d4c117 100644 #include "../lib/thermal.hpp" #include "../lib/update_service.hpp" #ifdef BMCWEB_ENABLE_VM_NBDPROXY -@@ -202,6 +205,13 @@ class RedfishService +@@ -209,6 +212,13 @@ class RedfishService nodes.emplace_back(std::make_unique<HypervisorInterface>(app)); nodes.emplace_back(std::make_unique<HypervisorSystem>(app)); @@ -445,10 +445,10 @@ index 0000000..0256b3f +} // namespace redfish diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp new file mode 100644 -index 0000000..a52d680 +index 0000000..d2f9dd5 --- /dev/null +++ b/redfish-core/lib/metric_report.hpp -@@ -0,0 +1,149 @@ +@@ -0,0 +1,164 @@ +/* +// Copyright (c) 2018-2020 Intel Corporation +// @@ -541,6 +541,7 @@ index 0000000..a52d680 + + using Readings = + std::vector<std::tuple<std::string, std::string, double, int32_t>>; ++ using TimestampAndReadings = std::tuple<int32_t, Readings>; + using MetricValues = std::vector<std::map<std::string, std::string>>; + + static MetricValues toMetricValues(const Readings& readings) @@ -575,7 +576,7 @@ index 0000000..a52d680 + [asyncResp]( + const boost::system::error_code ec, + const boost::container::flat_map< -+ std::string, std::variant<Readings, int32_t>>& ret) { ++ std::string, std::variant<TimestampAndReadings>>& ret) { + if (ec) + { + messages::internalError(asyncResp->res); @@ -583,12 +584,26 @@ index 0000000..a52d680 + return; + } + -+ json_util::assignIfPresent<int32_t>( -+ ret, "Timestamp", asyncResp->res.jsonValue["Timestamp"], -+ crow::utility::getDateTime); -+ json_util::assignIfPresent<Readings>( -+ ret, "Readings", asyncResp->res.jsonValue["MetricValues"], -+ toMetricValues); ++ auto found = ret.find("Readings"); ++ if (found == ret.end()) ++ { ++ messages::internalError(asyncResp->res); ++ BMCWEB_LOG_ERROR << "Missing Readings property"; ++ return; ++ } ++ ++ const TimestampAndReadings* timestampAndReadingsPtr = ++ std::get_if<TimestampAndReadings>(&found->second); ++ if (!timestampAndReadingsPtr) ++ { ++ messages::internalError(asyncResp->res); ++ return; ++ } ++ const auto& [timestamp, readings] = *timestampAndReadingsPtr; ++ asyncResp->res.jsonValue["Timestamp"] = ++ crow::utility::getDateTime(timestamp); ++ asyncResp->res.jsonValue["MetricValues"] = ++ toMetricValues(readings); + }, + "xyz.openbmc_project.MonitoringService", reportPath, + "xyz.openbmc_project.MonitoringService.Report"); diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch index 8a8690bf3..309d39ba0 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-support-for-POST-in-MetricReportDefinitions.patch @@ -234,7 +234,7 @@ index d82ae59..ecbab0c 100644 +static constexpr size_t maxShortParamLength = 255; +static constexpr size_t maxLongParamLength = 1024; +static constexpr size_t maxDbusNameLength = 255; -+static constexpr size_t maxArraySize = 100; ++static constexpr size_t maxArraySize = 200; +static constexpr size_t maxReportIdLen = + maxDbusNameLength - std::string_view(telemetry::telemetryPath).size() - + std::string_view("/").size(); diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch index e996ac585..f95a0fe47 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Add-support-for-OnRequest-in-MetricReportDefinition.patch @@ -1,4 +1,4 @@ -From 9fc7d722b3192df9940062185b40ebb0fabad518 Mon Sep 17 00:00:00 2001 +From 1ccc028dc20ab1e585de225b8c50a7492499008c Mon Sep 17 00:00:00 2001 From: Krzysztof Grobelny <krzysztof.grobelny@intel.com> Date: Mon, 8 Jun 2020 15:16:10 +0200 Subject: [PATCH 4/5] Add support for "OnRequest" in MetricReportDefinition @@ -94,7 +94,7 @@ index 05ed00f..6c4e810 100644 { messages::resourceNotFound(asyncResp->res, schemaType, id); diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -index a52d680..877e7f1 100644 +index d2f9dd5..f8230a5 100644 --- a/redfish-core/lib/metric_report.hpp +++ b/redfish-core/lib/metric_report.hpp @@ -85,7 +85,7 @@ class MetricReport : public Node @@ -106,7 +106,7 @@ index a52d680..877e7f1 100644 } using Readings = -@@ -143,6 +143,57 @@ class MetricReport : public Node +@@ -158,6 +158,57 @@ class MetricReport : public Node "xyz.openbmc_project.MonitoringService.Report"); } diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch index f7da8a556..8c7ef2c27 100644 --- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0005-Add-support-for-MetricDefinition-scheme.patch @@ -1,4 +1,4 @@ -From b1da8901b5985d6a77b63ca9eb0570b46528f0bd Mon Sep 17 00:00:00 2001 +From fe2ed86210958f23fa0a8bd14c260e9cf4648e5a Mon Sep 17 00:00:00 2001 From: "Wludzik, Jozef" <jozef.wludzik@intel.com> Date: Mon, 8 Jun 2020 17:15:54 +0200 Subject: [PATCH 5/5] Add support for MetricDefinition scheme @@ -17,15 +17,15 @@ Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00 --- redfish-core/include/redfish.hpp | 3 + redfish-core/include/utils/telemetry_utils.hpp | 2 + - redfish-core/lib/metric_definition.hpp | 300 +++++++++++++++++++++++++ - redfish-core/lib/metric_report.hpp | 65 +++++- + redfish-core/lib/metric_definition.hpp | 299 +++++++++++++++++++++++++ + redfish-core/lib/metric_report.hpp | 66 +++++- redfish-core/lib/sensors.hpp | 43 +++- redfish-core/lib/telemetry_service.hpp | 2 + 6 files changed, 402 insertions(+), 13 deletions(-) create mode 100644 redfish-core/lib/metric_definition.hpp diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp -index 3d4c117..2a12bf9 100644 +index 898f548..1c3b5de 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp @@ -25,6 +25,7 @@ @@ -36,7 +36,7 @@ index 3d4c117..2a12bf9 100644 #include "../lib/metric_report.hpp" #include "../lib/metric_report_definition.hpp" #include "../lib/network_protocol.hpp" -@@ -206,6 +207,8 @@ class RedfishService +@@ -213,6 +214,8 @@ class RedfishService nodes.emplace_back(std::make_unique<HypervisorSystem>(app)); nodes.emplace_back(std::make_unique<TelemetryService>(app)); @@ -60,10 +60,10 @@ index 6c4e810..bb747c4 100644 static constexpr const char* metricReportUri = diff --git a/redfish-core/lib/metric_definition.hpp b/redfish-core/lib/metric_definition.hpp new file mode 100644 -index 0000000..837a068 +index 0000000..ff1b1ad --- /dev/null +++ b/redfish-core/lib/metric_definition.hpp -@@ -0,0 +1,300 @@ +@@ -0,0 +1,299 @@ +/* +// Copyright (c) 2018-2020 Intel Corporation +// @@ -323,7 +323,6 @@ index 0000000..837a068 + asyncResp->res.jsonValue["MetricType"] = "Numeric"; + asyncResp->res.jsonValue["Implementation"] = "PhysicalSensor"; + asyncResp->res.jsonValue["IsLinear"] = true; -+ asyncResp->res.jsonValue["TimestampAccuracy"] = "PT0.1S"; + auto unit = sensorUnits.find(id); + if (unit != sensorUnits.end()) + { @@ -365,12 +364,12 @@ index 0000000..837a068 + +} // namespace redfish diff --git a/redfish-core/lib/metric_report.hpp b/redfish-core/lib/metric_report.hpp -index 877e7f1..be72b18 100644 +index f8230a5..d4cdee1 100644 --- a/redfish-core/lib/metric_report.hpp +++ b/redfish-core/lib/metric_report.hpp -@@ -91,6 +91,9 @@ class MetricReport : public Node - using Readings = +@@ -92,6 +92,9 @@ class MetricReport : public Node std::vector<std::tuple<std::string, std::string, double, int32_t>>; + using TimestampAndReadings = std::tuple<int32_t, Readings>; using MetricValues = std::vector<std::map<std::string, std::string>>; + using ReadingParameters = + std::vector<std::tuple<std::vector<sdbusplus::message::object_path>, @@ -378,7 +377,7 @@ index 877e7f1..be72b18 100644 static MetricValues toMetricValues(const Readings& readings) { -@@ -109,6 +112,49 @@ class MetricReport : public Node +@@ -110,6 +113,49 @@ class MetricReport : public Node return metricValues; } @@ -428,22 +427,23 @@ index 877e7f1..be72b18 100644 static void getReportProperties(const std::shared_ptr<AsyncResp> asyncResp, const std::string& reportPath, const std::string& id) -@@ -124,7 +170,8 @@ class MetricReport : public Node +@@ -125,7 +171,9 @@ class MetricReport : public Node [asyncResp]( const boost::system::error_code ec, const boost::container::flat_map< -- std::string, std::variant<Readings, int32_t>>& ret) { +- std::string, std::variant<TimestampAndReadings>>& ret) { + std::string, -+ std::variant<Readings, int32_t, ReadingParameters>>& ret) { ++ std::variant<TimestampAndReadings, ++ ReadingParameters>>& ret) { if (ec) { messages::internalError(asyncResp->res); -@@ -138,6 +185,22 @@ class MetricReport : public Node - json_util::assignIfPresent<Readings>( - ret, "Readings", asyncResp->res.jsonValue["MetricValues"], - toMetricValues); +@@ -153,6 +201,22 @@ class MetricReport : public Node + crow::utility::getDateTime(timestamp); + asyncResp->res.jsonValue["MetricValues"] = + toMetricValues(readings); + -+ auto found = ret.find("ReadingParameters"); ++ found = ret.find("ReadingParameters"); + if (found != ret.end()) + { + auto params = @@ -462,7 +462,7 @@ index 877e7f1..be72b18 100644 "xyz.openbmc_project.MonitoringService", reportPath, "xyz.openbmc_project.MonitoringService.Report"); diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp -index f12bbe0..1fa1009 100644 +index 48aa439..e700081 100644 --- a/redfish-core/lib/sensors.hpp +++ b/redfish-core/lib/sensors.hpp @@ -53,20 +53,39 @@ static constexpr std::string_view thermal = "Thermal"; |