[Mellanox] implement sfp.reset for CMIS management (#16862)
- Why I did it For CMIS host management module, we need a different implementation for sfp.reset. This PR is to implement it - How I did it For SW control modules, do reset from hw_reset For FW control modules, do reset as the original way - How to verify it Manual test sonic-mgmt platform test
This commit is contained in:
parent
37a9c25cfb
commit
d8a1ffbace
@ -26,6 +26,7 @@ try:
|
||||
import ctypes
|
||||
import subprocess
|
||||
import os
|
||||
import threading
|
||||
from sonic_py_common.logger import Logger
|
||||
from sonic_py_common.general import check_output_pipe
|
||||
from . import utils
|
||||
@ -219,6 +220,9 @@ class SdkHandleContext(object):
|
||||
deinitialize_sdk_handle(self.sdk_handle)
|
||||
|
||||
class NvidiaSFPCommon(SfpOptoeBase):
|
||||
sfp_index_to_logical_port_dict = {}
|
||||
sfp_index_to_logical_lock = threading.Lock()
|
||||
|
||||
def __init__(self, sfp_index):
|
||||
super(NvidiaSFPCommon, self).__init__()
|
||||
self.index = sfp_index + 1
|
||||
@ -248,6 +252,30 @@ class NvidiaSFPCommon(SfpOptoeBase):
|
||||
|
||||
return oper_state, error_type
|
||||
|
||||
@classmethod
|
||||
def get_sfp_index_to_logical_port(cls, force=False):
|
||||
if not cls.sfp_index_to_logical_port_dict or force:
|
||||
config_db = utils.DbUtils.get_db_instance('CONFIG_DB')
|
||||
port_data = config_db.get_table('PORT')
|
||||
for key, data in port_data.items():
|
||||
if data['index'] not in cls.sfp_index_to_logical_port_dict:
|
||||
cls.sfp_index_to_logical_port_dict[int(data['index']) - 1] = key
|
||||
|
||||
@classmethod
|
||||
def get_logical_port_by_sfp_index(cls, sfp_index):
|
||||
with cls.sfp_index_to_logical_lock:
|
||||
cls.get_sfp_index_to_logical_port()
|
||||
logical_port_name = cls.sfp_index_to_logical_port_dict.get(sfp_index)
|
||||
if not logical_port_name:
|
||||
cls.get_sfp_index_to_logical_port(force=True)
|
||||
else:
|
||||
config_db = utils.DbUtils.get_db_instance('CONFIG_DB')
|
||||
current_index = int(config_db.get('CONFIG_DB', f'PORT|{logical_port_name}', 'index'))
|
||||
if current_index != sfp_index:
|
||||
cls.get_sfp_index_to_logical_port(force=True)
|
||||
logical_port_name = cls.sfp_index_to_logical_port_dict.get(sfp_index)
|
||||
return logical_port_name
|
||||
|
||||
|
||||
class SFP(NvidiaSFPCommon):
|
||||
"""Platform-specific SFP class"""
|
||||
@ -299,6 +327,17 @@ class SFP(NvidiaSFPCommon):
|
||||
Returns:
|
||||
bool: True if device is present, False if not
|
||||
"""
|
||||
if DeviceDataManager.is_independent_mode():
|
||||
if utils.read_int_from_file(f'/sys/module/sx_core/asic0/module{self.sdk_index}/control') != 0:
|
||||
if not utils.read_int_from_file(f'/sys/module/sx_core/asic0/module{self.sdk_index}/hw_present'):
|
||||
return False
|
||||
if not utils.read_int_from_file(f'/sys/module/sx_core/asic0/module{self.sdk_index}/power_good'):
|
||||
return False
|
||||
if not utils.read_int_from_file(f'/sys/module/sx_core/asic0/module{self.sdk_index}/power_on'):
|
||||
return False
|
||||
if utils.read_int_from_file(f'/sys/module/sx_core/asic0/module{self.sdk_index}/hw_reset') == 1:
|
||||
return False
|
||||
|
||||
eeprom_raw = self._read_eeprom(0, 1, log_on_error=False)
|
||||
return eeprom_raw is not None
|
||||
|
||||
@ -455,8 +494,17 @@ class SFP(NvidiaSFPCommon):
|
||||
|
||||
refer plugins/sfpreset.py
|
||||
"""
|
||||
file_path = SFP_SDK_MODULE_SYSFS_ROOT_TEMPLATE.format(self.sdk_index) + SFP_SYSFS_RESET
|
||||
return utils.write_file(file_path, '1')
|
||||
try:
|
||||
if not self.is_sw_control():
|
||||
file_path = SFP_SDK_MODULE_SYSFS_ROOT_TEMPLATE.format(self.sdk_index) + SFP_SYSFS_RESET
|
||||
return utils.write_file(file_path, '1')
|
||||
else:
|
||||
file_path = SFP_SDK_MODULE_SYSFS_ROOT_TEMPLATE.format(self.sdk_index) + SFP_SYSFS_HWRESET
|
||||
return utils.write_file(file_path, '0') and utils.write_file(file_path, '1')
|
||||
except Exception as e:
|
||||
print(f'Failed to reset module - {e}')
|
||||
logger.log_error(f'Failed to reset module - {e}')
|
||||
return False
|
||||
|
||||
|
||||
@classmethod
|
||||
@ -918,15 +966,15 @@ class SFP(NvidiaSFPCommon):
|
||||
return False
|
||||
|
||||
db = utils.DbUtils.get_db_instance('STATE_DB')
|
||||
control_type = db.get('STATE_DB', f'TRANSCEIVER_MODULES_MGMT|{self.sdk_index}', 'control_type')
|
||||
control_file_value = utils.read_int_from_file(f'/sys/module/sx_core/asic0/module{self.sdk_index}/control')
|
||||
logical_port = NvidiaSFPCommon.get_logical_port_by_sfp_index(self.sdk_index)
|
||||
if not logical_port:
|
||||
raise Exception(f'Module {self.sdk_index} is not present or in initialization')
|
||||
|
||||
if control_type == 'SW_CONTROL' and control_file_value == 1:
|
||||
return True
|
||||
elif control_type == 'FW_CONTROL' and control_file_value == 0:
|
||||
return False
|
||||
else:
|
||||
raise Exception(f'Module {self.sdk_index} is in initialization, please retry later')
|
||||
initialized = db.exists('STATE_DB', f'TRANSCEIVER_STATUS|{logical_port}')
|
||||
if not initialized:
|
||||
raise Exception(f'Module {self.sdk_index} is not present or in initialization')
|
||||
|
||||
return utils.read_int_from_file(f'/sys/module/sx_core/asic0/module{self.sdk_index}/control') == 1
|
||||
|
||||
|
||||
class RJ45Port(NvidiaSFPCommon):
|
||||
|
@ -381,9 +381,9 @@ class DbUtils:
|
||||
cls.db_instances.data = {}
|
||||
|
||||
if db_name not in cls.db_instances.data:
|
||||
from swsscommon.swsscommon import SonicV2Connector
|
||||
db = SonicV2Connector(use_unix_socket_path=True)
|
||||
db.connect(db_name)
|
||||
from swsscommon.swsscommon import ConfigDBConnector
|
||||
db = ConfigDBConnector(use_unix_socket_path=True)
|
||||
db.db_connect(db_name)
|
||||
cls.db_instances.data[db_name] = db
|
||||
return cls.db_instances.data[db_name]
|
||||
except Exception as e:
|
||||
|
@ -266,9 +266,14 @@ class TestSfp:
|
||||
@mock.patch('sonic_platform.utils.write_file')
|
||||
def test_reset(self, mock_write):
|
||||
sfp = SFP(0)
|
||||
sfp.is_sw_control = mock.MagicMock(return_value=False)
|
||||
mock_write.return_value = True
|
||||
assert sfp.reset()
|
||||
mock_write.assert_called_with('/sys/module/sx_core/asic0/module0/reset', '1')
|
||||
sfp.is_sw_control.return_value = True
|
||||
assert sfp.reset()
|
||||
sfp.is_sw_control.side_effect = Exception('')
|
||||
assert not sfp.reset()
|
||||
|
||||
@mock.patch('sonic_platform.sfp.SFP.read_eeprom')
|
||||
def test_get_xcvr_api(self, mock_read):
|
||||
@ -332,31 +337,33 @@ class TestSfp:
|
||||
assert sfp.get_temperature_warning_threashold() == 75.0
|
||||
assert sfp.get_temperature_critical_threashold() == 85.0
|
||||
|
||||
@mock.patch('sonic_platform.sfp.NvidiaSFPCommon.get_logical_port_by_sfp_index')
|
||||
@mock.patch('sonic_platform.utils.read_int_from_file')
|
||||
@mock.patch('sonic_platform.device_data.DeviceDataManager.is_independent_mode')
|
||||
@mock.patch('sonic_platform.utils.DbUtils.get_db_instance')
|
||||
def test_is_sw_control(self, mock_get_db, mock_mode, mock_read):
|
||||
def test_is_sw_control(self, mock_get_db, mock_mode, mock_read, mock_get_logical):
|
||||
sfp = SFP(0)
|
||||
mock_mode.return_value = False
|
||||
assert not sfp.is_sw_control()
|
||||
mock_mode.return_value = True
|
||||
|
||||
mock_db = mock.MagicMock()
|
||||
mock_get_db.return_value = mock_db
|
||||
mock_db.get = mock.MagicMock(return_value=None)
|
||||
mock_get_logical.return_value = None
|
||||
with pytest.raises(Exception):
|
||||
sfp.is_sw_control()
|
||||
|
||||
mock_read.return_value = 0
|
||||
mock_db.get.return_value = 'FW_CONTROL'
|
||||
assert not sfp.is_sw_control()
|
||||
mock_read.return_value = 1
|
||||
mock_db.get.return_value = 'SW_CONTROL'
|
||||
assert sfp.is_sw_control()
|
||||
mock_read.return_value = 0
|
||||
mock_get_logical.return_value = 'Ethernet0'
|
||||
mock_db = mock.MagicMock()
|
||||
mock_get_db.return_value = mock_db
|
||||
mock_db.exists = mock.MagicMock(return_value=False)
|
||||
with pytest.raises(Exception):
|
||||
sfp.is_sw_control()
|
||||
|
||||
mock_db.exists.return_value = True
|
||||
mock_read.return_value = 0
|
||||
assert not sfp.is_sw_control()
|
||||
mock_read.return_value = 1
|
||||
assert sfp.is_sw_control()
|
||||
|
||||
@mock.patch('sonic_platform.device_data.DeviceDataManager.is_independent_mode', mock.MagicMock(return_value=False))
|
||||
@mock.patch('sonic_platform.sfp.SFP.is_sw_control', mock.MagicMock(return_value=False))
|
||||
@mock.patch('sonic_platform.utils.is_host', mock.MagicMock(side_effect = [True, True, False, False]))
|
||||
|
Loading…
Reference in New Issue
Block a user