From d590c2873e833b78eb5d9f93cb9a083662495c82 Mon Sep 17 00:00:00 2001 From: kewei-arista <146126091+kewei-arista@users.noreply.github.com> Date: Wed, 5 Nov 2025 11:19:53 -0800 Subject: [PATCH] [202505] Skip setting lpmode of a xcvr if it's not supported (#698) * Skip setting lpmode of a xcvr if it's not supported to stop noise like: moby202 ERR pmon#xcvrd[34]: SFF-MAIN: Ethernet513: Failed to take module out of low power mode. * add test case --- sonic-xcvrd/tests/test_xcvrd.py | 49 +++++++++++++++++++++++++++++++-- sonic-xcvrd/xcvrd/sff_mgr.py | 19 +++++++------ 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index c8c24f6..05facdd 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -2170,9 +2170,10 @@ def test_SffManagerTask_get_admin_status(self, mock_get_cfg_port_tbl): mock_get_cfg_port_tbl.assert_called_once_with(0) mock_get_cfg_port_tbl.return_value.hget.assert_called_once_with(lport, 'admin_status') + @patch('xcvrd.xcvrd.helper_logger') @patch('xcvrd.xcvrd.platform_chassis') @patch('xcvrd.sff_mgr.PortChangeObserver', MagicMock(handle_port_update_event=MagicMock())) - def test_SffManagerTask_task_worker(self, mock_chassis): + def test_SffManagerTask_task_worker(self, mock_chassis, mock_logger): mock_xcvr_api = MagicMock() mock_xcvr_api.tx_disable_channel = MagicMock(return_value=True) mock_xcvr_api.is_flat_memory = MagicMock(return_value=False) @@ -2189,7 +2190,7 @@ def test_SffManagerTask_task_worker(self, mock_chassis): task = SffManagerTask(DEFAULT_NAMESPACE, threading.Event(), mock_chassis, - helper_logger) + mock_logger) # TX enable case: port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET, { @@ -2270,8 +2271,52 @@ def test_SffManagerTask_task_worker(self, mock_chassis): task.task_worker() assert mock_sfp.get_presence.call_count == 1 assert mock_xcvr_api.tx_disable_channel.call_count == 2 + mock_logger.log_error.assert_called_once_with( + "SFF-MAIN: Ethernet0: module not present!") mock_sfp.get_presence = MagicMock(return_value=True) + # lpmode setting case + # 1. error logged when lpmode is suppoted but unsuccessful + port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET, + {'type': 'QSFP28'}) + task.on_port_update_event(port_change_event) + mock_xcvr_api.set_lpmode = MagicMock(return_value=False) + mock_xcvr_api.get_lpmode_support = MagicMock(return_value=True) + task.port_dict_prev = {} + task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True]) + task.task_worker() + assert len(mock_logger.log_error.call_args_list) == 2 + mock_logger.log_error.assert_called_with( + "SFF-MAIN: Ethernet0: Failed to take module out of low power mode.") + + # 2. no error logged when lpmode is suppoted and successful + port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET, + {'type': 'QSFP28'}) + task.on_port_update_event(port_change_event) + mock_xcvr_api.set_lpmode = MagicMock(return_value=True) + mock_xcvr_api.get_lpmode_support = MagicMock(return_value=True) + task.port_dict_prev = {} + task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True]) + task.task_worker() + assert len(mock_logger.log_error.call_args_list) == 2 + mock_logger.log_error.assert_called_with( + "SFF-MAIN: Ethernet0: Failed to take module out of low power mode.") + + # 3. no error logged when lpmode is not suppoted + port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET, + {'type': 'QSFP28'}) + task.on_port_update_event(port_change_event) + mock_xcvr_api.set_lpmode = MagicMock(return_value=False) + mock_xcvr_api.get_lpmode_support = MagicMock(return_value=False) + task.port_dict_prev = {} + task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True]) + task.task_worker() + assert len(mock_logger.log_error.call_args_list) == 2 + mock_logger.log_error.assert_called_with( + "SFF-MAIN: Ethernet0: Failed to take module out of low power mode.") + mock_xcvr_api.set_lpmode = MagicMock(return_value=True) + mock_xcvr_api.get_lpmode_support = MagicMock(return_value=True) + def test_CmisManagerTask_update_port_transceiver_status_table_sw_cmis_state(self): port_mapping = PortMapping() stop_event = threading.Event() diff --git a/sonic-xcvrd/xcvrd/sff_mgr.py b/sonic-xcvrd/xcvrd/sff_mgr.py index bd6948a..f23776e 100644 --- a/sonic-xcvrd/xcvrd/sff_mgr.py +++ b/sonic-xcvrd/xcvrd/sff_mgr.py @@ -440,16 +440,17 @@ def task_worker(self): continue if xcvr_inserted or (admin_status_changed and data[self.ADMIN_STATUS] == "up"): - set_lp_success = ( - sfp.set_lpmode(False) - if isinstance(api, Sff8472Api) - else api.set_lpmode(False) - ) - if not set_lp_success: - self.log_error( - "{}: Failed to take module out of low power mode.".format( - lport) + if api.get_lpmode_support(): + set_lp_success = ( + sfp.set_lpmode(False) + if isinstance(api, Sff8472Api) + else api.set_lpmode(False) ) + if not set_lp_success: + self.log_error( + "{}: Failed to take module out of low power mode.".format( + lport) + ) if active_lanes is None: active_lanes = self.get_active_lanes_for_lport(lport, subport_idx,