From 4fcd8913fbcdd5d4083565d6fcad1ed34dd233f0 Mon Sep 17 00:00:00 2001 From: Eric Zhu Date: Mon, 8 Aug 2022 21:20:07 -0500 Subject: [PATCH 1/2] add optoe based sfp implementation Why I did it Add sfp-refactor optoe based sfp implementation for Seastone2 How I did it Inherit and implement the sfp api according to new sfp-refactor architecture How to verify it Verify sfp status and sfp configure commands on seastone2 with new implementation --- .../sonic_platform_config/sfp.json | 1 + .../platform_api/sonic_platform/chassis.py | 6 +- .../platform_api/sonic_platform/sfp.py | 4 + .../platform_api/sonic_platform/sfp_optoe.py | 177 ++++++++++++++++++ 4 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp_optoe.py diff --git a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json index d12f0c3ffc1b..d6857a6da823 100644 --- a/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json +++ b/device/celestica/x86_64-cel_seastone_2-r0/sonic_platform_config/sfp.json @@ -1,5 +1,6 @@ { "port_num": 33, + "sfp_api": "sfp_optoe", "eeprom_path": "/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom", "port_i2c_mapping": [ 2, diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/chassis.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/chassis.py index aa7671484889..f51d41d6352e 100644 --- a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/chassis.py +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/chassis.py @@ -63,13 +63,17 @@ def __initialize_fan(self): def __initialize_sfp(self): from sonic_platform.sfp import Sfp + from sonic_platform.sfp_optoe import SfpOptoe sfp_config_path = self._api_common.get_config_path(self.SFP_CONFIG) sfp_config = self._api_common.load_json_file(sfp_config_path) sfp_index = 0 for index in range(0, sfp_config['port_num']): - sfp = Sfp(sfp_index, conf=sfp_config) + if sfp_config['sfp_api'] == "sfp_optoe": + sfp = SfpOptoe(sfp_index, conf=sfp_config) + else: + sfp = Sfp(sfp_index, conf=sfp_config) self._sfp_list.append(sfp) sfp_index += 1 self.sfp_module_initialized = True diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py index b0c0a63d5a42..831b166144c8 100644 --- a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp.py @@ -819,6 +819,7 @@ def get_transceiver_info(self): sfp_interface_bulk_raw[start: end], 0) transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value'] + transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value'] transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value'] transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value'] transceiver_info_dict['vendor_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value'] @@ -2035,3 +2036,6 @@ def set_power_override(self, power_override, power_set): return True return False + + def read_eeprom(self, offset, num_bytes): + return self._read_eeprom_specific_bytes(offset, num_bytes) diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp_optoe.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp_optoe.py new file mode 100644 index 000000000000..26f327f014ff --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp_optoe.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python + +############################################################################# +# Celestica +# +# Module contains an implementation of SONiC Platform Base API and +# provides the sfp status which are available in the platform +# +############################################################################# + +import os +import syslog +import time + +try: + from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase + #from sonic_platform_base.sfp_base import SfpBase + from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper + from sonic_platform.common import Common +except ImportError as e: + raise ImportError(str(e) + "- required module not found") + +QSFP_INFO_OFFSET = 128 + + +class SfpOptoe(SfpOptoeBase): + """Platform-specific SfpOptoe class""" + + def __init__(self, sfp_index=0, conf=None): + SfpOptoeBase.__init__(self) + + self._sfp_index = sfp_index + self._config = conf + self._sfp_type = None + self._api_common = Common(self._config) + self._read_porttab_mappings() + + @property + def sfp_type(self): + if self._sfp_type is None: + self._sfp_type = self._detect_sfp_type() + return self._sfp_type + + def _detect_sfp_type(self): + sfp_type = 'N/A' + info = self.get_transceiver_info() + if info: + sfp_type = info.get("type_abbrv_name") + # XXX: Need this hack until xcvrd is refactored + if sfp_type in ["OSFP-8X", "QSFP-DD"]: + sfp_type = "QSFP_DD" + return sfp_type + + def _read_porttab_mappings(self): + self._sfputil_helper = SfpUtilHelper() + self._sfputil_helper.read_porttab_mappings( + self._get_path_to_port_config_file()) + + def _get_path_to_port_config_file(self): + host_platform_root_path = '/usr/share/sonic/device' + docker_hwsku_path = '/usr/share/sonic/hwsku' + + host_platform_path = "/".join([host_platform_root_path, + self._api_common.platform]) + hwsku_path = "/".join([host_platform_path, self._api_common.hwsku] + ) if self._api_common.is_host() else docker_hwsku_path + + return "/".join([hwsku_path, "port_config.ini"]) + + def get_eeprom_path(self): + eeprom_path = self._config['eeprom_path'] + port_to_i2c_mapping = self._config['port_i2c_mapping'] + port_eeprom_path = eeprom_path.format( + port_to_i2c_mapping[self._sfp_index]) + + return port_eeprom_path + + def get_name(self): + """ + Retrieves the human-readable name of a sfp by 1-based index + + Returns: + :param index: An integer, 1-based index of the sfp of which to query status + :return: String, + A string representing the name of the sfp. + """ + return self._sfputil_helper.physical_to_logical[self._sfp_index + 1] or "Unknown" + + def get_presence(self): + """ + Retrieves the presence of the device + Returns: + bool: True if device is present, False if not + """ + return self._api_common.get_output(self._sfp_index, self._config['get_presence'], False) + + def get_position_in_parent(self): + return self._sfp_index + + def is_replaceable(self): + return True + + def get_status(self): + """ + Retrieves the operational status of the device + + Returns: + A boolean value, True if device is operating properly, False if not + """ + if not self.get_presence(): + return False + reset = self.get_reset_status() + if reset: + status = False + else: + status = True + return status + + def get_reset_status(self): + """ + Retrieves the reset status of SFP + Returns: + A Boolean, True if reset enabled, False if disabled + """ + return self._api_common.get_output(self._sfp_index, self._config['get_reset_status'], False) + + def get_lpmode(self): + """ + Retrieves the lpmode (low power mode) status of this SFP + Returns: + A Boolean, True if lpmode is enabled, False if disabled + """ + return self._api_common.get_output(self._sfp_index, self._config['get_lpmode'], False) + + def reset(self): + """ + Reset SFP and return all user module settings to their default srate. + + Returns: + A boolean, True if successful, False if not + """ + config = self._config['reset'] + # Convert our register value back to a hex string and write back + output1 = self._api_common.set_output(self._sfp_index, "0x0", config) + + # Sleep 1 second to allow it to settle + time.sleep(1) + # Flip the bit back high and write back to the register to take port out of reset + output2 = self._api_common.set_output(self._sfp_index, "0x1", config) + + return True if (output1 and output2) else False + + def set_lpmode(self, lpmode): + """ + Sets the lpmode (low power mode) of SFP + + Args: + lpmode: A Boolean, True to enable lpmode, False to disable it + Note : lpmode can be overridden by set_power_override + + Returns: + A boolean, True if lpmode is set successfully, False if not + """ + return self._api_common.set_output(self._sfp_index, str(lpmode), self._config['set_lpmode']) + + def get_error_description(self): + """ + Retrives the error descriptions of the SFP module + + Returns: + String that represents the current error descriptions of vendor specific errors + In case there are multiple errors, they should be joined by '|', + like: "Bad EEPROM|Unsupported cable" + """ + if not self.get_presence(): + return self.SFP_STATUS_UNPLUGGED + return self.SFP_STATUS_OK From 9cf745b62875b4623851eadd2e1ef9eb3c72feda Mon Sep 17 00:00:00 2001 From: Eric Zhu Date: Thu, 18 Aug 2022 01:43:08 +0000 Subject: [PATCH 2/2] fix the lgtm bot alerts --- .../services/platform_api/sonic_platform/sfp_optoe.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp_optoe.py b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp_optoe.py index 26f327f014ff..7dec451513c1 100644 --- a/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp_optoe.py +++ b/platform/broadcom/sonic-platform-modules-cel/services/platform_api/sonic_platform/sfp_optoe.py @@ -8,20 +8,16 @@ # ############################################################################# -import os -import syslog import time try: from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase #from sonic_platform_base.sfp_base import SfpBase from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper - from sonic_platform.common import Common + from .common import Common except ImportError as e: raise ImportError(str(e) + "- required module not found") -QSFP_INFO_OFFSET = 128 - class SfpOptoe(SfpOptoeBase): """Platform-specific SfpOptoe class"""