diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index 54e11427d..93c6c5915 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -1699,6 +1699,7 @@ def test_CmisManagerTask_task_worker(self, mock_chassis, mock_get_status_tbl): mock_xcvr_api.get_module_pwr_up_duration = MagicMock(return_value=70000.0) mock_xcvr_api.get_datapath_deinit_duration = MagicMock(return_value=600000.0) mock_xcvr_api.get_cmis_rev = MagicMock(return_value='5.0') + mock_xcvr_api.get_supported_freq_config = MagicMock(return_value=(0xA0,0,0,191300,196100)) mock_xcvr_api.get_dpinit_pending = MagicMock(return_value={ 'DPInitPending1': True, 'DPInitPending2': True, @@ -2573,7 +2574,7 @@ def test_DaemonXcvrd_init_deinit_cold(self): xcvrdaemon.deinit() status_tbl.hdel.assert_called() - + @patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', MagicMock(return_value=(test_path, '/invalid/path'))) def test_load_optical_si_file_from_platform_folder(self): assert optics_si_parser.load_optics_si_settings() != {} @@ -2589,6 +2590,25 @@ def test_load_media_settings_file_from_platform_folder(self): @patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', MagicMock(return_value=('/invalid/path', test_path))) def test_load_media_settings_file_from_hwsku_folder(self): assert media_settings_parser.load_media_settings() != {} + + @pytest.mark.parametrize("lport, freq, grid, expected", [ + (1, 193100, 75, True), + (1, 193100, 100, False), + (1, 193125, 75, False), + (1, 193100, 25, False), + (1, 191295, 75, False), + (1, 196105, 75, False) + ]) + def test_CmisManagerTask_validate_frequency_and_grid(self, lport, freq, grid, expected): + mock_xcvr_api = MagicMock() + mock_xcvr_api.get_supported_freq_config = MagicMock() + mock_xcvr_api.get_supported_freq_config.return_value = (0x80, 0, 0, 191300, 196100) + port_mapping = PortMapping() + stop_event = threading.Event() + task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event) + result = task.validate_frequency_and_grid(mock_xcvr_api, lport, freq, grid) + assert result == expected + def wait_until(total_wait_time, interval, call_back, *args, **kwargs): wait_time = 0 diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index e1235773e..f3b096f52 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1207,15 +1207,32 @@ def configure_tx_output_power(self, api, lport, tx_power): self.log_error("{} configured tx power {} > maximum power {} supported".format(lport, tx_power, max_p)) return api.set_tx_power(tx_power) - def configure_laser_frequency(self, api, lport, freq, grid=75): - _, _, _, lowf, highf = api.get_supported_freq_config() + def validate_frequency_and_grid(self, api, lport, freq, grid=75): + supported_grid, _, _, lowf, highf = api.get_supported_freq_config() if freq < lowf: self.log_error("{} configured freq:{} GHz is lower than the supported freq:{} GHz".format(lport, freq, lowf)) + return False if freq > highf: self.log_error("{} configured freq:{} GHz is higher than the supported freq:{} GHz".format(lport, freq, highf)) - chan = int(round((freq - 193100)/25)) - if chan % 3 != 0: - self.log_error("{} configured freq:{} GHz is NOT in 75GHz grid".format(lport, freq)) + return False + if grid == 75: + if (supported_grid >> 7) & 0x1 != 1: + self.log_error("{} configured freq:{}GHz supported grid:{} 75GHz is not supported".format(lport, freq, supported_grid)) + return False + chan = int(round((freq - 193100)/25)) + if chan % 3 != 0: + self.log_error("{} configured freq:{}GHz is NOT in 75GHz grid".format(lport, freq)) + return False + elif grid == 100: + if (supported_grid >> 5) & 0x1 != 1: + self.log_error("{} configured freq:{}GHz 100GHz is not supported".format(lport, freq)) + return False + else: + self.log_error("{} configured freq:{}GHz {}GHz is not supported".format(lport, freq, grid)) + return False + return True + + def configure_laser_frequency(self, api, lport, freq, grid=75): if api.get_tuning_in_progress(): self.log_error("{} Tuning in progress, subport selection may fail!".format(lport)) return api.set_laser_freq(freq, grid) @@ -1442,11 +1459,15 @@ def task_worker(self): # For ZR module, Datapath needes to be re-initlialized on new channel selection if api.is_coherent_module(): - freq = self.port_dict[lport]['laser_freq'] - # If user requested frequency is NOT the same as configured on the module - # force datapath re-initialization - if 0 != freq and freq != api.get_laser_config_freq(): - need_update = True + freq = self.port_dict[lport]['laser_freq'] + # If user requested frequency is NOT the same as configured on the module + # force datapath re-initialization + if 0 != freq and freq != api.get_laser_config_freq(): + if self.validate_frequency_and_grid(api, lport, freq) == True: + need_update = True + else: + # clear setting of invalid frequency config + self.port_dict[lport]['laser_freq'] = 0 if not need_update: # No application updates