Skip to content

Commit 2fd07a9

Browse files
harshit-agheraedtanous
authored andcommitted
Fabric: add support for PCIe Switch Port Metrics
This patch enable support for following properties for Port Metrics URI of a PCIe Switch. [1] - PCIeErrors.CorrectableErrorCount - PCIeErrors.NonFatalErrorCount - PCIeErrors.FatalErrorCount - PCIeErrors.L0ToRecoveryCount - PCIeErrors.ReplayCount - PCIeErrors.ReplayRolloverCount - PCIeErrors.NAKSentCount - PCIeErrors.NAKReceivedCount - PCIeErrors.UnsupportedRequestCount The patch uses "xyz.openbmc_project.Metric.Value" Interface for PCIe Port Metrics properties. Association between a Metric and a Port is `measuring` and `measured_by`. PDI patch - https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/84839 dbus-sensors patches - https://gerrit.openbmc.org/c/openbmc/dbus-sensors/+/84132 Tested: Build an image for nvl32-obmc machine with the following patch cherry picked. https://gerrit.openbmc.org/c/openbmc/dbus-sensors/+/84132 https://gerrit.openbmc.org/c/openbmc/openbmc/+/85490 The openbmc patch cherry-picks the following patches that are currently under review. ``` 1. device tree https://lore.kernel.org/all/[email protected]/ 2. mctpd patches CodeConstruct/mctp#85 3. u-boot changes https://lore.kernel.org/openbmc/[email protected]/T/#t 4. kernel changes as specified in the openbmc patch (for espi) 5. entity-manager changes https://gerrit.openbmc.org/c/openbmc/entity-manager/+/85455 6. platform-init changes https://gerrit.openbmc.org/c/openbmc/platform-init/+/85456 7. spi changes https://lore.kernel.org/all/[email protected]/ ``` redfish service validator is passing. ``` $ curl -k -u 'root:0penBmc' https://${bmc_ip}/redfish/v1/Fabrics/fabric/Switches/Nvidia_ConnectX_0/Ports/UP_0/Metrics/ { "@odata.id": "/redfish/v1/Fabrics/fabric/Switches/Nvidia_ConnectX_0/Ports/UP_0/Metrics", "@odata.type": "#PortMetrics.v1_3_0.PortMetrics", "Id": "Metrics", "Name": "Nvidia_ConnectX_0 UP_0 Port Metrics", "PCIeErrors": { "CorrectableErrorCount": 0, "FatalErrorCount": 0, "L0ToRecoveryCount": 1, "NAKReceivedCount": 0, "NAKSentCount": 0, "NonFatalErrorCount": 0, "ReplayCount": 0, "ReplayRolloverCount": 0, "UnsupportedRequestCount": 0 } }% ``` [1]: https://redfish.dmtf.org/schemas/v1/PortMetrics_v1.xml Change-Id: I7cca75fa5d4c77a4b02d35f7ce0b024f325ceff0 Signed-off-by: Harshit Aghera <[email protected]>
1 parent ec2bf16 commit 2fd07a9

3 files changed

Lines changed: 150 additions & 10 deletions

File tree

docs/Redfish.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,16 @@ functions the same like the default implementation under the System resource.
12831283
- @odata.type
12841284
- Id
12851285
- Name
1286+
- PCIeErrors
1287+
- CorrectableErrorCount
1288+
- NonFatalErrorCount
1289+
- FatalErrorCount
1290+
- L0ToRecoveryCount
1291+
- ReplayCount
1292+
- ReplayRolloverCount
1293+
- NAKSentCount
1294+
- NAKReceivedCount
1295+
- UnsupportedRequestCount
12861296

12871297
[1]: https://www.dmtf.org/standards/redfish
12881298
[2]: https://github.com/DMTF/Redfish-Service-Validator

redfish-core/lib/switch_port.hpp

Lines changed: 137 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,13 @@
2424
#include <cstddef>
2525
#include <format>
2626
#include <functional>
27+
#include <limits>
2728
#include <memory>
2829
#include <optional>
2930
#include <string>
3031
#include <string_view>
3132
#include <utility>
3233

