Skip to content

Commit

Permalink
[Mellanox] Implement low power mode for cmis host management (#17159)
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
Junchao-Mellanox authored Dec 11, 2023
1 parent ee598de commit b0bb3d4
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
30 changes: 30 additions & 0 deletions platform/mellanox/mlnx-platform-api/sonic_platform/sfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
46 changes: 46 additions & 0 deletions platform/mellanox/mlnx-platform-api/tests/test_sfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand All @@ -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]))
Expand All @@ -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)

0 comments on commit b0bb3d4

Please sign in to comment.