summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2021-05-03 20:49:59 +0300
committerJason M. Bills <jason.m.bills@linux.intel.com>2021-05-03 21:06:56 +0300
commite370fd750e2821620ec427f26f8efab0069824ff (patch)
tree9acce8ae4bf8b88a4e71b1bbcd2e69cd3c166ea5 /meta-openbmc-mods
parentab16ab3d0de4dc9d130ae3db366c38888f1ada5a (diff)
downloadopenbmc-e370fd750e2821620ec427f26f8efab0069824ff.tar.xz
Update to internal 0.47
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods')
-rw-r--r--meta-openbmc-mods/conf/layer.conf2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend4
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_git.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0038-Revert-Disable-nbd-proxy-from-the-build.patch50
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch543
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch401
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0003-Move-EventService-init-to-later-stage.patch50
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch477
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch627
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch243
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README22
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Sync_ReadingUnit_with_Redfish_Sensor_Schema.patch227
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-POST-and-DELETE-in-MetricReportDefinitions.patch35
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch256
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Sync-Telmetry-service-with-EventService.patch224
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend18
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/peci/peci-pcie_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libpldm-intel_git.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-wrapper.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpwplus.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/nvmemi-daemon.bb6
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pldmd.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pmci-launcher.bb2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/telemetry/telemetry_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend2
-rwxr-xr-xmeta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend2
-rw-r--r--meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample2
-rw-r--r--meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample2
37 files changed, 2847 insertions, 384 deletions
diff --git a/meta-openbmc-mods/conf/layer.conf b/meta-openbmc-mods/conf/layer.conf
index 1f69c2c1c..fc30a04ef 100644
--- a/meta-openbmc-mods/conf/layer.conf
+++ b/meta-openbmc-mods/conf/layer.conf
@@ -17,6 +17,6 @@ USERADDEXTENSION = "useradd-staticids"
USERADD_UID_TABLES = "files/passwd"
USERADD_GID_TABLES = "files/group"
-LAYER_CONF_VERSION = "13"
+LAYER_CONF_VERSION = "14"
INTELBASE = '${@os.path.normpath("${LAYERDIR}/")}'
diff --git a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
index 18ab8cb9f..ead001a7c 100644
--- a/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-core/interfaces/libmctp_git.bb
@@ -2,7 +2,7 @@ SUMMARY = "libmctp"
DESCRIPTION = "Implementation of MCTP (DTMF DSP0236)"
SRC_URI = "git://github.com/openbmc/libmctp.git"
-SRCREV = "e889b19f4b349cd5c4ff186ff3c3b604c8f9c7b6"
+SRCREV = "eba19a3b122a39ef2b5dbda49b418a202f78a48d"
PV = "0.1+git${SRCPV}"
diff --git a/meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb b/meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb
index d6de78175..d8bfc68c0 100644
--- a/meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb
+++ b/meta-openbmc-mods/meta-common/recipes-core/safec/safec_3.4.bb
@@ -7,7 +7,7 @@ SECTION = "lib"
inherit autotools pkgconfig
S = "${WORKDIR}/git"
-SRCREV = "0234bec46da4863f849f100c2f5336412ab2f69b"
+SRCREV = "a4abce065446410d137cece7cd017ff80251713d"
SRC_URI = "git://github.com/rurban/safeclib.git"
COMPATIBLE_HOST = '(x86_64|i.86|powerpc|powerpc64|arm|aarch64).*-linux'
diff --git a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend
index 6b769b941..f89a2fbb0 100644
--- a/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-intel/intel-pfr/pfr-manager_%.bbappend
@@ -1,5 +1,5 @@
# Enable downstream autobump
SRC_URI = "git://github.com/openbmc/pfr-manager"
-SRCREV = "00acaffb3840d019bf0853d1ee93fdde947f47d2"
+SRCREV = "2dfaf507da581ed4c71d41c02976e4efafc1d634"
DEPENDS += " libgpiod \
"
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
index 7e79ac14b..4af0acc49 100644
--- a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed_%.bbappend
@@ -4,7 +4,7 @@ KBRANCH = "dev-5.10-intel"
KSRC = "git://github.com/Intel-BMC/linux;protocol=ssh;branch=${KBRANCH}"
# Include this as a comment only for downstream auto-bump
# SRC_URI = "git://github.com/Intel-BMC/linux;protocol=ssh;branch=dev-5.10-intel"
-SRCREV="e51019aa5cea44aa55b922261df9c7c7a4e5bcbc"
+SRCREV="807fd9e1636097ca70957a3ff373bd1280737e46"
do_compile_prepend(){
# device tree compiler flags
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
index 7e25bb26e..d988b7c93 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/fans/phosphor-pid-control_%.bbappend
@@ -4,7 +4,7 @@ inherit obmc-phosphor-systemd
SYSTEMD_SERVICE_${PN} = "phosphor-pid-control.service"
EXTRA_OECONF = "--enable-configure-dbus=yes"
-SRC_URI = "git://github.com/openbmc/phosphor-pid-control.git;nobranch=1"
-SRCREV = "1277543ac599de45d15db99d15bd0e89d3653c9b"
+SRC_URI = "git://github.com/openbmc/phosphor-pid-control.git"
+SRCREV = "d11a732a802cc281f4c1583275871fbc5f5ecced"
FILES_${PN} = "${bindir}/swampd ${bindir}/setsensor"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_git.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_git.bbappend
index ed48da4c0..a294ac520 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_git.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/host/phosphor-host-postd_git.bbappend
@@ -1,4 +1,4 @@
DEPENDS += " gtest"
#SRC_URI = "git://github.com/openbmc/phosphor-host-postd.git"
-SRCREV = "ba5258f7158e8a0e61043290aff0873358509158"
+SRCREV = "e2abf4429059b7ee3f90cc07f233a66b3022a176"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0038-Revert-Disable-nbd-proxy-from-the-build.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0038-Revert-Disable-nbd-proxy-from-the-build.patch
new file mode 100644
index 000000000..3e3f69d1c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0038-Revert-Disable-nbd-proxy-from-the-build.patch
@@ -0,0 +1,50 @@
+From 95f002dc969d7d6d64dbf2ee0db7dc1c1c6a9173 Mon Sep 17 00:00:00 2001
+From: Przemyslaw Czarnowski <przemyslaw.hawrylewicz.czarnowski@intel.com>
+Date: Thu, 18 Mar 2021 11:30:28 +0100
+Subject: [PATCH] Revert "Disable nbd proxy from the build"
+
+NBD Proxy has been disabled upstream. Reenable as we use it for Virtual
+Media
+
+This reverts commit efb8062c306474942bc94f15d748b2eb0b58fbb6.
+---
+ meson.build | 2 +-
+ meson_options.txt | 9 +--------
+ 2 files changed, 2 insertions(+), 9 deletions(-)
+
+diff --git a/meson.build b/meson.build
+index 66a066b..cef0a49 100644
+--- a/meson.build
++++ b/meson.build
+@@ -81,7 +81,7 @@ feature_map = {
+ 'static-hosting' : '-DBMCWEB_ENABLE_STATIC_HOSTING',
+ 'insecure-tftp-update' : '-DBMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE',
+ 'validate-unsecure-feature' : '-DBMCWEB_ENABLE_VALIDATION_UNSECURE_FEATURE',
+-#'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY',
++'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY',
+ 'vm-websocket' : '-DBMCWEB_ENABLE_VM_WEBSOCKET',
+ }
+
+diff --git a/meson_options.txt b/meson_options.txt
+index 9611631..7ee3ebb 100644
+--- a/meson_options.txt
++++ b/meson_options.txt
+@@ -3,14 +3,7 @@ option('yocto-deps', type: 'feature', value: 'disabled', description : 'Use YOCT
+ option('kvm', type : 'feature',value : 'enabled', description : 'Enable the KVM host video WebSocket. Path is \'/kvm/0\'. Video is from the BMC\'s \'/dev/video\' device.')
+ option ('tests', type : 'feature', value : 'enabled', description : 'Enable Unit tests for bmcweb')
+ option('vm-websocket', type : 'feature', value : 'enabled', description : '''Enable the Virtual Media WebSocket. Path is \'/vm/0/0\'to open the websocket. See https://github.com/openbmc/jsnbd/blob/master/README.''')
+-
+-# if you use this option and are seeing this comment, please comment here:
+-# https://github.com/openbmc/bmcweb/issues/188 and put forward your intentions
+-# for this code. At this point, no daemon has been upstreamed that implements
+-# this interface, so for the moment this appears to be dead code; In leiu of
+-# removing it, it has been disabled to try to give those that use it the
+-# opportunity to upstream their backend implementation
+-#option('vm-nbdproxy', type: 'feature', value : 'disabled', description : 'Enable the Virtual Media WebSocket.')
++option('vm-nbdproxy', type: 'feature', value : 'disabled', description : 'Enable the Virtual Media WebSocket.')
+ option('rest', type : 'feature', value : 'enabled', description : '''Enable Phosphor REST (D-Bus) APIs. Paths directly map Phosphor D-Bus object paths, for example, \'/xyz/openbmc_project/logging/entry/enumerate\'. See https://github.com/openbmc/docs/blob/master/rest-api.md.''')
+ option('redfish', type : 'feature',value : 'enabled', description: 'Enable Redfish APIs. Paths are under \'/redfish/v1/\'. See https://github.com/openbmc/bmcweb/blob/master/DEVELOPING.md#redfish.')
+ option('host-serial-socket', type : 'feature', value : 'enabled', description : 'Enable host serial console WebSocket. Path is \'/console0\'. See https://github.com/openbmc/docs/blob/master/console.md.')
+--
+2.26.2
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch
new file mode 100644
index 000000000..b46d30149
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch
@@ -0,0 +1,543 @@
+From ae55e89c14ea5abef0895409c956f5f4c38f330f Mon Sep 17 00:00:00 2001
+From: Sunitha Harish <sunithaharish04@gmail.com>
+Date: Fri, 19 Feb 2021 13:38:31 +0530
+Subject: [PATCH 1/2] EventService : Fix retry handling for http-client
+
+When the event send/receive is failed, the bmcweb does not handle
+the failure to tear-down the complete connection and start a fresh
+
+The keep-alive header from the event listener is read to update
+the connection states, so that the connection will be kept alive
+or closed as per the subscriber's specifications
+
+Updated the connection state machine to handle retry logic properly.
+Avoided multiple simultaneous async calls which crashes the bmcweb. So
+added connBusy flag which protects simultaneous async calls.
+
+Used boost http response parser as parser for producing the response
+message. Set the parser skip option to handle the empty response message
+from listening server.
+
+Tested by:
+ - Subscribe for the events at BMC using DMTF event listener
+ - Generate an event and see the same is received at the listener's console
+ - Update the listner to change the keep-alive to true/false and
+ observe the http-client connection states at bmcweb
+
+Change-Id: Ibb45691f139916ba2954da37beda9d4f91c7cef3
+Signed-off-by: Sunitha Harish <sunithaharish04@gmail.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ http/http_client.hpp | 289 ++++++++++--------
+ .../include/event_service_manager.hpp | 2 +-
+ 2 files changed, 163 insertions(+), 128 deletions(-)
+
+diff --git a/http/http_client.hpp b/http/http_client.hpp
+index 992ac2b..d116f6d 100644
+--- a/http/http_client.hpp
++++ b/http/http_client.hpp
+@@ -34,22 +34,28 @@ namespace crow
+ {
+
+ static constexpr uint8_t maxRequestQueueSize = 50;
++static constexpr unsigned int httpReadBodyLimit = 8192;
+
+ enum class ConnState
+ {
+ initialized,
+ resolveInProgress,
+ resolveFailed,
++ resolved,
+ connectInProgress,
+ connectFailed,
+ connected,
+ sendInProgress,
+ sendFailed,
++ recvInProgress,
+ recvFailed,
+ idle,
+- suspended,
++ closeInProgress,
+ closed,
+- terminated
++ suspended,
++ terminated,
++ abortConnection,
++ retry
+ };
+
+ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -58,11 +64,14 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ crow::async_resolve::Resolver resolver;
+ boost::beast::tcp_stream conn;
+ boost::asio::steady_timer timer;
+- boost::beast::flat_buffer buffer;
++ boost::beast::flat_static_buffer<httpReadBodyLimit> buffer;
+ boost::beast::http::request<boost::beast::http::string_body> req;
+- boost::beast::http::response<boost::beast::http::string_body> res;
+- std::vector<std::pair<std::string, std::string>> headers;
+- std::queue<std::string> requestDataQueue;
++ std::optional<
++ boost::beast::http::response_parser<boost::beast::http::string_body>>
++ parser;
++ boost::asio::ip::tcp::endpoint endpoint;
++ boost::circular_buffer_space_optimized<std::string> requestDataQueue{};
++ std::vector<boost::asio::ip::tcp::endpoint> endPoints;
+ ConnState state;
+ std::string subId;
+ std::string host;
+@@ -76,12 +85,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+
+ void doResolve()
+ {
+- if (state == ConnState::resolveInProgress)
+- {
+- return;
+- }
+ state = ConnState::resolveInProgress;
+-
+ BMCWEB_LOG_DEBUG << "Trying to resolve: " << host << ":" << port;
+
+ auto respHandler =
+@@ -89,78 +93,56 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ const boost::beast::error_code ec,
+ const std::vector<boost::asio::ip::tcp::endpoint>&
+ endpointList) {
+- if (ec)
++ if (ec || (endpointList.size() == 0))
+ {
+ BMCWEB_LOG_ERROR << "Resolve failed: " << ec.message();
+ self->state = ConnState::resolveFailed;
+- self->checkQueue();
++ self->handleConnState();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Resolved";
+- self->doConnect(endpointList);
++ self->endPoints.assign(endpointList.begin(),
++ endpointList.end());
++ self->state = ConnState::resolved;
++ self->handleConnState();
+ };
+ resolver.asyncResolve(host, port, std::move(respHandler));
+ }
+
+- void doConnect(
+- const std::vector<boost::asio::ip::tcp::endpoint>& endpointList)
++ void doConnect()
+ {
+- if (state == ConnState::connectInProgress)
+- {
+- return;
+- }
+ state = ConnState::connectInProgress;
+
+ BMCWEB_LOG_DEBUG << "Trying to connect to: " << host << ":" << port;
+
+ conn.expires_after(std::chrono::seconds(30));
+ conn.async_connect(
+- endpointList, [self(shared_from_this())](
+- const boost::beast::error_code ec,
+- const boost::asio::ip::tcp::endpoint& endpoint) {
++ endPoints, [self(shared_from_this())](
++ const boost::beast::error_code ec,
++ const boost::asio::ip::tcp::endpoint& endpoint) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "Connect " << endpoint
+ << " failed: " << ec.message();
+ self->state = ConnState::connectFailed;
+- self->checkQueue();
++ self->handleConnState();
+ return;
+ }
+- self->state = ConnState::connected;
+ BMCWEB_LOG_DEBUG << "Connected to: " << endpoint;
+-
+- self->checkQueue();
++ self->state = ConnState::connected;
++ self->handleConnState();
+ });
+ }
+
+ void sendMessage(const std::string& data)
+ {
+- if (state == ConnState::sendInProgress)
+- {
+- return;
+- }
+ state = ConnState::sendInProgress;
+
+ BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port;
+
+- req.version(static_cast<int>(11)); // HTTP 1.1
+- req.target(uri);
+- req.method(boost::beast::http::verb::post);
+-
+- // Set headers
+- for (const auto& [key, value] : headers)
+- {
+- req.set(key, value);
+- }
+- req.set(boost::beast::http::field::host, host);
+- req.keep_alive(true);
+-
+ req.body() = data;
+ req.prepare_payload();
+
+- // Set a timeout on the operation
+- conn.expires_after(std::chrono::seconds(30));
+-
+ // Send the HTTP request to the remote host
+ boost::beast::http::async_write(
+ conn, req,
+@@ -171,7 +153,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ BMCWEB_LOG_ERROR << "sendMessage() failed: "
+ << ec.message();
+ self->state = ConnState::sendFailed;
+- self->checkQueue();
++ self->handleConnState();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
+@@ -184,9 +166,18 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+
+ void recvMessage()
+ {
++ state = ConnState::recvInProgress;
++
++ parser.emplace(std::piecewise_construct, std::make_tuple());
++ parser->body_limit(httpReadBodyLimit);
++ // Since these are all push style eventing, we are not
++ // bothered about response body parsing.
++ // Check only for the response header
++ parser->skip(true);
++
+ // Receive the HTTP response
+ boost::beast::http::async_read(
+- conn, buffer, res,
++ conn, buffer, *parser,
+ [self(shared_from_this())](const boost::beast::error_code& ec,
+ const std::size_t& bytesTransferred) {
+ if (ec)
+@@ -194,30 +185,46 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ BMCWEB_LOG_ERROR << "recvMessage() failed: "
+ << ec.message();
+ self->state = ConnState::recvFailed;
+- self->checkQueue();
++ self->handleConnState();
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
+ << bytesTransferred;
+- boost::ignore_unused(bytesTransferred);
+-
+- // Discard received data. We are not interested.
+- BMCWEB_LOG_DEBUG << "recvMessage() data: " << self->res;
++ BMCWEB_LOG_DEBUG << "recvMessage() data: "
++ << self->parser->get();
+
+ // Send is successful, Lets remove data from queue
+ // check for next request data in queue.
+- self->requestDataQueue.pop();
++ if (!self->requestDataQueue.empty())
++ {
++ self->requestDataQueue.pop_front();
++ }
+ self->state = ConnState::idle;
+- self->checkQueue();
++
++ // Keep the connection alive if server supports it
++ // Else close the connection
++ BMCWEB_LOG_DEBUG << "recvMessage() keepalive : "
++ << self->parser->keep_alive();
++ if (!self->parser->keep_alive())
++ {
++ // Abort the connection since server is not keep-alive
++ // enabled
++ self->state = ConnState::abortConnection;
++ }
++ // Transfer ownership of the response
++ self->parser->release();
++
++ self->handleConnState();
+ });
+ }
+
+ void doClose()
+ {
++ state = ConnState::closeInProgress;
+ boost::beast::error_code ec;
+ conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
++ conn.close();
+
+- state = ConnState::closed;
+ // not_connected happens sometimes so don't bother reporting it.
+ if (ec && ec != boost::beast::errc::not_connected)
+ {
+@@ -225,112 +232,139 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Connection closed gracefully";
+- }
+-
+- void checkQueue(const bool newRecord = false)
+- {
+- if (requestDataQueue.empty())
++ if ((state != ConnState::suspended) && (state != ConnState::terminated))
+ {
+- // TODO: Having issue in keeping connection alive. So lets close if
+- // nothing to be transferred.
+- doClose();
+-
+- BMCWEB_LOG_DEBUG << "requestDataQueue is empty\n";
+- return;
++ state = ConnState::closed;
++ handleConnState();
+ }
++ }
+
++ void waitAndRetry()
++ {
+ if (retryCount >= maxRetryAttempts)
+ {
+- BMCWEB_LOG_ERROR << "Maximum number of retries is reached.";
++ BMCWEB_LOG_ERROR << "Maximum number of retries reached.";
+
+ // Clear queue.
+ while (!requestDataQueue.empty())
+ {
+- requestDataQueue.pop();
++ requestDataQueue.pop_front();
+ }
+
+- BMCWEB_LOG_DEBUG << "Retry policy is set to " << retryPolicyAction;
++ BMCWEB_LOG_DEBUG << "Retry policy: " << retryPolicyAction;
+ if (retryPolicyAction == "TerminateAfterRetries")
+ {
+ // TODO: delete subscription
+ state = ConnState::terminated;
+- return;
+ }
+ if (retryPolicyAction == "SuspendRetries")
+ {
+ state = ConnState::suspended;
+- return;
+ }
+- // keep retrying, reset count and continue.
++ // Reset the retrycount to zero so that client can try connecting
++ // again if needed
+ retryCount = 0;
++ handleConnState();
++ return;
+ }
+
+- if ((state == ConnState::connectFailed) ||
+- (state == ConnState::sendFailed) ||
+- (state == ConnState::recvFailed))
++ if (runningTimer)
+ {
+- if (newRecord)
+- {
+- // We are already running async wait and retry.
+- // Since record is added to queue, it gets the
+- // turn in FIFO.
+- return;
+- }
+-
+- if (runningTimer)
+- {
+- BMCWEB_LOG_DEBUG << "Retry timer is already running.";
+- return;
+- }
+- runningTimer = true;
+-
+- retryCount++;
+-
+- BMCWEB_LOG_DEBUG << "Attempt retry after " << retryIntervalSecs
+- << " seconds. RetryCount = " << retryCount;
+- timer.expires_after(std::chrono::seconds(retryIntervalSecs));
+- timer.async_wait(
+- [self = shared_from_this()](const boost::system::error_code&) {
+- self->runningTimer = false;
+- self->connStateCheck();
+- });
++ BMCWEB_LOG_DEBUG << "Retry timer is already running.";
+ return;
+ }
+- // reset retry count.
+- retryCount = 0;
+- connStateCheck();
++ runningTimer = true;
+
++ retryCount++;
++
++ BMCWEB_LOG_DEBUG << "Attempt retry after " << retryIntervalSecs
++ << " seconds. RetryCount = " << retryCount;
++ timer.expires_after(std::chrono::seconds(retryIntervalSecs));
++ timer.async_wait(
++ [self = shared_from_this()](const boost::system::error_code ec) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "async_wait failed: " << ec.message();
++ // Ignore the error and continue the retry loop to attempt
++ // sending the event as per the retry policy
++ }
++ self->runningTimer = false;
++
++ // Lets close connection and start from resolve.
++ self->doClose();
++ });
+ return;
+ }
+
+- void connStateCheck()
++ void handleConnState()
+ {
+ switch (state)
+ {
+ case ConnState::resolveInProgress:
+ case ConnState::connectInProgress:
+ case ConnState::sendInProgress:
+- case ConnState::suspended:
+- case ConnState::terminated:
+- // do nothing
++ case ConnState::recvInProgress:
++ case ConnState::closeInProgress:
++ {
++ BMCWEB_LOG_DEBUG << "Async operation is already in progress";
+ break;
++ }
+ case ConnState::initialized:
+ case ConnState::closed:
++ {
++ if (requestDataQueue.empty())
++ {
++ BMCWEB_LOG_DEBUG << "requestDataQueue is empty";
++ return;
++ }
++ doResolve();
++ break;
++ }
++ case ConnState::resolved:
++ {
++ doConnect();
++ break;
++ }
++ case ConnState::suspended:
++ case ConnState::terminated:
++ {
++ doClose();
++ break;
++ }
++ case ConnState::resolveFailed:
+ case ConnState::connectFailed:
+ case ConnState::sendFailed:
+ case ConnState::recvFailed:
+- case ConnState::resolveFailed:
++ case ConnState::retry:
+ {
+- doResolve();
++ // In case of failures during connect and handshake
++ // the retry policy will be applied
++ waitAndRetry();
+ break;
+ }
+ case ConnState::connected:
+ case ConnState::idle:
+ {
++ // State idle means, previous attempt is successful
++ // State connected means, client connection is established
++ // successfully
++ if (requestDataQueue.empty())
++ {
++ BMCWEB_LOG_DEBUG << "requestDataQueue is empty";
++ return;
++ }
+ std::string data = requestDataQueue.front();
+ sendMessage(data);
+ break;
+ }
++ case ConnState::abortConnection:
++ {
++ // Server did not want to keep alive the session
++ doClose();
++ break;
++ }
++ default:
++ break;
+ }
+ }
+
+@@ -339,37 +373,38 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ const std::string& destIP, const std::string& destPort,
+ const std::string& destUri) :
+ conn(ioc),
+- timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
+- retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0),
++ timer(ioc), req(boost::beast::http::verb::post, destUri, 11),
++ state(ConnState::initialized), subId(id), host(destIP), port(destPort),
++ uri(destUri), retryCount(0), maxRetryAttempts(5), retryIntervalSecs(0),
+ retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
+ {
+- state = ConnState::initialized;
++ // Set the request header
++ req.set(boost::beast::http::field::host, host);
++ req.set(boost::beast::http::field::content_type, "application/json");
++ req.keep_alive(true);
++
++ requestDataQueue.set_capacity(maxRequestQueueSize);
+ }
+
+ void sendData(const std::string& data)
+ {
+- if (state == ConnState::suspended)
++ if ((state == ConnState::suspended) || (state == ConnState::terminated))
+ {
+ return;
+ }
+-
+- if (requestDataQueue.size() <= maxRequestQueueSize)
+- {
+- requestDataQueue.push(data);
+- checkQueue(true);
+- }
+- else
+- {
+- BMCWEB_LOG_ERROR << "Request queue is full. So ignoring data.";
+- }
+-
++ requestDataQueue.push_back(data);
++ handleConnState();
+ return;
+ }
+
+- void setHeaders(
++ void addHeaders(
+ const std::vector<std::pair<std::string, std::string>>& httpHeaders)
+ {
+- headers = httpHeaders;
++ // Set custom headers
++ for (const auto& [key, value] : httpHeaders)
++ {
++ req.set(key, value);
++ }
+ }
+
+ void setRetryConfig(const uint32_t retryAttempts,
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 148c703..bffa68f 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -412,7 +412,7 @@ class Subscription
+ reqHeaders.emplace_back(std::pair(key, val));
+ }
+ }
+- conn->setHeaders(reqHeaders);
++ conn->addHeaders(reqHeaders);
+ conn->sendData(msg);
+ this->eventSeqNum++;
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch
new file mode 100644
index 000000000..b1f61c6fd
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0002-EventService-https-client-support.patch
@@ -0,0 +1,401 @@
+From 579fda953ec991b4e7f9d7194b08f6aa103fa0ec Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 22 Feb 2021 17:07:47 +0000
+Subject: [PATCH 2/2] EventService: https client support
+
+Add https client support for push style
+eventing. Using this BMC can push the event
+logs/telemetry data to event listener over
+secure http channel.
+
+Tested:
+ - Created subscription with https destination
+ url. Using SubmitTestEvent action set the
+ event and can see event on event listener.
+ - Validator passed.
+
+Change-Id: I44c3918b39baa2eb5fddda9d635f99aa280a422a
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ http/http_client.hpp | 255 ++++++++++++------
+ .../include/event_service_manager.hpp | 2 +-
+ 2 files changed, 175 insertions(+), 82 deletions(-)
+
+diff --git a/http/http_client.hpp b/http/http_client.hpp
+index d116f6d..cebc857 100644
+--- a/http/http_client.hpp
++++ b/http/http_client.hpp
+@@ -20,6 +20,7 @@
+ #include <boost/beast/core/flat_buffer.hpp>
+ #include <boost/beast/core/tcp_stream.hpp>
+ #include <boost/beast/http/message.hpp>
++#include <boost/beast/ssl/ssl_stream.hpp>
+ #include <boost/beast/version.hpp>
+ #include <include/async_resolve.hpp>
+
+@@ -44,6 +45,8 @@ enum class ConnState
+ resolved,
+ connectInProgress,
+ connectFailed,
++ handshakeInProgress,
++ handshakeFailed,
+ connected,
+ sendInProgress,
+ sendFailed,
+@@ -62,7 +65,9 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ {
+ private:
+ crow::async_resolve::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;
+ boost::asio::steady_timer timer;
+ boost::beast::flat_static_buffer<httpReadBodyLimit> buffer;
+ boost::beast::http::request<boost::beast::http::string_body> req;
+@@ -112,23 +117,52 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ void doConnect()
+ {
+ state = ConnState::connectInProgress;
++ sslConn.emplace(conn, ctx);
+
+ BMCWEB_LOG_DEBUG << "Trying to connect to: " << host << ":" << port;
++ auto respHandler = [self(shared_from_this())](
++ const boost::beast::error_code ec,
++ const boost::asio::ip::tcp::endpoint& endpoint) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "Connect " << endpoint
++ << " failed: " << ec.message();
++ self->state = ConnState::connectFailed;
++ self->handleConnState();
++ return;
++ }
+
++ BMCWEB_LOG_DEBUG << "Connected to: " << endpoint;
++ if (self->sslConn)
++ {
++ self->performHandshake();
++ }
++ else
++ {
++ self->handleConnState();
++ }
++ };
+ conn.expires_after(std::chrono::seconds(30));
+- conn.async_connect(
+- endPoints, [self(shared_from_this())](
+- const boost::beast::error_code ec,
+- const boost::asio::ip::tcp::endpoint& endpoint) {
++ conn.async_connect(endPoints, std::move(respHandler));
++ }
++
++ void performHandshake()
++ {
++ state = ConnState::handshakeInProgress;
++
++ sslConn->async_handshake(
++ boost::asio::ssl::stream_base::client,
++ [self(shared_from_this())](const boost::beast::error_code ec) {
+ if (ec)
+ {
+- BMCWEB_LOG_ERROR << "Connect " << endpoint
+- << " failed: " << ec.message();
+- self->state = ConnState::connectFailed;
++ BMCWEB_LOG_ERROR << "SSL handshake failed: "
++ << ec.message();
++ self->state = ConnState::handshakeFailed;
+ self->handleConnState();
+ return;
+ }
+- BMCWEB_LOG_DEBUG << "Connected to: " << endpoint;
++
++ BMCWEB_LOG_DEBUG << "SSL Handshake successfull";
+ self->state = ConnState::connected;
+ self->handleConnState();
+ });
+@@ -136,106 +170,159 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+
+ void sendMessage(const std::string& data)
+ {
+- state = ConnState::sendInProgress;
+-
+ BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port;
++ state = ConnState::sendInProgress;
+
+ req.body() = data;
+ req.prepare_payload();
+
+- // Send the HTTP request to the remote host
+- boost::beast::http::async_write(
+- conn, req,
+- [self(shared_from_this())](const boost::beast::error_code& ec,
+- const std::size_t& bytesTransferred) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "sendMessage() failed: "
+- << ec.message();
+- self->state = ConnState::sendFailed;
+- self->handleConnState();
+- return;
+- }
+- BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
+- << bytesTransferred;
+- boost::ignore_unused(bytesTransferred);
++ auto respHandler = [self(shared_from_this())](
++ const boost::beast::error_code ec,
++ const std::size_t& bytesTransferred) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "sendMessage() failed: " << ec.message();
++ self->state = ConnState::sendFailed;
++ self->handleConnState();
++ return;
++ }
+
+- self->recvMessage();
+- });
+- }
++ BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
++ << bytesTransferred;
++ boost::ignore_unused(bytesTransferred);
++ self->recvMessage();
++ };
+
++ conn.expires_after(std::chrono::seconds(30));
++ if (sslConn)
++ {
++ boost::beast::http::async_write(*sslConn, req,
++ std::move(respHandler));
++ }
++ else
++ {
++ boost::beast::http::async_write(conn, req, std::move(respHandler));
++ }
++ }
+ void recvMessage()
+ {
+ state = ConnState::recvInProgress;
+
++ auto respHandler = [self(shared_from_this())](
++ const boost::beast::error_code ec,
++ const std::size_t& bytesTransferred) {
++ if (ec && ec != boost::asio::ssl::error::stream_truncated)
++ {
++ BMCWEB_LOG_ERROR << "recvMessage() failed: " << ec.message();
++
++ self->state = ConnState::recvFailed;
++ self->handleConnState();
++ return;
++ }
++
++ BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
++ << bytesTransferred;
++ boost::ignore_unused(bytesTransferred);
++ // Send is successful, Lets remove data from queue
++ // check for next request data in queue.
++ if (!self->requestDataQueue.empty())
++ {
++ self->requestDataQueue.pop_front();
++ }
++ self->state = ConnState::idle;
++ // Keep the connection alive if server supports it
++ // Else close the connection
++ BMCWEB_LOG_DEBUG << "recvMessage() keepalive : "
++ << self->parser->keep_alive();
++ if (!self->parser->keep_alive())
++ {
++ // Abort the connection since server is not keep-alive enabled
++ self->state = ConnState::abortConnection;
++ }
++ // Transfer ownership of the response
++ self->parser->release();
++
++ self->handleConnState();
++ };
+ parser.emplace(std::piecewise_construct, std::make_tuple());
+ parser->body_limit(httpReadBodyLimit);
+ // Since these are all push style eventing, we are not
+ // bothered about response body parsing.
+ // Check only for the response header
+ parser->skip(true);
++ conn.expires_after(std::chrono::seconds(30));
++ if (sslConn)
++ {
++ boost::beast::http::async_read(*sslConn, buffer, *parser,
++ std::move(respHandler));
++ }
++ else
++ {
++ boost::beast::http::async_read(conn, buffer, *parser,
++ std::move(respHandler));
++ }
++ }
++ void doClose()
++ {
++ state = ConnState::closeInProgress;
+
+- // Receive the HTTP response
+- boost::beast::http::async_read(
+- conn, buffer, *parser,
+- [self(shared_from_this())](const boost::beast::error_code& ec,
+- const std::size_t& bytesTransferred) {
++ // Set the timeout on the tcp stream socket for the async operation
++ conn.expires_after(std::chrono::seconds(30));
++ if (sslConn)
++ {
++ sslConn->async_shutdown([self = shared_from_this()](
++ const boost::system::error_code ec) {
+ if (ec)
+ {
+- BMCWEB_LOG_ERROR << "recvMessage() failed: "
+- << ec.message();
+- self->state = ConnState::recvFailed;
+- self->handleConnState();
+- return;
++ // Many https server closes connection abruptly
++ // i.e witnout close_notify. More details are at
++ // https://github.com/boostorg/beast/issues/824
++ if (ec == boost::asio::ssl::error::stream_truncated)
++ {
++ BMCWEB_LOG_INFO << "doClose(): Connection "
++ "closed by server. ";
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "doClose() failed: "
++ << ec.message();
++ }
+ }
+- BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
+- << bytesTransferred;
+- BMCWEB_LOG_DEBUG << "recvMessage() data: "
+- << self->parser->get();
+-
+- // Send is successful, Lets remove data from queue
+- // check for next request data in queue.
+- if (!self->requestDataQueue.empty())
++ else
+ {
+- self->requestDataQueue.pop_front();
++ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
+ }
+- self->state = ConnState::idle;
++ self->conn.close();
+
+- // Keep the connection alive if server supports it
+- // Else close the connection
+- BMCWEB_LOG_DEBUG << "recvMessage() keepalive : "
+- << self->parser->keep_alive();
+- if (!self->parser->keep_alive())
++ if ((self->state != ConnState::suspended) &&
++ (self->state != ConnState::terminated))
+ {
+- // Abort the connection since server is not keep-alive
+- // enabled
+- self->state = ConnState::abortConnection;
++ self->state = ConnState::closed;
++ self->handleConnState();
+ }
+- // Transfer ownership of the response
+- self->parser->release();
+-
+- self->handleConnState();
+ });
+- }
+-
+- void doClose()
+- {
+- state = ConnState::closeInProgress;
+- boost::beast::error_code ec;
+- conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
+- conn.close();
+-
+- // not_connected happens sometimes so don't bother reporting it.
+- if (ec && ec != boost::beast::errc::not_connected)
+- {
+- BMCWEB_LOG_ERROR << "shutdown failed: " << ec.message();
+- return;
+ }
+- BMCWEB_LOG_DEBUG << "Connection closed gracefully";
+- if ((state != ConnState::suspended) && (state != ConnState::terminated))
++ else
+ {
+- state = ConnState::closed;
+- handleConnState();
++ boost::beast::error_code ec;
++ conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
++ ec);
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "doClose() failed: " << ec.message();
++ }
++ else
++ {
++ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
++ }
++ conn.close();
++
++ if ((state != ConnState::suspended) &&
++ (state != ConnState::terminated))
++ {
++ state = ConnState::closed;
++ handleConnState();
++ }
+ }
+ }
+
+@@ -302,6 +389,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ {
+ case ConnState::resolveInProgress:
+ case ConnState::connectInProgress:
++ case ConnState::handshakeInProgress:
+ case ConnState::sendInProgress:
+ case ConnState::recvInProgress:
+ case ConnState::closeInProgress:
+@@ -333,6 +421,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
+ case ConnState::resolveFailed:
+ case ConnState::connectFailed:
++ case ConnState::handshakeFailed:
+ case ConnState::sendFailed:
+ case ConnState::recvFailed:
+ case ConnState::retry:
+@@ -371,7 +460,8 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ public:
+ explicit HttpClient(boost::asio::io_context& ioc, const std::string& id,
+ const std::string& destIP, const std::string& destPort,
+- const std::string& destUri) :
++ const std::string& destUri,
++ const std::string& uriProto) :
+ conn(ioc),
+ timer(ioc), req(boost::beast::http::verb::post, destUri, 11),
+ state(ConnState::initialized), subId(id), host(destIP), port(destPort),
+@@ -384,8 +474,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ req.keep_alive(true);
+
+ requestDataQueue.set_capacity(maxRequestQueueSize);
++ if (uriProto == "https")
++ {
++ sslConn.emplace(conn, ctx);
++ }
+ }
+-
+ void sendData(const std::string& data)
+ {
+ if ((state == ConnState::suspended) || (state == ConnState::terminated))
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index bffa68f..1e6f496 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -387,7 +387,7 @@ class Subscription
+ {
+ conn = std::make_shared<crow::HttpClient>(
+ crow::connections::systemBus->get_io_context(), id, host, port,
+- path);
++ path, uriProto);
+ }
+
+ Subscription(const std::shared_ptr<boost::beast::tcp_stream>& adaptor) :
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0003-Move-EventService-init-to-later-stage.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0003-Move-EventService-init-to-later-stage.patch
new file mode 100644
index 000000000..f910915ce
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0003-Move-EventService-init-to-later-stage.patch
@@ -0,0 +1,50 @@
+From 2dcfef0170ca5ba1f934de6934db64b545ab3b55 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 23 Mar 2021 23:36:40 +0000
+Subject: [PATCH] Move EventService init to later stage
+
+The bmcweb crash issue seen when there is eventservice
+config with subscriptions in persistent file.
+
+During EventService instantiation, it uses the "get_io_context()"
+from systemBus, so it should be called after systemBus init. So
+moved the EventService instantiation after systemBus initialization.
+
+Tested:
+ - bmcweb crash issue resolved.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: Iab52f0e89478e306af475066fb5691153a05677d
+---
+ src/webserver_main.cpp | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
+index 3b9631a..f0e2207 100644
+--- a/src/webserver_main.cpp
++++ b/src/webserver_main.cpp
+@@ -80,9 +80,6 @@ int main(int /*argc*/, char** /*argv*/)
+ #ifdef BMCWEB_ENABLE_REDFISH
+ crow::redfish::requestRoutes(app);
+ redfish::RedfishService redfish(app);
+-
+- // Create EventServiceManager instance and initialize Config
+- redfish::EventServiceManager::getInstance();
+ #endif
+
+ #ifdef BMCWEB_ENABLE_DBUS_REST
+@@ -116,6 +113,11 @@ int main(int /*argc*/, char** /*argv*/)
+ crow::connections::systemBus =
+ std::make_shared<sdbusplus::asio::connection>(*io);
+
++#ifdef BMCWEB_ENABLE_REDFISH
++ // Create EventServiceManager instance and initialize Config
++ redfish::EventServiceManager::getInstance();
++#endif
++
+ #ifdef BMCWEB_ENABLE_VM_NBDPROXY
+ crow::nbd_proxy::requestRoutes(app);
+ #endif
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch
new file mode 100644
index 000000000..0d31fbc72
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0004-Add-Server-Sent-Events-support.patch
@@ -0,0 +1,477 @@
+From e93a6a02b0fba3371144d474422fadacc3f25fde Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Fri, 12 Mar 2021 18:53:25 +0000
+Subject: [PATCH 4/6] Add Server-Sent-Events support
+
+Server-Sent Events is a standard describing how servers can
+initiate data transmission towards clients once an initial
+client connection has been established. Unlike websockets
+(which are bidirectional), Server-Sent Events are
+unidirectional and commonly used to send message updates or
+continuous data streams to a browser client.
+
+This is base patch for adding Server-Sent events support to
+bmcweb. Redfish eventservice SSE style subscription uses
+this and will be loaded on top of this commit.
+
+Tested:
+ - Tested using follow-up patch on top which adds
+ support for Redfish EventService SSE style subscription
+ and observed events are getting sent periodically.
+
+Change-Id: I36956565cbba30c2007852c9471f477f6d1736e9
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ http/http_connection.hpp | 14 +-
+ http/http_response.hpp | 7 +-
+ http/routing.hpp | 70 ++++++++++
+ http/server_sent_event.hpp | 279 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 364 insertions(+), 6 deletions(-)
+ create mode 100644 http/server_sent_event.hpp
+
+diff --git a/http/http_connection.hpp b/http/http_connection.hpp
+index 4482f8d..2c8bf40 100644
+--- a/http/http_connection.hpp
++++ b/http/http_connection.hpp
+@@ -326,7 +326,7 @@ class Connection :
+ BMCWEB_LOG_INFO << "Request: "
+ << " " << this << " HTTP/" << req->version() / 10 << "."
+ << req->version() % 10 << ' ' << req->methodString()
+- << " " << req->target() << " " << req->ipAddress;
++ << " " << req->url << " " << req->ipAddress;
+
+ needToCallAfterHandlers = false;
+
+@@ -345,11 +345,15 @@ class Connection :
+ boost::asio::post(self->adaptor.get_executor(),
+ [self] { self->completeRequest(); });
+ };
+- if (req->isUpgrade() &&
+- boost::iequals(
+- req->getHeaderValue(boost::beast::http::field::upgrade),
+- "websocket"))
++
++ if ((req->isUpgrade() &&
++ boost::iequals(req->getHeaderValue(
++ boost::beast::http::field::upgrade),
++ "websocket")) ||
++ (req->url == "/sse"))
+ {
++ BMCWEB_LOG_DEBUG << "Request: " << this
++ << " is getting upgraded";
+ handler->handleUpgrade(*req, res, std::move(adaptor));
+ // delete lambda with self shared_ptr
+ // to enable connection destruction
+diff --git a/http/http_response.hpp b/http/http_response.hpp
+index cd00ec8..ffd6dda 100644
+--- a/http/http_response.hpp
++++ b/http/http_response.hpp
+@@ -13,10 +13,15 @@ namespace crow
+ template <typename Adaptor, typename Handler>
+ class Connection;
+
++template <typename Adaptor>
++class SseConnectionImpl;
++
+ struct Response
+ {
+ template <typename Adaptor, typename Handler>
+ friend class crow::Connection;
++ template <typename Adaptor>
++ friend class crow::SseConnectionImpl;
+ using response_type =
+ boost::beast::http::response<boost::beast::http::string_body>;
+
+@@ -136,8 +141,8 @@ struct Response
+
+ private:
+ bool completed{};
+- std::function<void()> completeRequestHandler;
+ std::function<bool()> isAliveHelper;
++ std::function<void()> completeRequestHandler;
+
+ // In case of a JSON object, set the Content-Type header
+ void jsonMode()
+diff --git a/http/routing.hpp b/http/routing.hpp
+index 65c7b70..0824939 100644
+--- a/http/routing.hpp
++++ b/http/routing.hpp
+@@ -6,6 +6,7 @@
+ #include "http_response.hpp"
+ #include "logging.hpp"
+ #include "privileges.hpp"
++#include "server_sent_event.hpp"
+ #include "sessions.hpp"
+ #include "utility.hpp"
+ #include "websocket.hpp"
+@@ -390,6 +391,67 @@ class WebSocketRule : public BaseRule
+ std::function<void(crow::websocket::Connection&)> errorHandler;
+ };
+
++class SseSocketRule : public BaseRule
++{
++ using self_t = SseSocketRule;
++
++ public:
++ SseSocketRule(const std::string& ruleIn) : BaseRule(ruleIn)
++ {}
++
++ void validate() override
++ {}
++
++ void handle(const Request&, Response& res, const RoutingParams&) override
++ {
++ res.result(boost::beast::http::status::not_found);
++ res.end();
++ }
++
++ void handleUpgrade(const Request& req, Response&,
++ boost::asio::ip::tcp::socket&& adaptor) override
++ {
++ std::shared_ptr<crow::SseConnectionImpl<boost::asio::ip::tcp::socket>>
++ myConnection = std::make_shared<
++ crow::SseConnectionImpl<boost::asio::ip::tcp::socket>>(
++ req, std::move(adaptor), openHandler, closeHandler);
++ myConnection->start();
++ }
++#ifdef BMCWEB_ENABLE_SSL
++ void handleUpgrade(const Request& req, Response&,
++ boost::beast::ssl_stream<boost::asio::ip::tcp::socket>&&
++ adaptor) override
++ {
++ std::shared_ptr<crow::SseConnectionImpl<
++ boost::beast::ssl_stream<boost::asio::ip::tcp::socket>>>
++ myConnection = std::make_shared<crow::SseConnectionImpl<
++ boost::beast::ssl_stream<boost::asio::ip::tcp::socket>>>(
++ req, std::move(adaptor), openHandler, closeHandler);
++ myConnection->start();
++ }
++#endif
++
++ template <typename Func>
++ self_t& onopen(Func f)
++ {
++ openHandler = f;
++ return *this;
++ }
++
++ template <typename Func>
++ self_t& onclose(Func f)
++ {
++ closeHandler = f;
++ return *this;
++ }
++
++ private:
++ std::function<void(std::shared_ptr<crow::SseConnection>&,
++ const crow::Request&, crow::Response&)>
++ openHandler;
++ std::function<void(std::shared_ptr<crow::SseConnection>&)> closeHandler;
++};
++
+ template <typename T>
+ struct RuleParameterTraits
+ {
+@@ -402,6 +464,14 @@ struct RuleParameterTraits
+ return *p;
+ }
+
++ SseSocketRule& serverSentEvent()
++ {
++ self_t* self = static_cast<self_t*>(this);
++ SseSocketRule* p = new SseSocketRule(self->rule);
++ self->ruleToUpgrade.reset(p);
++ return *p;
++ }
++
+ self_t& name(const std::string_view name) noexcept
+ {
+ self_t* self = static_cast<self_t*>(this);
+diff --git a/http/server_sent_event.hpp b/http/server_sent_event.hpp
+new file mode 100644
+index 0000000..41d18ed
+--- /dev/null
++++ b/http/server_sent_event.hpp
+@@ -0,0 +1,279 @@
++#pragma once
++#include "http_request.hpp"
++
++#include <boost/algorithm/string/predicate.hpp>
++#include <boost/asio/buffer.hpp>
++#include <boost/beast/http/buffer_body.hpp>
++#include <boost/beast/websocket.hpp>
++
++#include <array>
++#include <functional>
++
++#ifdef BMCWEB_ENABLE_SSL
++#include <boost/beast/websocket/ssl.hpp>
++#endif
++
++namespace crow
++{
++
++struct SseConnection : std::enable_shared_from_this<SseConnection>
++{
++ public:
++ SseConnection(const crow::Request& reqIn) : req(reqIn)
++ {}
++ virtual ~SseConnection() = default;
++
++ virtual boost::asio::io_context& getIoContext() = 0;
++ virtual void sendSSEHeader() = 0;
++ virtual void completeRequest() = 0;
++ virtual void close(const std::string_view msg = "quit") = 0;
++ virtual void sendEvent(const std::string_view id,
++ const std::string_view msg) = 0;
++
++ crow::Request req;
++ crow::Response res;
++};
++
++template <typename Adaptor>
++class SseConnectionImpl : public SseConnection
++{
++ public:
++ SseConnectionImpl(
++ const crow::Request& reqIn, Adaptor adaptorIn,
++ std::function<void(std::shared_ptr<SseConnection>&,
++ const crow::Request&, crow::Response&)>
++ openHandler,
++ std::function<void(std::shared_ptr<SseConnection>&)> closeHandler) :
++ SseConnection(reqIn),
++ adaptor(std::move(adaptorIn)), openHandler(std::move(openHandler)),
++ closeHandler(std::move(closeHandler))
++ {
++ BMCWEB_LOG_DEBUG << "SseConnectionImpl: SSE constructor " << this;
++ }
++
++ ~SseConnectionImpl() override
++ {
++ res.completeRequestHandler = nullptr;
++ BMCWEB_LOG_DEBUG << "SseConnectionImpl: SSE destructor " << this;
++ }
++
++ boost::asio::io_context& getIoContext() override
++ {
++ return static_cast<boost::asio::io_context&>(
++ adaptor.get_executor().context());
++ }
++
++ void start()
++ {
++ // Register for completion callback.
++ res.completeRequestHandler = [this, self(shared_from_this())] {
++ boost::asio::post(this->adaptor.get_executor(),
++ [self] { self->completeRequest(); });
++ };
++
++ if (openHandler)
++ {
++ std::shared_ptr<SseConnection> self = this->shared_from_this();
++ openHandler(self, req, res);
++ }
++ }
++
++ void close(const std::string_view msg) override
++ {
++ BMCWEB_LOG_DEBUG << "Closing SSE connection " << this << " - " << msg;
++ boost::beast::get_lowest_layer(adaptor).close();
++
++ // send notification to handler for cleanup
++ if (closeHandler)
++ {
++ std::shared_ptr<SseConnection> self = this->shared_from_this();
++ closeHandler(self);
++ }
++ }
++
++ void sendSSEHeader() override
++ {
++ BMCWEB_LOG_DEBUG << "Starting SSE connection";
++ using BodyType = boost::beast::http::buffer_body;
++ auto response =
++ std::make_shared<boost::beast::http::response<BodyType>>(
++ boost::beast::http::status::ok, 11);
++ auto serializer =
++ std::make_shared<boost::beast::http::response_serializer<BodyType>>(
++ *response);
++
++ response->set(boost::beast::http::field::server, "bmcweb");
++ response->set(boost::beast::http::field::content_type,
++ "text/event-stream");
++ response->body().data = nullptr;
++ response->body().size = 0;
++ response->body().more = true;
++
++ boost::beast::http::async_write_header(
++ adaptor, *serializer,
++ [this, self(shared_from_this()), response, serializer](
++ const boost::beast::error_code& ec, const std::size_t&) {
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "Error sending header" << ec;
++ close("async_write_header failed");
++ return;
++ }
++ BMCWEB_LOG_DEBUG << "SSE header sent - Connection established";
++
++ // SSE stream header sent, So lets setup monitor.
++ // Any read data on this stream will be error in case of SSE.
++ setupRead();
++ });
++ }
++
++ void setupRead()
++ {
++ adaptor.async_read_some(
++ outputBuffer.prepare(outputBuffer.capacity() - outputBuffer.size()),
++ [this](const boost::system::error_code& ec, std::size_t bytesRead) {
++ BMCWEB_LOG_DEBUG << "async_read_some: Read " << bytesRead
++ << " bytes";
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "Read error: " << ec;
++ }
++ outputBuffer.commit(bytesRead);
++ outputBuffer.consume(bytesRead);
++
++ // After establishing SSE stream, Reading data on this
++ // stream means client is disobeys the SSE protocol.
++ // Read the data to avoid buffer attacks and close connection.
++ close("Close SSE connection");
++ return;
++ });
++ }
++
++ void doWrite()
++ {
++ if (doingWrite)
++ {
++ return;
++ }
++ if (inputBuffer.size() == 0)
++ {
++ BMCWEB_LOG_DEBUG << "inputBuffer is empty... Bailing out";
++ return;
++ }
++ doingWrite = true;
++
++ adaptor.async_write_some(
++ inputBuffer.data(), [this, self(shared_from_this())](
++ boost::beast::error_code ec,
++ const std::size_t& bytesTransferred) {
++ doingWrite = false;
++ inputBuffer.consume(bytesTransferred);
++
++ if (ec == boost::asio::error::eof)
++ {
++ BMCWEB_LOG_ERROR << "async_write_some() SSE stream closed";
++ close("SSE stream closed");
++ return;
++ }
++
++ if (ec)
++ {
++ BMCWEB_LOG_ERROR << "async_write_some() failed: "
++ << ec.message();
++ close("async_write_some failed");
++ return;
++ }
++ BMCWEB_LOG_DEBUG << "async_write_some() bytes transferred: "
++ << bytesTransferred;
++
++ doWrite();
++ });
++ }
++
++ void completeRequest() override
++ {
++ BMCWEB_LOG_DEBUG << "SSE completeRequest() handler";
++ if (res.body().empty() && !res.jsonValue.empty())
++ {
++ res.addHeader("Content-Type", "application/json");
++ res.body() = res.jsonValue.dump(
++ 2, ' ', true, nlohmann::json::error_handler_t::replace);
++ }
++
++ res.preparePayload();
++ auto serializer =
++ std::make_shared<boost::beast::http::response_serializer<
++ boost::beast::http::string_body>>(*res.stringResponse);
++
++ boost::beast::http::async_write(
++ adaptor, *serializer,
++ [this, self(shared_from_this()),
++ serializer](const boost::system::error_code& ec,
++ std::size_t bytesTransferred) {
++ BMCWEB_LOG_DEBUG << this << " async_write " << bytesTransferred
++ << " bytes";
++ if (ec)
++ {
++ BMCWEB_LOG_DEBUG << this << " from async_write failed";
++ return;
++ }
++ res.clear();
++
++ BMCWEB_LOG_DEBUG << this
++ << " Closing SSE connection - Request invalid";
++ close("Request invalid");
++ });
++
++ // delete lambda with self shared_ptr
++ // to enable connection destruction
++ res.completeRequestHandler = nullptr;
++ }
++
++ void sendEvent(const std::string_view id,
++ const std::string_view msg) override
++ {
++ if (msg.empty())
++ {
++ BMCWEB_LOG_DEBUG << "Empty data, bailing out.";
++ return;
++ }
++
++ std::string rawData;
++ if (!id.empty())
++ {
++ rawData += "id: ";
++ rawData.append(id.begin(), id.end());
++ rawData += "\n";
++ }
++
++ rawData += "data: ";
++ for (char character : msg)
++ {
++ rawData += character;
++ if (character == '\n')
++ {
++ rawData += "data: ";
++ }
++ }
++ rawData += "\n\n";
++
++ boost::asio::buffer_copy(inputBuffer.prepare(rawData.size()),
++ boost::asio::buffer(rawData));
++ inputBuffer.commit(rawData.size());
++
++ doWrite();
++ }
++
++ private:
++ Adaptor adaptor;
++
++ boost::beast::flat_static_buffer<1024U * 8U> outputBuffer;
++ boost::beast::flat_static_buffer<1024U * 64U> inputBuffer;
++ bool doingWrite = false;
++
++ std::function<void(std::shared_ptr<SseConnection>&, const crow::Request&,
++ crow::Response&)>
++ openHandler;
++ std::function<void(std::shared_ptr<SseConnection>&)> closeHandler;
++};
++} // namespace crow
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch
new file mode 100644
index 000000000..e2eaf1761
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch
@@ -0,0 +1,627 @@
+From dbaf8c1dc402da97fec723d050e063cd283d8736 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 16 Mar 2021 15:37:24 +0000
+Subject: [PATCH 5/6] Add SSE style subscription support to eventservice
+
+This commit adds the SSE style eventservice subscription
+style event. Using this, end user can subscribe for
+Redfish event logs using GET on SSE usri from
+browser.
+URI: /redfish/v1/EventService/Subscriptions/SSE
+
+Tested:
+ - From Browser did GET on above SSE URI and
+ generated some Redfish event logs(power cycle)
+ and saw redfish event logs streaming on browser.
+ - After SSE registration, Check Subscription collections
+ and GET on individual subscription and saw desired
+ response.
+ - Ran RedfishValidation and its passed.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: I7f4b7a34974080739c4ba968ed570489af0474de
+---
+ http/http_connection.hpp | 2 +-
+ include/eventservice_sse.hpp | 75 +++++
+ .../include/event_service_manager.hpp | 77 ++++-
+ redfish-core/include/server_sent_events.hpp | 291 ------------------
+ redfish-core/lib/event_service.hpp | 4 +-
+ src/webserver_main.cpp | 2 +
+ 6 files changed, 149 insertions(+), 302 deletions(-)
+ create mode 100644 include/eventservice_sse.hpp
+ delete mode 100644 redfish-core/include/server_sent_events.hpp
+
+diff --git a/http/http_connection.hpp b/http/http_connection.hpp
+index 2c8bf40..1ab776c 100644
+--- a/http/http_connection.hpp
++++ b/http/http_connection.hpp
+@@ -350,7 +350,7 @@ class Connection :
+ boost::iequals(req->getHeaderValue(
+ boost::beast::http::field::upgrade),
+ "websocket")) ||
+- (req->url == "/sse"))
++ (req->url == "/redfish/v1/EventService/Subscriptions/SSE"))
+ {
+ BMCWEB_LOG_DEBUG << "Request: " << this
+ << " is getting upgraded";
+diff --git a/include/eventservice_sse.hpp b/include/eventservice_sse.hpp
+new file mode 100644
+index 0000000..6c98e6e
+--- /dev/null
++++ b/include/eventservice_sse.hpp
+@@ -0,0 +1,75 @@
++#pragma once
++
++#include <app.hpp>
++#include <event_service_manager.hpp>
++
++namespace redfish
++{
++namespace eventservice_sse
++{
++
++static bool createSubscription(std::shared_ptr<crow::SseConnection>& conn,
++ const crow::Request& req, crow::Response& res)
++{
++ if ((EventServiceManager::getInstance().getNumberOfSubscriptions() >=
++ maxNoOfSubscriptions) ||
++ EventServiceManager::getInstance().getNumberOfSSESubscriptions() >=
++ maxNoOfSSESubscriptions)
++ {
++ BMCWEB_LOG_ERROR << "Max SSE subscriptions reached";
++ messages::eventSubscriptionLimitExceeded(res);
++ res.end();
++ return false;
++ }
++ BMCWEB_LOG_DEBUG << "Request query param size: " << req.urlParams.size();
++
++ std::shared_ptr<redfish::Subscription> subValue =
++ std::make_shared<redfish::Subscription>(std::move(conn));
++
++ // GET on this URI means, Its SSE subscriptionType.
++ subValue->subscriptionType = redfish::subscriptionTypeSSE;
++
++ // TODO: parse $filter query params and fill config.
++ subValue->protocol = "Redfish";
++ subValue->retryPolicy = "TerminateAfterRetries";
++ subValue->eventFormatType = "Event";
++
++ std::string id =
++ redfish::EventServiceManager::getInstance().addSubscription(subValue,
++ false);
++ if (id.empty())
++ {
++ messages::internalError(res);
++ res.end();
++ return false;
++ }
++
++ return true;
++}
++
++static void deleteSubscription(std::shared_ptr<crow::SseConnection>& conn)
++{
++ redfish::EventServiceManager::getInstance().deleteSubscription(conn);
++}
++
++inline void requestRoutes(App& app)
++{
++ BMCWEB_ROUTE(app, "/redfish/v1/EventService/Subscriptions/SSE")
++ .privileges({"ConfigureComponents", "ConfigureManager"})
++ .serverSentEvent()
++ .onopen([](std::shared_ptr<crow::SseConnection>& conn,
++ const crow::Request& req, crow::Response& res) {
++ BMCWEB_LOG_DEBUG << "Connection " << conn << " opened.";
++ if (createSubscription(conn, req, res))
++ {
++ // All success, lets send SSE haader
++ conn->sendSSEHeader();
++ }
++ })
++ .onclose([](std::shared_ptr<crow::SseConnection>& conn) {
++ BMCWEB_LOG_DEBUG << "Connection " << conn << " closed";
++ deleteSubscription(conn);
++ });
++}
++} // namespace eventservice_sse
++} // namespace redfish
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 148c703..e3eba86 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -22,13 +22,15 @@
+ #include <sys/inotify.h>
+
+ #include <boost/asio/io_context.hpp>
++#include <boost/beast/core/span.hpp>
+ #include <boost/container/flat_map.hpp>
+ #include <error_messages.hpp>
+ #include <http_client.hpp>
+ #include <random.hpp>
+-#include <server_sent_events.hpp>
++#include <server_sent_event.hpp>
+ #include <utils/json_utils.hpp>
+
++#include <algorithm>
+ #include <cstdlib>
+ #include <ctime>
+ #include <fstream>
+@@ -45,9 +47,13 @@ using EventServiceConfig = std::tuple<bool, uint32_t, uint32_t>;
+ static constexpr const char* eventFormatType = "Event";
+ static constexpr const char* metricReportFormatType = "MetricReport";
+
++static constexpr const char* subscriptionTypeSSE = "SSE";
+ static constexpr const char* eventServiceFile =
+ "/var/lib/bmcweb/eventservice_config.json";
+
++static constexpr const uint8_t maxNoOfSubscriptions = 20;
++static constexpr const uint8_t maxNoOfSSESubscriptions = 10;
++
+ #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
+ static std::optional<boost::asio::posix::stream_descriptor> inotifyConn;
+ static constexpr const char* redfishEventLogDir = "/var/log";
+@@ -390,11 +396,9 @@ class Subscription
+ path);
+ }
+
+- Subscription(const std::shared_ptr<boost::beast::tcp_stream>& adaptor) :
+- eventSeqNum(1)
+- {
+- sseConn = std::make_shared<crow::ServerSentEvents>(adaptor);
+- }
++ Subscription(const std::shared_ptr<crow::SseConnection>& adaptor) :
++ sseConn(adaptor), eventSeqNum(1)
++ {}
+
+ ~Subscription() = default;
+
+@@ -419,7 +423,7 @@ class Subscription
+
+ if (sseConn != nullptr)
+ {
+- sseConn->sendData(eventSeqNum, msg);
++ sseConn->sendEvent(std::to_string(eventSeqNum), msg);
+ }
+ }
+
+@@ -509,6 +513,7 @@ class Subscription
+
+ this->sendEvent(
+ msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace));
++ this->eventSeqNum++;
+ }
+ #endif
+
+@@ -579,14 +584,39 @@ class Subscription
+ return eventSeqNum;
+ }
+
++ void setSubscriptionId(const std::string& id)
++ {
++ BMCWEB_LOG_DEBUG << "Subscription ID: " << id;
++ subId = id;
++ }
++
++ std::string getSubscriptionId()
++ {
++ return subId;
++ }
++
++ std::optional<std::string>
++ getSubscriptionId(const std::shared_ptr<crow::SseConnection>& connPtr)
++ {
++ if (sseConn != nullptr && connPtr == sseConn)
++ {
++ BMCWEB_LOG_DEBUG << __FUNCTION__
++ << " conn matched, subId: " << subId;
++ return subId;
++ }
++
++ return std::nullopt;
++ }
++
+ private:
++ std::shared_ptr<crow::SseConnection> sseConn = nullptr;
+ uint64_t eventSeqNum;
+ std::string host;
+ std::string port;
+ std::string path;
+ std::string uriProto;
+ std::shared_ptr<crow::HttpClient> conn = nullptr;
+- std::shared_ptr<crow::ServerSentEvents> sseConn = nullptr;
++ std::string subId;
+ };
+
+ static constexpr const bool defaultEnabledState = true;
+@@ -977,6 +1007,8 @@ class EventServiceManager
+ subValue->updateRetryConfig(retryAttempts, retryTimeoutInterval);
+ subValue->updateRetryPolicy();
+
++ // Set Subscription ID for back trace
++ subValue->setSubscriptionId(id);
+ return id;
+ }
+
+@@ -1001,11 +1033,40 @@ class EventServiceManager
+ }
+ }
+
++ void deleteSubscription(const std::shared_ptr<crow::SseConnection>& connPtr)
++ {
++ for (const auto& it : this->subscriptionsMap)
++ {
++ std::shared_ptr<Subscription> entry = it.second;
++ if (entry->subscriptionType == subscriptionTypeSSE)
++ {
++ std::optional<std::string> id =
++ entry->getSubscriptionId(connPtr);
++ if (id)
++ {
++ deleteSubscription(*id);
++ return;
++ }
++ }
++ }
++ }
++
+ size_t getNumberOfSubscriptions()
+ {
+ return subscriptionsMap.size();
+ }
+
++ size_t getNumberOfSSESubscriptions() const
++ {
++ auto count = std::count_if(
++ subscriptionsMap.begin(), subscriptionsMap.end(),
++ [this](const std::pair<std::string, std::shared_ptr<Subscription>>&
++ entry) {
++ return (entry.second->subscriptionType == subscriptionTypeSSE);
++ });
++ return static_cast<size_t>(count);
++ }
++
+ std::vector<std::string> getAllIDs()
+ {
+ std::vector<std::string> idList;
+diff --git a/redfish-core/include/server_sent_events.hpp b/redfish-core/include/server_sent_events.hpp
+deleted file mode 100644
+index 578fa19..0000000
+--- a/redfish-core/include/server_sent_events.hpp
++++ /dev/null
+@@ -1,291 +0,0 @@
+-
+-/*
+-// Copyright (c) 2020 Intel Corporation
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-// http://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-*/
+-#pragma once
+-#include "node.hpp"
+-
+-#include <boost/asio/strand.hpp>
+-#include <boost/beast/core/span.hpp>
+-#include <boost/beast/http/buffer_body.hpp>
+-#include <boost/beast/http/message.hpp>
+-#include <boost/beast/version.hpp>
+-
+-#include <cstdlib>
+-#include <functional>
+-#include <iostream>
+-#include <memory>
+-#include <queue>
+-#include <string>
+-
+-namespace crow
+-{
+-
+-static constexpr uint8_t maxReqQueueSize = 50;
+-
+-enum class SseConnState
+-{
+- startInit,
+- initInProgress,
+- initialized,
+- initFailed,
+- sendInProgress,
+- sendFailed,
+- idle,
+- suspended,
+- closed
+-};
+-
+-class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+-{
+- private:
+- std::shared_ptr<boost::beast::tcp_stream> sseConn;
+- std::queue<std::pair<uint64_t, std::string>> requestDataQueue;
+- std::string outBuffer;
+- SseConnState state;
+- int retryCount;
+- int maxRetryAttempts;
+-
+- void sendEvent(const std::string& id, const std::string& msg)
+- {
+- if (msg.empty())
+- {
+- BMCWEB_LOG_DEBUG << "Empty data, bailing out.";
+- return;
+- }
+-
+- if (state == SseConnState::sendInProgress)
+- {
+- return;
+- }
+- state = SseConnState::sendInProgress;
+-
+- if (!id.empty())
+- {
+- outBuffer += "id: ";
+- outBuffer.append(id.begin(), id.end());
+- outBuffer += "\n";
+- }
+-
+- outBuffer += "data: ";
+- for (char character : msg)
+- {
+- outBuffer += character;
+- if (character == '\n')
+- {
+- outBuffer += "data: ";
+- }
+- }
+- outBuffer += "\n\n";
+-
+- doWrite();
+- }
+-
+- void doWrite()
+- {
+- if (outBuffer.empty())
+- {
+- BMCWEB_LOG_DEBUG << "All data sent successfully.";
+- // Send is successful, Lets remove data from queue
+- // check for next request data in queue.
+- requestDataQueue.pop();
+- state = SseConnState::idle;
+- checkQueue();
+- return;
+- }
+-
+- sseConn->async_write_some(
+- boost::asio::buffer(outBuffer.data(), outBuffer.size()),
+- [self(shared_from_this())](
+- boost::beast::error_code ec,
+- [[maybe_unused]] const std::size_t& bytesTransferred) {
+- self->outBuffer.erase(0, bytesTransferred);
+-
+- if (ec == boost::asio::error::eof)
+- {
+- // Send is successful, Lets remove data from queue
+- // check for next request data in queue.
+- self->requestDataQueue.pop();
+- self->state = SseConnState::idle;
+- self->checkQueue();
+- return;
+- }
+-
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "async_write_some() failed: "
+- << ec.message();
+- self->state = SseConnState::sendFailed;
+- self->checkQueue();
+- return;
+- }
+- BMCWEB_LOG_DEBUG << "async_write_some() bytes transferred: "
+- << bytesTransferred;
+-
+- self->doWrite();
+- });
+- }
+-
+- void startSSE()
+- {
+- if (state == SseConnState::initInProgress)
+- {
+- return;
+- }
+- state = SseConnState::initInProgress;
+-
+- BMCWEB_LOG_DEBUG << "starting SSE connection ";
+- using BodyType = boost::beast::http::buffer_body;
+- auto response =
+- std::make_shared<boost::beast::http::response<BodyType>>(
+- boost::beast::http::status::ok, 11);
+- auto serializer =
+- std::make_shared<boost::beast::http::response_serializer<BodyType>>(
+- *response);
+-
+- // TODO: Add hostname in http header.
+- response->set(boost::beast::http::field::server, "iBMC");
+- response->set(boost::beast::http::field::content_type,
+- "text/event-stream");
+- response->body().data = nullptr;
+- response->body().size = 0;
+- response->body().more = true;
+-
+- boost::beast::http::async_write_header(
+- *sseConn, *serializer,
+- [this, response,
+- serializer](const boost::beast::error_code& ec,
+- [[maybe_unused]] const std::size_t& bytesTransferred) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "Error sending header" << ec;
+- state = SseConnState::initFailed;
+- checkQueue();
+- return;
+- }
+-
+- BMCWEB_LOG_DEBUG << "startSSE Header sent.";
+- state = SseConnState::initialized;
+- checkQueue();
+- });
+- }
+-
+- void checkQueue(const bool newRecord = false)
+- {
+- if (requestDataQueue.empty())
+- {
+- BMCWEB_LOG_DEBUG << "requestDataQueue is empty\n";
+- return;
+- }
+-
+- if (retryCount >= maxRetryAttempts)
+- {
+- BMCWEB_LOG_ERROR << "Maximum number of retries is reached.";
+-
+- // Clear queue.
+- while (!requestDataQueue.empty())
+- {
+- requestDataQueue.pop();
+- }
+-
+- // TODO: Take 'DeliveryRetryPolicy' action.
+- // For now, doing 'SuspendRetries' action.
+- state = SseConnState::suspended;
+- return;
+- }
+-
+- if ((state == SseConnState::initFailed) ||
+- (state == SseConnState::sendFailed))
+- {
+- if (newRecord)
+- {
+- // We are already running async wait and retry.
+- // Since record is added to queue, it gets the
+- // turn in FIFO.
+- return;
+- }
+-
+- retryCount++;
+- // TODO: Perform async wait for retryTimeoutInterval before proceed.
+- }
+- else
+- {
+- // reset retry count.
+- retryCount = 0;
+- }
+-
+- switch (state)
+- {
+- case SseConnState::initInProgress:
+- case SseConnState::sendInProgress:
+- case SseConnState::suspended:
+- case SseConnState::startInit:
+- case SseConnState::closed:
+- // do nothing
+- break;
+- case SseConnState::initFailed:
+- {
+- startSSE();
+- break;
+- }
+- case SseConnState::initialized:
+- case SseConnState::idle:
+- case SseConnState::sendFailed:
+- {
+- std::pair<uint64_t, std::string> reqData =
+- requestDataQueue.front();
+- sendEvent(std::to_string(reqData.first), reqData.second);
+- break;
+- }
+- }
+-
+- return;
+- }
+-
+- public:
+- ServerSentEvents(const ServerSentEvents&) = delete;
+- ServerSentEvents& operator=(const ServerSentEvents&) = delete;
+- ServerSentEvents(ServerSentEvents&&) = delete;
+- ServerSentEvents& operator=(ServerSentEvents&&) = delete;
+-
+- ServerSentEvents(const std::shared_ptr<boost::beast::tcp_stream>& adaptor) :
+- sseConn(adaptor), state(SseConnState::startInit), retryCount(0),
+- maxRetryAttempts(5)
+- {
+- startSSE();
+- }
+-
+- ~ServerSentEvents() = default;
+-
+- void sendData(const uint64_t& id, const std::string& data)
+- {
+- if (state == SseConnState::suspended)
+- {
+- return;
+- }
+-
+- if (requestDataQueue.size() <= maxReqQueueSize)
+- {
+- requestDataQueue.push(std::pair(id, data));
+- checkQueue(true);
+- }
+- else
+- {
+- BMCWEB_LOG_ERROR << "Request queue is full. So ignoring data.";
+- }
+- }
+-};
+-
+-} // namespace crow
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index be6f04d..1875ec9 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -34,8 +34,6 @@ static constexpr const std::array<const char*, 1> supportedResourceTypes = {
+ "Task"};
+ #endif
+
+-static constexpr const uint8_t maxNoOfSubscriptions = 20;
+-
+ class EventService : public Node
+ {
+ public:
+@@ -59,6 +57,8 @@ class EventService : public Node
+ {"@odata.type", "#EventService.v1_5_0.EventService"},
+ {"Id", "EventService"},
+ {"Name", "Event Service"},
++ {"ServerSentEventUri",
++ "/redfish/v1/EventService/Subscriptions/SSE"},
+ {"Subscriptions",
+ {{"@odata.id", "/redfish/v1/EventService/Subscriptions"}}},
+ {"Actions",
+diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
+index 3b9631a..bf8e705 100644
+--- a/src/webserver_main.cpp
++++ b/src/webserver_main.cpp
+@@ -5,6 +5,7 @@
+ #include <cors_preflight.hpp>
+ #include <dbus_monitor.hpp>
+ #include <dbus_singleton.hpp>
++#include <eventservice_sse.hpp>
+ #include <hostname_monitor.hpp>
+ #include <ibm/management_console_rest.hpp>
+ #include <image_upload.hpp>
+@@ -79,6 +80,7 @@ int main(int /*argc*/, char** /*argv*/)
+
+ #ifdef BMCWEB_ENABLE_REDFISH
+ crow::redfish::requestRoutes(app);
++ redfish::eventservice_sse::requestRoutes(app);
+ redfish::RedfishService redfish(app);
+
+ // Create EventServiceManager instance and initialize Config
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch
new file mode 100644
index 000000000..e83e05c96
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/0006-Add-EventService-SSE-filter-support.patch
@@ -0,0 +1,243 @@
+From 693de7b901e7618585e0e8d848fc37fa0cccd18e Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Wed, 17 Mar 2021 01:16:50 +0000
+Subject: [PATCH 6/6] Add EventService SSE filter support
+
+This commit implements the Event Service SSE stream
+filters support. As per redfish specification:
+The SSE streams have these formats:
+ - Metric report SSE stream
+ - Event message SSE stream
+
+To reduce the amount of data, service supports $filter
+query parameter in SSE URI.
+Below properties support as filter criteria:
+ - EventFormatType( Event & MetricReport)
+ - MessageId
+ - RegistryPrefix
+ - MetricReportDefinition
+
+For more details, refer Redfish specification section 13.5.2
+
+Tested:
+ Created SSE stream with different filters and observed
+ desired events on SSE stream client(browser), some examples
+ - To get all Redfish events,
+ URI: /redfish/v1/EventService/Subscriptions/SSE?$filter=(EventFormatType%20eq%20Event)
+ - To get Redfish events with RegistryPrefix "OpenBMC"
+ URi: /redfish/v1/EventService/Subscriptions/SSE?$filter=(RegistryPrefix%20eq%20OpenBMC)
+ - To get only DC power of Events,
+ URI: /redfish/v1/EventService/Subscriptions/SSE?$filter=(EventFormatType%20eq%20Event)%20and%20(MessageId%20eq%20DCPowerOff)
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: I55c6f53bb5e57aa1f2d1601f1a16525a33b13bd2
+---
+ include/eventservice_sse.hpp | 94 ++++++++++++++++++-
+ redfish-core/include/error_messages.hpp | 9 ++
+ .../include/event_service_manager.hpp | 5 +
+ redfish-core/lib/event_service.hpp | 4 -
+ redfish-core/src/error_messages.cpp | 26 +++++
+ 5 files changed, 130 insertions(+), 8 deletions(-)
+
+diff --git a/include/eventservice_sse.hpp b/include/eventservice_sse.hpp
+index 6c98e6e..ff72c4d 100644
+--- a/include/eventservice_sse.hpp
++++ b/include/eventservice_sse.hpp
+@@ -23,16 +23,102 @@ static bool createSubscription(std::shared_ptr<crow::SseConnection>& conn,
+ }
+ BMCWEB_LOG_DEBUG << "Request query param size: " << req.urlParams.size();
+
++ // EventService SSE supports only "$filter" query param.
++ if (req.urlParams.size() > 1)
++ {
++ messages::invalidQueryFilter(res);
++ res.end();
++ return false;
++ }
++ std::string eventFormatType;
++ std::string queryFilters;
++ if (req.urlParams.size())
++ {
++ boost::urls::url_view::params_type::iterator it =
++ req.urlParams.find("$filter");
++ if (it == req.urlParams.end())
++ {
++ messages::invalidQueryFilter(res);
++ res.end();
++ return false;
++ }
++ queryFilters = it->value();
++ }
++ else
++ {
++ eventFormatType = "Event";
++ }
++
++ std::vector<std::string> msgIds;
++ std::vector<std::string> regPrefixes;
++ std::vector<std::string> mrdsArray;
++ if (!queryFilters.empty())
++ {
++ // Reading from query params.
++ bool status = readSSEQueryParams(queryFilters, eventFormatType, msgIds,
++ regPrefixes, mrdsArray);
++ if (!status)
++ {
++ messages::invalidObject(res, queryFilters);
++ res.end();
++ return false;
++ }
++
++ // RegsitryPrefix and messageIds are mutuly exclusive as per redfish
++ // specification.
++ if (regPrefixes.size() && msgIds.size())
++ {
++ messages::mutualExclusiveProperties(res, "RegistryPrefix",
++ "MessageId");
++ res.end();
++ return false;
++ }
++
++ if (!eventFormatType.empty())
++ {
++ if (std::find(supportedEvtFormatTypes.begin(),
++ supportedEvtFormatTypes.end(),
++ eventFormatType) == supportedEvtFormatTypes.end())
++ {
++ messages::propertyValueNotInList(res, eventFormatType,
++ "EventFormatType");
++ res.end();
++ return false;
++ }
++ }
++ else
++ {
++ // If nothing specified, using default "Event"
++ eventFormatType = "Event";
++ }
++
++ if (!regPrefixes.empty())
++ {
++ for (const std::string& it : regPrefixes)
++ {
++ if (std::find(supportedRegPrefixes.begin(),
++ supportedRegPrefixes.end(),
++ it) == supportedRegPrefixes.end())
++ {
++ messages::propertyValueNotInList(res, it, "RegistryPrefix");
++ res.end();
++ return false;
++ }
++ }
++ }
++ }
++
+ std::shared_ptr<redfish::Subscription> subValue =
+ std::make_shared<redfish::Subscription>(std::move(conn));
+
+ // GET on this URI means, Its SSE subscriptionType.
+- subValue->subscriptionType = redfish::subscriptionTypeSSE;
+-
+- // TODO: parse $filter query params and fill config.
++ subValue->subscriptionType = subscriptionTypeSSE;
+ subValue->protocol = "Redfish";
+ subValue->retryPolicy = "TerminateAfterRetries";
+- subValue->eventFormatType = "Event";
++ subValue->eventFormatType = eventFormatType;
++ subValue->registryMsgIds = msgIds;
++ subValue->registryPrefixes = regPrefixes;
++ subValue->metricReportDefinitions = mrdsArray;
+
+ std::string id =
+ redfish::EventServiceManager::getInstance().addSubscription(subValue,
+diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
+index 7dfdc80..922dae9 100644
+--- a/redfish-core/include/error_messages.hpp
++++ b/redfish-core/include/error_messages.hpp
+@@ -959,6 +959,15 @@ nlohmann::json mutualExclusiveProperties(const std::string& arg1,
+ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
+ const std::string& arg2);
+
++/**
++ * @brief Formats InvalidQueryFilter message into JSON
++ * Message body: "The requested URL contains the invalid query filters"
++ *
++ * @returns Message InvalidQueryFilter formatted to JSON */
++nlohmann::json invalidQueryFilter();
++
++void invalidQueryFilter(crow::Response& res);
++
+ } // namespace messages
+
+ } // namespace redfish
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index e3eba86..8f120b1 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -54,6 +54,11 @@ static constexpr const char* eventServiceFile =
+ static constexpr const uint8_t maxNoOfSubscriptions = 20;
+ static constexpr const uint8_t maxNoOfSSESubscriptions = 10;
+
++static constexpr const std::array<const char*, 2> supportedEvtFormatTypes = {
++ eventFormatType, metricReportFormatType};
++static constexpr const std::array<const char*, 3> supportedRegPrefixes = {
++ "Base", "OpenBMC", "Task"};
++
+ #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
+ static std::optional<boost::asio::posix::stream_descriptor> inotifyConn;
+ static constexpr const char* redfishEventLogDir = "/var/log";
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index 1875ec9..4d1ac9f 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -19,10 +19,6 @@
+ 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*, 3> supportedRetryPolicies = {
+ "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
+
+diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
+index cfbc9c2..3493132 100644
+--- a/redfish-core/src/error_messages.cpp
++++ b/redfish-core/src/error_messages.cpp
+@@ -2147,6 +2147,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
+ addMessageToErrorJson(res.jsonValue, mutualExclusiveProperties(arg1, arg2));
+ }
+
++/**
++ * @internal
++ * @brief Formats InvalidQueryFilter into JSON
++ *
++ * See header file for more information
++ * @endinternal
++ */
++nlohmann::json invalidQueryFilter()
++{
++ return nlohmann::json{
++ {"@odata.type", "#Message.v1_0_0.Message"},
++ {"MessageId", "Base.1.5.0.InvalidQueryFilter"},
++ {"Message", "The requested url contains the invalid query filter."},
++ {"MessageArgs", nlohmann::json::array()},
++ {"Severity", "Warning"},
++ {"Resolution",
++ "Ensure the correct query filter is specified in requested url "
++ "and resubmit the request."}};
++}
++
++void invalidQueryFilter(crow::Response& res)
++{
++ res.result(boost::beast::http::status::bad_request);
++ addMessageToErrorJson(res.jsonValue, invalidQueryFilter());
++}
++
+ } // namespace messages
+
+ } // namespace redfish
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README
new file mode 100644
index 000000000..55340bb5c
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/eventservice/README
@@ -0,0 +1,22 @@
+Eventservice specific patches: Temporary pulling down
+the upstream patches. These will be remove as soon as
+thee gets merged upstream.
+
+Upstream revision information:
+ - EventService : Fix retry handling for http-client
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/40731/18
+
+ - EventService: https client support
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/31735/38
+
+ - Move EventService init to later stage
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41516
+
+ - Add Server-Sent-Events support
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41258/5
+
+ - Add SSE style subscription support to eventservice
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41319/5
+
+ - Add EventService SSE filter support
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/41349/2
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Sync_ReadingUnit_with_Redfish_Sensor_Schema.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Sync_ReadingUnit_with_Redfish_Sensor_Schema.patch
new file mode 100644
index 000000000..e3b25da90
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0001-Sync_ReadingUnit_with_Redfish_Sensor_Schema.patch
@@ -0,0 +1,227 @@
+From 4b7e67d7200c0aba1b27478968d4f71449f1406a Mon Sep 17 00:00:00 2001
+From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
+Date: Mon, 8 Mar 2021 14:35:54 +0000
+Subject: [PATCH] Sync ReadingUnit with Redfish Sensor Schema
+
+Actual attribute "ReadingUnits" does not match with Redfish Sensor
+Schema. This change match "ReadingUnits" with Redfish Sensor Scheme
+1.0.0 and add missing "ReadingType" attribute. This change affect all
+users that depends on old units that does not match with Redfish
+standard. Added toReadingType and toReadingUnit function that uses
+values taken from Redfish Sensor Scheme 1.0.0. Latest version 1.2.0 of
+Sensor scheme defines units same units.
+
+Tested:
+ - RedfishServiceValidator pass
+
+Change-Id: I0c8820eba7271022c427cd25dec321db36aa0176
+Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
+Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
+---
+ redfish-core/lib/power.hpp | 4 +-
+ redfish-core/lib/sensors.hpp | 107 +++++++++++++++++++++++++++++------
+ redfish-core/lib/thermal.hpp | 4 +-
+ 3 files changed, 94 insertions(+), 21 deletions(-)
+
+diff --git a/redfish-core/lib/power.hpp b/redfish-core/lib/power.hpp
+index 1c7a009..99c45ef 100644
+--- a/redfish-core/lib/power.hpp
++++ b/redfish-core/lib/power.hpp
+@@ -153,7 +153,7 @@ class Power : public Node
+ res.jsonValue["PowerControl"] = nlohmann::json::array();
+
+ auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
+- res, chassisName, sensors::dbus::types.at(sensors::node::power),
++ res, chassisName, sensors::dbus::paths.at(sensors::node::power),
+ sensors::node::power);
+
+ getChassisData(sensorAsyncResp);
+@@ -336,7 +336,7 @@ class Power : public Node
+
+ const std::string& chassisName = params[0];
+ auto asyncResp = std::make_shared<SensorsAsyncResp>(
+- res, chassisName, sensors::dbus::types.at(sensors::node::power),
++ res, chassisName, sensors::dbus::paths.at(sensors::node::power),
+ sensors::node::power);
+
+ std::optional<std::vector<nlohmann::json>> voltageCollections;
+diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
+index 35114bf..af030f0 100644
+--- a/redfish-core/lib/sensors.hpp
++++ b/redfish-core/lib/sensors.hpp
+@@ -54,9 +54,10 @@ static constexpr std::string_view thermal = "Thermal";
+
+ namespace dbus
+ {
++
+ static const boost::container::flat_map<std::string_view,
+ std::vector<const char*>>
+- types = {{node::power,
++ paths = {{node::power,
+ {"/xyz/openbmc_project/sensors/voltage",
+ "/xyz/openbmc_project/sensors/power"}},
+ {node::sensors,
+@@ -67,6 +68,88 @@ static const boost::container::flat_map<std::string_view,
+ {"/xyz/openbmc_project/sensors/fan_tach",
+ "/xyz/openbmc_project/sensors/temperature",
+ "/xyz/openbmc_project/sensors/fan_pwm"}}};
++} // namespace dbus
++
++inline const char* toReadingType(const std::string& sensorType)
++{
++ if (sensorType == "voltage")
++ {
++ return "Voltage";
++ }
++ if (sensorType == "power")
++ {
++ return "Power";
++ }
++ if (sensorType == "current")
++ {
++ return "Current";
++ }
++ if (sensorType == "fan_tach")
++ {
++ return "Rotational";
++ }
++ if (sensorType == "temperature")
++ {
++ return "Temperature";
++ }
++ if (sensorType == "fan_pwm" || sensorType == "utilization")
++ {
++ return "Percent";
++ }
++ if (sensorType == "altitude")
++ {
++ return "Altitude";
++ }
++ if (sensorType == "airflow")
++ {
++ return "AirFlow";
++ }
++ if (sensorType == "energy")
++ {
++ return "EnergyJoules";
++ }
++ return "";
++}
++
++inline const char* toReadingUnits(const std::string& sensorType)
++{
++ if (sensorType == "voltage")
++ {
++ return "V";
++ }
++ if (sensorType == "power")
++ {
++ return "W";
++ }
++ if (sensorType == "current")
++ {
++ return "A";
++ }
++ if (sensorType == "fan_tach")
++ {
++ return "RPM";
++ }
++ if (sensorType == "temperature")
++ {
++ return "Cel";
++ }
++ if (sensorType == "fan_pwm" || sensorType == "utilization")
++ {
++ return "%";
++ }
++ if (sensorType == "altitude")
++ {
++ return "m";
++ }
++ if (sensorType == "airflow")
++ {
++ return "cft_i/min";
++ }
++ if (sensorType == "energy")
++ {
++ return "J";
++ }
++ return "";
+ }
+ } // namespace sensors
+
+@@ -854,18 +937,8 @@ inline void objectInterfacesToJson(
+ if (sensorsAsyncResp->chassisSubNode == sensors::node::sensors)
+ {
+ sensorJson["@odata.type"] = "#Sensor.v1_0_0.Sensor";
+- if (sensorType == "power")
+- {
+- sensorJson["ReadingUnits"] = "Watts";
+- }
+- else if (sensorType == "current")
+- {
+- sensorJson["ReadingUnits"] = "Amperes";
+- }
+- else if (sensorType == "utilization")
+- {
+- sensorJson["ReadingUnits"] = "Percent";
+- }
++ sensorJson["ReadingType"] = sensors::toReadingType(sensorType);
++ sensorJson["ReadingUnits"] = sensors::toReadingUnits(sensorType);
+ }
+ else if (sensorType == "temperature")
+ {
+@@ -2979,8 +3052,8 @@ inline void retrieveUriToDbusMap(const std::string& chassis,
+ const std::string& node,
+ SensorsAsyncResp::DataCompleteCb&& mapComplete)
+ {
+- auto typesIt = sensors::dbus::types.find(node);
+- if (typesIt == sensors::dbus::types.end())
++ auto pathIt = sensors::dbus::paths.find(node);
++ if (pathIt == sensors::dbus::paths.end())
+ {
+ BMCWEB_LOG_ERROR << "Wrong node provided : " << node;
+ mapComplete(boost::beast::http::status::bad_request, {});
+@@ -2995,7 +3068,7 @@ inline void retrieveUriToDbusMap(const std::string& chassis,
+ uriToDbus) { mapCompleteCb(status, uriToDbus); };
+
+ auto resp = std::make_shared<SensorsAsyncResp>(
+- *respBuffer, chassis, typesIt->second, node, std::move(callback));
++ *respBuffer, chassis, pathIt->second, node, std::move(callback));
+ getChassisData(resp);
+ }
+
+@@ -3030,7 +3103,7 @@ class SensorCollection : public Node
+ const std::string& chassisId = params[0];
+ std::shared_ptr<SensorsAsyncResp> asyncResp =
+ std::make_shared<SensorsAsyncResp>(
+- res, chassisId, sensors::dbus::types.at(sensors::node::sensors),
++ res, chassisId, sensors::dbus::paths.at(sensors::node::sensors),
+ sensors::node::sensors);
+
+ auto getChassisCb =
+diff --git a/redfish-core/lib/thermal.hpp b/redfish-core/lib/thermal.hpp
+index 8e01bee..00acdf9 100644
+--- a/redfish-core/lib/thermal.hpp
++++ b/redfish-core/lib/thermal.hpp
+@@ -48,7 +48,7 @@ class Thermal : public Node
+ }
+ const std::string& chassisName = params[0];
+ auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
+- res, chassisName, sensors::dbus::types.at(sensors::node::thermal),
++ res, chassisName, sensors::dbus::paths.at(sensors::node::thermal),
+ sensors::node::thermal);
+
+ // TODO Need to get Chassis Redundancy information.
+@@ -71,7 +71,7 @@ class Thermal : public Node
+ allCollections;
+
+ auto asyncResp = std::make_shared<SensorsAsyncResp>(
+- res, chassisName, sensors::dbus::types.at(sensors::node::thermal),
++ res, chassisName, sensors::dbus::paths.at(sensors::node::thermal),
+ sensors::node::thermal);
+
+ if (!json_util::readJson(req, asyncResp->res, "Temperatures",
+--
+2.25.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-POST-and-DELETE-in-MetricReportDefinitions.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-POST-and-DELETE-in-MetricReportDefinitions.patch
index fd7e8a445..aaf3f17c7 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-POST-and-DELETE-in-MetricReportDefinitions.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0002-Add-POST-and-DELETE-in-MetricReportDefinitions.patch
@@ -1,4 +1,4 @@
-From bc1635622e122f307fb3b8eb9bbd66ea576a8f0c Mon Sep 17 00:00:00 2001
+From 03c4ece83b58b954323111a1a7b2bf2b61402d7e Mon Sep 17 00:00:00 2001
From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
Date: Mon, 18 May 2020 11:56:57 +0200
Subject: [PATCH 2/4] Add POST and DELETE in MetricReportDefinitions
@@ -31,26 +31,39 @@ Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: I2fed96848594451e22fde686f8c066d7770cc65a
---
meson.build | 1 +
- redfish-core/include/utils/time_utils.hpp | 138 ++++++++++-
- redfish-core/lib/metric_report_definition.hpp | 328 ++++++++++++++++++++++++++
- redfish-core/ut/time_utils_test.cpp | 63 +++++
- 4 files changed, 528 insertions(+), 2 deletions(-)
+ .../include/utils/telemetry_utils.hpp | 2 +
+ redfish-core/include/utils/time_utils.hpp | 138 +++++++-
+ redfish-core/lib/metric_report_definition.hpp | 328 ++++++++++++++++++
+ redfish-core/ut/time_utils_test.cpp | 63 ++++
+ 5 files changed, 530 insertions(+), 2 deletions(-)
create mode 100644 redfish-core/ut/time_utils_test.cpp
diff --git a/meson.build b/meson.build
-index 7a16e91..3d65b01 100644
+index 66a066b..22a8c4a 100644
--- a/meson.build
+++ b/meson.build
-@@ -330,6 +330,7 @@ srcfiles_bmcweb = ['src/webserver_main.cpp','redfish-core/src/error_messages.cpp
- srcfiles_unittest = ['include/ut/dbus_utility_test.cpp',
+@@ -345,6 +345,7 @@ srcfiles_unittest = ['include/ut/dbus_utility_test.cpp',
'redfish-core/ut/privileges_test.cpp',
'redfish-core/ut/lock_test.cpp',
+ 'redfish-core/ut/configfile_test.cpp',
+ 'redfish-core/ut/time_utils_test.cpp',
'http/ut/utility_test.cpp']
# Gather the Configuration data
+diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
+index a3a8156..0a3af5f 100644
+--- a/redfish-core/include/utils/telemetry_utils.hpp
++++ b/redfish-core/include/utils/telemetry_utils.hpp
+@@ -1,5 +1,7 @@
+ #pragma once
+
++#include "dbus_utility.hpp"
++
+ namespace redfish
+ {
+
diff --git a/redfish-core/include/utils/time_utils.hpp b/redfish-core/include/utils/time_utils.hpp
-index dd4ea75..e94801b 100644
+index 4a87ba0..9965d4d 100644
--- a/redfish-core/include/utils/time_utils.hpp
+++ b/redfish-core/include/utils/time_utils.hpp
@@ -1,7 +1,13 @@
@@ -212,7 +225,7 @@ index dd4ea75..e94801b 100644
/**
* @brief Convert time value into duration format that is based on ISO 8601.
* Example output: "P12DT1M5.5S"
-@@ -36,8 +171,7 @@ std::string toDurationString(std::chrono::milliseconds ms)
+@@ -36,8 +171,7 @@ inline std::string toDurationString(std::chrono::milliseconds ms)
std::string fmt;
fmt.reserve(sizeof("PxxxxxxxxxxxxDTxxHxxMxx.xxxxxxS"));
@@ -654,5 +667,5 @@ index 0000000..70999ce
+ EXPECT_THAT(redfish::time_utils::toDurationString(ms), Eq(expected));
+}
--
-2.16.6
+2.17.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch
index 99af0ab86..03feec633 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0003-Add-support-for-MetricDefinition-scheme.patch
@@ -1,4 +1,4 @@
-From 462b2e814698e12a18b4956eb3c6421c34a3a4ba Mon Sep 17 00:00:00 2001
+From b6ccf463b4cfb8df4a904f06c5f4852029a96c50 Mon Sep 17 00:00:00 2001
From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
Date: Tue, 15 Dec 2020 12:28:17 +0100
Subject: [PATCH 3/4] Add support for MetricDefinition scheme
@@ -9,9 +9,6 @@ by Telemetry service. Metrics are grouped by following
categories: temperature, power, voltage, current, fan_tach,
fan_pwm, utilization.
-Added generic function to fill ReadingUnits and ReadingType
-in Sensor node.
-
Tested:
- MetricDefinitions response is filled with existing sensors,
it works with and without Telemetry service
@@ -24,18 +21,15 @@ Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Change-Id: I3086e1302e1ba2e5442d1367939fd5507a0cbc00
---
- redfish-core/include/redfish.hpp | 3 +
- redfish-core/include/utils/telemetry_utils.hpp | 2 +
- redfish-core/lib/metric_definition.hpp | 283 +++++++++++++++++++++++++
- redfish-core/lib/power.hpp | 4 +-
- redfish-core/lib/sensors.hpp | 85 ++++++--
- redfish-core/lib/telemetry_service.hpp | 2 +
- redfish-core/lib/thermal.hpp | 4 +-
- 7 files changed, 361 insertions(+), 22 deletions(-)
+ redfish-core/include/redfish.hpp | 3 +
+ .../include/utils/telemetry_utils.hpp | 2 +
+ redfish-core/lib/metric_definition.hpp | 283 ++++++++++++++++++
+ redfish-core/lib/telemetry_service.hpp | 2 +
+ 4 files changed, 290 insertions(+)
create mode 100644 redfish-core/lib/metric_definition.hpp
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
-index e94c0f3..83f2300 100644
+index aad28ac..dfcb8cd 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -25,6 +25,7 @@
@@ -46,8 +40,8 @@ index e94c0f3..83f2300 100644
#include "../lib/metric_report.hpp"
#include "../lib/metric_report_definition.hpp"
#include "../lib/network_protocol.hpp"
-@@ -213,6 +214,8 @@ class RedfishService
- nodes.emplace_back(std::make_unique<HypervisorSystem>(app));
+@@ -215,6 +216,8 @@ class RedfishService
+ nodes.emplace_back(std::make_unique<HypervisorResetActionInfo>(app));
nodes.emplace_back(std::make_unique<TelemetryService>(app));
+ nodes.emplace_back(std::make_unique<MetricDefinitionCollection>(app));
@@ -56,10 +50,10 @@ index e94c0f3..83f2300 100644
std::make_unique<MetricReportDefinitionCollection>(app));
nodes.emplace_back(std::make_unique<MetricReportDefinition>(app));
diff --git a/redfish-core/include/utils/telemetry_utils.hpp b/redfish-core/include/utils/telemetry_utils.hpp
-index a3a8156..c1b7639 100644
+index 0a3af5f..54b5133 100644
--- a/redfish-core/include/utils/telemetry_utils.hpp
+++ b/redfish-core/include/utils/telemetry_utils.hpp
-@@ -8,6 +8,8 @@ namespace telemetry
+@@ -10,6 +10,8 @@ namespace telemetry
constexpr const char* service = "xyz.openbmc_project.Telemetry";
constexpr const char* reportInterface = "xyz.openbmc_project.Telemetry.Report";
@@ -70,7 +64,7 @@ index a3a8156..c1b7639 100644
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..4a40af5
+index 0000000..f9c7779
--- /dev/null
+++ b/redfish-core/lib/metric_definition.hpp
@@ -0,0 +1,283 @@
@@ -96,7 +90,7 @@ index 0000000..4a40af5
+ crow::connections::systemBus->async_method_call(
+ [asyncResp,
+ callback = std::move(cb)](const boost::system::error_code ec,
-+ std::vector<std::string>& chassises) {
++ std::vector<std::string>& chassis) {
+ if (ec)
+ {
+ messages::internalError(asyncResp->res);
@@ -105,18 +99,18 @@ index 0000000..4a40af5
+ }
+
+ std::vector<std::string> chassisNames;
-+ chassisNames.reserve(chassises.size());
-+ for (const std::string& chassis : chassises)
++ chassisNames.reserve(chassis.size());
++ for (const auto& path : chassis)
+ {
-+ sdbusplus::message::object_path path(chassis);
-+ std::string name = path.filename();
++ sdbusplus::message::object_path dbusPath = path;
++ std::string name = dbusPath.filename();
+ if (name.empty())
+ {
+ messages::internalError(asyncResp->res);
-+ BMCWEB_LOG_ERROR << "Invalid chassis: " << chassis;
++ BMCWEB_LOG_ERROR << "Invalid chassis: " << dbusPath.str;
+ return;
+ }
-+ chassisNames.push_back(name);
++ chassisNames.emplace_back(std::move(name));
+ }
+
+ callback(chassisNames);
@@ -131,14 +125,15 @@ index 0000000..4a40af5
+namespace telemetry
+{
+
-+class DefinitionCollectionReduce
++class MetricDefinitionCollectionReduce
+{
+ public:
-+ DefinitionCollectionReduce(const std::shared_ptr<AsyncResp>& asyncResp) :
++ MetricDefinitionCollectionReduce(
++ const std::shared_ptr<AsyncResp>& asyncResp) :
+ asyncResp{asyncResp}
+ {}
+
-+ ~DefinitionCollectionReduce()
++ ~MetricDefinitionCollectionReduce()
+ {
+ if (asyncResp->res.result() != boost::beast::http::status::ok)
+ {
@@ -179,15 +174,15 @@ index 0000000..4a40af5
+ boost::container::flat_set<std::string> dbusTypes;
+};
+
-+class DefinitionReduce
++class MetricDefinitionReduce
+{
+ public:
-+ DefinitionReduce(const std::shared_ptr<AsyncResp>& asyncResp,
-+ const std::string& id) :
++ MetricDefinitionReduce(const std::shared_ptr<AsyncResp>& asyncResp,
++ const std::string& id) :
+ id(id),
+ pattern{'/' + id + '/'}, asyncResp{asyncResp}
+ {}
-+ ~DefinitionReduce()
++ ~MetricDefinitionReduce()
+ {
+ if (asyncResp->res.result() != boost::beast::http::status::ok)
+ {
@@ -259,11 +254,10 @@ index 0000000..4a40af5
+ res.jsonValue["Members@odata.count"] = 0;
+
+ auto asyncResp = std::make_shared<AsyncResp>(res);
-+ auto collectionReduce =
-+ std::make_shared<telemetry::DefinitionCollectionReduce>(asyncResp);
+ utils::getChassisNames(
-+ [asyncResp,
-+ collectionReduce](const std::vector<std::string>& chassisNames) {
++ [asyncResp](const std::vector<std::string>& chassisNames) {
++ auto collectionReduce = std::make_shared<
++ telemetry::MetricDefinitionCollectionReduce>(asyncResp);
+ for (const std::string& chassisName : chassisNames)
+ {
+ for (const auto& [sensorNode, _] : sensors::dbus::paths)
@@ -322,11 +316,11 @@ index 0000000..4a40af5
+ }
+
+ const std::string& id = params[0];
-+ auto definitionGather =
-+ std::make_shared<telemetry::DefinitionReduce>(asyncResp, id);
+ utils::getChassisNames(
-+ [asyncResp,
-+ definitionGather](const std::vector<std::string>& chassisNames) {
++ [asyncResp, id](const std::vector<std::string>& chassisNames) {
++ auto definitionGather =
++ std::make_shared<telemetry::MetricDefinitionReduce>(
++ asyncResp, id);
+ for (const std::string& chassisName : chassisNames)
+ {
+ for (const auto& [sensorNode, dbusPaths] :
@@ -357,164 +351,6 @@ index 0000000..4a40af5
+};
+
+} // namespace redfish
-diff --git a/redfish-core/lib/power.hpp b/redfish-core/lib/power.hpp
-index 1c7a009..99c45ef 100644
---- a/redfish-core/lib/power.hpp
-+++ b/redfish-core/lib/power.hpp
-@@ -153,7 +153,7 @@ class Power : public Node
- res.jsonValue["PowerControl"] = nlohmann::json::array();
-
- auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
-- res, chassisName, sensors::dbus::types.at(sensors::node::power),
-+ res, chassisName, sensors::dbus::paths.at(sensors::node::power),
- sensors::node::power);
-
- getChassisData(sensorAsyncResp);
-@@ -336,7 +336,7 @@ class Power : public Node
-
- const std::string& chassisName = params[0];
- auto asyncResp = std::make_shared<SensorsAsyncResp>(
-- res, chassisName, sensors::dbus::types.at(sensors::node::power),
-+ res, chassisName, sensors::dbus::paths.at(sensors::node::power),
- sensors::node::power);
-
- std::optional<std::vector<nlohmann::json>> voltageCollections;
-diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
-index 14c9593..5080f77 100644
---- a/redfish-core/lib/sensors.hpp
-+++ b/redfish-core/lib/sensors.hpp
-@@ -54,9 +54,10 @@ static constexpr std::string_view thermal = "Thermal";
-
- namespace dbus
- {
-+
- static const boost::container::flat_map<std::string_view,
- std::vector<const char*>>
-- types = {{node::power,
-+ paths = {{node::power,
- {"/xyz/openbmc_project/sensors/voltage",
- "/xyz/openbmc_project/sensors/power"}},
- {node::sensors,
-@@ -67,6 +68,64 @@ static const boost::container::flat_map<std::string_view,
- {"/xyz/openbmc_project/sensors/fan_tach",
- "/xyz/openbmc_project/sensors/temperature",
- "/xyz/openbmc_project/sensors/fan_pwm"}}};
-+} // namespace dbus
-+
-+inline const char* toReadingType(const std::string& sensorType)
-+{
-+ if (sensorType == "voltage")
-+ {
-+ return "Voltage";
-+ }
-+ if (sensorType == "power")
-+ {
-+ return "Power";
-+ }
-+ if (sensorType == "current")
-+ {
-+ return "Current";
-+ }
-+ if (sensorType == "fan_tach")
-+ {
-+ return "Rotational";
-+ }
-+ if (sensorType == "temperature")
-+ {
-+ return "Temperature";
-+ }
-+ if (sensorType == "fan_pwm" || sensorType == "utilization")
-+ {
-+ return "Percent";
-+ }
-+ return "";
-+}
-+
-+inline const char* toReadingUnits(const std::string& sensorType)
-+{
-+ if (sensorType == "voltage")
-+ {
-+ return "V";
-+ }
-+ if (sensorType == "power")
-+ {
-+ return "W";
-+ }
-+ if (sensorType == "current")
-+ {
-+ return "A";
-+ }
-+ if (sensorType == "fan_tach")
-+ {
-+ return "RPM";
-+ }
-+ if (sensorType == "temperature")
-+ {
-+ return "Cel";
-+ }
-+ if (sensorType == "fan_pwm" || sensorType == "utilization")
-+ {
-+ return "%";
-+ }
-+ return "";
- }
- } // namespace sensors
-
-@@ -345,11 +404,11 @@ inline void reduceSensorList(
- return;
- }
-
-- for (const char* type : sensorsAsyncResp->types)
-+ for (const char* path : sensorsAsyncResp->types)
- {
- for (const std::string& sensor : *allSensors)
- {
-- if (boost::starts_with(sensor, type))
-+ if (boost::starts_with(sensor, path))
- {
- activeSensors->emplace(sensor);
- }
-@@ -853,18 +912,8 @@ inline void objectInterfacesToJson(
- if (sensorsAsyncResp->chassisSubNode == sensors::node::sensors)
- {
- sensorJson["@odata.type"] = "#Sensor.v1_0_0.Sensor";
-- if (sensorType == "power")
-- {
-- sensorJson["ReadingUnits"] = "Watts";
-- }
-- else if (sensorType == "current")
-- {
-- sensorJson["ReadingUnits"] = "Amperes";
-- }
-- else if (sensorType == "utilization")
-- {
-- sensorJson["ReadingUnits"] = "Percent";
-- }
-+ sensorJson["ReadingType"] = sensors::toReadingType(sensorType);
-+ sensorJson["ReadingUnits"] = sensors::toReadingUnits(sensorType);
- }
- else if (sensorType == "temperature")
- {
-@@ -2976,8 +3025,8 @@ inline void retrieveUriToDbusMap(const std::string& chassis,
- const std::string& node,
- SensorsAsyncResp::DataCompleteCb&& mapComplete)
- {
-- auto typesIt = sensors::dbus::types.find(node);
-- if (typesIt == sensors::dbus::types.end())
-+ auto typesIt = sensors::dbus::paths.find(node);
-+ if (typesIt == sensors::dbus::paths.end())
- {
- BMCWEB_LOG_ERROR << "Wrong node provided : " << node;
- mapComplete(boost::beast::http::status::bad_request, {});
-@@ -3027,7 +3076,7 @@ class SensorCollection : public Node
- const std::string& chassisId = params[0];
- std::shared_ptr<SensorsAsyncResp> asyncResp =
- std::make_shared<SensorsAsyncResp>(
-- res, chassisId, sensors::dbus::types.at(sensors::node::sensors),
-+ res, chassisId, sensors::dbus::paths.at(sensors::node::sensors),
- sensors::node::sensors);
-
- auto getChassisCb =
diff --git a/redfish-core/lib/telemetry_service.hpp b/redfish-core/lib/telemetry_service.hpp
index 61ca891..a8c8b03 100644
--- a/redfish-core/lib/telemetry_service.hpp
@@ -528,28 +364,6 @@ index 61ca891..a8c8b03 100644
res.jsonValue["MetricReportDefinitions"]["@odata.id"] =
"/redfish/v1/TelemetryService/MetricReportDefinitions";
res.jsonValue["MetricReports"]["@odata.id"] =
-diff --git a/redfish-core/lib/thermal.hpp b/redfish-core/lib/thermal.hpp
-index 8e01bee..00acdf9 100644
---- a/redfish-core/lib/thermal.hpp
-+++ b/redfish-core/lib/thermal.hpp
-@@ -48,7 +48,7 @@ class Thermal : public Node
- }
- const std::string& chassisName = params[0];
- auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
-- res, chassisName, sensors::dbus::types.at(sensors::node::thermal),
-+ res, chassisName, sensors::dbus::paths.at(sensors::node::thermal),
- sensors::node::thermal);
-
- // TODO Need to get Chassis Redundancy information.
-@@ -71,7 +71,7 @@ class Thermal : public Node
- allCollections;
-
- auto asyncResp = std::make_shared<SensorsAsyncResp>(
-- res, chassisName, sensors::dbus::types.at(sensors::node::thermal),
-+ res, chassisName, sensors::dbus::paths.at(sensors::node::thermal),
- sensors::node::thermal);
-
- if (!json_util::readJson(req, asyncResp->res, "Temperatures",
--
-2.16.6
+2.17.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Sync-Telmetry-service-with-EventService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Sync-Telmetry-service-with-EventService.patch
index 3df9fe5ae..f2ebce6e3 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Sync-Telmetry-service-with-EventService.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0004-Sync-Telmetry-service-with-EventService.patch
@@ -1,4 +1,4 @@
-From 14a429586fd8ccb82c72611fe3310860db2e643b Mon Sep 17 00:00:00 2001
+From efcd128a3d66fce33200fd4211ba5abf13a81375 Mon Sep 17 00:00:00 2001
From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
Date: Tue, 15 Dec 2020 12:30:31 +0100
Subject: [PATCH 4/4] Sync Telmetry service with EventService
@@ -17,12 +17,12 @@ Tested:
Change-Id: I2fc1841a6c9259a8bff30b34bddc0d4aabd41912
Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
---
- redfish-core/include/event_service_manager.hpp | 157 +++++++++----------------
- redfish-core/lib/metric_report.hpp | 28 +++--
- 2 files changed, 71 insertions(+), 114 deletions(-)
+ .../include/event_service_manager.hpp | 156 ++++++------------
+ redfish-core/lib/metric_report.hpp | 28 ++--
+ 2 files changed, 69 insertions(+), 115 deletions(-)
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index 3db9f0c..5c5a6c1 100644
+index 148c703..27e41e3 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -14,6 +14,7 @@
@@ -33,7 +33,7 @@ index 3db9f0c..5c5a6c1 100644
#include "node.hpp"
#include "registries.hpp"
#include "registries/base_message_registry.hpp"
-@@ -510,48 +511,29 @@ class Subscription
+@@ -512,47 +513,32 @@ class Subscription
}
#endif
@@ -62,8 +62,8 @@ index 3db9f0c..5c5a6c1 100644
- nlohmann::json metricValuesArray = nlohmann::json::array();
- for (const auto& it : readings)
-+ nlohmann::json json;
-+ if (!telemetry::fillReport(json, id, var))
++ nlohmann::json msg;
++ if (!telemetry::fillReport(msg, id, var))
{
- metricValuesArray.push_back({});
- nlohmann::json& entry = metricValuesArray.back();
@@ -74,9 +74,12 @@ index 3db9f0c..5c5a6c1 100644
- {"MetricProperty", property},
- {"MetricValue", std::to_string(value)},
- {"Timestamp", crow::utility::getDateTime(timestamp)}};
++ BMCWEB_LOG_ERROR << "Failed to fill the MetricReport for DBus "
++ "Report with id "
++ << id;
+ return;
}
--
+
- nlohmann::json msg = {
- {"@odata.id", "/redfish/v1/TelemetryService/MetricReports/" + id},
- {"@odata.type", "#MetricReport.v1_3_0.MetricReport"},
@@ -86,43 +89,31 @@ index 3db9f0c..5c5a6c1 100644
- {"MetricReportDefinition", {{"@odata.id", metricReportDef}}},
- {"MetricValues", metricValuesArray}};
-
-- this->sendEvent(msg.dump());
-+ this->sendEvent(json.dump());
+ this->sendEvent(
+ msg.dump(2, ' ', true, nlohmann::json::error_handler_t::replace));
}
-
- void updateRetryConfig(const uint32_t retryAttempts,
-@@ -1342,56 +1324,72 @@ class EventServiceManager
+@@ -1348,75 +1334,6 @@ class EventServiceManager
}
#endif
-
- void getMetricReading(const std::string& service,
- const std::string& objPath, const std::string& intf)
-+ void unregisterMetricReportSignal()
- {
+- {
- std::size_t found = objPath.find_last_of('/');
- if (found == std::string::npos)
-+ if (matchTelemetryMonitor)
- {
+- {
- BMCWEB_LOG_DEBUG << "Invalid objPath received";
- return;
-+ BMCWEB_LOG_DEBUG << "Metrics report signal - Unregister";
-+ matchTelemetryMonitor.reset();
-+ matchTelemetryMonitor = nullptr;
- }
-+ }
-
+- }
+-
- std::string idStr = objPath.substr(found + 1);
- if (idStr.empty())
-+ void registerMetricReportSignal()
-+ {
-+ if (!serviceEnabled || matchTelemetryMonitor)
- {
+- {
- BMCWEB_LOG_DEBUG << "Invalid ID in objPath";
-+ BMCWEB_LOG_DEBUG << "Not registering metric report signal.";
- return;
- }
-
+- return;
+- }
+-
- crow::connections::systemBus->async_method_call(
- [idStr{std::move(idStr)}](
- const boost::system::error_code ec,
@@ -130,120 +121,113 @@ index 3db9f0c..5c5a6c1 100644
- std::string, std::variant<int32_t, ReadingsObjType>>&
- resp) {
- if (ec)
-+ BMCWEB_LOG_DEBUG << "Metrics report signal - Register";
-+ std::string matchStr = "type='signal',member='PropertiesChanged',"
-+ "interface='org.freedesktop.DBus.Properties',"
-+ "path_namespace=/xyz/openbmc_project/Telemetry/"
-+ "Reports/TelemetryService,"
-+ "arg0=xyz.openbmc_project.Telemetry.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_DEBUG
- << "D-Bus call failed to GetAll metric readings.";
-+ BMCWEB_LOG_ERROR << "TelemetryMonitor Signal error";
- return;
- }
-
+- return;
+- }
+-
- const int32_t* timestampPtr =
- std::get_if<int32_t>(&resp["Timestamp"]);
- if (!timestampPtr)
-+ std::string intf;
-+ std::vector<std::pair<
-+ std::string, std::variant<telemetry::TimestampReadings>>>
-+ props;
-+ std::vector<std::string> invalidProp;
-+
-+ msg.read(intf, props, invalidProp);
-+ if (intf != "xyz.openbmc_project.Telemetry.Report")
- {
+- {
- BMCWEB_LOG_DEBUG << "Failed to Get timestamp.";
- return;
- }
-
+- return;
+- }
+-
- ReadingsObjType* readingsPtr =
- std::get_if<ReadingsObjType>(&resp["Readings"]);
- if (!readingsPtr)
-+ const std::variant<telemetry::TimestampReadings>* varPtr =
-+ nullptr;
-+ for (const auto& [key, var] : props)
-+ {
-+ if (key == "Readings")
-+ {
-+ varPtr = &var;
-+ break;
-+ }
-+ }
-+ if (!varPtr)
- {
+- {
- BMCWEB_LOG_DEBUG << "Failed to Get Readings property.";
- return;
- }
-
+- return;
+- }
+-
- if (!readingsPtr->size())
-+ sdbusplus::message::object_path path(msg.get_path());
-+ std::string id = path.filename();
-+ if (id.empty())
- {
+- {
- BMCWEB_LOG_DEBUG << "No metrics report to be transferred";
-+ BMCWEB_LOG_ERROR << "Failed to get Id from path";
- return;
- }
-
-@@ -1401,52 +1399,9 @@ class EventServiceManager
- std::shared_ptr<Subscription> entry = it.second;
- if (entry->eventFormatType == metricReportFormatType)
- {
+- 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);
-+ entry->filterAndSendReports(id, *varPtr);
- }
- }
+- }
+- }
- },
- service, objPath, "org.freedesktop.DBus.Properties", "GetAll",
- intf);
- }
-
-- void unregisterMetricReportSignal()
-- {
-- if (matchTelemetryMonitor)
-- {
-- BMCWEB_LOG_DEBUG << "Metrics report signal - Unregister";
-- matchTelemetryMonitor.reset();
-- matchTelemetryMonitor = nullptr;
-- }
-- }
--
-- void registerMetricReportSignal()
-- {
-- if (!serviceEnabled || matchTelemetryMonitor)
-- {
-- BMCWEB_LOG_DEBUG << "Not registering metric report signal.";
-- return;
-- }
--
-- BMCWEB_LOG_DEBUG << "Metrics report signal - Register";
+ void unregisterMetricReportSignal()
+ {
+ if (matchTelemetryMonitor)
+@@ -1436,9 +1353,11 @@ class EventServiceManager
+ }
+
+ BMCWEB_LOG_DEBUG << "Metrics report signal - Register";
- std::string matchStr(
- "type='signal',member='ReportUpdate', "
- "interface='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";
-- return;
-- }
--
++ std::string matchStr = "type='signal',member='PropertiesChanged',"
++ "interface='org.freedesktop.DBus.Properties',"
++ "path_namespace=/xyz/openbmc_project/Telemetry/"
++ "Reports/TelemetryService,"
++ "arg0=xyz.openbmc_project.Telemetry.Report";
+
+ matchTelemetryMonitor = std::make_shared<sdbusplus::bus::match::match>(
+ *crow::connections::systemBus, matchStr,
+@@ -1449,10 +1368,43 @@ class EventServiceManager
+ return;
+ }
+
- std::string service = msg.get_sender();
- std::string objPath = msg.get_path();
- std::string intf = msg.get_interface();
- getMetricReading(service, objPath, intf);
++ sdbusplus::message::object_path path(msg.get_path());
++ std::string id = path.filename();
++ if (id.empty())
++ {
++ BMCWEB_LOG_ERROR << "Failed to get Id from path";
++ return;
++ }
++
++ std::string intf;
++ std::vector<std::pair<
++ std::string, std::variant<telemetry::TimestampReadings>>>
++ props;
++ std::vector<std::string> invalidProps;
++ msg.read(intf, props, invalidProps);
++
++ auto found =
++ std::find_if(props.begin(), props.end(), [](const auto& x) {
++ return x.first == "Readings";
++ });
++ if (found == props.end())
++ {
++ BMCWEB_LOG_ERROR
++ << "Failed to get Readings from Report properties";
++ return;
++ }
++
++ std::variant<telemetry::TimestampReadings>& readings =
++ found->second;
++ for (const auto& it :
++ EventServiceManager::getInstance().subscriptionsMap)
++ {
++ Subscription& entry = *it.second.get();
++ if (entry.eventFormatType == metricReportFormatType)
++ {
++ entry.filterAndSendReports(id, readings);
++ }
++ }
});
}
@@ -307,5 +291,5 @@ index 9caf4a3..e79a41c 100644
telemetry::service, reportPath,
"org.freedesktop.DBus.Properties", "Get",
--
-2.16.6
+2.17.1
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
index 35c6e90bc..cfb47a49b 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/README
@@ -3,11 +3,11 @@ Until change is integrated they will be manually merged here to enable feature i
Current revisions:
- Add POST and DELETE in MetricReportDefinitions
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/32536/58
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/32536/63
- Add support for MetricDefinition scheme
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/54
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/33363/60
- Sync Telmetry service with EventService
- https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/38798/21
+ https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/38798/26
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
index db8a7a90f..d42618b78 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb_%.bbappend
@@ -1,5 +1,5 @@
SRC_URI = "git://github.com/openbmc/bmcweb.git"
-SRCREV = "2b3da45876aac57a36d3093379a992d699e7e396"
+SRCREV = "8e6c099ac8d4b4b3163a26b58fa0f9abb987979a"
DEPENDS += "boost-url"
RDEPENDS_${PN} += "phosphor-nslcd-authority-cert-config"
@@ -15,7 +15,6 @@ GROUPADD_PARAM_${PN} = "web; redfish "
SRC_URI += "file://0001-Firmware-update-configuration-changes.patch \
file://0002-Use-chip-id-based-UUID-for-Service-Root.patch \
file://0004-bmcweb-handle-device-or-resource-busy-exception.patch \
- file://0005-EventService-https-client-support.patch \
file://0006-Define-Redfish-interface-Registries-Bios.patch \
file://0007-BIOS-config-Add-support-for-PATCH-operation.patch \
file://0008-Add-support-to-ResetBios-action.patch \
@@ -28,8 +27,18 @@ SRC_URI += "file://0001-Firmware-update-configuration-changes.patch \
SRC_URI += "file://0037-Add-state-sensor-messages-to-the-registry.patch \
"
+# EventService: Temporary pulled to downstream. See eventservice\README for details
+SRC_URI += "file://eventservice/0001-EventService-Fix-retry-handling-for-http-client.patch \
+ file://eventservice/0002-EventService-https-client-support.patch \
+ file://eventservice/0003-Move-EventService-init-to-later-stage.patch \
+ file://eventservice/0004-Add-Server-Sent-Events-support.patch \
+ file://eventservice/0005-Add-SSE-style-subscription-support-to-eventservice.patch \
+ file://eventservice/0006-Add-EventService-SSE-filter-support.patch \
+"
+
# Temporary downstream mirror of upstream patches, see telemetry\README for details
-SRC_URI += "file://telemetry/0002-Add-POST-and-DELETE-in-MetricReportDefinitions.patch \
+SRC_URI += "file://telemetry/0001-Sync_ReadingUnit_with_Redfish_Sensor_Schema.patch \
+ file://telemetry/0002-Add-POST-and-DELETE-in-MetricReportDefinitions.patch \
file://telemetry/0003-Add-support-for-MetricDefinition-scheme.patch \
file://telemetry/0004-Sync-Telmetry-service-with-EventService.patch \
"
@@ -39,6 +48,9 @@ SRC_URI += "file://0001-Add-ConnectedVia-property-to-virtual-media-item-temp.pat
file://0003-Set-Inserted-redfish-property-for-not-inserted-resou.patch \
"
+SRC_URI += "file://0038-Revert-Disable-nbd-proxy-from-the-build.patch \
+"
+
# Temporary fix: Move it to service file
do_install_append() {
install -d ${D}/var/lib/bmcweb
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/peci/peci-pcie_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/peci/peci-pcie_%.bbappend
index 6744b172c..48f72ab36 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/peci/peci-pcie_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/peci/peci-pcie_%.bbappend
@@ -1,3 +1,3 @@
SRC_URI = "git://github.com/openbmc/peci-pcie"
-SRCREV = "0b79f3e485554957a4b24d5f0cefc5bc577ad301"
+SRCREV = "d570dfd4f3a7c38b029f74a8194eeb3911b5f6a5"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb
index de34f59a9..ae498beb8 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libmctp-intel_git.bb
@@ -2,7 +2,7 @@ SUMMARY = "libmctp_intel"
DESCRIPTION = "Implementation of MCTP(DMTF DSP0236)"
SRC_URI = "git://github.com/Intel-BMC/libmctp.git;protocol=ssh"
-SRCREV = "f1532e4b19ff198d20782adf5fb9dcce36eea995"
+SRCREV = "dca36d524d22d6efab3f7bfd6adda69dbebb1bf3"
S = "${WORKDIR}/git"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libpldm-intel_git.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libpldm-intel_git.bb
index 1b4be8136..0ed7add07 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libpldm-intel_git.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/libpldm-intel_git.bb
@@ -2,7 +2,7 @@ SUMMARY = "libpldm_intel"
DESCRIPTION = "Provides encode/decode APIs for PLDM specifications"
SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "86d4e9d3f2214c825ed76b38865abc47d2c7a11f"
+SRCREV = "07adfb357cdb679bf9bbcf2eaff7406cfb5fd52b"
S = "${WORKDIR}/git/libpldm_intel"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb
index 02921bae6..6a418c330 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-emulator.bb
@@ -5,7 +5,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=bcd9ada3a943f58551867d72893cc9ab"
SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "86d4e9d3f2214c825ed76b38865abc47d2c7a11f"
+SRCREV = "07adfb357cdb679bf9bbcf2eaff7406cfb5fd52b"
S = "${WORKDIR}/git/mctp_emulator"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-wrapper.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-wrapper.bb
index 4fdd3b0d6..3e8119c66 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-wrapper.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctp-wrapper.bb
@@ -5,7 +5,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=bcd9ada3a943f58551867d72893cc9ab"
SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "86d4e9d3f2214c825ed76b38865abc47d2c7a11f"
+SRCREV = "07adfb357cdb679bf9bbcf2eaff7406cfb5fd52b"
S = "${WORKDIR}/git/mctp_wrapper"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb
index a48a45513..c152eef70 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpd.bb
@@ -5,7 +5,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${PN}/LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "86d4e9d3f2214c825ed76b38865abc47d2c7a11f"
+SRCREV = "07adfb357cdb679bf9bbcf2eaff7406cfb5fd52b"
S = "${WORKDIR}/git"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpwplus.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpwplus.bb
index 837560d78..1fbeefced 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpwplus.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/mctpwplus.bb
@@ -5,7 +5,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=615045c30a05cde5c0e924854d43c327"
SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "86d4e9d3f2214c825ed76b38865abc47d2c7a11f"
+SRCREV = "07adfb357cdb679bf9bbcf2eaff7406cfb5fd52b"
S = "${WORKDIR}/git/mctpwplus"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/nvmemi-daemon.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/nvmemi-daemon.bb
index 510535363..d53ac712e 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/nvmemi-daemon.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/nvmemi-daemon.bb
@@ -4,14 +4,14 @@ DESCRIPTION = "Implementation of NVMe MI daemon"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
-SRC_URI = "git://github.com/Intel-BMC/nvme-mi.git;protocol=ssh;nobranch=1"
-SRCREV = "23fad1d6ffd8ccd16b1369b96734a9701fc2802a"
+SRC_URI = "git://github.com/Intel-BMC/nvme-mi.git;protocol=ssh"
+SRCREV = "63e1cf7f8b950d37fdb035745bf740ec87ede6ae"
S = "${WORKDIR}/git"
PV = "1.0+git${SRCPV}"
inherit meson systemd
SYSTEMD_SERVICE_${PN} += "xyz.openbmc_project.nvme-mi.service"
-DEPENDS = "boost sdbusplus systemd phosphor-logging mctpwplus googletest"
+DEPENDS = "boost sdbusplus systemd phosphor-logging mctpwplus googletest nlohmann-json"
EXTRA_OEMESON = "-Dyocto_dep='enabled' -Dtests='enabled'"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pldmd.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pldmd.bb
index a561bfa23..08571570b 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pldmd.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pldmd.bb
@@ -5,7 +5,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327"
SRC_URI += "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "86d4e9d3f2214c825ed76b38865abc47d2c7a11f"
+SRCREV = "07adfb357cdb679bf9bbcf2eaff7406cfb5fd52b"
S = "${WORKDIR}/git/pldmd"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pmci-launcher.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pmci-launcher.bb
index 02e4c5ad8..8b4ee807a 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pmci-launcher.bb
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/pmci/pmci-launcher.bb
@@ -5,7 +5,7 @@ LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://LICENSE;md5=e3fc50a88d0a364313df4b21ef20c29e"
SRC_URI = "git://github.com/Intel-BMC/pmci.git;protocol=ssh"
-SRCREV = "86d4e9d3f2214c825ed76b38865abc47d2c7a11f"
+SRCREV = "07adfb357cdb679bf9bbcf2eaff7406cfb5fd52b"
S = "${WORKDIR}/git/pmci_launcher"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
index bb1268e0a..d0370ba00 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -1,7 +1,7 @@
FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
PROJECT_SRC_DIR := "${THISDIR}/${PN}"
-SRCREV = "d05867c0d32065d36b13bd452f7aff9dcb20ac2f"
+SRCREV = "0947d7c1cb9dc5ae4bc740d18aff059cb896c309"
#SRC_URI = "git://github.com/openbmc/dbus-sensors.git"
SRC_URI += "\
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/telemetry/telemetry_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/telemetry/telemetry_%.bbappend
index 1c8de604c..dcbe656b1 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/telemetry/telemetry_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/telemetry/telemetry_%.bbappend
@@ -1,5 +1,5 @@
SRC_URI = "git://github.com/openbmc/telemetry.git"
-SRCREV = "9f9ff90a39219ff3a2f1179f74fc9a6dc857e5ab"
+SRCREV = "d7cebdd37fade28b0efd34bb9d641135bff758a0"
EXTRA_OEMESON += " -Dmax-reports=5"
EXTRA_OEMESON += " -Dmax-reading-parameters=200"
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend
index 87ad21d71..bdb411121 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/webui/webui-vue_%.bbappend
@@ -1,6 +1,6 @@
# Enable downstream autobump
SRC_URI = "git://github.com/openbmc/webui-vue.git"
-SRCREV = "b0fadef1f96df99ff5eb0637527f04bc793c8d6e"
+SRCREV = "1915d8c4992c1a4165e8ae108e4d799b3b4ce86a"
do_compile_prepend() {
cp -vf ${S}/.env.intel ${S}/.env
diff --git a/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend b/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend
index 6681e7075..26c96db24 100755
--- a/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend
+++ b/meta-openbmc-mods/meta-common/recipes-x86/chassis/x86-power-control_%.bbappend
@@ -1,6 +1,6 @@
# Enable downstream autobump
SRC_URI = "git://github.com/openbmc/x86-power-control.git;protocol=ssh"
-SRCREV = "22e0bec01e283819c13310640918c89f4a74fb56"
+SRCREV = "92caa4c639903ef076e2f09e985291781edd927d"
FILESEXTRAPATHS_append := "${THISDIR}/${PN}:"
diff --git a/meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample b/meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample
index f76660ab9..546cd7b31 100644
--- a/meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample
+++ b/meta-openbmc-mods/meta-wht/conf/bblayers.conf.sample
@@ -1,6 +1,6 @@
# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
-LCONF_VERSION = "13"
+LCONF_VERSION = "14"
BBPATH = "${TOPDIR}"
BBFILES ?= ""
diff --git a/meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample b/meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample
index 4b9445344..925cdbd97 100644
--- a/meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample
+++ b/meta-openbmc-mods/meta-wolfpass/conf/bblayers.conf.sample
@@ -1,6 +1,6 @@
# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
-LCONF_VERSION = "13"
+LCONF_VERSION = "14"
BBPATH = "${TOPDIR}"
BBFILES ?= ""