33-
static constexpr const char* inventoryPath = "/xyz/openbmc_project/inventory";
34-
static constexpr std::array<std::string_view, 1> portInterface = {
35-
"xyz.openbmc_project.Inventory.Connector.Port"};
36-
3734
namespace redfish
3835
{
3936
inline port::PortType dBusSensorPortTypeToRedfish(const std::string& portType)
@@ -132,10 +129,127 @@ inline void afterGetFabricSwitchPortInfo(
132129
}
133130
}
134131

132+
inline void populateMetricsProperty(
133+
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
134+
const nlohmann::json::json_pointer& jsonPtr,
135+
const boost::system::error_code& ec, double value)
136+
{
137+
if (ec)
138+
{
139+
BMCWEB_LOG_DEBUG(
140+
"DBus response error on GetProperty {} for property {}", ec,
141+
jsonPtr.to_string());
142+
return;
143+
}
144+
145+
if (!std::isfinite(value))
146+
{
147+
BMCWEB_LOG_DEBUG("Received non-finite value for property {}",
148+
jsonPtr.to_string());
149+
150+
asyncResp->res.jsonValue[jsonPtr] = nullptr;
151+
}
152+
else
153+
{
154+
asyncResp->res.jsonValue[jsonPtr] = static_cast<int64_t>(value);
155+
}
156+
}
157+
158+
inline void getMetricProperty(
159+
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
160+
const std::string& serviceName,
161+
const sdbusplus::message::object_path& objectPath,
162+
const nlohmann::json::json_pointer& jsonPtr)
163+
{
164+
dbus::utility::getProperty<double>(
165+
serviceName, objectPath, "xyz.openbmc_project.Metric.Value", "Value",
166+
std::bind_front(populateMetricsProperty, asyncResp, jsonPtr));
167+
}
168+
169+
inline void handleFabricSwitchPortMetricsPathPortMetricsGet(
170+
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
171+
const boost::system::error_code& ec,
172+
const dbus::utility::MapperGetSubTreeResponse& object)
173+
{
174+
if (ec)
175+
{
176+
BMCWEB_LOG_ERROR("DBus response error on GetAssociatedSubTree{}", ec);
177+
messages::internalError(asyncResp->res);
178+
return;
179+
}
180+
181+
for (const auto& [path, service] : object)
182+
{
183+
if (service.size() != 1)
184+
{
185+
continue;
186+
}
187+
188+
sdbusplus::message::object_path objectPah(path);
189+
190+
const std::string metricType = objectPah.parent_path().filename();
191+
const std::string metricName = objectPah.filename();
192+
193+
if (metricType != "pcie")
194+
{
195+
continue;
196+
}
197+
198+
const auto& serviceName = service.begin()->first;
199+
200+
if (metricName == "correctable_error_count")
201+
{
202+
getMetricProperty(asyncResp, serviceName, path,
203+
"/PCIeErrors/CorrectableErrorCount"_json_pointer);
204+
}
205+
else if (metricName == "non_fatal_error_count")
206+
{
207+
getMetricProperty(asyncResp, serviceName, path,
208+
"/PCIeErrors/NonFatalErrorCount"_json_pointer);
209+
}
210+
else if (metricName == "fatal_error_count")
211+
{
212+
getMetricProperty(asyncResp, serviceName, path,
213+
"/PCIeErrors/FatalErrorCount"_json_pointer);
214+
}
215+
else if (metricName == "l0_to_recovery_count")
216+
{
217+
getMetricProperty(asyncResp, serviceName, path,
218+
"/PCIeErrors/L0ToRecoveryCount"_json_pointer);
219+
}
220+
else if (metricName == "replay_count")
221+
{
222+
getMetricProperty(asyncResp, serviceName, path,
223+
"/PCIeErrors/ReplayCount"_json_pointer);
224+
}
225+
else if (metricName == "replay_rollover_count")
226+
{
227+
getMetricProperty(asyncResp, serviceName, path,
228+
"/PCIeErrors/ReplayRolloverCount"_json_pointer);
229+
}
230+
else if (metricName == "nak_sent_count")
231+
{
232+
getMetricProperty(asyncResp, serviceName, path,
233+
"/PCIeErrors/NAKSentCount"_json_pointer);
234+
}
235+
else if (metricName == "nak_received_count")
236+
{
237+
getMetricProperty(asyncResp, serviceName, path,
238+
"/PCIeErrors/NAKReceivedCount"_json_pointer);
239+
}
240+
else if (metricName == "unsupported_request_count")
241+
{
242+
getMetricProperty(
243+
asyncResp, serviceName, path,
244+
"/PCIeErrors/UnsupportedRequestCount"_json_pointer);
245+
}
246+
}
247+
}
248+
135249
inline void handleFabricSwitchPortPathPortMetricsGet(
136250
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
137251
const std::string& fabricId, const std::string& switchId,
138-
const std::string& portId, [[maybe_unused]] const std::string& portPath,
252+
const std::string& portId, const std::string& portPath,
139253
[[maybe_unused]] const std::string& serviceName)
140254
{
141255
asyncResp->res.jsonValue["@odata.type"] = "#PortMetrics.v1_3_0.PortMetrics";
@@ -145,6 +259,15 @@ inline void handleFabricSwitchPortPathPortMetricsGet(
145259
asyncResp->res.jsonValue["Id"] = "Metrics";
146260
asyncResp->res.jsonValue["Name"] =
147261
std::format("{} {} Port Metrics", switchId, portId);
262+
263+
const sdbusplus::message::object_path associationPath =
264+
sdbusplus::message::object_path(portPath) / "measured_by";
265+
dbus::utility::getAssociatedSubTree(
266+
associationPath,
267+
sdbusplus::message::object_path("/xyz/openbmc_project/metric"), 0,
268+
std::array<std::string_view, 1>{"xyz.openbmc_project.Metric.Value"},
269+
std::bind_front(handleFabricSwitchPortMetricsPathPortMetricsGet,
270+
asyncResp));
148271
}
149272

150273
inline void handleFabricSwitchPortPathPortGet(
@@ -170,7 +293,7 @@ inline void handleFabricSwitchPortPathPortGet(
170293
switchId, portId);
171294

172295
dbus::utility::getAllProperties(
173-
serviceName, portPath, std::string{portInterface[0]},
296+
serviceName, portPath, "xyz.openbmc_project.Inventory.Connector.Port",
174297
std::bind_front(afterGetFabricSwitchPortInfo, asyncResp));
175298
}
176299

@@ -226,8 +349,10 @@ inline void getAssociatedPortPath(
226349
{
227350
std::string associationPath = switchPath + "/connecting";
228351
dbus::utility::getAssociatedSubTree(
229-
associationPath, sdbusplus::message::object_path{inventoryPath}, 0,
230-
portInterface,
352+
associationPath,
353+
sdbusplus::message::object_path{"/xyz/openbmc_project/inventory"}, 0,
354+
std::array<std::string_view, 1>{
355+
"xyz.openbmc_project.Inventory.Connector.Port"},
231356
std::bind_front(afterHandleFabricSwitchPortPaths, asyncResp, portId,
232357
std::move(callback)));
233358
}
@@ -273,8 +398,10 @@ inline void getFabricSwitchPortPaths(
273398
{
274399
std::string associationPath = switchPath + "/connecting";
275400
dbus::utility::getAssociatedSubTreePaths(
276-
associationPath, sdbusplus::message::object_path{inventoryPath}, 0,
277-
portInterface,
401+
associationPath,
402+
sdbusplus::message::object_path{"/xyz/openbmc_project/inventory"}, 0,
403+
std::array<std::string_view, 1>{
404+
"xyz.openbmc_project.Inventory.Connector.Port"},
278405
std::bind_front(handleFabricSwitchPathPortCollection, asyncResp,
279406
fabricId, switchId));
280407
}

test/redfish-core/lib/service_root_test.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ void assertServiceRootGet(crow::Response& res)
5858
EXPECT_EQ(json["Managers"]["@odata.id"], "/redfish/v1/Managers");
5959
EXPECT_EQ(json["Managers"].size(), 1);
6060

61+
EXPECT_EQ(json["Fabrics"]["@odata.id"], "/redfish/v1/Fabrics");
62+
EXPECT_EQ(json["Fabrics"].size(), 1);
63+
6164
EXPECT_EQ(json["Name"], "Root Service");
6265
EXPECT_EQ(json["RedfishVersion"], "1.17.0");
6366

0 commit comments

Comments
 (0)