Skip to content

Commit 41b1c82

Browse files
stepanblyschakvadymhlushko-mlnx
authored andcommitted
[CMIS] Skip re-init flow for SW-controlled ports in case of fastboot (sonic-net#497)
* [CMIS] Skip re-init flow for SW-controlled ports in case of fastboot Signed-off-by: vadymhlushko-mlnx <vadymh@nvidia.com> * Change the log message Signed-off-by: Stepan Blyschak <stepanb@nvidia.com> --------- Signed-off-by: vadymhlushko-mlnx <vadymh@nvidia.com> Signed-off-by: Stepan Blyschak <stepanb@nvidia.com> Co-authored-by: vadymhlushko-mlnx <vadymh@nvidia.com>
1 parent 76cf1dc commit 41b1c82

File tree

2 files changed

+282
-4
lines changed

2 files changed

+282
-4
lines changed

sonic-xcvrd/tests/test_xcvrd.py

+274-1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ def test_CmisManagerTask_task_run_with_exception(self):
180180

181181
@patch('xcvrd.xcvrd.PortChangeObserver', MagicMock(handle_port_update_event=MagicMock()))
182182
@patch('xcvrd.xcvrd.CmisManagerTask.wait_for_port_config_done', MagicMock())
183+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(False)))
183184
@patch('xcvrd.xcvrd.get_cmis_application_desired', MagicMock(side_effect=KeyError))
184185
@patch('xcvrd.xcvrd.log_exception_traceback')
185186
@patch('xcvrd.xcvrd.XcvrTableHelper.get_status_tbl')
@@ -1509,6 +1510,7 @@ def test_CmisManagerTask_get_configured_tx_power_from_db(self, mock_table_helper
15091510
assert task.get_configured_tx_power_from_db('Ethernet0') == -10
15101511

15111512
@patch('xcvrd.xcvrd.platform_chassis')
1513+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(False)))
15121514
@patch('xcvrd.xcvrd.PortChangeObserver', MagicMock(handle_port_update_event=MagicMock()))
15131515
def test_CmisManagerTask_task_run_stop(self, mock_chassis):
15141516
mock_object = MagicMock()
@@ -1752,6 +1754,7 @@ def test_CmisManagerTask_post_port_active_apsel_to_db(self):
17521754

