Skip to content

Commit dedab0c

Browse files
[CMIS] Skip re-init flow for SW-controlled ports in case of fastboot. Add UT
Signed-off-by: vadymhlushko-mlnx <[email protected]>
1 parent df0ff63 commit dedab0c

File tree

2 files changed

+285
-4
lines changed

2 files changed

+285
-4
lines changed

sonic-xcvrd/tests/test_xcvrd.py

+277-1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ def test_CmisManagerTask_task_run_with_exception(self):
159159

160160
@patch('xcvrd.xcvrd_utilities.port_mapping.subscribe_port_update_event', MagicMock(return_value=(None, None)))
161161
@patch('xcvrd.xcvrd_utilities.port_mapping.handle_port_update_event', MagicMock())
162+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(False)))
162163
@patch('xcvrd.xcvrd.CmisManagerTask.wait_for_port_config_done', MagicMock())
163164
@patch('xcvrd.xcvrd.get_cmis_application_desired', MagicMock(side_effect=KeyError))
164165
@patch('xcvrd.xcvrd.log_exception_traceback')
@@ -1043,6 +1044,7 @@ def test_CmisManagerTask_get_configured_tx_power_from_db(self, mock_table_helper
10431044
assert task.get_configured_tx_power_from_db('Ethernet0') == -10
10441045

10451046
@patch('xcvrd.xcvrd.platform_chassis')
1047+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(False)))
10461048
@patch('xcvrd.xcvrd_utilities.port_mapping.subscribe_port_update_event', MagicMock(return_value=(None, None)))
10471049
@patch('xcvrd.xcvrd_utilities.port_mapping.handle_port_update_event', MagicMock())
10481050
def test_CmisManagerTask_task_run_stop(self, mock_chassis):
@@ -1287,6 +1289,7 @@ def test_CmisManagerTask_post_port_active_apsel_to_db(self):
12871289

12881290
@patch('xcvrd.xcvrd.XcvrTableHelper.get_status_tbl')
12891291
@patch('xcvrd.xcvrd.platform_chassis')
1292+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(False)))
12901293
@patch('xcvrd.xcvrd_utilities.port_mapping.subscribe_port_update_event', MagicMock(return_value=(None, None)))
12911294
@patch('xcvrd.xcvrd_utilities.port_mapping.handle_port_update_event', MagicMock())
12921295
@patch('xcvrd.xcvrd._wrapper_get_sfp_type', MagicMock(return_value='QSFP_DD'))
@@ -1460,7 +1463,7 @@ def test_CmisManagerTask_task_worker(self, mock_chassis, mock_get_status_tbl):
14601463
task.xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
14611464
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
14621465
task.task_worker()
1463-
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
1466+
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
14641467

14651468
task.port_mapping.logical_port_list = MagicMock()
14661469
port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
@@ -1486,6 +1489,279 @@ def test_CmisManagerTask_task_worker(self, mock_chassis, mock_get_status_tbl):
14861489
task.task_worker()
14871490
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_FAILED
14881491

