From 72ec212fa75378b2b60e5210fa04f0b1eebc0462 Mon Sep 17 00:00:00 2001 From: Kebo Liu Date: Sat, 12 Sep 2020 04:23:23 +0800 Subject: [PATCH] [Mellanox] Refactor SFP related platform API and plugins with new SDK API (#5326) Refactor SFP reset, low power get/set API, and plugins with new SDK SX APIs. Previously they were calling SDK SXD APIs which have glibc dependency because of shared memory usage. Remove implementation "set_power_override", "tx_disable_channel", "tx_disable" which using SXD APIs, once related SDK SX API available, will add them back based on new SDK SX APIs. --- .../plugins/sfplpmget.py | 56 +-- .../plugins/sfplpmset.py | 173 +++++----- .../plugins/sfpreset.py | 73 ++-- .../mlnx-platform-api/sonic_platform/sfp.py | 326 ++++++------------ 4 files changed, 255 insertions(+), 373 deletions(-) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py index a4a53fb099..2f19edfa1a 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmget.py @@ -1,43 +1,51 @@ #!/usr/bin/env python +""" +This utility get the power mode of a given module. +""" -import sys, errno -import os -from python_sdk_api.sxd_api import * +import sys +import errno from python_sdk_api.sx_api import * +def mgmt_phy_mod_pwr_attr_get(handle, module_id, power_attr_type): + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_get(handle, module_id, sx_mgmt_phy_mod_pwr_attr_p) + assert SX_STATUS_SUCCESS == rc, "sx_mgmt_phy_mod_pwr_attr_get failed" + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t_p_value(sx_mgmt_phy_mod_pwr_attr_p) + pwr_mode_attr = sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr + return pwr_mode_attr.admin_pwr_mode_e, pwr_mode_attr.oper_pwr_mode_e + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) + # Check if SFP port number is provided if len(sys.argv) < 2: - print "SFP module number is missed." - print "Usage: sfplpmget.py " + print("SFP module number is missed.") + print("Usage: sfplpmget.py ") sys.exit(errno.EINVAL) # Init SDK API rc, handle = sx_api_open(None) if (rc != SX_STATUS_SUCCESS): - print "Failed to open api handle.\nPlease check that SDK is running." - sys.exit(errno.EACCES) - -pid = os.getpid() -rc = sxd_access_reg_init(pid, None, 0) -if (rc != 0): - print "Failed to initializing register access.\nPlease check that SDK is running." + print("Failed to open api handle.\nPlease check that SDK is running.") sys.exit(errno.EACCES) # Get SFP module number sfp_module = int(sys.argv[1]) - 1 -# Get MCION -mcion = ku_mcion_reg() -mcion.module = sfp_module -meta = sxd_reg_meta_t() -meta.dev_id = 1 -meta.swid = 0 -meta.access_cmd = SXD_ACCESS_CMD_GET +admin_pwr_mode, oper_pwr_mode = mgmt_phy_mod_pwr_attr_get(handle, sfp_module, SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E) -rc = sxd_access_reg_mcion(mcion, meta, 1, None, None) -assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_mcion failed, rc = %d" % rc +lpm_status = None +if oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_HIGH_E: + lpm_status = False +elif oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E: + lpm_status = True +else: + print("LPM UNKNOWN") -# Get low power mode status -lpm_mask = 1 << 8 -lpm_status = (lpm_mask & mcion.module_status_bits) != 0 print "LPM ON" if lpm_status else "LPM OFF" + +sx_api_close(handle) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py index 9fafaa9514..132d342575 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfplpmset.py @@ -1,23 +1,17 @@ #!/usr/bin/env python +""" +This utility set the power mode of a given module. +""" -import sys, errno -import os -from python_sdk_api.sxd_api import * +import sys +import errno from python_sdk_api.sx_api import * -REGISTER_NUM = 1 -SXD_LOG_VERBOSITY_LEVEL = 0 + DEVICE_ID = 1 SWITCH_ID = 0 SX_PORT_ATTR_ARR_SIZE = 64 -PMAOS_ASE = 1 -PMAOS_EE = 1 -PMAOS_E = 2 -PMAOS_RST = 0 -PMAOS_ENABLE = 1 -PMAOS_DISABLE = 2 - PORT_TYPE_CPU = 4 PORT_TYPE_NVE = 8 PORT_TYPE_OFFSET = 28 @@ -36,7 +30,7 @@ def is_port_admin_status_up(log_port): admin_state_p = new_sx_port_admin_state_t_p() module_state_p = new_sx_port_module_state_t_p() rc = sx_api_port_state_get(handle, log_port, oper_state_p, admin_state_p, module_state_p) - assert rc == SXD_STATUS_SUCCESS, "sx_api_port_state_get failed, rc = %d" % rc + assert rc == SX_STATUS_SUCCESS, "sx_api_port_state_get failed, rc = %d" % rc admin_state = sx_port_admin_state_t_p_value(admin_state_p) if admin_state == SX_PORT_ADMIN_STATUS_UP: @@ -54,116 +48,109 @@ def get_log_ports(handle, sfp_module): port_cnt_p = new_uint32_t_p() uint32_t_p_assign(port_cnt_p, SX_PORT_ATTR_ARR_SIZE) - rc = sx_api_port_device_get(handle, DEVICE_ID , SWITCH_ID, port_attributes_list, port_cnt_p) + rc = sx_api_port_device_get(handle, DEVICE_ID, SWITCH_ID, port_attributes_list, port_cnt_p) assert rc == SX_STATUS_SUCCESS, "sx_api_port_device_get failed, rc = %d" % rc port_cnt = uint32_t_p_value(port_cnt_p) log_port_list = [] for i in range(0, port_cnt): port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list, i) - if is_nve(int(port_attributes.log_port)) == False \ - and is_cpu(int(port_attributes.log_port)) == False \ + if not is_nve(int(port_attributes.log_port)) \ + and not is_cpu(int(port_attributes.log_port)) \ and port_attributes.port_mapping.module_port == sfp_module \ and is_port_admin_status_up(port_attributes.log_port): log_port_list.append(port_attributes.log_port) return log_port_list -def init_sx_meta_data(): - meta = sxd_reg_meta_t() - meta.dev_id = DEVICE_ID - meta.swid = SWITCH_ID - return meta +def mgmt_phy_mod_pwr_attr_set(handle, module_id, power_attr_type, admin_pwr_mode): + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_mode_attr = sx_mgmt_phy_mod_pwr_mode_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_mode_attr.admin_pwr_mode_e = admin_pwr_mode + sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr = sx_mgmt_phy_mod_pwr_mode_attr + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_set(handle, SX_ACCESS_CMD_SET, module_id, sx_mgmt_phy_mod_pwr_attr_p) + assert SX_STATUS_SUCCESS == rc, "sx_mgmt_phy_mod_pwr_attr_set failed" + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) -def set_sfp_admin_status(sfp_module, admin_status): - # Get PMAOS - pmaos = ku_pmaos_reg() - pmaos.module = sfp_module - meta = init_sx_meta_data() - meta.access_cmd = SXD_ACCESS_CMD_GET - rc = sxd_access_reg_pmaos(pmaos, meta, REGISTER_NUM, None, None) - assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc +def mgmt_phy_mod_pwr_attr_get(handle, module_id, power_attr_type): + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_get(handle, module_id, sx_mgmt_phy_mod_pwr_attr_p) + assert SX_STATUS_SUCCESS == rc, "sx_mgmt_phy_mod_pwr_attr_get failed" + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t_p_value(sx_mgmt_phy_mod_pwr_attr_p) + pwr_mode_attr = sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr + return pwr_mode_attr.admin_pwr_mode_e, pwr_mode_attr.oper_pwr_mode_e + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) - # Set admin status to PMAOS - pmaos.ase = PMAOS_ASE - pmaos.ee = PMAOS_EE - pmaos.e = PMAOS_E - pmaos.rst = PMAOS_RST - if admin_status == SX_PORT_ADMIN_STATUS_DOWN: - pmaos.admin_status = PMAOS_DISABLE + +def pwr_attr_set(handle, module_id, ports, attr_type, power_mode): + # Check if the module already works in the same mode + admin_pwr_mode, oper_pwr_mode = mgmt_phy_mod_pwr_attr_get(handle, module_id, attr_type) + if (power_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E and oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E) \ + or (power_mode == SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E and admin_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E): + return + try: + # Bring the port down + for port in ports: + set_port_admin_status_by_log_port(handle, port, SX_PORT_ADMIN_STATUS_DOWN) + # Set the desired power mode + mgmt_phy_mod_pwr_attr_set(handle, module_id, attr_type, power_mode) + # Bring the port up + finally: + for port in ports: + set_port_admin_status_by_log_port(handle, port, SX_PORT_ADMIN_STATUS_UP) + +def set_lpmode(handle, cmd, module_id): + # Construct the port module map. + log_port_list = get_log_ports(handle, module_id) + + if cmd == "enable": + pwr_attr_set(handle, module_id, log_port_list, SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E, SX_MGMT_PHY_MOD_PWR_MODE_LOW_E) + print("Enabled low power mode for module [%d]" % module_id) + elif cmd == "disable": + pwr_attr_set(handle, module_id, log_port_list, SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E, SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E) + print("Disabled low power mode for module [%d]" % module_id) else: - pmaos.admin_status = PMAOS_ENABLE + print("Error: Invalid command") + sys.exit(0) - meta.access_cmd = SXD_ACCESS_CMD_SET - rc = sxd_access_reg_pmaos(pmaos, meta, REGISTER_NUM, None, None) - assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc - -def set_sfp_lpmode(sfp_module, lpm_enable): - # Get PMMP - pmmp = ku_pmmp_reg() - pmmp.module = sfp_module - meta = init_sx_meta_data() - meta.access_cmd = SXD_ACCESS_CMD_GET - rc = sxd_access_reg_pmmp(pmmp, meta, REGISTER_NUM, None, None) - assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmmp failed, rc = %d" % rc - - # Set low power mode status - lpm_mask = 1 << 8 - if lpm_enable: - pmmp.eeprom_override = pmmp.eeprom_override | lpm_mask - else: - pmmp.eeprom_override = pmmp.eeprom_override & (~lpm_mask) - - meta.access_cmd = SXD_ACCESS_CMD_SET - rc = sxd_access_reg_pmmp(pmmp, meta, REGISTER_NUM, None, None) - assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmmp failed, rc = %d" % rc - -# Check if SFP port number is provided if len(sys.argv) < 3: - print "SFP module number or LPM is missed." - print "Usage: sfplpmset.py " + print("SFP module number or LPM is missed.") + print("Usage: sfplpmset.py ") sys.exit(errno.EINVAL) +cmd = None lpm_enable = None if sys.argv[2] == 'on': lpm_enable = True + cmd = 'enable' elif sys.argv[2] == 'off': lpm_enable = False + cmd = 'disable' else: - print "Unrecognized LPM parameter. Please use or values" + print("Unrecognized LPM parameter. Please use or values") sys.exit(errno.EINVAL) -# Init SDK API -rc, handle = sx_api_open(None) -if (rc != SX_STATUS_SUCCESS): - print "Failed to open api handle.\nPlease check that SDK is running." - sys.exit(errno.EACCES) - -pid = os.getpid() -rc = sxd_access_reg_init(pid, None, SXD_LOG_VERBOSITY_LEVEL) -if (rc != SXD_STATUS_SUCCESS): - print "Failed to initializing register access.\nPlease check that SDK is running." - sys.exit(errno.EACCES); - # Get SFP module sfp_module = int(sys.argv[1]) - 1 -# Get all ports at admin up status that related to the SFP module -log_port_list = get_log_ports(handle, sfp_module) +print "[+] opening sdk" +rc, handle = sx_api_open(None) -# SET SFP related ports to admin down status -for log_port in log_port_list: - set_port_admin_status_by_log_port(handle, log_port, SX_PORT_ADMIN_STATUS_DOWN) +if (rc != SX_STATUS_SUCCESS): + print("Failed to open api handle.\nPlease check that SDK is running.") + sys.exit(errno.EACCES) -# Disable admin status before LPM settings -set_sfp_admin_status(sfp_module, SX_PORT_ADMIN_STATUS_DOWN) +# Set low power mode +set_lpmode(handle, cmd, sfp_module) -# Set low power mode status -set_sfp_lpmode(sfp_module, lpm_enable) - -# Enable admin status after LPM settings -set_sfp_admin_status(sfp_module, SX_PORT_ADMIN_STATUS_UP) - -# SET SFP related ports to admin up status -for log_port in log_port_list: - set_port_admin_status_by_log_port(handle, log_port, SX_PORT_ADMIN_STATUS_UP) +sx_api_close(handle) diff --git a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py index 2ba6c6d7bc..2e6de2e8bc 100644 --- a/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py +++ b/device/mellanox/x86_64-mlnx_msn2700-r0/plugins/sfpreset.py @@ -1,45 +1,28 @@ -#!/usr/bin/env python - -import sys, errno -import os -from python_sdk_api.sxd_api import * -from python_sdk_api.sx_api import * - -# Check if SFP port number is provided -if len(sys.argv) < 2: - print "SFP module number or LPM is missed." - print "Usage: sfpreset.py " - sys.exit(errno.EINVAL) - -# Init SDK API -rc, handle = sx_api_open(None) -if (rc != SX_STATUS_SUCCESS): - print "Failed to open api handle.\nPlease check that SDK is running." - sys.exit(errno.EACCES) - -pid = os.getpid() -rc = sxd_access_reg_init(pid, None, 0) -if (rc != 0): - print "Failed to initializing register access.\nPlease check that SDK is running." - sys.exit(errno.EACCES) - -# Get SFP module number -sfp_module = int(sys.argv[1]) - 1 - -# Get PMAOS -pmaos = ku_pmaos_reg() -pmaos.module = sfp_module -meta = sxd_reg_meta_t() -meta.dev_id = 1 -meta.swid = 0 -meta.access_cmd = SXD_ACCESS_CMD_GET - -rc = sxd_access_reg_pmaos(pmaos, meta, 1, None, None) -assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc - -# Reset SFP -pmaos.rst = 1 -meta.access_cmd = SXD_ACCESS_CMD_SET -rc = sxd_access_reg_pmaos(pmaos, meta, 1, None, None) -assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc -print "Reset flag is set" +#!/usr/bin/env python +""" +This utility reset the given SFP module. +""" + +import sys +import errno +from python_sdk_api.sx_api import * + +# Check if SFP port number is provided +if len(sys.argv) < 2: + print("SFP module number or LPM is missed.") + print("Usage: sfpreset.py ") + sys.exit(errno.EINVAL) + +# Init SDK API +rc, handle = sx_api_open(None) +if rc != SX_STATUS_SUCCESS: + print("Failed to open api handle.\nPlease check that SDK is running.") + sys.exit(errno.EACCES) + +# Get SFP module number +sfp_module = int(sys.argv[1]) - 1 + +rc = sx_mgmt_phy_mod_reset(handle, sfp_module) +assert rc == SX_STATUS_SUCCESS, "sx_mgmt_phy_mod_reset failed, rc = %d" % rc + +sx_api_close(handle) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py index afe0dd0cc1..1d6a618a37 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py @@ -92,8 +92,8 @@ XCVR_SECOND_APPLICATION_LIST_WIDTH_QSFP_DD = 28 # in function get_transceiver_info and get_transceiver_bulk_status # XCVR_INTERFACE_DATA_SIZE stands for the max size to be read # this variable is only used by get_transceiver_info. -# please be noted that each time some new value added to the function -# we should make sure that it falls into the area +# please be noted that each time some new value added to the function +# we should make sure that it falls into the area # [XCVR_INTERFACE_DATA_START, XCVR_INTERFACE_DATA_SIZE] or # adjust XCVR_INTERFACE_MAX_SIZE to contain the new data # It's same for [QSFP_DOM_BULK_DATA_START, QSFP_DOM_BULK_DATA_SIZE] and @@ -197,12 +197,12 @@ QSFP_DD_CHANNL_STATUS_WIDTH = 1 # identifier value of xSFP module which is in the first byte of the EEPROM # if the identifier value falls into SFP_TYPE_CODE_LIST the module is treated as a SFP module and parsed according to 8472 # for QSFP_TYPE_CODE_LIST the module is treated as a QSFP module and parsed according to 8436/8636 -# Originally the type (SFP/QSFP) of each module is determined according to the SKU dictionary +# Originally the type (SFP/QSFP) of each module is determined according to the SKU dictionary # where the type of each FP port is defined. The content of EEPROM is parsed according to its type. # However, sometimes the SFP module can be fit in an adapter and then pluged into a QSFP port. # In this case the EEPROM content is in format of SFP but parsed as QSFP, causing failure. -# To resolve that issue the type field of the xSFP module is also fetched so that we can know exectly what type the -# module is. Currently only the following types are recognized as SFP/QSFP module. +# To resolve that issue the type field of the xSFP module is also fetched so that we can know exectly what type the +# module is. Currently only the following types are recognized as SFP/QSFP module. # Meanwhile, if the a module's identifier value can't be recognized, it will be parsed according to the SKU dictionary. # This is because in the future it's possible that some new identifier value which is not regonized but backward compatible # with the current format and by doing so it can be parsed as much as possible. @@ -217,7 +217,7 @@ QSFP_DD_TYPE_CODE_LIST = [ '18' # QSFP-DD Double Density 8X Pluggable Transceiver ] -qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', +qsfp_cable_length_tup = ('Length(km)', 'Length OM3(2m)', 'Length OM2(m)', 'Length OM1(m)', 'Length Cable Assembly(m)') @@ -225,7 +225,7 @@ sfp_cable_length_tup = ('LengthSMFkm-UnitsOfKm', 'LengthSMF(UnitsOf100m)', 'Length50um(UnitsOf10m)', 'Length62.5um(UnitsOfm)', 'LengthCable(UnitsOfm)', 'LengthOM3(UnitsOf10m)') -sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', +sfp_compliance_code_tup = ('10GEthernetComplianceCode', 'InfinibandComplianceCode', 'ESCONComplianceCodes', 'SONETComplianceCodes', 'EthernetComplianceCodes','FibreChannelLinkLength', 'FibreChannelTechnology', 'SFP+CableTechnology', @@ -274,9 +274,11 @@ MCIA_ADDR_TX_DISABLE = 110 MCIA_ADDR_TX_DISABLE_BIT = 6 PORT_TYPE_NVE = 8 +PORT_TYPE_CPU = 4 PORT_TYPE_OFFSET = 28 PORT_TYPE_MASK = 0xF0000000 NVE_MASK = PORT_TYPE_MASK & (PORT_TYPE_NVE << PORT_TYPE_OFFSET) +CPU_MASK = PORT_TYPE_MASK & (PORT_TYPE_CPU << PORT_TYPE_OFFSET) # Global logger class instance logger = Logger() @@ -555,7 +557,7 @@ class SFP(SfpBase): Returns: A dict which contains following keys/values : ================================================================================ - keys |Value Format |Information + keys |Value Format |Information ---------------------------|---------------|---------------------------- type |1*255VCHAR |type of SFP hardware_rev |1*255VCHAR |hardware version of SFP @@ -714,7 +716,7 @@ class SFP(SfpBase): sfp_cable_len_data = sfpi_obj.parse_cable_len(sfp_cable_len_raw, 0) else: return None - + sfp_media_type_raw = self._read_eeprom_specific_bytes(XCVR_MEDIA_TYPE_OFFSET_QSFP_DD, XCVR_MEDIA_TYPE_WIDTH_QSFP_DD) if sfp_media_type_raw is not None: sfp_media_type_dict = sfpi_obj.parse_media_type(sfp_media_type_raw, 0) @@ -828,14 +830,14 @@ class SFP(SfpBase): for key in qsfp_compliance_code_tup: if key in sfp_interface_bulk_data['data']['Specification compliance']['value']: - compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] + compliance_code_dict[key] = sfp_interface_bulk_data['data']['Specification compliance']['value'][key]['value'] sfp_ext_specification_compliance_raw = self._read_eeprom_specific_bytes(offset + XCVR_EXT_SPECIFICATION_COMPLIANCE_OFFSET, XCVR_EXT_SPECIFICATION_COMPLIANCE_WIDTH) if sfp_ext_specification_compliance_raw is not None: sfp_ext_specification_compliance_data = sfpi_obj.parse_ext_specification_compliance(sfp_ext_specification_compliance_raw[0 : 1], 0) if sfp_ext_specification_compliance_data['data']['Extended Specification compliance']['value'] != "Unspecified": compliance_code_dict['Extended Specification compliance'] = sfp_ext_specification_compliance_data['data']['Extended Specification compliance']['value'] transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) - + transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['Nominal Bit Rate(100Mbs)']['value']) else: for key in sfp_cable_length_tup: @@ -849,7 +851,7 @@ class SFP(SfpBase): transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) transceiver_info_dict['nominal_bit_rate'] = str(sfp_interface_bulk_data['data']['NominalSignallingRate(UnitsOf100Mbd)']['value']) - + return transceiver_info_dict @@ -860,7 +862,7 @@ class SFP(SfpBase): Returns: A dict which contains following keys/values : ======================================================================== - keys |Value Format |Information + keys |Value Format |Information ---------------------------|---------------|---------------------------- RX LOS |BOOLEAN |RX lost-of-signal status, | |True if has RX los, False if not. @@ -1237,12 +1239,12 @@ class SFP(SfpBase): A Boolean, True if reset enabled, False if disabled for QSFP, originally I would like to make use of Initialization complete flag bit - which is at Page a0 offset 6 bit 0 to test whether reset is complete. + which is at Page a0 offset 6 bit 0 to test whether reset is complete. However as unit testing was carried out I find this approach may fail because: 1. we make use of ethtool to read data on I2C bus rather than to read directly 2. ethtool is unable to access I2C during QSFP module being reset In other words, whenever the flag is able to be retrived, the value is always be 1 - As a result, it doesn't make sense to retrieve that flag. Just treat successfully + As a result, it doesn't make sense to retrieve that flag. Just treat successfully retrieving data as "data ready". for SFP it seems that there is not flag indicating whether reset succeed. However, we can also do it in the way for QSFP. @@ -1444,7 +1446,7 @@ class SFP(SfpBase): Returns: A hex of 4 bits (bit 0 to bit 3 as channel 0 to channel 3) to represent TX channels which have been disabled in this SFP. - As an example, a returned value of 0x5 indicates that channel 0 + As an example, a returned value of 0x5 indicates that channel 0 and channel 2 have been disabled. """ tx_disable_list = self.get_tx_disable() @@ -1457,6 +1459,21 @@ class SFP(SfpBase): return tx_disabled + def mgmt_phy_mod_pwr_attr_get(self, power_attr_type): + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_get(self.sdk_handle, self.sdk_index, sx_mgmt_phy_mod_pwr_attr_p) + assert SX_STATUS_SUCCESS == rc, "sx_mgmt_phy_mod_pwr_attr_get failed" + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t_p_value(sx_mgmt_phy_mod_pwr_attr_p) + pwr_mode_attr = sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr + return pwr_mode_attr.admin_pwr_mode_e, pwr_mode_attr.oper_pwr_mode_e + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) + + def get_lpmode(self): """ Retrieves the lpmode (low power mode) status of this SFP @@ -1464,28 +1481,15 @@ class SFP(SfpBase): Returns: A Boolean, True if lpmode is enabled, False if disabled """ - if self.sfp_type == QSFP_TYPE: - if self._open_sdk(): - # Get MCION - mcion = ku_mcion_reg() - mcion.module = self.sdk_index - meta = self._init_sx_meta_data() - meta.access_cmd = SXD_ACCESS_CMD_GET + handle = self._open_sdk() + if handle is None: + logger.log_error("SDK handler is missing for sfp %d object" % self.index) + return False - rc = sxd_access_reg_mcion(mcion, meta, REGISTER_NUM, None, None) - self._close_sdk() + admin_pwr_mode, oper_pwr_mode = self.mgmt_phy_mod_pwr_attr_get(SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E) - if rc != SXD_STATUS_SUCCESS: - logger.log_warning("sxd_access_reg_mcion getting failed, rc = %d" % rc) - return None - - # Get low power mode status - lpm_mask = 1 << 8 - lpm_status = (lpm_mask & mcion.module_status_bits) != 0 - - return lpm_status - else: - return NotImplementedError + self._close_sdk() + return oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E def get_power_override(self): @@ -1580,7 +1584,7 @@ class SFP(SfpBase): if self.sfp_type == QSFP_TYPE: offset = 0 offset_xcvr = 128 - + sfpd_obj = sff8436Dom() if sfpd_obj is None: return None @@ -1596,7 +1600,7 @@ class SFP(SfpBase): return None if self.sfp_type == QSFP_DD_TYPE: - offset = 128 + offset = 128 sfpd_obj = qsfp_dd_Dom() if sfpd_obj is None: @@ -1641,7 +1645,7 @@ class SFP(SfpBase): if self.sfp_type == QSFP_TYPE: offset = 0 offset_xcvr = 128 - + sfpd_obj = sff8436Dom() if sfpd_obj is None: return None @@ -1653,7 +1657,7 @@ class SFP(SfpBase): tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX2Bias']['value'])) tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX3Bias']['value'])) tx_bias_list.append(self._convert_string_to_num(dom_channel_monitor_data['data']['TX4Bias']['value'])) - + elif self.sfp_type == QSFP_DD_TYPE: # page 11h if self.dom_rx_tx_power_bias_supported: @@ -1713,7 +1717,7 @@ class SFP(SfpBase): elif self.sfp_type == QSFP_TYPE: offset = 0 offset_xcvr = 128 - + sfpd_obj = sff8436Dom() if sfpd_obj is None: return None @@ -1861,64 +1865,15 @@ class SFP(SfpBase): """ handle = self._open_sdk() if handle is None: + logger.log_error("SDK handler is missing for sfp %d object" % self.index) return False - # Get PMAOS - pmaos = ku_pmaos_reg() - pmaos.module = self.sdk_index - meta = self._init_sx_meta_data() - meta.access_cmd = SXD_ACCESS_CMD_GET - - rc = sxd_access_reg_pmaos(pmaos, meta, REGISTER_NUM, None, None) - if rc != SXD_STATUS_SUCCESS: - logger.log_warning("sxd_access_reg_pmaos getting failed, rc = %d" % rc) - self._close_sdk() - return None - - # Reset SFP - pmaos.rst = 1 - meta.access_cmd = SXD_ACCESS_CMD_SET - rc = sxd_access_reg_pmaos(pmaos, meta, REGISTER_NUM, None, None) - if rc != SXD_STATUS_SUCCESS: - logger.log_warning("sxd_access_reg_pmaos setting failed, rc = %d" % rc) + rc = sx_mgmt_phy_mod_reset(self.sdk_handle, self.sdk_index) + if rc != SX_STATUS_SUCCESS: + logger.log_warning("sx_mgmt_phy_mod_reset failed, rc = %d" % rc) self._close_sdk() - return rc == SXD_STATUS_SUCCESS - - - def _write_i2c_via_mcia(self, page, i2caddr, address, data, mask): - handle = self._open_sdk() - if handle is None: - return False - - mcia = ku_mcia_reg() - - meta = self._init_sx_meta_data() - meta.access_cmd = SXD_ACCESS_CMD_GET - - mcia.module = self.sdk_index - mcia.page_number = page - mcia.i2c_device_address = i2caddr - mcia.device_address = address - mcia.size = 1 - rc = sxd_access_reg_mcia(mcia, meta, REGISTER_NUM, None, None) - if rc != SXD_STATUS_SUCCESS: - logger.log_warning("sxd_access_reg_mcia getting failed, rc = %d" % rc) - self._close_sdk() - return False - - original_data = (mcia.dword_0 >> 24) & 0x000000FF - updated_data = original_data & (~mask) - updated_data |= (data & mask) - - mcia.dword_0 = (updated_data << 24) & 0xFF000000 - meta.access_cmd = SXD_ACCESS_CMD_SET - rc = sxd_access_reg_mcia(mcia, meta, REGISTER_NUM, None, None) - if rc != SXD_STATUS_SUCCESS: - logger.log_warning("sxd_access_reg_mcia setting failed, rc = %d" % rc) - - self._close_sdk() - return rc == SXD_STATUS_SUCCESS + return rc == SX_STATUS_SUCCESS def tx_disable(self, tx_disable): @@ -1935,34 +1890,7 @@ class SFP(SfpBase): for SFP, make use of bit 6 of byte at (offset 110, a2h (i2c addr 0x51)) to disable/enable tx for QSFP, set all channels to disable/enable tx """ - if self.sfp_type == SFP_TYPE: - if self.dom_tx_disable_supported: - handle = self._open_sdk() - if handle is None: - return False - - tx_disable_mask = 1 << MCIA_ADDR_TX_DISABLE_BIT - if tx_disable: - tx_disable_bit = tx_disable_mask - else: - tx_disable_bit = 0 - - return self._write_i2c_via_mcia(2, 0x51, MCIA_ADDR_TX_DISABLE, tx_disable_bit, tx_disable_mask) - else: - return False - elif self.sfp_type == QSFP_TYPE: - if self.dom_tx_disable_supported: - channel_mask = 0x0f - if tx_disable: - disable_flag = channel_mask - else: - disable_flag = 0 - - return self._write_i2c_via_mcia(0, 0x50, MCIA_ADDR_TX_CHANNEL_DISABLE, disable_flag, channel_mask) - else: - return False - else: - return NotImplementedError + return NotImplementedError def tx_disable_channel(self, channel, disable): @@ -1980,25 +1908,17 @@ class SFP(SfpBase): QSFP: page a0, address 86, lower 4 bits """ - if self.sfp_type == QSFP_TYPE: - if self.dom_tx_disable_supported: - channel_mask = 1 << channel - if disable: - disable_flag = channel_mask - else: - disable_flag = 0 - - return self._write_i2c_via_mcia(0, 0x50, MCIA_ADDR_TX_CHANNEL_DISABLE, disable_flag, channel_mask) - else: - return False - else: - return NotImplementedError + return NotImplementedError def is_nve(self, port): return (port & NVE_MASK) != 0 + def is_cpu(self, port): + return (port & CPU_MASK) != 0 + + def is_port_admin_status_up(self, log_port): oper_state_p = new_sx_port_oper_state_t_p() admin_state_p = new_sx_port_admin_state_t_p() @@ -2015,11 +1935,14 @@ class SFP(SfpBase): def set_port_admin_status_by_log_port(self, log_port, admin_status): rc = sx_api_port_state_set(self.sdk_handle, log_port, admin_status) - assert rc == SX_STATUS_SUCCESS, "sx_api_port_state_set failed, rc = %d" % rc + if SX_STATUS_SUCCESS != rc: + logger.log_error("sx_api_port_state_set failed, rc = %d" % rc) + + return SX_STATUS_SUCCESS == rc - # Get all the ports related to the sfp, if port admin status is up, put it to list - def get_log_ports(self): + def get_logical_ports(self): + # Get all the ports related to the sfp, if port admin status is up, put it to list port_attributes_list = new_sx_port_attributes_t_arr(SX_PORT_ATTR_ARR_SIZE) port_cnt_p = new_uint32_t_p() uint32_t_p_assign(port_cnt_p, SX_PORT_ATTR_ARR_SIZE) @@ -2031,58 +1954,56 @@ class SFP(SfpBase): log_port_list = [] for i in range(0, port_cnt): port_attributes = sx_port_attributes_t_arr_getitem(port_attributes_list, i) - if self.is_nve(int(port_attributes.log_port)) == False \ - and port_attributes.port_mapping.module_port == self.sdk_index \ - and self.is_port_admin_status_up(port_attributes.log_port): + if not self.is_nve(int(port_attributes.log_port)) \ + and not self.is_cpu(int(port_attributes.log_port)) \ + and port_attributes.port_mapping.module_port == self.sdk_index \ + and self.is_port_admin_status_up(port_attributes.log_port): log_port_list.append(port_attributes.log_port) return log_port_list - def _set_sfp_admin_status_raw(self, admin_status): - # Get PMAOS - pmaos = ku_pmaos_reg() - pmaos.module = self.sdk_index - meta = self._init_sx_meta_data() - meta.access_cmd = SXD_ACCESS_CMD_GET - rc = sxd_access_reg_pmaos(pmaos, meta, REGISTER_NUM, None, None) - assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc + def mgmt_phy_mod_pwr_attr_set(self, power_attr_type, admin_pwr_mode): + result = False + sx_mgmt_phy_mod_pwr_attr = sx_mgmt_phy_mod_pwr_attr_t() + sx_mgmt_phy_mod_pwr_mode_attr = sx_mgmt_phy_mod_pwr_mode_attr_t() + sx_mgmt_phy_mod_pwr_attr.power_attr_type = power_attr_type + sx_mgmt_phy_mod_pwr_mode_attr.admin_pwr_mode_e = admin_pwr_mode + sx_mgmt_phy_mod_pwr_attr.pwr_mode_attr = sx_mgmt_phy_mod_pwr_mode_attr + sx_mgmt_phy_mod_pwr_attr_p = new_sx_mgmt_phy_mod_pwr_attr_t_p() + sx_mgmt_phy_mod_pwr_attr_t_p_assign(sx_mgmt_phy_mod_pwr_attr_p, sx_mgmt_phy_mod_pwr_attr) + try: + rc = sx_mgmt_phy_mod_pwr_attr_set(self.sdk_handle, SX_ACCESS_CMD_SET, self.sdk_index, sx_mgmt_phy_mod_pwr_attr_p) + if SX_STATUS_SUCCESS != rc: + logger.log_error("sx_mgmt_phy_mod_pwr_attr_set failed, rc = %d" % rc) + result = False + else: + result = True + finally: + delete_sx_mgmt_phy_mod_pwr_attr_t_p(sx_mgmt_phy_mod_pwr_attr_p) - # Set admin status to PMAOS - pmaos.ase = PMAOS_ASE - pmaos.ee = PMAOS_EE - pmaos.e = PMAOS_E - pmaos.rst = PMAOS_RST - if admin_status == SX_PORT_ADMIN_STATUS_DOWN: - pmaos.admin_status = PMAOS_DISABLE - else: - pmaos.admin_status = PMAOS_ENABLE - - meta.access_cmd = SXD_ACCESS_CMD_SET - rc = sxd_access_reg_pmaos(pmaos, meta, REGISTER_NUM, None, None) - assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmaos failed, rc = %d" % rc + return result - def _set_lpmode_raw(self, lpmode): - # Get PMMP - pmmp = ku_pmmp_reg() - pmmp.module = self.sdk_index - meta = self._init_sx_meta_data() - meta.access_cmd = SXD_ACCESS_CMD_GET - rc = sxd_access_reg_pmmp(pmmp, meta, REGISTER_NUM, None, None) - assert rc == SXD_STATUS_SUCCESS, "sxd_access_reg_pmmp failed, rc = %d" % rc + def _set_lpmode_raw(self, ports, attr_type, power_mode): + result = False + # Check if the module already works in the same mode + admin_pwr_mode, oper_pwr_mode = self.mgmt_phy_mod_pwr_attr_get(attr_type) + if (power_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E and oper_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_LOW_E) \ + or (power_mode == SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E and admin_pwr_mode == SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E): + return True + try: + # Bring the port down + for port in ports: + self.set_port_admin_status_by_log_port(port, SX_PORT_ADMIN_STATUS_DOWN) + # Set the desired power mode + result = self.mgmt_phy_mod_pwr_attr_set(attr_type, power_mode) + finally: + # Bring the port up + for port in ports: + self.set_port_admin_status_by_log_port(port, SX_PORT_ADMIN_STATUS_UP) - # Set low power mode status - lpm_mask = 1 << PMMP_LPMODE_BIT - if lpmode: - pmmp.eeprom_override = pmmp.eeprom_override | lpm_mask - else: - pmmp.eeprom_override = pmmp.eeprom_override & (~lpm_mask) - - meta.access_cmd = SXD_ACCESS_CMD_SET - rc = sxd_access_reg_pmmp(pmmp, meta, REGISTER_NUM, None, None) - - return rc + return result def set_lpmode(self, lpmode): @@ -2098,24 +2019,18 @@ class SFP(SfpBase): """ handle = self._open_sdk() if handle is None: + logger.log_error("SDK handler is missing for sfp %d object" % self.index) return False - try: - log_port_list = self.get_log_ports() - for log_port in log_port_list: - self.set_port_admin_status_by_log_port(log_port, SX_PORT_ADMIN_STATUS_DOWN) - self._set_sfp_admin_status_raw(SX_PORT_ADMIN_STATUS_DOWN) - result = self._set_lpmode_raw(lpmode) - - self._set_sfp_admin_status_raw(SX_PORT_ADMIN_STATUS_UP) - for log_port in log_port_list: - self.set_port_admin_status_by_log_port(log_port, SX_PORT_ADMIN_STATUS_DOWN) - - return result == SXD_STATUS_SUCCESS - except: - logger.log_warning("set_lpmode failed due to some SDK failure") - self._close_sdk() - return False + log_port_list = self.get_logical_ports() + if lpmode: + self._set_lpmode_raw(log_port_list, SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E, SX_MGMT_PHY_MOD_PWR_MODE_LOW_E) + logger.log_info("Enabled low power mode for module [%d]" % (self.sdk_index)) + else: + self._set_lpmode_raw(log_port_list, SX_MGMT_PHY_MOD_PWR_ATTR_PWR_MODE_E, SX_MGMT_PHY_MOD_PWR_MODE_AUTO_E) + logger.log_info( "Disabled low power mode for module [%d]" % (self.sdk_index)) + self._close_sdk() + return True def set_power_override(self, power_override, power_set): @@ -2123,7 +2038,7 @@ class SFP(SfpBase): Sets SFP power level using power_override and power_set Args: - power_override : + power_override : A Boolean, True to override set_lpmode and use power_set to control SFP power, False to disable SFP power control through power_override/power_set and use set_lpmode @@ -2137,15 +2052,4 @@ class SFP(SfpBase): A boolean, True if power-override and power_set are set successfully, False if not """ - if self.sfp_type == QSFP_TYPE: - power_override_bit = 0 - if power_override: - power_override_bit |= 1 << MCIA_ADDR_POWER_OVERRIDE_POR_BIT - power_set_bit = 0 - if power_set: - power_set_bit |= 1 << MCIA_ADDR_POWER_OVERRIDE_PS_BIT - power_override_mask = 1 << MCIA_ADDR_POWER_OVERRIDE_PS_BIT | 1 << MCIA_ADDR_POWER_OVERRIDE_POR_BIT - - return self._write_i2c_via_mcia(0, 0x50, MCIA_ADDR_POWER_OVERRIDE, power_set_bit|power_override_bit, power_override_mask) - else: - return NotImplementedError + return NotImplementedError