diff --git a/platform/broadcom/sonic-platform-modules-nexthop/common/nexthop/pddf_config_parser.py b/platform/broadcom/sonic-platform-modules-nexthop/common/nexthop/pddf_config_parser.py index bc7a17700e0..4f0e0f5ebba 100644 --- a/platform/broadcom/sonic-platform-modules-nexthop/common/nexthop/pddf_config_parser.py +++ b/platform/broadcom/sonic-platform-modules-nexthop/common/nexthop/pddf_config_parser.py @@ -6,10 +6,12 @@ """ import json +import os import re from dataclasses import dataclass from enum import Enum +from sonic_py_common import device_info PDDF_DEVICE_JSON_PATH = "/usr/share/sonic/platform/pddf/pddf-device.json" PD_PLUGIN_JSON_PATH = "/usr/share/sonic/platform/pddf/pd-plugin.json" @@ -40,6 +42,26 @@ def load_pd_plugin_config() -> dict: return config +def load_platform_json() -> dict: + """ + Load and parse platform.json configuration file. + + Returns: + Dictionary containing the platform.json configuration. + + Raises: + FileNotFoundError: If platform.json file does not exist. + json.JSONDecodeError: If the file contains invalid JSON. + Exception: For other file reading errors. + """ + platform_path = device_info.get_path_to_platform_dir() + platform_json_file = os.path.join(platform_path, device_info.PLATFORM_JSON_FILE) + + with open(platform_json_file, 'r') as f: + config = json.load(f) + return config + + def extract_fpga_attrs(config, fpga_types): """Extract fpga attrs information from PDDF config. Raise exception on error.""" fpga_attrs = {} diff --git a/platform/broadcom/sonic-platform-modules-nexthop/common/sonic_platform/asic_thermal.py b/platform/broadcom/sonic-platform-modules-nexthop/common/sonic_platform/asic_thermal.py index 3d770693843..2f07283ec66 100644 --- a/platform/broadcom/sonic-platform-modules-nexthop/common/sonic_platform/asic_thermal.py +++ b/platform/broadcom/sonic-platform-modules-nexthop/common/sonic_platform/asic_thermal.py @@ -2,13 +2,23 @@ # Copyright 2025 Nexthop Systems Inc. All rights reserved. # SPDX-License-Identifier: Apache-2.0 + +import logging from sonic_platform_pddf_base.pddf_asic_thermal import PddfAsicThermal +from swsscommon import swsscommon +from sonic_py_common import syslogger +from nexthop.pddf_config_parser import load_platform_json from .thermal import PidThermalMixin, MinMaxTempMixin +SYSLOG_IDENTIFIER = "nh_asic_thermal" +log = syslogger.SysLogger(SYSLOG_IDENTIFIER, log_level=logging.INFO, enable_runtime_config=False) + class AsicThermal(PddfAsicThermal, MinMaxTempMixin, PidThermalMixin): """PDDF Platform-Specific ASIC Thermal class""" + _polling_enabled_checked = False + def __init__( self, index, @@ -25,7 +35,73 @@ def __init__( PidThermalMixin.__init__(self, dev_info) + def _get_platform_asic_sensor_config(self): + """ + Read ASIC sensor configuration from platform.json. + Returns a tuple of (poll_interval, poll_admin_status) or (None, None) if not found. + """ + try: + platform_json = load_platform_json() + + asic_sensors = platform_json.get("asic_sensors", {}) + if not asic_sensors: + return None, None + + poll_interval = asic_sensors.get("poll_interval") + poll_admin_status = asic_sensors.get("poll_admin_status") + + return poll_interval, poll_admin_status + except Exception as e: + log.log_warning(f"Failed to read ASIC sensor configuration from platform.json: {str(e)}") + return None, None + + def _ensure_asic_sensor_polling_enabled(self): + """ + Ensure ASIC sensor polling is enabled in CONFIG_DB. + This is called every time we read temperature to guarantee polling is active. + """ + if AsicThermal._polling_enabled_checked: + return + + try: + desired_interval, desired_admin_status = self._get_platform_asic_sensor_config() + + if desired_admin_status is None: + AsicThermal._polling_enabled_checked = True + return + + desired_interval = desired_interval if desired_interval is not None else "10" + + config_db = swsscommon.ConfigDBConnector() + config_db.connect() + + asic_sensors_config = config_db.get_table("ASIC_SENSORS") + + poller_status = asic_sensors_config.get("ASIC_SENSORS_POLLER_STATUS", {}) + admin_status = poller_status.get("admin_status", "") + + if admin_status != desired_admin_status: + config_db.mod_entry("ASIC_SENSORS", "ASIC_SENSORS_POLLER_STATUS", + {"admin_status": desired_admin_status}) + log.log_info(f"Updated ASIC sensor polling admin_status to {desired_admin_status}") + + poller_interval = asic_sensors_config.get("ASIC_SENSORS_POLLER_INTERVAL", {}) + current_interval = poller_interval.get("interval", "") + + if current_interval != desired_interval: + config_db.mod_entry("ASIC_SENSORS", "ASIC_SENSORS_POLLER_INTERVAL", + {"interval": desired_interval}) + log.log_info(f"Updated ASIC sensor polling interval to {desired_interval}") + + AsicThermal._polling_enabled_checked = True + + except Exception as e: + log.log_error(f"Failed to update ASIC sensor polling: {str(e)}") + pass + def get_temperature(self): + self._ensure_asic_sensor_polling_enabled() + temp = super().get_temperature() self._update_min_max_temp(temp) return temp