17531755
@patch('xcvrd.xcvrd.XcvrTableHelper.get_status_tbl')
17541756
@patch('xcvrd.xcvrd.platform_chassis')
1757+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(False)))
17551758
@patch('xcvrd.xcvrd.PortChangeObserver', MagicMock(handle_port_update_event=MagicMock()))
17561759
@patch('xcvrd.xcvrd._wrapper_get_sfp_type', MagicMock(return_value='QSFP_DD'))
17571760
@patch('xcvrd.xcvrd.CmisManagerTask.wait_for_port_config_done', MagicMock())
@@ -1925,7 +1928,7 @@ def test_CmisManagerTask_task_worker(self, mock_chassis, mock_get_status_tbl):
19251928
task.xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
19261929
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
19271930
task.task_worker()
1928-
assert get_cmis_state_from_state_db('Ethernei1', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet1'))) == CMIS_STATE_UNKNOWN
1931+
assert get_cmis_state_from_state_db('Ethernet1', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet1'))) == CMIS_STATE_UNKNOWN
19291932

19301933
task.port_mapping.logical_port_list = MagicMock()
19311934
port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
@@ -1952,6 +1955,276 @@ def test_CmisManagerTask_task_worker(self, mock_chassis, mock_get_status_tbl):
19521955
task.task_worker()
19531956
assert not get_cmis_state_from_state_db('Ethernet1', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet1'))) == CMIS_STATE_DP_DEINIT
19541957

1958+
@patch('xcvrd.xcvrd.XcvrTableHelper.get_status_tbl')
1959+
@patch('xcvrd.xcvrd.platform_chassis')
1960+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(True)))
1961+
@patch('xcvrd.xcvrd.PortChangeObserver', MagicMock(handle_port_update_event=MagicMock()))
1962+
@patch('xcvrd.xcvrd._wrapper_get_sfp_type', MagicMock(return_value='QSFP_DD'))
1963+
@patch('xcvrd.xcvrd.CmisManagerTask.wait_for_port_config_done', MagicMock())
1964+
@patch('xcvrd.xcvrd.is_cmis_api', MagicMock(return_value=True))
1965+
def test_CmisManagerTask_task_worker_fastboot(self, mock_chassis, mock_get_status_tbl):
1966+
mock_get_status_tbl = Table("STATE_DB", TRANSCEIVER_STATUS_TABLE)
1967+
mock_xcvr_api = MagicMock()
1968+
mock_xcvr_api.set_datapath_deinit = MagicMock(return_value=True)
1969+
mock_xcvr_api.set_datapath_init = MagicMock(return_value=True)
1970+
mock_xcvr_api.tx_disable_channel = MagicMock(return_value=True)
1971+
mock_xcvr_api.set_lpmode = MagicMock(return_value=True)
1972+
mock_xcvr_api.set_application = MagicMock(return_value=True)
1973+
mock_xcvr_api.is_flat_memory = MagicMock(return_value=False)
1974+
mock_xcvr_api.is_coherent_module = MagicMock(return_value=True)
1975+
mock_xcvr_api.get_tx_config_power = MagicMock(return_value=0)
1976+
mock_xcvr_api.get_laser_config_freq = MagicMock(return_value=0)
1977+
mock_xcvr_api.get_module_type_abbreviation = MagicMock(return_value='QSFP-DD')
1978+
mock_xcvr_api.get_datapath_init_duration = MagicMock(return_value=60000.0)
1979+
mock_xcvr_api.get_module_pwr_up_duration = MagicMock(return_value=70000.0)
1980+
mock_xcvr_api.get_datapath_deinit_duration = MagicMock(return_value=600000.0)
1981+
mock_xcvr_api.get_cmis_rev = MagicMock(return_value='5.0')
1982+
mock_xcvr_api.get_dpinit_pending = MagicMock(return_value={
1983+
'DPInitPending1': True,
1984+
'DPInitPending2': True,
1985+
'DPInitPending3': True,
1986+
'DPInitPending4': True,
1987+
'DPInitPending5': True,
1988+
'DPInitPending6': True,
1989+
'DPInitPending7': True,
1990+
'DPInitPending8': True
1991+
})
1992+
mock_xcvr_api.get_application_advertisement = MagicMock(return_value={
1993+
1: {
1994+
'host_electrical_interface_id': '400GAUI-8 C2M (Annex 120E)',
1995+
'module_media_interface_id': '400GBASE-DR4 (Cl 124)',
1996+
'media_lane_count': 4,
1997+
'host_lane_count': 8,
1998+
'host_lane_assignment_options': 1,
1999+
'media_lane_assignment_options': 1
2000+
},
2001+
2: {
2002+
'host_electrical_interface_id': '100GAUI-2 C2M (Annex 135G)',
2003+
'module_media_interface_id': '100G-FR/100GBASE-FR1 (Cl 140)',
2004+
'media_lane_count': 1,
2005+
'host_lane_count': 2,
2006+
'host_lane_assignment_options': 85,
2007+
'media_lane_assignment_options': 15
2008+
}
2009+
})
2010+
mock_xcvr_api.get_module_state = MagicMock(return_value='ModuleReady')
2011+
mock_xcvr_api.get_config_datapath_hostlane_status = MagicMock(return_value={
2012+
'ConfigStatusLane1': 'ConfigSuccess',
2013+
'ConfigStatusLane2': 'ConfigSuccess',
2014+
'ConfigStatusLane3': 'ConfigSuccess',
2015+
'ConfigStatusLane4': 'ConfigSuccess',
2016+
'ConfigStatusLane5': 'ConfigSuccess',
2017+
'ConfigStatusLane6': 'ConfigSuccess',
2018+
'ConfigStatusLane7': 'ConfigSuccess',
2019+
'ConfigStatusLane8': 'ConfigSuccess'
2020+
})
2021+
mock_xcvr_api.get_datapath_state = MagicMock(side_effect=[
2022+
{
2023+
'DP1State': 'DataPathDeactivated',
2024+
'DP2State': 'DataPathDeactivated',
2025+
'DP3State': 'DataPathDeactivated',
2026+
'DP4State': 'DataPathDeactivated',
2027+
'DP5State': 'DataPathDeactivated',
2028+
'DP6State': 'DataPathDeactivated',
2029+
'DP7State': 'DataPathDeactivated',
2030+
'DP8State': 'DataPathDeactivated'
2031+
},
2032+
{
2033+
'DP1State': 'DataPathInitialized',
2034+
'DP2State': 'DataPathInitialized',
2035+
'DP3State': 'DataPathInitialized',
2036+
'DP4State': 'DataPathInitialized',
2037+
'DP5State': 'DataPathInitialized',
2038+
'DP6State': 'DataPathInitialized',
2039+
'DP7State': 'DataPathInitialized',
2040+
'DP8State': 'DataPathInitialized'
2041+
},
2042+
{
2043+
'DP1State': 'DataPathActivated',
2044+
'DP2State': 'DataPathActivated',
2045+
'DP3State': 'DataPathActivated',
2046+
'DP4State': 'DataPathActivated',
2047+
'DP5State': 'DataPathActivated',
2048+
'DP6State': 'DataPathActivated',
2049+
'DP7State': 'DataPathActivated',
2050+
'DP8State': 'DataPathActivated'
2051+
}
2052+
])
2053+
mock_sfp = MagicMock()
2054+
mock_sfp.get_presence = MagicMock(return_value=True)
2055+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_xcvr_api)
2056+
2057+
mock_chassis.get_all_sfps = MagicMock(return_value=[mock_sfp])
2058+
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)
2059+
2060+
port_mapping = PortMapping()
2061+
stop_event = threading.Event()
2062+
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
2063+
task.port_mapping.logical_port_list = ['Ethernet0']
2064+
task.xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
2065+
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
2066+
task.task_worker()
2067+
assert get_cmis_state_from_state_db('Ethernet0', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet0'))) == CMIS_STATE_UNKNOWN
2068+
2069+
task.port_mapping.logical_port_list = MagicMock()
2070+
port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
2071+
task.on_port_update_event(port_change_event)
2072+
assert task.isPortConfigDone
2073+
2074+
port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET,
2075+
{'speed':'400000', 'lanes':'1,2,3,4,5,6,7,8'})
2076+
task.on_port_update_event(port_change_event)
2077+
assert len(task.port_dict) == 1
2078+
assert get_cmis_state_from_state_db('Ethernet0', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet0'))) == CMIS_STATE_INSERTED
2079+
2080+
task.get_host_tx_status = MagicMock(return_value='false')
2081+
task.get_port_admin_status = MagicMock(return_value='up')
2082+
task.get_configured_tx_power_from_db = MagicMock(return_value=-13)
2083+
task.get_configured_laser_freq_from_db = MagicMock(return_value=193100)
2084+
task.configure_tx_output_power = MagicMock(return_value=1)
2085+
task.configure_laser_frequency = MagicMock(return_value=1)
2086+
2087+
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
2088+
task.task_worker()
2089+
2090+
assert get_cmis_state_from_state_db('Ethernet0', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet0'))) == CMIS_STATE_READY
2091+
2092+
2093+
@patch('xcvrd.xcvrd.XcvrTableHelper.get_status_tbl')
2094+
@patch('xcvrd.xcvrd.platform_chassis')
2095+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(False)))
2096+
@patch('xcvrd.xcvrd.PortChangeObserver', MagicMock(handle_port_update_event=MagicMock()))
2097+
@patch('xcvrd.xcvrd._wrapper_get_sfp_type', MagicMock(return_value='QSFP_DD'))
2098+
@patch('xcvrd.xcvrd.CmisManagerTask.wait_for_port_config_done', MagicMock())
2099+
@patch('xcvrd.xcvrd.is_cmis_api', MagicMock(return_value=True))
2100+
def test_CmisManagerTask_task_worker_host_tx_ready_false(self, mock_chassis, mock_get_status_tbl):
2101+
mock_get_status_tbl = Table("STATE_DB", TRANSCEIVER_STATUS_TABLE)
2102+
mock_xcvr_api = MagicMock()
2103+
mock_xcvr_api.set_datapath_deinit = MagicMock(return_value=True)
2104+
mock_xcvr_api.set_datapath_init = MagicMock(return_value=True)
2105+
mock_xcvr_api.tx_disable_channel = MagicMock(return_value=True)
2106+
mock_xcvr_api.set_lpmode = MagicMock(return_value=True)
2107+
mock_xcvr_api.set_application = MagicMock(return_value=True)
2108+
mock_xcvr_api.is_flat_memory = MagicMock(return_value=False)
2109+
mock_xcvr_api.is_coherent_module = MagicMock(return_value=True)
2110+
mock_xcvr_api.get_tx_config_power = MagicMock(return_value=0)
2111+
mock_xcvr_api.get_laser_config_freq = MagicMock(return_value=0)
2112+
mock_xcvr_api.get_module_type_abbreviation = MagicMock(return_value='QSFP-DD')
2113+
mock_xcvr_api.get_datapath_init_duration = MagicMock(return_value=60000.0)
2114+
mock_xcvr_api.get_module_pwr_up_duration = MagicMock(return_value=70000.0)
2115+
mock_xcvr_api.get_datapath_deinit_duration = MagicMock(return_value=600000.0)
2116+
mock_xcvr_api.get_cmis_rev = MagicMock(return_value='5.0')
2117+
mock_xcvr_api.get_dpinit_pending = MagicMock(return_value={
2118+
'DPInitPending1': True,
2119+
'DPInitPending2': True,
2120+
'DPInitPending3': True,
2121+
'DPInitPending4': True,
2122+
'DPInitPending5': True,
2123+
'DPInitPending6': True,
2124+
'DPInitPending7': True,
2125+
'DPInitPending8': True
2126+
})
2127+
mock_xcvr_api.get_application_advertisement = MagicMock(return_value={
2128+
1: {
2129+
'host_electrical_interface_id': '400GAUI-8 C2M (Annex 120E)',
2130+
'module_media_interface_id': '400GBASE-DR4 (Cl 124)',
2131+
'media_lane_count': 4,
2132+
'host_lane_count': 8,
2133+
'host_lane_assignment_options': 1,
2134+
'media_lane_assignment_options': 1
2135+
},
2136+
2: {
2137+
'host_electrical_interface_id': '100GAUI-2 C2M (Annex 135G)',
2138+
'module_media_interface_id': '100G-FR/100GBASE-FR1 (Cl 140)',
2139+
'media_lane_count': 1,
2140+
'host_lane_count': 2,
2141+
'host_lane_assignment_options': 85,
2142+
'media_lane_assignment_options': 15
2143+
}
2144+
})
2145+
mock_xcvr_api.get_module_state = MagicMock(return_value='ModuleReady')
2146+
mock_xcvr_api.get_config_datapath_hostlane_status = MagicMock(return_value={
2147+
'ConfigStatusLane1': 'ConfigSuccess',
2148+
'ConfigStatusLane2': 'ConfigSuccess',
2149+
'ConfigStatusLane3': 'ConfigSuccess',
2150+
'ConfigStatusLane4': 'ConfigSuccess',
2151+
'ConfigStatusLane5': 'ConfigSuccess',
2152+
'ConfigStatusLane6': 'ConfigSuccess',
2153+
'ConfigStatusLane7': 'ConfigSuccess',
2154+
'ConfigStatusLane8': 'ConfigSuccess'
2155+
})
2156+
mock_xcvr_api.get_datapath_state = MagicMock(side_effect=[
2157+
{
2158+
'DP1State': 'DataPathDeactivated',
2159+
'DP2State': 'DataPathDeactivated',
2160+
'DP3State': 'DataPathDeactivated',
2161+
'DP4State': 'DataPathDeactivated',
2162+
'DP5State': 'DataPathDeactivated',
2163+
'DP6State': 'DataPathDeactivated',
2164+
'DP7State': 'DataPathDeactivated',
2165+
'DP8State': 'DataPathDeactivated'
2166+
},
2167+
{
2168+
'DP1State': 'DataPathInitialized',
2169+
'DP2State': 'DataPathInitialized',
2170+
'DP3State': 'DataPathInitialized',
2171+
'DP4State': 'DataPathInitialized',
2172+
'DP5State': 'DataPathInitialized',
2173+
'DP6State': 'DataPathInitialized',
2174+
'DP7State': 'DataPathInitialized',
2175+
'DP8State': 'DataPathInitialized'
2176+
},
2177+
{
2178+
'DP1State': 'DataPathActivated',
2179+
'DP2State': 'DataPathActivated',
2180+
'DP3State': 'DataPathActivated',
2181+
'DP4State': 'DataPathActivated',
2182+
'DP5State': 'DataPathActivated',
2183+
'DP6State': 'DataPathActivated',
2184+
'DP7State': 'DataPathActivated',
2185+
'DP8State': 'DataPathActivated'
2186+
}
2187+
])
2188+
mock_sfp = MagicMock()
2189+
mock_sfp.get_presence = MagicMock(return_value=True)
2190+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_xcvr_api)
2191+
2192+
mock_chassis.get_all_sfps = MagicMock(return_value=[mock_sfp])
2193+
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)
2194+
2195+
port_mapping = PortMapping()
2196+
stop_event = threading.Event()
2197+
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
2198+
task.port_mapping.logical_port_list = ['Ethernet0']
2199+
task.xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
2200+
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
2201+
task.task_worker()
2202+
assert get_cmis_state_from_state_db('Ethernet0', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet0'))) == CMIS_STATE_UNKNOWN
2203+
2204+
task.port_mapping.logical_port_list = MagicMock()
2205+
port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
2206+
task.on_port_update_event(port_change_event)
2207+
assert task.isPortConfigDone
2208+
2209+
port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET,
2210+
{'speed':'400000', 'lanes':'1,2,3,4,5,6,7,8'})
2211+
task.on_port_update_event(port_change_event)
2212+
assert len(task.port_dict) == 1
2213+
assert get_cmis_state_from_state_db('Ethernet0', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet0'))) == CMIS_STATE_INSERTED
2214+
2215+
task.get_host_tx_status = MagicMock(return_value='false')
2216+
task.get_port_admin_status = MagicMock(return_value='up')
2217+
task.get_configured_tx_power_from_db = MagicMock(return_value=-13)
2218+
task.get_configured_laser_freq_from_db = MagicMock(return_value=193100)
2219+
task.configure_tx_output_power = MagicMock(return_value=1)
2220+
task.configure_laser_frequency = MagicMock(return_value=1)
2221+
2222+
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
2223+
task.task_worker()
2224+
2225+
assert mock_xcvr_api.tx_disable_channel.call_count == 1
2226+
assert get_cmis_state_from_state_db('Ethernet0', task.xcvr_table_helper.get_status_tbl(task.port_mapping.get_asic_id_for_logical_port('Ethernet0'))) == CMIS_STATE_READY
2227+
19552228
@pytest.mark.parametrize("lport, expected_dom_polling", [
19562229
('Ethernet0', 'disabled'),
19572230
('Ethernet4', 'disabled'),

sonic-xcvrd/xcvrd/xcvrd.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,8 @@ def task_worker(self):
13141314
for lport in logical_port_list:
13151315
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_UNKNOWN)
13161316

1317+
is_fast_reboot = is_fast_reboot_enabled()
1318+
13171319
# APPL_DB for CONFIG updates, and STATE_DB for insertion/removal
13181320
port_change_observer = PortChangeObserver(self.namespaces, helper_logger,
13191321
self.task_stopping_event,
@@ -1460,9 +1462,12 @@ def task_worker(self):
14601462

14611463
if self.port_dict[lport]['host_tx_ready'] != 'true' or \
14621464
self.port_dict[lport]['admin_status'] != 'up':
1463-
self.log_notice("{} Forcing Tx laser OFF".format(lport))
1464-
# Force DataPath re-init
1465-
api.tx_disable_channel(media_lanes_mask, True)
1465+
if is_fast_reboot and self.check_datapath_state(api, host_lanes_mask, ['DataPathActivated']):
1466+
self.log_notice("{} Skip datapath re-init in fast-reboot".format(lport))
1467+
else:
1468+
self.log_notice("{} Forcing Tx laser OFF".format(lport))
1469+
# Force DataPath re-init
1470+
api.tx_disable_channel(media_lanes_mask, True)
14661471
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
14671472
continue
14681473
# Configure the target output power if ZR module

0 commit comments

Comments
 (0)