Skip to content

Commit

Permalink
Cross validate Sensors against PM config validator
Browse files Browse the repository at this point in the history
Summary:
Extract sensor name and validate the symlink against PM config validator.

With that, we fixed Montblanc sensor service config.

Next step:
1. Request CLS to change regarding naming issues -- E.g. SMB_TSENSOR* in MCB unit.
2. Validate correct PmUnitName is defined for the SlotPath.

Reviewed By: somasun

Differential Revision: D65923827

fbshipit-source-id: 21a2f06e61565b4427c4975b3f50a58fe6d4ecc2
  • Loading branch information
Justin Kim authored and facebook-github-bot committed Nov 18, 2024
1 parent 4d04855 commit cec3306
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 147 deletions.
120 changes: 60 additions & 60 deletions fboss/platform/configs/montblanc/sensor_service.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,46 @@
"slotPath": "/",
"pmUnitName": "MINIPACK3_MCB",
"sensors": [
{
"name": "SMB_LEFT_U51_TEMP",
"sysfsPath": "/run/devmap/sensors/SMB_TSENSOR5/temp1_input",
"type": 3,
"thresholds": {
"upperCriticalVal": 85,
"maxAlarmVal": 80
},
"compute": "@/1000"
},
{
"name": "SMB_OUTLET_U57_TEMP",
"sysfsPath": "/run/devmap/sensors/SMB_TSENSOR2/temp1_input",
"type": 3,
"thresholds": {
"upperCriticalVal": 95,
"maxAlarmVal": 90
},
"compute": "@/1000"
},
{
"name": "SMB_BEHIND_TH5_U39_TEMP",
"sysfsPath": "/run/devmap/sensors/SMB_TSENSOR3/temp1_input",
"type": 3,
"thresholds": {
"upperCriticalVal": 95,
"maxAlarmVal": 90
},
"compute": "@/1000"
},
{
"name": "SMB_RIGHT_U182_TEMP",
"sysfsPath": "/run/devmap/sensors/SMB_TSENSOR6/temp1_input",
"type": 3,
"thresholds": {
"upperCriticalVal": 85,
"maxAlarmVal": 80
},
"compute": "@/1000"
},
{
"name": "CPU_UNCORE_TEMP",
"sysfsPath": "/run/devmap/sensors/CPU_CORE_TEMP/temp1_input",
Expand Down Expand Up @@ -598,26 +638,6 @@
"slotPath": "/SCM_SLOT@0/COMESE_SLOT@0",
"pmUnitName": "NETLAKE",
"sensors": [
{
"name": "COME_U18_INLET_SENSOR_TMP75_TEMP",
"sysfsPath": "/run/devmap/sensors/COME_TSENSOR1/temp1_input",
"type": 3,
"thresholds": {
"maxAlarmVal": 60,
"upperCriticalVal": 65
},
"compute": "@/1000"
},
{
"name": "COME_U39_OUTLET_SENSOR_TMP75_TEMP",
"sysfsPath": "/run/devmap/sensors/COME_TSENSOR2/temp1_input",
"type": 3,
"thresholds": {
"maxAlarmVal": 60,
"upperCriticalVal": 65
},
"compute": "@/1000"
},
{
"name": "COME_PU31_TDA38640_PVNN_PCH_VIN",
"sysfsPath": "/run/devmap/sensors/COME_VOLTAGE_MONITOR1/in1_input",
Expand Down Expand Up @@ -1388,6 +1408,26 @@
"slotPath": "/SCM_SLOT@0",
"pmUnitName": "MINIPACK3_SCM",
"sensors": [
{
"name": "COME_U18_INLET_SENSOR_TMP75_TEMP",
"sysfsPath": "/run/devmap/sensors/COME_TSENSOR1/temp1_input",
"type": 3,
"thresholds": {
"maxAlarmVal": 60,
"upperCriticalVal": 65
},
"compute": "@/1000"
},
{
"name": "COME_U39_OUTLET_SENSOR_TMP75_TEMP",
"sysfsPath": "/run/devmap/sensors/COME_TSENSOR2/temp1_input",
"type": 3,
"thresholds": {
"maxAlarmVal": 60,
"upperCriticalVal": 65
},
"compute": "@/1000"
},
{
"name": "SCM_M2_SSD_TEMP",
"sysfsPath": "/run/devmap/sensors/SCM_M2_SSD_TEMP/temp1_input",
Expand Down Expand Up @@ -1669,46 +1709,6 @@
"slotPath": "/SMB_SLOT@0",
"pmUnitName": "MINIPACK3_SMB",
"sensors": [
{
"name": "SMB_LEFT_U51_TEMP",
"sysfsPath": "/run/devmap/sensors/SMB_TSENSOR5/temp1_input",
"type": 3,
"thresholds": {
"upperCriticalVal": 85,
"maxAlarmVal": 80
},
"compute": "@/1000"
},
{
"name": "SMB_OUTLET_U57_TEMP",
"sysfsPath": "/run/devmap/sensors/SMB_TSENSOR2/temp1_input",
"type": 3,
"thresholds": {
"upperCriticalVal": 95,
"maxAlarmVal": 90
},
"compute": "@/1000"
},
{
"name": "SMB_BEHIND_TH5_U39_TEMP",
"sysfsPath": "/run/devmap/sensors/SMB_TSENSOR3/temp1_input",
"type": 3,
"thresholds": {
"upperCriticalVal": 95,
"maxAlarmVal": 90
},
"compute": "@/1000"
},
{
"name": "SMB_RIGHT_U182_TEMP",
"sysfsPath": "/run/devmap/sensors/SMB_TSENSOR6/temp1_input",
"type": 3,
"thresholds": {
"upperCriticalVal": 85,
"maxAlarmVal": 80
},
"compute": "@/1000"
},
{
"name": "SMB_XP3R3V_CLK",
"sysfsPath": "/run/devmap/sensors/SMB_VOLTAGE_MONITOR1/in0_input",
Expand Down
2 changes: 1 addition & 1 deletion fboss/platform/platform_manager/ConfigValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ConfigValidator {
virtual bool isValidSlotPath(
const PlatformConfig& platformConfig,
const std::string& slotPath);
bool isValidDeviceName(
virtual bool isValidDeviceName(
const PlatformConfig& platformConfig,
const std::string& slotPath,
const std::string& deviceName);
Expand Down
1 change: 1 addition & 0 deletions fboss/platform/sensor_service/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ cpp_library(
exported_deps = [
"fbsource//third-party/fmt:fmt",
"//fboss/platform/platform_manager:config_validator",
"//fboss/platform/platform_manager:utils",
"//fboss/platform/sensor_service/if:sensor_config-cpp2-types",
"//folly/logging:logging",
],
Expand Down
131 changes: 93 additions & 38 deletions fboss/platform/sensor_service/ConfigValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@
#include <folly/logging/xlog.h>
#include <re2/re2.h>

#include "fboss/platform/platform_manager/Utils.h"

namespace facebook::fboss::platform::sensor_service {
using namespace sensor_config;
namespace {
const re2::RE2 kSensorSymlinkRegex{"(?P<Path>/run/devmap/sensors/.+)(/.+)+"};
}; // namespace

ConfigValidator::ConfigValidator(
const std::shared_ptr<platform_manager::ConfigValidator>& pmConfigValidator)
Expand All @@ -16,64 +21,114 @@ ConfigValidator::ConfigValidator(
bool ConfigValidator::isValid(
const SensorConfig& sensorConfig,
const std::optional<platform_manager::PlatformConfig>& platformConfig) {
for (std::unordered_set<std::pair<std::string, std::string>> usedSlotPaths;
const auto& pmUnitSensors : *sensorConfig.pmUnitSensorsList()) {
if (!isValidPmUnitSensors(pmUnitSensors, usedSlotPaths)) {
return false;
}
if (!isValidPmUnitSensorsList(*sensorConfig.pmUnitSensorsList())) {
return false;
}
// This is Darwin if platformConfig=std::nullopt
// Until it onboards PM, we can't cross-validate against PM.
if (!platformConfig) {
return true;
}
// Cross-validation agains platform_manager::ConfigValidator.
for (const auto& pmUnitSensors : *sensorConfig.pmUnitSensorsList()) {
if (!pmConfigValidator_->isValidSlotPath(
*platformConfig, *pmUnitSensors.slotPath())) {
if (!isPmValidPmUnitSensorList(
*platformConfig, *sensorConfig.pmUnitSensorsList())) {
return false;
}
return true;
}

bool ConfigValidator::isValidPmUnitSensorsList(
const std::vector<sensor_config::PmUnitSensors>& pmUnitSensorsList) {
std::unordered_set<std::pair<std::string, std::string>> usedSlotPaths;
for (const auto& pmUnitSensors : pmUnitSensorsList) {
if (usedSlotPaths.contains(
{*pmUnitSensors.slotPath(), *pmUnitSensors.pmUnitName()})) {
XLOG(ERR) << fmt::format(
"(SlotPath {}, PmUnitName {}) is a duplicate",
*pmUnitSensors.slotPath(),
*pmUnitSensors.pmUnitName());
return false;
}
usedSlotPaths.insert(
{*pmUnitSensors.slotPath(), *pmUnitSensors.pmUnitName()});
if (!isValidPmSensors(*pmUnitSensors.sensors())) {
return false;
}
}
return true;
}

bool ConfigValidator::isValidPmUnitSensors(
const PmUnitSensors& pmUnitSensors,
std::unordered_set<std::pair<std::string, std::string>>& usedSlotPaths) {
if (usedSlotPaths.contains(
{*pmUnitSensors.slotPath(), *pmUnitSensors.pmUnitName()})) {
XLOG(ERR) << fmt::format(
"(SlotPath {}, PmUnitName {}) is a duplicate",
*pmUnitSensors.slotPath(),
*pmUnitSensors.pmUnitName());
return false;
}
usedSlotPaths.insert(
{*pmUnitSensors.slotPath(), *pmUnitSensors.pmUnitName()});
for (std::unordered_set<std::string> usedSensorNames;
const auto& pmSensor : *pmUnitSensors.sensors()) {
if (!isValidPmSensor(pmSensor, usedSensorNames)) {
bool ConfigValidator::isValidPmSensors(const std::vector<PmSensor>& pmSensors) {
std::unordered_set<std::string> usedSensorNames;
for (const auto& pmSensor : pmSensors) {
if (pmSensor.name()->empty()) {
XLOG(ERR) << "PmSensor name must be non-empty";
return false;
}
if (usedSensorNames.contains(*pmSensor.name())) {
XLOG(ERR) << fmt::format(
"SensorName {} is a duplicate", *pmSensor.name());
return false;
}
usedSensorNames.emplace(*pmSensor.name());
if (!pmSensor.sysfsPath()->starts_with("/run/devmap/sensors/")) {
XLOG(ERR) << "PmSensor sysfsPath must start with /run/devmap/sensors/";
return false;
}
}
return true;
}

bool ConfigValidator::isValidPmSensor(
const PmSensor& pmSensor,
std::unordered_set<std::string>& usedSensorNames) {
if (pmSensor.name()->empty()) {
XLOG(ERR) << "PmSensor name must be non-empty";
return false;
}
if (usedSensorNames.contains(*pmSensor.name())) {
XLOG(ERR) << fmt::format("SensorName {} is a duplicate", *pmSensor.name());
return false;
bool ConfigValidator::isPmValidPmUnitSensorList(
const platform_manager::PlatformConfig& platformConfig,
const std::vector<sensor_config::PmUnitSensors>& pmUnitSensorsList) {
for (const auto& pmUnitSensors : pmUnitSensorsList) {
if (!pmConfigValidator_->isValidSlotPath(
platformConfig, *pmUnitSensors.slotPath())) {
return false;
}
if (!isPmValidPmSensors(
platformConfig,
*pmUnitSensors.slotPath(),
*pmUnitSensors.sensors())) {
return false;
}
}
usedSensorNames.emplace(*pmSensor.name());
if (!pmSensor.sysfsPath()->starts_with("/run/devmap/sensors/")) {
XLOG(ERR) << "PmSensor sysfsPath must start with /run/devmap/sensors/";
return false;
return true;
}

bool ConfigValidator::isPmValidPmSensors(
const platform_manager::PlatformConfig& platformConfig,
const std::string& pmUnitSensorsSlotPath,
const std::vector<sensor_config::PmSensor>& pmSensors) {
for (const auto& pmSensor : pmSensors) {
std::string symlink;
if (!re2::RE2::FullMatch(
*pmSensor.sysfsPath(), kSensorSymlinkRegex, &symlink)) {
XLOG(ERR) << fmt::format(
"Fail to extract sensor symlink from {}", *pmSensor.sysfsPath());
return false;
}
if (!platformConfig.symbolicLinkToDevicePath()->contains(symlink)) {
XLOG(ERR) << fmt::format(
"{} is not defined in PlatformConfig::symbolicLinkToDevicePath",
symlink);
return false;
}
auto [slotPath, deviceName] = platform_manager::Utils().parseDevicePath(
platformConfig.symbolicLinkToDevicePath()->at(symlink));
if (pmUnitSensorsSlotPath != slotPath) {
XLOG(ERR) << fmt::format(
"PmUnitSensors SlotPath {} doesn't match with SlotPath {} of {}",
pmUnitSensorsSlotPath,
slotPath,
symlink);
return false;
}
if (!pmConfigValidator_->isValidDeviceName(
platformConfig, pmUnitSensorsSlotPath, deviceName)) {
return false;
}
}
return true;
}
Expand Down
18 changes: 12 additions & 6 deletions fboss/platform/sensor_service/ConfigValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ class ConfigValidator {
bool isValid(
const sensor_config::SensorConfig& sensorConfig,
const std::optional<platform_manager::PlatformConfig>& platformConfig);
bool isValidPmUnitSensors(
const sensor_config::PmUnitSensors& PmUnitSensors,
std::unordered_set<std::pair<std::string, std::string>>& usedSlotPaths);
bool isValidPmSensor(
const sensor_config::PmSensor& pmSensor,
std::unordered_set<std::string>& usedSensorNames);
// Local validation
bool isValidPmUnitSensorsList(
const std::vector<sensor_config::PmUnitSensors>& pmUnitSensorsList);
bool isValidPmSensors(const std::vector<sensor_config::PmSensor>& pmSensor);
bool isValidSlotPath(const std::string& slotPath);
// PlatformManager validation
bool isPmValidPmUnitSensorList(
const platform_manager::PlatformConfig& platformConfig,
const std::vector<sensor_config::PmUnitSensors>& pmUnitSensorsList);
bool isPmValidPmSensors(
const platform_manager::PlatformConfig& platformConfig,
const std::string& pmUnitSensorsSlotPath,
const std::vector<sensor_config::PmSensor>& pmSensors);

private:
const std::shared_ptr<platform_manager::ConfigValidator> pmConfigValidator_;
Expand Down
Loading

0 comments on commit cec3306

Please sign in to comment.