summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb
diff options
context:
space:
mode:
authorJason M. Bills <jason.m.bills@linux.intel.com>2020-09-21 22:59:23 +0300
committerJason M. Bills <jason.m.bills@linux.intel.com>2020-09-22 00:17:37 +0300
commit5d3fc64c142786581d792d145231c835afbcdded (patch)
tree18d6cc15665dd2a3cf3ffbdf72cc3aabedc1ba1b /meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb
parentf99301c1a626951ee7feee081a1494e795d0e243 (diff)
downloadopenbmc-5d3fc64c142786581d792d145231c835afbcdded.tar.xz
Update to internal 0.74-57
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb')
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch390
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0007-cpudimm-get-cpu-details-from-Redfish.patch231
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0008-systems-Fix-for-Processor-Summary-Model.patch138
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-MetricReportDefinitions-filter-not-working.patch112
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch33
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-Fix-EventService-stops-sending-events.patch67
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0011-Deallocate-memory-during-failed-case.patch32
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0012-System-Replace-chassis-name-in-Redfish.patch64
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0013-url_view-throws-if-a-parse-error-is-found.patch54
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0014-add-sufficient-delay-to-create-fw-update-object.patch44
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0015-Add-firmware-activation-messages-to-the-registry.patch72
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0016-EventService-Fix-type-mismatch-in-MetricReport.patch (renamed from meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch)23
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0017-Add-MutualExclusiveProperties-registry.patch151
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0018-Add-sse-event-sequence-number.patch74
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-EventService-Limit-SSE-connections-as-per-design.patch108
-rw-r--r--meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch262
16 files changed, 1694 insertions, 161 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
index 274dd044a..23eac280d 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0005-EventService-https-client-support.patch
@@ -1,4 +1,4 @@
-From f388587781c3d874b13b50ad39e8674f0bc08049 Mon Sep 17 00:00:00 2001
+From 1f91d5708cbe30610c0c8bbc4910709b99b8f270 Mon Sep 17 00:00:00 2001
From: AppaRao Puli <apparao.puli@linux.intel.com>
Date: Mon, 25 May 2020 16:14:39 +0530
Subject: [PATCH] EventService: https client support
@@ -17,12 +17,12 @@ Tested:
Change-Id: I44c3918b39baa2eb5fddda9d635f99aa280a422a
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
---
- http/http_client.hpp | 270 +++++++++++++++++--------
+ http/http_client.hpp | 325 +++++++++++++++++--------
redfish-core/include/event_service_manager.hpp | 2 +-
- 2 files changed, 186 insertions(+), 86 deletions(-)
+ 2 files changed, 226 insertions(+), 101 deletions(-)
diff --git a/http/http_client.hpp b/http/http_client.hpp
-index e6a7db1..27d2af3 100644
+index e6a7db1..6d3d702 100644
--- a/http/http_client.hpp
+++ b/http/http_client.hpp
@@ -17,6 +17,7 @@
@@ -33,19 +33,42 @@ index e6a7db1..27d2af3 100644
#include <boost/beast/version.hpp>
#include <cstdlib>
-@@ -49,7 +50,10 @@ enum class ConnState
+@@ -30,12 +31,14 @@ namespace crow
+ {
+
+ static constexpr uint8_t maxRequestQueueSize = 50;
++static constexpr unsigned int httpReadBodyLimit = 1024;
+
+ enum class ConnState
+ {
+ initialized,
+ connectInProgress,
+ connectFailed,
++ sslHandshakeInProgress,
+ connected,
+ sendInProgress,
+ sendFailed,
+@@ -49,53 +52,97 @@ enum class ConnState
class HttpClient : public std::enable_shared_from_this<HttpClient>
{
private:
-- boost::beast::tcp_stream conn;
-+ boost::asio::io_context& ioc;
+ boost::asio::ssl::context ctx{boost::asio::ssl::context::tlsv12_client};
-+ std::shared_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>> sslConn;
-+ std::shared_ptr<boost::beast::tcp_stream> conn;
+ boost::beast::tcp_stream conn;
++ std::optional<boost::beast::ssl_stream<boost::beast::tcp_stream&>> sslConn;
boost::asio::steady_timer timer;
- boost::beast::flat_buffer buffer;
+- boost::beast::flat_buffer buffer;
++ boost::beast::flat_static_buffer<httpReadBodyLimit> buffer;
++ std::optional<
++ boost::beast::http::response_parser<boost::beast::http::string_body>>
++ parser;
boost::beast::http::request<boost::beast::http::string_body> req;
-@@ -62,14 +66,37 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+- boost::beast::http::response<boost::beast::http::string_body> res;
+ boost::asio::ip::tcp::resolver::results_type endpoint;
+- std::vector<std::pair<std::string, std::string>> headers;
++ boost::beast::http::fields fields;
+ std::queue<std::string> requestDataQueue;
+- ConnState state;
+ std::string subId;
std::string host;
std::string port;
std::string uri;
@@ -55,59 +78,28 @@ index e6a7db1..27d2af3 100644
uint32_t retryIntervalSecs;
std::string retryPolicyAction;
bool runningTimer;
++ ConnState state;
-+ inline boost::beast::tcp_stream& getConn()
-+ {
-+ if (useSsl)
-+ {
-+ return (boost::beast::get_lowest_layer(*sslConn));
-+ }
-+ else
-+ {
-+ return (*conn);
-+ }
-+ }
-+
void doConnect()
{
+- if (state == ConnState::connectInProgress)
+ if (useSsl)
+ {
-+ sslConn = std::make_shared<
-+ boost::beast::ssl_stream<boost::beast::tcp_stream>>(ioc, ctx);
-+ }
-+ else
-+ {
-+ conn = std::make_shared<boost::beast::tcp_stream>(ioc);
++ sslConn.emplace(conn, ctx);
+ }
+
- if (state == ConnState::connectInProgress)
++ if ((state == ConnState::connectInProgress) ||
++ (state == ConnState::sslHandshakeInProgress))
{
return;
-@@ -77,25 +104,53 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
state = ConnState::connectInProgress;
BMCWEB_LOG_DEBUG << "Trying to connect to: " << host << ":" << port;
- // Set a timeout on the operation
-- conn.expires_after(std::chrono::seconds(30));
-- conn.async_connect(endpoint, [self(shared_from_this())](
-- const boost::beast::error_code& ec,
-- const boost::asio::ip::tcp::resolver::
-- results_type::endpoint_type& ep) {
-- if (ec)
-- {
-- BMCWEB_LOG_ERROR << "Connect " << ep
-- << " failed: " << ec.message();
-- self->state = ConnState::connectFailed;
-- self->checkQueue();
-- return;
-- }
-- self->state = ConnState::connected;
-- BMCWEB_LOG_DEBUG << "Connected to: " << ep;
-
-- self->checkQueue();
-- });
++
+ auto respHandler =
-+ [self(shared_from_this())](const boost::beast::error_code& ec,
++ [self(shared_from_this())](const boost::beast::error_code ec,
+ const boost::asio::ip::tcp::resolver::
+ results_type::endpoint_type& ep) {
+ if (ec)
@@ -119,7 +111,7 @@ index e6a7db1..27d2af3 100644
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "Connected to: " << ep;
-+ if (self->useSsl)
++ if (self->sslConn)
+ {
+ self->performHandshake();
+ }
@@ -130,57 +122,91 @@ index e6a7db1..27d2af3 100644
+ }
+ };
+
-+ getConn().expires_after(std::chrono::seconds(30));
-+ getConn().async_connect(endpoint, std::move(respHandler));
+ conn.expires_after(std::chrono::seconds(30));
+- conn.async_connect(endpoint, [self(shared_from_this())](
+- const boost::beast::error_code& ec,
+- const boost::asio::ip::tcp::resolver::
+- results_type::endpoint_type& ep) {
+- if (ec)
+- {
+- BMCWEB_LOG_ERROR << "Connect " << ep
+- << " failed: " << ec.message();
+- self->state = ConnState::connectFailed;
+- self->checkQueue();
+- return;
+- }
+- self->state = ConnState::connected;
+- BMCWEB_LOG_DEBUG << "Connected to: " << ep;
++ conn.async_connect(endpoint, std::move(respHandler));
+ }
-+
+
+- self->checkQueue();
+- });
+ void performHandshake()
+ {
++ if (state == ConnState::sslHandshakeInProgress)
++ {
++ return;
++ }
++ state = ConnState::sslHandshakeInProgress;
++
+ sslConn->async_handshake(
+ boost::asio::ssl::stream_base::client,
-+ [self(shared_from_this())](const boost::beast::error_code& ec) {
++ [self(shared_from_this())](const boost::beast::error_code ec) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR << "SSL handshake failed: "
+ << ec.message();
-+ self->state = ConnState::connectFailed;
-+ self->doCloseAndCheckQueue();
++ self->doCloseAndCheckQueue(ConnState::connectFailed);
+ return;
+ }
+ self->state = ConnState::connected;
-+ BMCWEB_LOG_DEBUG << "SSL Handshake successfull \n";
++ BMCWEB_LOG_DEBUG << "SSL Handshake successfull";
+
+ self->checkQueue();
+ });
}
void sendMessage(const std::string& data)
-@@ -108,7 +163,10 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
-
- BMCWEB_LOG_DEBUG << __FUNCTION__ << "(): " << host << ":" << port;
+@@ -106,100 +153,167 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ }
+ 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);
++ BMCWEB_LOG_DEBUG << host << ":" << port;
+
+- // Set headers
+- for (const auto& [key, value] : headers)
+ req = {};
-+ res = {};
++ for (const auto& field : fields)
+ {
+- req.set(key, value);
++ req.set(field.name_string(), field.value());
+ }
+ req.set(boost::beast::http::field::host, host);
++ req.set(boost::beast::http::field::content_type, "text/plain");
+
-+ req.version(11); // HTTP 1.1
- req.target(uri);
- req.method(boost::beast::http::verb::post);
++ req.version(static_cast<int>(11)); // HTTP 1.1
++ req.target(uri);
++ req.method(boost::beast::http::verb::post);
+ req.keep_alive(true);
-@@ -123,83 +181,121 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
req.body() = data;
req.prepare_payload();
- // Set a timeout on the operation
- conn.expires_after(std::chrono::seconds(30));
+ auto respHandler = [self(shared_from_this())](
-+ const boost::beast::error_code& ec,
++ 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->doCloseAndCheckQueue();
++ self->doCloseAndCheckQueue(ConnState::sendFailed);
+ return;
+ }
+ BMCWEB_LOG_DEBUG << "sendMessage() bytes transferred: "
@@ -208,15 +234,15 @@ index e6a7db1..27d2af3 100644
- self->recvMessage();
- });
-+ getConn().expires_after(std::chrono::seconds(30));
-+ if (useSsl)
++ 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));
++ boost::beast::http::async_write(conn, req, std::move(respHandler));
+ }
}
@@ -227,109 +253,141 @@ index e6a7db1..27d2af3 100644
- conn, buffer, res,
- [self(shared_from_this())](const boost::beast::error_code& ec,
- const std::size_t& bytesTransferred) {
-- if (ec)
-- {
-- BMCWEB_LOG_ERROR << "recvMessage() failed: "
-- << ec.message();
-- self->state = ConnState::recvFailed;
-- self->checkQueue();
-- return;
-- }
-- BMCWEB_LOG_DEBUG << "recvMessage() bytes transferred: "
-- << bytesTransferred;
-- boost::ignore_unused(bytesTransferred);
+ auto respHandler = [self(shared_from_this())](
-+ const boost::beast::error_code& ec,
++ const boost::beast::error_code ec,
+ const std::size_t& bytesTransferred) {
+ if (ec && ec != boost::beast::http::error::partial_message)
+ {
+ BMCWEB_LOG_ERROR << "recvMessage() failed: " << ec.message();
-+ self->state = ConnState::recvFailed;
-+ self->doCloseAndCheckQueue();
++ self->doCloseAndCheckQueue(ConnState::recvFailed);
+ 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;
-+ // Discard received data. We are not interested.
-+ BMCWEB_LOG_DEBUG << "recvMessage() data: " << self->res;
-
-- // Send is successful, Lets remove data from queue
-- // check for next request data in queue.
-- self->requestDataQueue.pop();
-- self->state = ConnState::idle;
-- self->checkQueue();
-- });
++
++ // TODO: check for return status code and perform
++ // retry if fails(Ex: 40x). Take action depending on
++ // retry policy.
++ BMCWEB_LOG_DEBUG << "recvMessage() data: "
++ << self->parser->get().body();
++
+ // Send is successful, Lets remove data from queue
+ // check for next request data in queue.
+ self->requestDataQueue.pop();
-+ self->state = ConnState::idle;
+
-+ if (ec == boost::beast::http::error::partial_message)
-+ {
-+ // Least bothered about recv message. Partial
-+ // message means, already data is sent. Lets close
-+ // connection and let next request open connection
-+ // to avoid truncated stream.
-+ self->state = ConnState::closed;
-+ self->doCloseAndCheckQueue();
-+ return;
-+ }
++ // Transfer ownership of the response
++ self->parser->release();
+
-+ self->checkQueue();
++ // TODO: Implement the keep-alive connections.
++ // Most of the web servers close connection abruptly
++ // and might be reason due to which its observed that
++ // stream_truncated(Next read) or partial_message
++ // errors. So for now, closing connection and re-open
++ // for all cases.
++ self->doCloseAndCheckQueue(ConnState::closed);
+ };
+
-+ getConn().expires_after(std::chrono::seconds(30));
-+ if (useSsl)
++ parser.emplace(std::piecewise_construct, std::make_tuple());
++ parser->body_limit(httpReadBodyLimit);
++ buffer.consume(buffer.size());
++
++ conn.expires_after(std::chrono::seconds(30));
++ if (sslConn)
+ {
-+ boost::beast::http::async_read(*sslConn, buffer, res,
++ boost::beast::http::async_read(*sslConn, buffer, *parser,
+ std::move(respHandler));
+ }
+ else
+ {
-+ boost::beast::http::async_read(*conn, buffer, res,
++ boost::beast::http::async_read(conn, buffer, *parser,
+ std::move(respHandler));
+ }
- }
-
++ }
++
++ void doCloseAndCheckQueue(const ConnState setState = ConnState::closed)
++ {
++ if (sslConn)
++ {
++ conn.expires_after(std::chrono::seconds(30));
++ sslConn->async_shutdown([self = shared_from_this(),
++ setState{std::move(setState)}](
++ const boost::system::error_code ec) {
+ if (ec)
+ {
+- BMCWEB_LOG_ERROR << "recvMessage() failed: "
+- << ec.message();
+- self->state = ConnState::recvFailed;
+- self->checkQueue();
+- 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_ERROR
++ << "doCloseAndCheckQueue(): Connection "
++ "closed by server. ";
++ }
++ else
++ {
++ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
++ << ec.message();
++ }
+ }
+- 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;
+-
+- // Send is successful, Lets remove data from queue
+- // check for next request data in queue.
+- self->requestDataQueue.pop();
+- self->state = ConnState::idle;
++ else
++ {
++ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
++ }
++ self->conn.cancel();
++ self->state = setState;
+ self->checkQueue();
+ });
+- }
+-
- void doClose()
-+ void doCloseAndCheckQueue()
- {
- boost::beast::error_code ec;
+- {
+- boost::beast::error_code ec;
- conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
-+ getConn().cancel();
-+ getConn().expires_after(std::chrono::seconds(30));
-+ getConn().socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
-+ ec);
-
+-
- state = ConnState::closed;
- // not_connected happens sometimes so don't bother reporting it.
- if (ec && ec != boost::beast::errc::not_connected)
-+ if (ec && ec != boost::asio::error::eof)
++ }
++ else
{
- BMCWEB_LOG_ERROR << "shutdown failed: " << ec.message();
- 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)
++ boost::beast::error_code ec;
++ conn.expires_after(std::chrono::seconds(30));
++ conn.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both,
++ ec);
++ if (ec)
+ {
-+ BMCWEB_LOG_DEBUG
-+ << "doCloseAndCheckQueue(): Connection closed by server.";
++ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
++ << ec.message();
+ }
+ else
+ {
-+ BMCWEB_LOG_ERROR << "doCloseAndCheckQueue() failed: "
-+ << ec.message();
++ BMCWEB_LOG_DEBUG << "Connection closed gracefully...";
+ }
- }
+
-+ getConn().close();
- BMCWEB_LOG_DEBUG << "Connection closed gracefully";
-+ checkQueue();
++ conn.close();
++ state = setState;
++ checkQueue();
+ }
+- BMCWEB_LOG_DEBUG << "Connection closed gracefully";
+ return;
}
@@ -344,7 +402,7 @@ index e6a7db1..27d2af3 100644
BMCWEB_LOG_DEBUG << "requestDataQueue is empty\n";
return;
}
-@@ -257,17 +353,20 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -257,16 +371,17 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
BMCWEB_LOG_DEBUG << "Attempt retry after " << retryIntervalSecs
<< " seconds. RetryCount = " << retryCount;
timer.expires_after(std::chrono::seconds(retryIntervalSecs));
@@ -360,38 +418,66 @@ index e6a7db1..27d2af3 100644
+ });
return;
}
- else
+- else
++
++ if (state == ConnState::idle)
{
- // reset retry count.
-- retryCount = 0;
-+ if (state == ConnState::idle)
-+ {
-+ // State idle means, previous attempt is successful.
-+ retryCount = 0;
-+ }
++ // State idle means, previous attempt is successful.
+ retryCount = 0;
}
connStateCheck();
-
-@@ -310,10 +409,11 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+@@ -279,6 +394,7 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ switch (state)
+ {
+ case ConnState::connectInProgress:
++ case ConnState::sslHandshakeInProgress:
+ case ConnState::sendInProgress:
+ case ConnState::suspended:
+ case ConnState::terminated:
+@@ -310,15 +426,19 @@ 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) :
-- conn(ioc),
+ const std::string& destUri,
+ const bool inUseSsl = true) :
-+ ioc(ioc),
+ conn(ioc),
timer(ioc), subId(id), host(destIP), port(destPort), uri(destUri),
- retryCount(0), maxRetryAttempts(5),
+- retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
+ useSsl(inUseSsl), retryCount(0), maxRetryAttempts(5),
- retryPolicyAction("TerminateAfterRetries"), runningTimer(false)
++ retryPolicyAction("TerminateAfterRetries"), runningTimer(false),
++ state(ConnState::initialized)
{
boost::asio::ip::tcp::resolver resolver(ioc);
++ // TODO: Use async_resolver. boost asio example
++ // code as is crashing with async_resolve().
++ // It needs debug.
+ endpoint = resolver.resolve(host, port);
+- state = ConnState::initialized;
+ }
+
+ void sendData(const std::string& data)
+@@ -344,7 +464,12 @@ class HttpClient : public std::enable_shared_from_this<HttpClient>
+ void setHeaders(
+ const std::vector<std::pair<std::string, std::string>>& httpHeaders)
+ {
+- headers = httpHeaders;
++ // Set headers
++ for (const auto& [key, value] : httpHeaders)
++ {
++ // TODO: Validate the header fileds before assign.
++ fields.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 6362112..3ab2605 100644
+index 9c42e06..2a02920 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
-@@ -383,7 +383,7 @@ class Subscription
+@@ -384,7 +384,7 @@ class Subscription
{
conn = std::make_shared<crow::HttpClient>(
crow::connections::systemBus->get_io_context(), id, host, port,
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0007-cpudimm-get-cpu-details-from-Redfish.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0007-cpudimm-get-cpu-details-from-Redfish.patch
new file mode 100644
index 000000000..ccf13e2af
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0007-cpudimm-get-cpu-details-from-Redfish.patch
@@ -0,0 +1,231 @@
+From 7e50451bc8d4c4e8fa5ee1b0e2af86c800ea2efc Mon Sep 17 00:00:00 2001
+From: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Mon, 13 Apr 2020 23:31:06 +0000
+Subject: [PATCH] cpudimm: get cpu details from Redfish
+
+Modified the code to fetch cpu details from Redfish
+
+Note: This patch will be removed after code is up streamed.
+https://gerrit.openbmc-project.xyz/#/c/openbmc/bmcweb/+/31294/
+
+Tested:
+1. Verified redfish validator passed
+2. Get cpu details from Redfish
+GET: https://<BMC-IP>/redfish/v1/Systems/system/Processors/cpu0
+Response:
+{
+ "@odata.id": "/redfish/v1/Systems/system/Processors/cpu0",
+ "@odata.type": "#Processor.v1_7_0.Processor",
+ "Id": "cpu0",
+ "InstructionSet": "x86-64",
+ "Manufacturer": "Intel(R) Corporation",
+ "MaxSpeedMHz": 4000,
+ "Model": "",
+ "Name": "Central Processor",
+ "ProcessorArchitecture": "x86",
+ "ProcessorId": {
+ "EffectiveFamily": "Intel Xeon processor",
+ "VendorId": "329300"
+ },
+ "ProcessorType": "CPU",
+ "SerialNumber": "",
+ "Socket": "CPU0",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Enabled"
+ },
+ "TotalCores": 18,
+ "TotalThreads": 36,
+ "Version": "Intel(R) Xeon(R) Gold 6139 CPU @ 2.30GHz"
+}
+
+GET: https://<BMC-IP>/redfish/v1/Systems/system/Processors/cpu1
+Response:
+{
+ "@odata.id": "/redfish/v1/Systems/system/Processors/cpu1",
+ "@odata.type": "#Processor.v1_7_0.Processor",
+ "Id": "cpu1",
+ "Name": "Processor",
+ "ProcessorType": "CPU",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Absent"
+ }
+}
+
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: Idcad6e643684f4912f24c259b075a443e1da5007
+---
+ redfish-core/lib/cpudimm.hpp | 81 ++++++++++++++++++++----------------
+ 1 file changed, 46 insertions(+), 35 deletions(-)
+
+diff --git a/redfish-core/lib/cpudimm.hpp b/redfish-core/lib/cpudimm.hpp
+index ed5e641..e332a11 100644
+--- a/redfish-core/lib/cpudimm.hpp
++++ b/redfish-core/lib/cpudimm.hpp
+@@ -73,8 +73,13 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ {
+ BMCWEB_LOG_DEBUG << "Get CPU resources by interface.";
+
+- const bool* present = nullptr;
+- const bool* functional = nullptr;
++ // Added for future purpose. Once present and functional attributes added
++ // in busctl call, need to add actual logic to fetch original values.
++ bool present = false;
++ const bool functional = true;
++ auto health = std::make_shared<HealthPopulate>(aResp);
++ health->populate();
++
+ for (const auto& interface : cpuInterfacesProperties)
+ {
+ for (const auto& property : interface.second)
+@@ -93,10 +98,13 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ {
+ // Slot is not populated, set status end return
+ aResp->res.jsonValue["Status"]["State"] = "Absent";
+- aResp->res.jsonValue["Status"]["Health"] = "OK";
+ // HTTP Code will be set up automatically, just return
+ return;
+ }
++ else
++ {
++ aResp->res.jsonValue["Status"]["State"] = "Enabled";
++ }
+
+ aResp->res.jsonValue["TotalCores"] = *coresCount;
+ }
+@@ -104,7 +112,7 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ {
+ aResp->res.jsonValue["Name"] = property.second;
+ }
+- else if (property.first == "Manufacturer")
++ else if (property.first == "ProcessorManufacturer")
+ {
+ const std::string* value =
+ std::get_if<std::string>(&property.second);
+@@ -128,50 +136,48 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ {
+ aResp->res.jsonValue["MaxSpeedMHz"] = property.second;
+ }
+- else if (property.first == "ProcessorThreadCount")
+- {
+- aResp->res.jsonValue["TotalThreads"] = property.second;
+- }
+- else if (property.first == "Model")
++ else if (property.first == "ProcessorSocket")
+ {
+ const std::string* value =
+ std::get_if<std::string>(&property.second);
+ if (value != nullptr)
+ {
+- aResp->res.jsonValue["Model"] = *value;
++ aResp->res.jsonValue["Socket"] = *value;
+ }
+ }
+- else if (property.first == "PartNumber")
++ else if (property.first == "ProcessorThreadCount")
+ {
+- aResp->res.jsonValue["PartNumber"] = property.second;
++ aResp->res.jsonValue["TotalThreads"] = property.second;
+ }
+- else if (property.first == "SerialNumber")
++ else if (property.first == "ProcessorFamily")
+ {
+- aResp->res.jsonValue["SerialNumber"] = property.second;
++ const std::string* value =
++ std::get_if<std::string>(&property.second);
++ if (value != nullptr)
++ {
++ aResp->res.jsonValue["ProcessorId"]["EffectiveFamily"] =
++ *value;
++ }
+ }
+- else if (property.first == "Version")
++ else if (property.first == "ProcessorVersion")
+ {
+ aResp->res.jsonValue["Version"] = property.second;
+ }
+- else if (property.first == "Present")
+- {
+- present = std::get_if<bool>(&property.second);
+- }
+- else if (property.first == "Functional")
++ else if (property.first == "ProcessorId")
+ {
+- functional = std::get_if<bool>(&property.second);
++ const uint32_t* value = std::get_if<uint32_t>(&property.second);
++
++ if (value != nullptr && *value != 0)
++ {
++ present = true;
++ aResp->res.jsonValue["ProcessorId"]["VendorId"] =
++ boost::lexical_cast<std::string>(*value);
++ }
+ }
+ }
+ }
+
+- if ((present == nullptr) || (functional == nullptr))
+- {
+- // Important property not in desired type
+- messages::internalError(aResp->res);
+- return;
+- }
+-
+- if (*present == false)
++ if (present == false)
+ {
+ aResp->res.jsonValue["Status"]["State"] = "Absent";
+ aResp->res.jsonValue["Status"]["Health"] = "OK";
+@@ -179,7 +185,7 @@ void getCpuDataByInterface(std::shared_ptr<AsyncResp> aResp,
+ else
+ {
+ aResp->res.jsonValue["Status"]["State"] = "Enabled";
+- if (*functional == true)
++ if (functional)
+ {
+ aResp->res.jsonValue["Status"]["Health"] = "OK";
+ }
+@@ -212,6 +218,7 @@ void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
+ aResp->res.jsonValue["Name"] = "Processor";
+ aResp->res.jsonValue["ProcessorType"] = "CPU";
+
++ bool slotPresent = false;
+ std::string corePath = objPath + "/core";
+ size_t totalCores = 0;
+ for (const auto& object : dbusData)
+@@ -237,6 +244,7 @@ void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
+ {
+ if (*present == true)
+ {
++ slotPresent = true;
+ totalCores++;
+ }
+ }
+@@ -249,13 +257,16 @@ void getCpuDataByService(std::shared_ptr<AsyncResp> aResp,
+ // In getCpuDataByInterface(), state and health are set
+ // based on the present and functional status. If core
+ // count is zero, then it has a higher precedence.
+- if (totalCores == 0)
++ if (slotPresent)
+ {
+- // Slot is not populated, set status end return
+- aResp->res.jsonValue["Status"]["State"] = "Absent";
+- aResp->res.jsonValue["Status"]["Health"] = "OK";
++ if (totalCores == 0)
++ {
++ // Slot is not populated, set status end return
++ aResp->res.jsonValue["Status"]["State"] = "Absent";
++ aResp->res.jsonValue["Status"]["Health"] = "OK";
++ }
++ aResp->res.jsonValue["TotalCores"] = totalCores;
+ }
+- aResp->res.jsonValue["TotalCores"] = totalCores;
+ return;
+ },
+ service, "/xyz/openbmc_project/inventory",
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0008-systems-Fix-for-Processor-Summary-Model.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0008-systems-Fix-for-Processor-Summary-Model.patch
new file mode 100644
index 000000000..d210e3808
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0008-systems-Fix-for-Processor-Summary-Model.patch
@@ -0,0 +1,138 @@
+From ea3f3da3b29c7ecca34c12f94ce1e0364cbf9d7c Mon Sep 17 00:00:00 2001
+From: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Date: Fri, 29 May 2020 00:50:46 +0000
+Subject: [PATCH] systems: Fix for Processor Summary Model
+
+Issue: Processor summary is not showing model name as expected from
+ Redfish
+
+Fix: Add condition to fetch valid model name in processor summary
+
+Tested:
+1. Verified redfish validator passed
+2. Get system details from Redfish
+GET: https://<BMC-IP>/redfish/v1/Systems/system/
+Before fix:
+Response:
+ "ProcessorSummary": {
+ "Count": 2,
+ "Model": "Unknown Processor Family",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Enabled"
+ }
+ },
+
+After fix:
+Response:
+ "ProcessorSummary": {
+ "Count": 1,
+ "Model": "Intel Xeon processor",
+ "Status": {
+ "Health": "OK",
+ "HealthRollup": "OK",
+ "State": "Enabled"
+ }
+ },
+
+Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
+Change-Id: I4af7132135aef26556839fabada623728b52be8b
+---
+ redfish-core/lib/systems.hpp | 73 +++++++++++++++++++++++-------------
+ 1 file changed, 46 insertions(+), 27 deletions(-)
+
+diff --git a/redfish-core/lib/systems.hpp b/redfish-core/lib/systems.hpp
+index 2baeaa7..884fbb6 100644
+--- a/redfish-core/lib/systems.hpp
++++ b/redfish-core/lib/systems.hpp
+@@ -325,40 +325,59 @@ void getComputerSystem(std::shared_ptr<AsyncResp> aResp,
+
+ if (properties.size() > 0)
+ {
++ const uint32_t* processorId = nullptr;
++ const std::string* procFamily = nullptr;
++ nlohmann::json& procSummary =
++ aResp->res.jsonValue["ProcessorSumm"
++ "ary"];
++ nlohmann::json& procCount =
++ procSummary["Count"];
++
++ auto procCountPtr = procCount.get_ptr<
++ nlohmann::json::
++ number_integer_t*>();
++ if (procCountPtr == nullptr)
++ {
++ messages::internalError(aResp->res);
++ return;
++ }
+ for (const auto& property : properties)
+ {
++
++ if (property.first == "ProcessorId")
++ {
++ processorId =
++ std::get_if<uint32_t>(
++ &property.second);
++ if (nullptr != procFamily)
++ break;
++ continue;
++ }
++
+ if (property.first ==
+ "ProcessorFamily")
+ {
+- const std::string* value =
++ procFamily =
+ std::get_if<std::string>(
+ &property.second);
+- if (value != nullptr)
+- {
+- nlohmann::json&
+- procSummary =
+- aResp->res.jsonValue
+- ["ProcessorSumm"
+- "ary"];
+- nlohmann::json& procCount =
+- procSummary["Count"];
+-
+- auto procCountPtr =
+- procCount.get_ptr<
+- nlohmann::json::
+- number_integer_t*>();
+- if (procCountPtr != nullptr)
+- {
+- // shouldn't be possible
+- // to be nullptr
+- *procCountPtr += 1;
+- }
+- procSummary["Status"]
+- ["State"] =
+- "Enabled";
+- procSummary["Model"] =
+- *value;
+- }
++ if (nullptr != processorId)
++ break;
++ continue;
++ }
++ }
++
++ if (procFamily != nullptr &&
++ processorId != nullptr)
++ {
++ if (procCountPtr != nullptr &&
++ *processorId != 0)
++ {
++ *procCountPtr += 1;
++ procSummary["Status"]["State"] =
++ "Enabled";
++
++ procSummary["Model"] =
++ *procFamily;
+ }
+ }
+ }
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-MetricReportDefinitions-filter-not-working.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-MetricReportDefinitions-filter-not-working.patch
new file mode 100644
index 000000000..64b3c1112
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Fix-MetricReportDefinitions-filter-not-working.patch
@@ -0,0 +1,112 @@
+From 455b1d4c687a5c14197af1c1aba80b579c75900e Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Mon, 3 Aug 2020 22:23:12 +0530
+Subject: [PATCH 1/2] Fix: MetricReportDefinitions filter not working
+
+The metric reports are not sending when user configures
+the MetricReportDefinitions filter. This is of odata json
+object type. Corrected code to properly handle odata type
+object and store it as string array to make filters faster.
+
+Tested:
+ - Created metric report EventService subscription type
+ with MetricReportDefinitions and events properly sent to
+ Event listener.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: If96564219da7d38a2ee5e415b89824ba25cd686d
+---
+ redfish-core/include/event_service_manager.hpp | 4 ++--
+ redfish-core/lib/event_service.hpp | 32 +++++++++++++++++++++-----
+ 2 files changed, 28 insertions(+), 8 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 214f1e4..7c47842 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -283,7 +283,7 @@ bool isFilterQuerySpecialChar(char c)
+ bool readSSEQueryParams(std::string sseFilter, std::string& formatType,
+ std::vector<std::string>& messageIds,
+ std::vector<std::string>& registryPrefixes,
+- std::vector<nlohmann::json>& metricReportDefinitions)
++ std::vector<std::string>& metricReportDefinitions)
+ {
+ sseFilter.erase(std::remove_if(sseFilter.begin(), sseFilter.end(),
+ isFilterQuerySpecialChar),
+@@ -369,7 +369,7 @@ class Subscription
+ std::vector<std::string> registryMsgIds;
+ std::vector<std::string> registryPrefixes;
+ std::vector<nlohmann::json> httpHeaders; // key-value pair
+- std::vector<nlohmann::json> metricReportDefinitions;
++ std::vector<std::string> metricReportDefinitions;
+
+ Subscription(const Subscription&) = delete;
+ Subscription& operator=(const Subscription&) = delete;
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index 8bd30f5..f59d093 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -229,7 +229,7 @@ class EventDestinationCollection : public Node
+ std::optional<std::vector<std::string>> msgIds;
+ std::optional<std::vector<std::string>> regPrefixes;
+ std::optional<std::vector<nlohmann::json>> headers;
+- std::optional<std::vector<nlohmann::json>> metricReportDefinitions;
++ std::optional<std::vector<nlohmann::json>> mrdJsonArray;
+
+ if (!json_util::readJson(
+ req, res, "Destination", destUrl, "Context", context,
+@@ -237,7 +237,7 @@ class EventDestinationCollection : public Node
+ "EventFormatType", eventFormatType, "HttpHeaders", headers,
+ "RegistryPrefixes", regPrefixes, "MessageIds", msgIds,
+ "DeliveryRetryPolicy", retryPolicy, "MetricReportDefinitions",
+- metricReportDefinitions))
++ mrdJsonArray))
+ {
+ return;
+ }
+@@ -387,9 +387,24 @@ class EventDestinationCollection : public Node
+ subValue->retryPolicy = "TerminateAfterRetries";
+ }
+
+- if (metricReportDefinitions)
++ if (mrdJsonArray)
+ {
+- subValue->metricReportDefinitions = *metricReportDefinitions;
++ for (nlohmann::json& mrdObj : *mrdJsonArray)
++ {
++ std::string mrdUri;
++ if (json_util::getValueFromJsonObject(mrdObj, "@odata.id",
++ mrdUri))
++ {
++ subValue->metricReportDefinitions.emplace_back(mrdUri);
++ }
++ else
++ {
++ messages::propertyValueFormatError(
++ asyncResp->res, mrdObj.dump(),
++ "MetricReportDefinitions");
++ return;
++ }
++ }
+ }
+
+ std::string id =
+@@ -565,8 +580,13 @@ class EventDestination : public Node
+ subValue->registryPrefixes;
+ asyncResp->res.jsonValue["MessageIds"] = subValue->registryMsgIds;
+ asyncResp->res.jsonValue["DeliveryRetryPolicy"] = subValue->retryPolicy;
+- asyncResp->res.jsonValue["MetricReportDefinitions"] =
+- subValue->metricReportDefinitions;
++
++ std::vector<nlohmann::json> mrdJsonArray;
++ for (const auto& mdrUri : subValue->metricReportDefinitions)
++ {
++ mrdJsonArray.push_back({{"@odata.id", mdrUri}});
++ }
++ asyncResp->res.jsonValue["MetricReportDefinitions"] = mrdJsonArray;
+ }
+
+ void doPatch(crow::Response& res, const crow::Request& req,
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch
new file mode 100644
index 000000000..90905762b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0009-Workaround-Fix-memory-leak.patch
@@ -0,0 +1,33 @@
+From f43d6ba7e32565a7881949070bd25cb13f50ebf7 Mon Sep 17 00:00:00 2001
+From: James Feist <james.feist@linux.intel.com>
+Date: Thu, 27 Aug 2020 13:56:52 -0700
+Subject: [PATCH 1/1] Workaround: Fix memory leak
+
+Req caputures self not allowing the connection to
+be freed. There is discussion in upstream about a
+real fix, this should be kept downstream only.
+
+Tested: Sent 1000 connections, saw no VSZ increase
+
+Change-Id: I63440abbe0882ffe228395b5d3bc869f10048ddc
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+---
+ http/http_connection.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/http/http_connection.h b/http/http_connection.h
+index 109a272..393c2e7 100644
+--- a/http/http_connection.h
++++ b/http/http_connection.h
+@@ -422,6 +422,8 @@ class Connection :
+ {
+ adaptor.close();
+ }
++ // HACK TO REMOVE MEMORY LEAK
++ req.reset();
+ }
+
+ void completeRequest()
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-Fix-EventService-stops-sending-events.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-Fix-EventService-stops-sending-events.patch
new file mode 100644
index 000000000..d7df52ddf
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0010-Fix-EventService-stops-sending-events.patch
@@ -0,0 +1,67 @@
+From 27705854ade6832bc1e91dada33fee43ee4b2bc9 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Sun, 2 Aug 2020 17:03:10 +0530
+Subject: [PATCH 2/2] Fix: EventService stops sending events
+
+When redfish log file(/var/log/redfish) is recreated
+by rsyslog daemon, EventService stops sending events
+to subscribers.
+
+The rsyslog service take redfish log files to back up
+as per design. EventService has inotify on redfish log
+file modifications. It needs to be removed from inotify
+watcher list and added with new File descriptor.
+Corrected code to handle remove & add of new descriptor.
+Also corrected code to properly handle last event timestamp.
+
+Tested:
+ - Ran stress test on redfish log file to create multiple
+ backup files and events sends to clients properly, in
+ all switching scenarios.
+
+Change-Id: Ic0378edfc2cae86d1f69f6df4c429d07c2744bdf
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 7c47842..4671995 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -1019,6 +1019,7 @@ class EventServiceManager
+ #ifndef BMCWEB_ENABLE_REDFISH_DBUS_LOG_ENTRIES
+ void cacheLastEventTimestamp()
+ {
++ lastEventTStr.clear();
+ std::ifstream logStream(redfishEventLogFile);
+ if (!logStream.good())
+ {
+@@ -1062,7 +1063,7 @@ class EventServiceManager
+ std::string logEntry;
+ while (std::getline(logStream, logEntry))
+ {
+- if (!startLogCollection)
++ if (!startLogCollection && !lastEventTStr.empty())
+ {
+ if (boost::starts_with(logEntry, lastEventTStr))
+ {
+@@ -1160,9 +1161,12 @@ class EventServiceManager
+ if (fileWatchDesc != -1)
+ {
+ BMCWEB_LOG_DEBUG
+- << "Redfish log file is already on "
+- "inotify_add_watch.";
+- return;
++ << "Remove and Add inotify watcher on "
++ "redfish event log file";
++ // Remove existing inotify watcher and add
++ // with new redfish event log file.
++ inotify_rm_watch(inotifyFd, fileWatchDesc);
++ fileWatchDesc = -1;
+ }
+
+ fileWatchDesc = inotify_add_watch(
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0011-Deallocate-memory-during-failed-case.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0011-Deallocate-memory-during-failed-case.patch
new file mode 100644
index 000000000..57ec01c7b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0011-Deallocate-memory-during-failed-case.patch
@@ -0,0 +1,32 @@
+From cf5ba2028909d4fa0ee3bba4b60620e72cd612f0 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Fri, 7 Aug 2020 01:37:28 +0530
+Subject: [PATCH] Deallocate memory during failed case
+
+Free memory during failed case inside
+pamFunctionConversation() function.
+
+Tested:
+ - Pam authentication works as normal.
+
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: I81c06a3d674b0806c96e5847cda6f208795bd02c
+---
+ include/pam_authenticate.hpp | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/include/pam_authenticate.hpp b/include/pam_authenticate.hpp
+index f2c7356..3e5c691 100644
+--- a/include/pam_authenticate.hpp
++++ b/include/pam_authenticate.hpp
+@@ -30,6 +30,7 @@ inline int pamFunctionConversation(int numMsg, const struct pam_message** msg,
+
+ if (resp == nullptr)
+ {
++ free(pass);
+ return PAM_AUTH_ERR;
+ }
+
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0012-System-Replace-chassis-name-in-Redfish.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0012-System-Replace-chassis-name-in-Redfish.patch
new file mode 100644
index 000000000..870b33249
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0012-System-Replace-chassis-name-in-Redfish.patch
@@ -0,0 +1,64 @@
+From e0e19506ac81b3fa858de30c90ed3d75e10df749 Mon Sep 17 00:00:00 2001
+From: srikanta mondal <srikantax.mondal@intel.com>
+Date: Wed, 12 Aug 2020 18:26:26 +0000
+Subject: [PATCH] System: Replace chassis name in Redfish
+
+Modify code to replace chassis name to WC_Baseboard
+
+Note: This patch will be removed after code is up streamed.
+https://gerrit.openbmc-project.xyz/#/c/openbmc/bmcweb/+/31748/
+
+Tested:
+1. Verified redfish validator passed
+2. Verified details from Redfish
+
+GET: https://<BMC-IP>/redfish/v1/Systems/system
+Response:
+{
+ ....
+ "Links": {
+ "Chassis": [
+ {
+ "@odata.id": "/redfish/v1/Chassis/WC_Baseboard"
+ }
+ ],
+ "ManagedBy": [
+ {
+ "@odata.id": "/redfish/v1/Managers/bmc"
+ }
+ ]
+ },
+ ....
+}
+
+GET: https://<BMC-IP>/redfish/v1/Chassis/WC_Baseboard
+Response:
+{
+ // SUCCESS
+}
+
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: srikanta mondal <srikantax.mondal@intel.com>
+---
+ redfish-core/lib/redfish_util.hpp | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/redfish-core/lib/redfish_util.hpp b/redfish-core/lib/redfish_util.hpp
+index 5701712..3adb392 100644
+--- a/redfish-core/lib/redfish_util.hpp
++++ b/redfish-core/lib/redfish_util.hpp
+@@ -57,9 +57,8 @@ void getMainChassisId(std::shared_ptr<AsyncResp> asyncResp,
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTree",
+ "/xyz/openbmc_project/inventory", 0,
+- std::array<const char*, 2>{
+- "xyz.openbmc_project.Inventory.Item.Board",
+- "xyz.openbmc_project.Inventory.Item.Chassis"});
++ std::array<const char*, 1>{
++ "xyz.openbmc_project.Inventory.Item.System"});
+ }
+ } // namespace redfish
+ #endif
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0013-url_view-throws-if-a-parse-error-is-found.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0013-url_view-throws-if-a-parse-error-is-found.patch
new file mode 100644
index 000000000..c7d4ca914
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0013-url_view-throws-if-a-parse-error-is-found.patch
@@ -0,0 +1,54 @@
+From 6ab885e4cabe28f74050b7e996868e4d8387e94d Mon Sep 17 00:00:00 2001
+From: Ed Tanous <ed@tanous.net>
+Date: Mon, 17 Aug 2020 15:04:58 -0700
+Subject: [PATCH] url_view throws if a parse error is found
+
+This causes a strange condition where the webserver crashes on bad urls.
+
+Tested:
+Loaded on RPI. Verified that this particular crash no longer breaks the
+fuzzer.
+
+Signed-off-by: Ed Tanous <ed@tanous.net>
+Signed-off-by: James Feist <james.feist@linux.intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+Change-Id: I459421e27c8d07c2bc45099b5942f7c7c929610d
+---
+ http/http_connection.h | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/http/http_connection.h b/http/http_connection.h
+index 8dba3d6..8db8108 100644
+--- a/http/http_connection.h
++++ b/http/http_connection.h
+@@ -728,9 +728,24 @@ class Connection :
+ return;
+ }
+
+- req->urlView = boost::urls::url_view(req->target());
+- req->url = req->urlView.encoded_path();
+-
++ // Note, despite the bmcweb coding policy on use of exceptions
++ // for error handling, this one particular use of exceptions is
++ // deemed acceptible, as it solved a significant error handling
++ // problem that resulted in seg faults, the exact thing that the
++ // exceptions rule is trying to avoid. If at some point,
++ // boost::urls makes the parser object public (or we port it
++ // into bmcweb locally) this will be replaced with
++ // parser::parse, which returns a status code
++
++ try
++ {
++ req->urlView = boost::urls::url_view(req->target());
++ req->url = req->urlView.encoded_path();
++ }
++ catch (std::exception& p)
++ {
++ BMCWEB_LOG_ERROR << p.what();
++ }
+ crow::authorization::authenticate(*req, res, session);
+
+ bool loggedIn = req && req->session;
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0014-add-sufficient-delay-to-create-fw-update-object.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0014-add-sufficient-delay-to-create-fw-update-object.patch
new file mode 100644
index 000000000..e6fd85f85
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0014-add-sufficient-delay-to-create-fw-update-object.patch
@@ -0,0 +1,44 @@
+From d7df47f5df9c6e389c3deeb418be8fb7c32bc6f4 Mon Sep 17 00:00:00 2001
+From: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
+Date: Tue, 25 Aug 2020 15:44:35 +0000
+Subject: [PATCH] add sufficient delay to create fw update object
+
+Add support to increase timeoutTimeSeconds to 10 secs to allow firmware
+object to create successfully to proceed for firmware update.
+
+Tested:
+Redfish validator passed.
+
+Updated the firmware using redfish for 16 times continuously.
+POST: https://<BMC_IP>/redfish/v1/UpdateService/
+ with <BMC_signed_cap> binary file
+firmware updated.
+{
+ "@odata.id": "/redfish/v1/TaskService/Tasks/0",
+ "@odata.type": "#Task.v1_4_3.Task",
+ "Id": "0",
+ "TaskState": "Running",
+ "TaskStatus": "OK"
+}
+
+Signed-off-by: Chalapathi Venkataramashetty <chalapathix.venkataramashetty@intel.com>
+---
+ redfish-core/lib/update_service.hpp | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
+index 9407d75..ec5ab8c 100644
+--- a/redfish-core/lib/update_service.hpp
++++ b/redfish-core/lib/update_service.hpp
+@@ -363,7 +363,7 @@ static void softwareInterfaceAdded(std::shared_ptr<AsyncResp> asyncResp,
+ static void monitorForSoftwareAvailable(
+ std::shared_ptr<AsyncResp> asyncResp, const crow::Request& req,
+ const std::string& url, const std::vector<std::string>& imgUriTargets,
+- int timeoutTimeSeconds = 5)
++ int timeoutTimeSeconds = 10)
+ {
+ // Only allow one FW update at a time
+ if (fwUpdateInProgress != false)
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0015-Add-firmware-activation-messages-to-the-registry.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0015-Add-firmware-activation-messages-to-the-registry.patch
new file mode 100644
index 000000000..6cc95eda5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0015-Add-firmware-activation-messages-to-the-registry.patch
@@ -0,0 +1,72 @@
+From d61d668f6db81bed90f41c3a128ce6fd652cc98c Mon Sep 17 00:00:00 2001
+From: "Jason M. Bills" <jason.m.bills@linux.intel.com>
+Date: Wed, 12 Aug 2020 14:45:32 -0700
+Subject: [PATCH] Add firmware activation messages to the registry
+
+In some situations a firmware requires activation rather than
+update. These messages are intended to cover those situations.
+
+Tested:
+Logged these events and confirmed that they appear correctly in
+Redfish.
+
+Change-Id: I6171b9584626e049349a26c414146f37c04768c7
+Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
+---
+ .../registries/openbmc_message_registry.hpp | 33 ++++++++++++++++++-
+ 1 file changed, 32 insertions(+), 1 deletion(-)
+
+diff --git a/redfish-core/include/registries/openbmc_message_registry.hpp b/redfish-core/include/registries/openbmc_message_registry.hpp
+index 236002e..58c085d 100644
+--- a/redfish-core/include/registries/openbmc_message_registry.hpp
++++ b/redfish-core/include/registries/openbmc_message_registry.hpp
+@@ -29,7 +29,7 @@ const Header header = {
+ "0.1.0",
+ "OpenBMC",
+ };
+-constexpr std::array<MessageEntry, 182> registry = {
++constexpr std::array<MessageEntry, 185> registry = {
+ MessageEntry{
+ "ADDDCCorrectable",
+ {
+@@ -443,6 +443,37 @@ constexpr std::array<MessageEntry, 182> registry = {
+ {"string"},
+ "None.",
+ }},
++ MessageEntry{
++ "FirmwareActivationCompleted",
++ {
++ "Indicates a firmware activation has completed successfully.",
++ "%1 firmware activation completed successfully.",
++ "OK",
++ "OK",
++ 1,
++ {"string"},
++ "None.",
++ }},
++ MessageEntry{"FirmwareActivationFailed",
++ {
++ "Indicates a firmware activation has failed.",
++ "%1 firmware activation failed: %2.",
++ "Warning",
++ "Warning",
++ 2,
++ {"string", "string"},
++ "None.",
++ }},
++ MessageEntry{"FirmwareActivationStarted",
++ {
++ "Indicates a firmware activation has started.",
++ "%1 firmware activation started.",
++ "OK",
++ "OK",
++ 1,
++ {"string"},
++ "None.",
++ }},
+ MessageEntry{"FirmwareUpdateCompleted",
+ {
+ "Indicates a firmware update has completed successfully.",
+--
+2.17.1
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0016-EventService-Fix-type-mismatch-in-MetricReport.patch
index 75d49b6d6..378ce6c47 100644
--- a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/telemetry/0006-Fix-MetricReport-timestamp-for-EventService.patch
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0016-EventService-Fix-type-mismatch-in-MetricReport.patch
@@ -1,18 +1,23 @@
-From b71f087a173c36a16526156fa34581673e2b860c Mon Sep 17 00:00:00 2001
+From cdfc5cfad41bcfa3fc0e53023bd62bdadf15ad86 Mon Sep 17 00:00:00 2001
From: "Wludzik, Jozef" <jozef.wludzik@intel.com>
Date: Fri, 24 Jul 2020 17:05:38 +0200
-Subject: [PATCH 6/6] Fix MetricReport timestamp for EventService
+Subject: [PATCH] EventService: Fix type mismatch in MetricReport
-Changed MetricReport timestamp type from std::string to int32_t.
+Fix the type mismatch in MetricReport data which
+is sent to Event Subscribers. Change below properties
+type to match with MetricReport schema.
+ - Timestamp: It should be uint32_t type.
+ - MetricValue: It should be string type.
Signed-off-by: Wludzik, Jozef <jozef.wludzik@intel.com>
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
Change-Id: I0a52b6963e7bedda89a216256f64764cd8799bf1
---
redfish-core/include/event_service_manager.hpp | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
-index d2f4f2a..dc04ccb 100644
+index 3e3058f..0f5c6b7 100644
--- a/redfish-core/include/event_service_manager.hpp
+++ b/redfish-core/include/event_service_manager.hpp
@@ -38,7 +38,7 @@ namespace redfish
@@ -36,12 +41,12 @@ index d2f4f2a..dc04ccb 100644
+
+ entry = {{"MetricId", id},
+ {"MetricProperty", property},
-+ {"MetricValue", value},
++ {"MetricValue", std::to_string(value)},
+ {"Timestamp", crow::utility::getDateTime(timestamp)}};
}
nlohmann::json msg = {
-@@ -1266,7 +1268,7 @@ class EventServiceManager
+@@ -1270,7 +1272,7 @@ class EventServiceManager
[idStr{std::move(idStr)}](
const boost::system::error_code ec,
boost::container::flat_map<
@@ -50,7 +55,7 @@ index d2f4f2a..dc04ccb 100644
resp) {
if (ec)
{
-@@ -1275,8 +1277,8 @@ class EventServiceManager
+@@ -1279,8 +1281,8 @@ class EventServiceManager
return;
}
@@ -61,7 +66,7 @@ index d2f4f2a..dc04ccb 100644
if (!timestampPtr)
{
BMCWEB_LOG_DEBUG << "Failed to Get timestamp.";
-@@ -1303,8 +1305,9 @@ class EventServiceManager
+@@ -1307,8 +1309,9 @@ class EventServiceManager
std::shared_ptr<Subscription> entry = it.second;
if (entry->eventFormatType == metricReportFormatType)
{
@@ -74,5 +79,5 @@ index d2f4f2a..dc04ccb 100644
}
},
--
-2.16.6
+2.7.4
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0017-Add-MutualExclusiveProperties-registry.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0017-Add-MutualExclusiveProperties-registry.patch
new file mode 100644
index 000000000..2b510e0b5
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0017-Add-MutualExclusiveProperties-registry.patch
@@ -0,0 +1,151 @@
+From 891a0a2deb616b7e3f135b5df8501947ce5d6ad4 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 8 Sep 2020 01:53:21 +0530
+Subject: [PATCH] Add MutualExclusiveProperties registry
+
+Add MutualExclusiveProperties message registry entry
+and error message.
+As per redfish specification, "RegistryPrefixes" and
+"MessageIds" are mutually exclusive. So add check for
+same in EventService and return MutualExclusiveProperties
+error message.
+
+Tested:
+ - Create subscription failed with error(bad request)
+ when the request body contain both "RegistryPrefixes"
+ and "MessageIds".
+
+Change-Id: I4c14f946977bce2ced8a7f96eb85855117fde9a8
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/error_messages.hpp | 14 +++++++++++
+ .../include/registries/base_message_registry.hpp | 18 +++++++++++++-
+ redfish-core/lib/event_service.hpp | 10 ++++++++
+ redfish-core/src/error_messages.cpp | 29 ++++++++++++++++++++++
+ 4 files changed, 70 insertions(+), 1 deletion(-)
+
+diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
+index 0243be9..9a2d1ca 100644
+--- a/redfish-core/include/error_messages.hpp
++++ b/redfish-core/include/error_messages.hpp
+@@ -787,6 +787,20 @@ nlohmann::json invalidUpload(const std::string& arg1, const std::string& arg2);
+ void invalidUpload(crow::Response& res, const std::string& arg1,
+ const std::string& arg2);
+
++/**
++ * @brief Formats MutualExclusiveProperties message into JSON
++ * Message body: "The properties <arg1> and <arg2> are mutually exclusive."
++ *
++ * @param[in] arg1 Parameter of message that will replace %1 in its body.
++ * @param[in] arg2 Parameter of message that will replace %2 in its body.
++ *
++ * @returns Message MutualExclusiveProperties formatted to JSON */
++nlohmann::json mutualExclusiveProperties(const std::string& arg1,
++ const std::string& arg2);
++
++void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
++ const std::string& arg2);
++
+ } // namespace messages
+
+ } // namespace redfish
+diff --git a/redfish-core/include/registries/base_message_registry.hpp b/redfish-core/include/registries/base_message_registry.hpp
+index 90aef56..7c385a0 100644
+--- a/redfish-core/include/registries/base_message_registry.hpp
++++ b/redfish-core/include/registries/base_message_registry.hpp
+@@ -36,7 +36,7 @@ const Header header = {
+ constexpr const char* url =
+ "https://redfish.dmtf.org/registries/Base.1.8.1.json";
+
+-constexpr std::array<MessageEntry, 73> registry = {
++constexpr std::array<MessageEntry, 74> registry = {
+ MessageEntry{
+ "AccessDenied",
+ {
+@@ -429,6 +429,22 @@ constexpr std::array<MessageEntry, 73> registry = {
+ "Resolve other reported errors and retry the current operation.",
+ }},
+ MessageEntry{
++ "MutualExclusiveProperties",
++ {
++ "Indicates that the requested operation could not be completed, "
++ "because of a conflict properties.",
++ "The properties '%1' and '%2' are mutually exclusive.",
++ "Warning",
++ "Warning",
++ 2,
++ {
++ "string",
++ "string",
++ },
++ "Ensure that the request body doesn't have mutually exclusive "
++ "properties and resubmit the request.",
++ }},
++ MessageEntry{
+ "NoOperation",
+ {
+ "Indicates that the requested operation will not perform any "
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index f59d093..4804d26 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -242,6 +242,16 @@ class EventDestinationCollection : public Node
+ return;
+ }
+
++ if (regPrefixes && msgIds)
++ {
++ if (regPrefixes->size() && msgIds->size())
++ {
++ messages::mutualExclusiveProperties(
++ asyncResp->res, "RegistryPrefixes", "MessageIds");
++ return;
++ }
++ }
++
+ // Validate the URL using regex expression
+ // Format: <protocol>://<host>:<port>/<uri>
+ // protocol: http/https
+diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
+index 160b73f..c6938ba 100644
+--- a/redfish-core/src/error_messages.cpp
++++ b/redfish-core/src/error_messages.cpp
+@@ -1750,6 +1750,35 @@ nlohmann::json invalidUpload(const std::string& arg1, const std::string& arg2)
+ {"Resolution", "None."}};
+ }
+
++/**
++ * @internal
++ * @brief Formats MutualExclusiveProperties into JSON
++ *
++ * See header file for more information
++ * @endinternal
++ */
++nlohmann::json mutualExclusiveProperties(const std::string& arg1,
++ const std::string& arg2)
++{
++ return nlohmann::json{
++ {"@odata.type", "#Message.v1_0_0.Message"},
++ {"MessageId", "Base.1.5.0.MutualExclusiveProperties"},
++ {"Message", "The properties " + arg1 + " and " + arg2 +
++ " are mutually exclusive."},
++ {"MessageArgs", {arg1, arg2}},
++ {"Severity", "Warning"},
++ {"Resolution",
++ "Ensure that the request body doesn't contain mutually exclusive "
++ "properties and resubmit the request."}};
++}
++
++void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
++ const std::string& arg2)
++{
++ res.result(boost::beast::http::status::bad_request);
++ addMessageToErrorJson(res.jsonValue, mutualExclusiveProperties(arg1, arg2));
++}
++
+ } // namespace messages
+
+ } // namespace redfish
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0018-Add-sse-event-sequence-number.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0018-Add-sse-event-sequence-number.patch
new file mode 100644
index 000000000..e2b8644d8
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0018-Add-sse-event-sequence-number.patch
@@ -0,0 +1,74 @@
+From c03fa3c7b6c98d299f18e106c1aabf655db10327 Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Fri, 4 Sep 2020 16:44:52 +0530
+Subject: [PATCH] Add sse event sequence number
+
+Add sequence number to sse events.
+This is different for event ID's.
+
+Tested:
+ - The sequence number increments properly
+ after sending sse events.
+
+Change-Id: I8f48082497094a0435d4a400cb8068c3af506a7a
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 2 +-
+ redfish-core/include/server_sent_events.hpp | 7 ++++---
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 4671995..1a99e54 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -415,7 +415,7 @@ class Subscription
+
+ if (sseConn != nullptr)
+ {
+- sseConn->sendData(eventSeqNum, msg);
++ sseConn->sendData(msg);
+ }
+ }
+
+diff --git a/redfish-core/include/server_sent_events.hpp b/redfish-core/include/server_sent_events.hpp
+index 1c4d2a5..23517ca 100644
+--- a/redfish-core/include/server_sent_events.hpp
++++ b/redfish-core/include/server_sent_events.hpp
+@@ -56,6 +56,7 @@ class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+ SseConnState state;
+ int retryCount;
+ int maxRetryAttempts;
++ uint64_t sseEventId;
+
+ void sendEvent(const std::string& id, const std::string& msg)
+ {
+@@ -260,7 +261,7 @@ class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+
+ ServerSentEvents(const std::shared_ptr<crow::Request::Adaptor>& adaptor) :
+ sseConn(std::move(adaptor)), state(SseConnState::startInit),
+- retryCount(0), maxRetryAttempts(5)
++ retryCount(0), maxRetryAttempts(5), sseEventId(1)
+ {
+ startSSE();
+ }
+@@ -268,7 +269,7 @@ class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+ ~ServerSentEvents()
+ {}
+
+- void sendData(const uint64_t& id, const std::string& data)
++ void sendData(const std::string& data)
+ {
+ if (state == SseConnState::suspended)
+ {
+@@ -277,7 +278,7 @@ class ServerSentEvents : public std::enable_shared_from_this<ServerSentEvents>
+
+ if (requestDataQueue.size() <= maxReqQueueSize)
+ {
+- requestDataQueue.push(std::pair(id, data));
++ requestDataQueue.push(std::pair(sseEventId++, data));
+ checkQueue(true);
+ }
+ else
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-EventService-Limit-SSE-connections-as-per-design.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-EventService-Limit-SSE-connections-as-per-design.patch
new file mode 100644
index 000000000..c6c0634ce
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0019-EventService-Limit-SSE-connections-as-per-design.patch
@@ -0,0 +1,108 @@
+From eb1f888660bd34bde0c049e48db2404803b57d6e Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 8 Sep 2020 02:37:19 +0530
+Subject: [PATCH] EventService: Limit SSE connections as per design
+
+Limit the number of SSE connections for event service.
+
+Tested:
+ - Tried creating more than 10 SSE connections and it fails.
+
+Change-Id: I4c7aa5c05a832115717e1261e330350ce59ab630
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/event_service_manager.hpp | 17 +++++++++++++++++
+ redfish-core/lib/event_service.hpp | 14 +++++++++-----
+ 2 files changed, 26 insertions(+), 5 deletions(-)
+
+diff --git a/redfish-core/include/event_service_manager.hpp b/redfish-core/include/event_service_manager.hpp
+index 502a6f7..22d1f10 100644
+--- a/redfish-core/include/event_service_manager.hpp
++++ b/redfish-core/include/event_service_manager.hpp
+@@ -44,6 +44,9 @@ 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* subscriptionTypeRedfishEvent = "RedfishEvent";
++static constexpr const char* subscriptionTypeSSE = "SSE";
++
+ static constexpr const char* eventServiceFile =
+ "/var/lib/bmcweb/eventservice_config.json";
+
+@@ -983,6 +986,20 @@ class EventServiceManager
+ return subscriptionsMap.size();
+ }
+
++ size_t getNumberOfSSESubscriptions()
++ {
++ size_t count = 0;
++ for (const auto& it : this->subscriptionsMap)
++ {
++ std::shared_ptr<Subscription> entry = it.second;
++ if (entry->subscriptionType == subscriptionTypeSSE)
++ {
++ count++;
++ }
++ }
++ return count;
++ }
++
+ std::vector<std::string> getAllIDs()
+ {
+ std::vector<std::string> idList;
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index 4804d26..f14c03e 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -27,6 +27,7 @@ static constexpr const std::array<const char*, 3> supportedRetryPolicies = {
+ "TerminateAfterRetries", "SuspendRetries", "RetryForever"};
+
+ static constexpr const uint8_t maxNoOfSubscriptions = 20;
++static constexpr const uint8_t maxNoOfSSESubscriptions = 10;
+
+ class EventService : public Node
+ {
+@@ -307,7 +308,7 @@ class EventDestinationCollection : public Node
+
+ if (subscriptionType)
+ {
+- if (*subscriptionType != "RedfishEvent")
++ if (*subscriptionType != subscriptionTypeRedfishEvent)
+ {
+ messages::propertyValueNotInList(
+ asyncResp->res, *subscriptionType, "SubscriptionType");
+@@ -317,7 +318,8 @@ class EventDestinationCollection : public Node
+ }
+ else
+ {
+- subValue->subscriptionType = "RedfishEvent"; // Default
++ subValue->subscriptionType =
++ subscriptionTypeRedfishEvent; // Default
+ }
+
+ if (protocol != "Redfish")
+@@ -450,8 +452,10 @@ class EventServiceSSE : public Node
+ void doGet(crow::Response& res, const crow::Request& req,
+ const std::vector<std::string>& params) override
+ {
+- if (EventServiceManager::getInstance().getNumberOfSubscriptions() >=
+- maxNoOfSubscriptions)
++ if ((EventServiceManager::getInstance().getNumberOfSubscriptions() >=
++ maxNoOfSubscriptions) ||
++ EventServiceManager::getInstance().getNumberOfSSESubscriptions() >=
++ maxNoOfSSESubscriptions)
+ {
+ messages::eventSubscriptionLimitExceeded(res);
+ res.end();
+@@ -464,7 +468,7 @@ class EventServiceSSE : public Node
+ std::make_shared<Subscription>(sseConn);
+
+ // GET on this URI means, Its SSE subscriptionType.
+- subValue->subscriptionType = "SSE";
++ subValue->subscriptionType = subscriptionTypeSSE;
+
+ // Default values
+ subValue->protocol = "Redfish";
+--
+2.7.4
+
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch
new file mode 100644
index 000000000..8f3e1fc9b
--- /dev/null
+++ b/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch
@@ -0,0 +1,262 @@
+From 5fd71f098aad2f6d64e94343738c43ffdff5709e Mon Sep 17 00:00:00 2001
+From: AppaRao Puli <apparao.puli@linux.intel.com>
+Date: Tue, 8 Sep 2020 16:19:30 +0530
+Subject: [PATCH] EventService: Validate SSE query filters
+
+Validate the query filters which are specified in
+requested url and return with error if not supported.
+Also RegistryPrefix and MessageId are mutually exclusive
+as per redfish specification. so return error if user
+specifies both.
+
+Tested:
+ - Checked with invalid query filters and it returns
+ the error.
+
+Change-Id: If07341f39d8c6b9bc229baae966f8569ebdd7b19
+Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
+---
+ redfish-core/include/error_messages.hpp | 9 ++
+ .../include/registries/base_message_registry.hpp | 14 ++-
+ redfish-core/lib/event_service.hpp | 99 +++++++++++++++-------
+ redfish-core/src/error_messages.cpp | 26 ++++++
+ 4 files changed, 116 insertions(+), 32 deletions(-)
+
+diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
+index 9a2d1ca..fd6bb48 100644
+--- a/redfish-core/include/error_messages.hpp
++++ b/redfish-core/include/error_messages.hpp
+@@ -801,6 +801,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/registries/base_message_registry.hpp b/redfish-core/include/registries/base_message_registry.hpp
+index 7c385a0..18085c8 100644
+--- a/redfish-core/include/registries/base_message_registry.hpp
++++ b/redfish-core/include/registries/base_message_registry.hpp
+@@ -36,7 +36,7 @@ const Header header = {
+ constexpr const char* url =
+ "https://redfish.dmtf.org/registries/Base.1.8.1.json";
+
+-constexpr std::array<MessageEntry, 74> registry = {
++constexpr std::array<MessageEntry, 75> registry = {
+ MessageEntry{
+ "AccessDenied",
+ {
+@@ -403,6 +403,18 @@ constexpr std::array<MessageEntry, 74> registry = {
+ "Either the object is malformed or the URI is not correct. "
+ "Correct the condition and resubmit the request if it failed.",
+ }},
++ MessageEntry{
++ "InvalidQueryFilter",
++ {
++ "Indicates the request url contains invalid query filter.",
++ "The requested url contains the invalid query filter.",
++ "Warning",
++ "Warning",
++ 0,
++ {},
++ "Ensure the correct query filter is specified in requested url "
++ "and resubmit the request if the operation failed.",
++ }},
+ MessageEntry{"MalformedJSON",
+ {
+ "Indicates that the request body was malformed JSON. "
+diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
+index f14c03e..b91b745 100644
+--- a/redfish-core/lib/event_service.hpp
++++ b/redfish-core/lib/event_service.hpp
+@@ -462,73 +462,110 @@ class EventServiceSSE : public Node
+ return;
+ }
+
+- std::shared_ptr<crow::Request::Adaptor> sseConn =
+- std::make_shared<crow::Request::Adaptor>(std::move(req.socket()));
+- std::shared_ptr<Subscription> subValue =
+- std::make_shared<Subscription>(sseConn);
+-
+- // GET on this URI means, Its SSE subscriptionType.
+- subValue->subscriptionType = subscriptionTypeSSE;
+-
+- // Default values
+- subValue->protocol = "Redfish";
+- subValue->retryPolicy = "TerminateAfterRetries";
+-
+- boost::urls::url_view::params_type::iterator it =
+- req.urlParams.find("$filter");
+- if (it == req.urlParams.end())
++ // It supports only "$filter" query param.
++ if (req.urlParams.size() > 1)
+ {
+- subValue->eventFormatType = "Event";
++ messages::invalidQueryFilter(res);
++ res.end();
++ return;
+ }
+
++ 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;
++ }
++ else
++ {
++ queryFilters = it->value();
++ }
++ }
+ else
+ {
+- std::string filters = it->value();
+- // Reading from query params.
+- bool status = readSSEQueryParams(
+- filters, subValue->eventFormatType, subValue->registryMsgIds,
+- subValue->registryPrefixes, subValue->metricReportDefinitions);
++ 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, filters);
++ messages::invalidObject(res, queryFilters);
++ res.end();
+ return;
+ }
+
+- if (!subValue->eventFormatType.empty())
++ // RegsitryPrefix and messageIds are mutuly exclusive as per redfish
++ // specification.
++ if (regPrefixes.size() && msgIds.size())
++ {
++ messages::mutualExclusiveProperties(res, "RegistryPrefix",
++ "MessageId");
++ res.end();
++ return;
++ }
++
++ if (!eventFormatType.empty())
+ {
+ if (std::find(supportedEvtFormatTypes.begin(),
+ supportedEvtFormatTypes.end(),
+- subValue->eventFormatType) ==
+- supportedEvtFormatTypes.end())
++ eventFormatType) == supportedEvtFormatTypes.end())
+ {
+- messages::propertyValueNotInList(
+- res, subValue->eventFormatType, "EventFormatType");
++ messages::propertyValueNotInList(res, eventFormatType,
++ "EventFormatType");
++ res.end();
+ return;
+ }
+ }
+ else
+ {
+ // If nothing specified, using default "Event"
+- subValue->eventFormatType.assign({"Event"});
++ eventFormatType.assign({"Event"});
+ }
+
+- if (!subValue->registryPrefixes.empty())
++ if (!regPrefixes.empty())
+ {
+- for (const std::string& it : subValue->registryPrefixes)
++ for (const std::string& it : regPrefixes)
+ {
+ if (std::find(supportedRegPrefixes.begin(),
+ supportedRegPrefixes.end(),
+ it) == supportedRegPrefixes.end())
+ {
+ messages::propertyValueNotInList(res, it,
+- "RegistryPrefixes");
++ "RegistryPrefix");
++ res.end();
+ return;
+ }
+ }
+ }
+ }
+
++ std::shared_ptr<crow::Request::Adaptor> sseConn =
++ std::make_shared<crow::Request::Adaptor>(std::move(req.socket()));
++ std::shared_ptr<Subscription> subValue =
++ std::make_shared<Subscription>(sseConn);
++
++ // GET on this URI means, Its SSE subscriptionType.
++ subValue->subscriptionType = subscriptionTypeSSE;
++ subValue->protocol = "Redfish";
++ subValue->retryPolicy = "TerminateAfterRetries";
++ subValue->eventFormatType = eventFormatType;
++ subValue->registryMsgIds = msgIds;
++ subValue->registryPrefixes = regPrefixes;
++ subValue->metricReportDefinitions = mrdsArray;
++
+ std::string id =
+ EventServiceManager::getInstance().addSubscription(subValue, false);
+ if (id.empty())
+diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
+index c6938ba..290d3f2 100644
+--- a/redfish-core/src/error_messages.cpp
++++ b/redfish-core/src/error_messages.cpp
+@@ -1779,6 +1779,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.7.4
+