From b0bb3d40d38d6f000f415ecbe5cdacc00b748a09 Mon Sep 17 00:00:00 2001 From: Junchao-Mellanox <57339448+Junchao-Mellanox@users.noreply.github.com> Date: Mon, 11 Dec 2023 16:42:01 +0800 Subject: [PATCH] [Mellanox] Implement low power mode for cmis host management (#17159) - Why I did it For cmis host management mode, the prevous sysfs cannot be used for low power mode setting. This PR reuses existing low power mode implementation in sonic_xcvr package when CMIS host management mode is enabled - How I did it Use sonic_xcvr low power mode implementation when CMIS host management mode is enabled. - How to verify it Manual test for CMIS host management mode Regression test for old mode and backward compatible test --- .../mlnx-platform-api/sonic_platform/sfp.py | 30 ++++++++++++ .../mlnx-platform-api/tests/test_sfp.py | 46 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py index 4b5c9bf4e924..e0e11a50ef20 100644 --- a/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py +++ b/platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py @@ -397,6 +397,18 @@ def get_lpmode(self): Returns: A Boolean, True if lpmode is enabled, False if disabled """ + try: + if self.is_sw_control(): + api = self.get_xcvr_api() + return api.get_lpmode() if api else False + elif DeviceDataManager.is_independent_mode(): + file_path = SFP_SDK_MODULE_SYSFS_ROOT_TEMPLATE.format(self.sdk_index) + SFP_SYSFS_POWER_MODE + power_mode = utils.read_int_from_file(file_path) + return power_mode == POWER_MODE_LOW + except Exception as e: + print(e) + return False + if utils.is_host(): # To avoid performance issue, # call class level method to avoid initialize the whole sonic platform API @@ -573,6 +585,24 @@ def set_lpmode(self, lpmode): Returns: A boolean, True if lpmode is set successfully, False if not """ + try: + if self.is_sw_control(): + api = self.get_xcvr_api() + if not api: + return False + if api.get_lpmode() == lpmode: + return True + api.set_lpmode(lpmode) + return api.get_lpmode() == lpmode + elif DeviceDataManager.is_independent_mode(): + # FW control under CMIS host management mode. + # Currently, we don't support set LPM under this mode. + # Just return False to indicate set Fail + return False + except Exception as e: + print(e) + return False + if utils.is_host(): # To avoid performance issue, # call class level method to avoid initialize the whole sonic platform API diff --git a/platform/mellanox/mlnx-platform-api/tests/test_sfp.py b/platform/mellanox/mlnx-platform-api/tests/test_sfp.py index d0805a0d6250..4dfcf0f073c1 100644 --- a/platform/mellanox/mlnx-platform-api/tests/test_sfp.py +++ b/platform/mellanox/mlnx-platform-api/tests/test_sfp.py @@ -312,6 +312,8 @@ def test_is_sw_control(self, mock_get_db, mock_mode, mock_read): with pytest.raises(Exception): 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])) @mock.patch('subprocess.check_output', mock.MagicMock(side_effect = ['True', 'False'])) @mock.patch('sonic_platform.sfp.SFP._get_lpmode', mock.MagicMock(side_effect = [True, False])) @@ -323,6 +325,8 @@ def test_get_lpmode(self): assert sfp.get_lpmode() assert not sfp.get_lpmode() + @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])) @mock.patch('subprocess.check_output', mock.MagicMock(side_effect = ['True', 'False'])) @mock.patch('sonic_platform.sfp.SFP._set_lpmode', mock.MagicMock(side_effect = [True, False])) @@ -333,3 +337,45 @@ def test_set_lpmode(self): assert not sfp.set_lpmode(True) assert sfp.set_lpmode(False) assert not sfp.set_lpmode(False) + + @mock.patch('sonic_platform.device_data.DeviceDataManager.is_independent_mode', mock.MagicMock(return_value=True)) + @mock.patch('sonic_platform.utils.read_int_from_file') + @mock.patch('sonic_platform.sfp.SFP.is_sw_control') + def test_get_lpmode_cmis_host_mangagement(self, mock_control, mock_read): + mock_control.return_value = True + sfp = SFP(0) + sfp.get_xcvr_api = mock.MagicMock(return_value=None) + assert not sfp.get_lpmode() + + mock_api = mock.MagicMock() + sfp.get_xcvr_api.return_value = mock_api + mock_api.get_lpmode = mock.MagicMock(return_value=False) + assert not sfp.get_lpmode() + + mock_api.get_lpmode.return_value = True + assert sfp.get_lpmode() + + mock_control.return_value = False + mock_read.return_value = 1 + assert sfp.get_lpmode() + + mock_read.return_value = 2 + assert not sfp.get_lpmode() + + @mock.patch('sonic_platform.device_data.DeviceDataManager.is_independent_mode', mock.MagicMock(return_value=True)) + @mock.patch('sonic_platform.sfp.SFP.is_sw_control') + def test_set_lpmode_cmis_host_mangagement(self, mock_control): + mock_control.return_value = True + sfp = SFP(0) + sfp.get_xcvr_api = mock.MagicMock(return_value=None) + assert not sfp.set_lpmode(False) + + mock_api = mock.MagicMock() + sfp.get_xcvr_api.return_value = mock_api + mock_api.get_lpmode = mock.MagicMock(return_value=False) + assert sfp.set_lpmode(False) + assert not sfp.set_lpmode(True) + + mock_control.return_value = False + assert not sfp.set_lpmode(True) + assert not sfp.set_lpmode(False)