Skip to content

Adding frequency grid validation for ZR optics #466

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 29, 2024
22 changes: 21 additions & 1 deletion sonic-xcvrd/tests/test_xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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() != {}
Expand All @@ -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
Expand Down
41 changes: 31 additions & 10 deletions sonic-xcvrd/xcvrd/xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down