1492+
@patch('xcvrd.xcvrd.XcvrTableHelper.get_status_tbl')
1493+
@patch('xcvrd.xcvrd.platform_chassis')
1494+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(True)))
1495+
@patch('xcvrd.xcvrd_utilities.port_mapping.subscribe_port_update_event', MagicMock(return_value=(None, None)))
1496+
@patch('xcvrd.xcvrd_utilities.port_mapping.handle_port_update_event', MagicMock())
1497+
@patch('xcvrd.xcvrd._wrapper_get_sfp_type', MagicMock(return_value='QSFP_DD'))
1498+
@patch('xcvrd.xcvrd.CmisManagerTask.wait_for_port_config_done', MagicMock())
1499+
@patch('xcvrd.xcvrd.is_cmis_api', MagicMock(return_value=True))
1500+
def test_CmisManagerTask_task_worker_fastboot(self, mock_chassis, mock_get_status_tbl):
1501+
mock_get_status_tbl = Table("STATE_DB", TRANSCEIVER_STATUS_TABLE)
1502+
mock_xcvr_api = MagicMock()
1503+
mock_xcvr_api.set_datapath_deinit = MagicMock(return_value=True)
1504+
mock_xcvr_api.set_datapath_init = MagicMock(return_value=True)
1505+
mock_xcvr_api.tx_disable_channel = MagicMock(return_value=True)
1506+
mock_xcvr_api.set_lpmode = MagicMock(return_value=True)
1507+
mock_xcvr_api.set_application = MagicMock(return_value=True)
1508+
mock_xcvr_api.is_flat_memory = MagicMock(return_value=False)
1509+
mock_xcvr_api.is_coherent_module = MagicMock(return_value=True)
1510+
mock_xcvr_api.get_tx_config_power = MagicMock(return_value=0)
1511+
mock_xcvr_api.get_laser_config_freq = MagicMock(return_value=0)
1512+
mock_xcvr_api.get_module_type_abbreviation = MagicMock(return_value='QSFP-DD')
1513+
mock_xcvr_api.get_datapath_init_duration = MagicMock(return_value=60000.0)
1514+
mock_xcvr_api.get_module_pwr_up_duration = MagicMock(return_value=70000.0)
1515+
mock_xcvr_api.get_datapath_deinit_duration = MagicMock(return_value=600000.0)
1516+
mock_xcvr_api.get_cmis_rev = MagicMock(return_value='5.0')
1517+
mock_xcvr_api.get_dpinit_pending = MagicMock(return_value={
1518+
'DPInitPending1': True,
1519+
'DPInitPending2': True,
1520+
'DPInitPending3': True,
1521+
'DPInitPending4': True,
1522+
'DPInitPending5': True,
1523+
'DPInitPending6': True,
1524+
'DPInitPending7': True,
1525+
'DPInitPending8': True
1526+
})
1527+
mock_xcvr_api.get_application_advertisement = MagicMock(return_value={
1528+
1: {
1529+
'host_electrical_interface_id': '400GAUI-8 C2M (Annex 120E)',
1530+
'module_media_interface_id': '400GBASE-DR4 (Cl 124)',
1531+
'media_lane_count': 4,
1532+
'host_lane_count': 8,
1533+
'host_lane_assignment_options': 1,
1534+
'media_lane_assignment_options': 1
1535+
},
1536+
2: {
1537+
'host_electrical_interface_id': '100GAUI-2 C2M (Annex 135G)',
1538+
'module_media_interface_id': '100G-FR/100GBASE-FR1 (Cl 140)',
1539+
'media_lane_count': 1,
1540+
'host_lane_count': 2,
1541+
'host_lane_assignment_options': 85,
1542+
'media_lane_assignment_options': 15
1543+
}
1544+
})
1545+
mock_xcvr_api.get_module_state = MagicMock(return_value='ModuleReady')
1546+
mock_xcvr_api.get_config_datapath_hostlane_status = MagicMock(return_value={
1547+
'ConfigStatusLane1': 'ConfigSuccess',
1548+
'ConfigStatusLane2': 'ConfigSuccess',
1549+
'ConfigStatusLane3': 'ConfigSuccess',
1550+
'ConfigStatusLane4': 'ConfigSuccess',
1551+
'ConfigStatusLane5': 'ConfigSuccess',
1552+
'ConfigStatusLane6': 'ConfigSuccess',
1553+
'ConfigStatusLane7': 'ConfigSuccess',
1554+
'ConfigStatusLane8': 'ConfigSuccess'
1555+
})
1556+
mock_xcvr_api.get_datapath_state = MagicMock(side_effect=[
1557+
{
1558+
'DP1State': 'DataPathDeactivated',
1559+
'DP2State': 'DataPathDeactivated',
1560+
'DP3State': 'DataPathDeactivated',
1561+
'DP4State': 'DataPathDeactivated',
1562+
'DP5State': 'DataPathDeactivated',
1563+
'DP6State': 'DataPathDeactivated',
1564+
'DP7State': 'DataPathDeactivated',
1565+
'DP8State': 'DataPathDeactivated'
1566+
},
1567+
{
1568+
'DP1State': 'DataPathInitialized',
1569+
'DP2State': 'DataPathInitialized',
1570+
'DP3State': 'DataPathInitialized',
1571+
'DP4State': 'DataPathInitialized',
1572+
'DP5State': 'DataPathInitialized',
1573+
'DP6State': 'DataPathInitialized',
1574+
'DP7State': 'DataPathInitialized',
1575+
'DP8State': 'DataPathInitialized'
1576+
},
1577+
{
1578+
'DP1State': 'DataPathActivated',
1579+
'DP2State': 'DataPathActivated',
1580+
'DP3State': 'DataPathActivated',
1581+
'DP4State': 'DataPathActivated',
1582+
'DP5State': 'DataPathActivated',
1583+
'DP6State': 'DataPathActivated',
1584+
'DP7State': 'DataPathActivated',
1585+
'DP8State': 'DataPathActivated'
1586+
}
1587+
])
1588+
mock_sfp = MagicMock()
1589+
mock_sfp.get_presence = MagicMock(return_value=True)
1590+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_xcvr_api)
1591+
1592+
mock_chassis.get_all_sfps = MagicMock(return_value=[mock_sfp])
1593+
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)
1594+
1595+
port_mapping = PortMapping()
1596+
stop_event = threading.Event()
1597+
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
1598+
task.port_mapping.logical_port_list = ['Ethernet0']
1599+
task.xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
1600+
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
1601+
task.task_worker()
1602+
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
1603+
1604+
task.port_mapping.logical_port_list = MagicMock()
1605+
port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
1606+
task.on_port_update_event(port_change_event)
1607+
assert task.isPortConfigDone
1608+
1609+
port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET,
1610+
{'speed':'400000', 'lanes':'1,2,3,4,5,6,7,8'})
1611+
task.on_port_update_event(port_change_event)
1612+
assert len(task.port_dict) == 1
1613+
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
1614+
1615+
task.get_host_tx_status = MagicMock(return_value='false')
1616+
task.get_port_admin_status = MagicMock(return_value='up')
1617+
task.get_configured_tx_power_from_db = MagicMock(return_value=-13)
1618+
task.get_configured_laser_freq_from_db = MagicMock(return_value=193100)
1619+
task.configure_tx_output_power = MagicMock(return_value=1)
1620+
task.configure_laser_frequency = MagicMock(return_value=1)
1621+
1622+
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
1623+
task.task_worker()
1624+
1625+
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
1626+
1627+
1628+
@patch('xcvrd.xcvrd.XcvrTableHelper.get_status_tbl')
1629+
@patch('xcvrd.xcvrd.platform_chassis')
1630+
@patch('xcvrd.xcvrd.is_fast_reboot_enabled', MagicMock(return_value=(False)))
1631+
@patch('xcvrd.xcvrd_utilities.port_mapping.subscribe_port_update_event', MagicMock(return_value=(None, None)))
1632+
@patch('xcvrd.xcvrd_utilities.port_mapping.handle_port_update_event', MagicMock())
1633+
@patch('xcvrd.xcvrd._wrapper_get_sfp_type', MagicMock(return_value='QSFP_DD'))
1634+
@patch('xcvrd.xcvrd.CmisManagerTask.wait_for_port_config_done', MagicMock())
1635+
@patch('xcvrd.xcvrd.is_cmis_api', MagicMock(return_value=True))
1636+
def test_CmisManagerTask_task_worker_host_tx_ready_false(self, mock_chassis, mock_get_status_tbl):
1637+
mock_get_status_tbl = Table("STATE_DB", TRANSCEIVER_STATUS_TABLE)
1638+
mock_xcvr_api = MagicMock()
1639+
mock_xcvr_api.set_datapath_deinit = MagicMock(return_value=True)
1640+
mock_xcvr_api.set_datapath_init = MagicMock(return_value=True)
1641+
mock_xcvr_api.tx_disable_channel = MagicMock(return_value=True)
1642+
mock_xcvr_api.set_lpmode = MagicMock(return_value=True)
1643+
mock_xcvr_api.set_application = MagicMock(return_value=True)
1644+
mock_xcvr_api.is_flat_memory = MagicMock(return_value=False)
1645+
mock_xcvr_api.is_coherent_module = MagicMock(return_value=True)
1646+
mock_xcvr_api.get_tx_config_power = MagicMock(return_value=0)
1647+
mock_xcvr_api.get_laser_config_freq = MagicMock(return_value=0)
1648+
mock_xcvr_api.get_module_type_abbreviation = MagicMock(return_value='QSFP-DD')
1649+
mock_xcvr_api.get_datapath_init_duration = MagicMock(return_value=60000.0)
1650+
mock_xcvr_api.get_module_pwr_up_duration = MagicMock(return_value=70000.0)
1651+
mock_xcvr_api.get_datapath_deinit_duration = MagicMock(return_value=600000.0)
1652+
mock_xcvr_api.get_cmis_rev = MagicMock(return_value='5.0')
1653+
mock_xcvr_api.get_dpinit_pending = MagicMock(return_value={
1654+
'DPInitPending1': True,
1655+
'DPInitPending2': True,
1656+
'DPInitPending3': True,
1657+
'DPInitPending4': True,
1658+
'DPInitPending5': True,
1659+
'DPInitPending6': True,
1660+
'DPInitPending7': True,
1661+
'DPInitPending8': True
1662+
})
1663+
mock_xcvr_api.get_application_advertisement = MagicMock(return_value={
1664+
1: {
1665+
'host_electrical_interface_id': '400GAUI-8 C2M (Annex 120E)',
1666+
'module_media_interface_id': '400GBASE-DR4 (Cl 124)',
1667+
'media_lane_count': 4,
1668+
'host_lane_count': 8,
1669+
'host_lane_assignment_options': 1,
1670+
'media_lane_assignment_options': 1
1671+
},
1672+
2: {
1673+
'host_electrical_interface_id': '100GAUI-2 C2M (Annex 135G)',
1674+
'module_media_interface_id': '100G-FR/100GBASE-FR1 (Cl 140)',
1675+
'media_lane_count': 1,
1676+
'host_lane_count': 2,
1677+
'host_lane_assignment_options': 85,
1678+
'media_lane_assignment_options': 15
1679+
}
1680+
})
1681+
mock_xcvr_api.get_module_state = MagicMock(return_value='ModuleReady')
1682+
mock_xcvr_api.get_config_datapath_hostlane_status = MagicMock(return_value={
1683+
'ConfigStatusLane1': 'ConfigSuccess',
1684+
'ConfigStatusLane2': 'ConfigSuccess',
1685+
'ConfigStatusLane3': 'ConfigSuccess',
1686+
'ConfigStatusLane4': 'ConfigSuccess',
1687+
'ConfigStatusLane5': 'ConfigSuccess',
1688+
'ConfigStatusLane6': 'ConfigSuccess',
1689+
'ConfigStatusLane7': 'ConfigSuccess',
1690+
'ConfigStatusLane8': 'ConfigSuccess'
1691+
})
1692+
mock_xcvr_api.get_datapath_state = MagicMock(side_effect=[
1693+
{
1694+
'DP1State': 'DataPathDeactivated',
1695+
'DP2State': 'DataPathDeactivated',
1696+
'DP3State': 'DataPathDeactivated',
1697+
'DP4State': 'DataPathDeactivated',
1698+
'DP5State': 'DataPathDeactivated',
1699+
'DP6State': 'DataPathDeactivated',
1700+
'DP7State': 'DataPathDeactivated',
1701+
'DP8State': 'DataPathDeactivated'
1702+
},
1703+
{
1704+
'DP1State': 'DataPathInitialized',
1705+
'DP2State': 'DataPathInitialized',
1706+
'DP3State': 'DataPathInitialized',
1707+
'DP4State': 'DataPathInitialized',
1708+
'DP5State': 'DataPathInitialized',
1709+
'DP6State': 'DataPathInitialized',
1710+
'DP7State': 'DataPathInitialized',
1711+
'DP8State': 'DataPathInitialized'
1712+
},
1713+
{
1714+
'DP1State': 'DataPathActivated',
1715+
'DP2State': 'DataPathActivated',
1716+
'DP3State': 'DataPathActivated',
1717+
'DP4State': 'DataPathActivated',
1718+
'DP5State': 'DataPathActivated',
1719+
'DP6State': 'DataPathActivated',
1720+
'DP7State': 'DataPathActivated',
1721+
'DP8State': 'DataPathActivated'
1722+
}
1723+
])
1724+
mock_sfp = MagicMock()
1725+
mock_sfp.get_presence = MagicMock(return_value=True)
1726+
mock_sfp.get_xcvr_api = MagicMock(return_value=mock_xcvr_api)
1727+
1728+
mock_chassis.get_all_sfps = MagicMock(return_value=[mock_sfp])
1729+
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)
1730+
1731+
port_mapping = PortMapping()
1732+
stop_event = threading.Event()
1733+
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
1734+
task.port_mapping.logical_port_list = ['Ethernet0']
1735+
task.xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
1736+
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
1737+
task.task_worker()
1738+
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
1739+
1740+
task.port_mapping.logical_port_list = MagicMock()
1741+
port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
1742+
task.on_port_update_event(port_change_event)
1743+
assert task.isPortConfigDone
1744+
1745+
port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET,
1746+
{'speed':'400000', 'lanes':'1,2,3,4,5,6,7,8'})
1747+
task.on_port_update_event(port_change_event)
1748+
assert len(task.port_dict) == 1
1749+
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
1750+
1751+
task.get_host_tx_status = MagicMock(return_value='false')
1752+
task.get_port_admin_status = MagicMock(return_value='up')
1753+
task.get_configured_tx_power_from_db = MagicMock(return_value=-13)
1754+
task.get_configured_laser_freq_from_db = MagicMock(return_value=193100)
1755+
task.configure_tx_output_power = MagicMock(return_value=1)
1756+
task.configure_laser_frequency = MagicMock(return_value=1)
1757+
1758+
task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])
1759+
task.task_worker()
1760+
1761+
assert mock_xcvr_api.tx_disable_channel.call_count == 1
1762+
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
1763+
1764+
14891765
@pytest.mark.parametrize("lport, expected_dom_polling", [
14901766
('Ethernet0', 'disabled'),
14911767
('Ethernet4', 'disabled'),

sonic-xcvrd/xcvrd/xcvrd.py

+8-3
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,8 @@ def task_worker(self):
12831283
for lport in logical_port_list:
12841284
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_UNKNOWN)
12851285

1286+
is_fast_reboot = is_fast_reboot_enabled()
1287+
12861288
# APPL_DB for CONFIG updates, and STATE_DB for insertion/removal
12871289
sel, asic_context = port_mapping.subscribe_port_update_event(self.namespaces, helper_logger)
12881290
while not self.task_stopping_event.is_set():
@@ -1430,9 +1432,12 @@ def task_worker(self):
14301432

14311433
if self.port_dict[lport]['host_tx_ready'] != 'true' or \
14321434
self.port_dict[lport]['admin_status'] != 'up':
1433-
self.log_notice("{} Forcing Tx laser OFF".format(lport))
1434-
# Force DataPath re-init
1435-
api.tx_disable_channel(media_lanes_mask, True)
1435+
if is_fast_reboot and self.check_datapath_state(api, host_lanes_mask, ['DataPathActivated']):
1436+
self.log_notice("{} Skip re-init flow".format(lport))
1437+
else:
1438+
self.log_notice("{} Forcing Tx laser OFF".format(lport))
1439+
# Force DataPath re-init
1440+
api.tx_disable_channel(media_lanes_mask, True)
14361441
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
14371442
continue
14381443
# Configure the target output power if ZR module

0 commit comments

Comments
 (0)