Skip to content

Commit 4ea12cf

Browse files
authored
Fix xcvrd to support 400G ZR optic (sonic-net#293)
* Fix xcvrd to support 400G ZR/DR optics * Fix xcvrd to support 400G ZR/DR optics * Revert changes in DomInfoUpdateTask::on_port_config_change * Fix xcvrd test after modifying on_port_config_change * Call get_datapath_init_duration to get the init expiration time. * Address comments 1. Clean up comments. 2. Revert port breakout fix and corresponding test change. 3. Check deinit duration for deinit case 4. Check datapath init pending * 1. Revert changes in on_port_update_event 2. check DpInitPending on module which supports CMIS 5.0 3. Specify sec in return value * Add code coverage * Add log for DpInit/DpDeinit duration
1 parent 23b6970 commit 4ea12cf

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

sonic-xcvrd/tests/test_xcvrd.py

+13
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,19 @@ def test_CmisManagerTask_task_worker(self, mock_chassis):
514514
mock_xcvr_api.get_tx_config_power = MagicMock(return_value=0)
515515
mock_xcvr_api.get_laser_config_freq = MagicMock(return_value=0)
516516
mock_xcvr_api.get_module_type_abbreviation = MagicMock(return_value='QSFP-DD')
517+
mock_xcvr_api.get_datapath_init_duration = MagicMock(return_value=60000.0)
518+
mock_xcvr_api.get_datapath_deinit_duration = MagicMock(return_value=600000.0)
519+
mock_xcvr_api.get_cmis_rev = MagicMock(return_value='5.0')
520+
mock_xcvr_api.get_dpinit_pending = MagicMock(return_value={
521+
'DPInitPending1': True,
522+
'DPInitPending2': True,
523+
'DPInitPending3': True,
524+
'DPInitPending4': True,
525+
'DPInitPending5': True,
526+
'DPInitPending6': True,
527+
'DPInitPending7': True,
528+
'DPInitPending8': True
529+
})
517530
mock_xcvr_api.get_application_advertisement = MagicMock(return_value={
518531
1: {
519532
'host_electrical_interface_id': '400GAUI-8 C2M (Annex 120E)',

sonic-xcvrd/xcvrd/xcvrd.py

+46-5
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,12 @@ def get_cmis_application_desired(self, api, channel, speed):
10731073

10741074
return (appl_code & 0xf)
10751075

1076+
def get_cmis_dp_init_duration_secs(self, api):
1077+
return api.get_datapath_init_duration()/1000
1078+
1079+
def get_cmis_dp_deinit_duration_secs(self, api):
1080+
return api.get_datapath_deinit_duration()/1000
1081+
10761082
def is_cmis_application_update_required(self, api, channel, speed):
10771083
"""
10781084
Check if the CMIS application update is required
@@ -1176,6 +1182,32 @@ def check_config_error(self, api, channel, states):
11761182

11771183
return done
11781184

1185+
def check_datapath_init_pending(self, api, channel):
1186+
"""
1187+
Check if the CMIS datapath init is pending
1188+
1189+
Args:
1190+
api:
1191+
XcvrApi object
1192+
channel:
1193+
Integer, a bitmask of the lanes on the host side
1194+
e.g. 0x5 for lane 0 and lane 2.
1195+
1196+
Returns:
1197+
Boolean, true if all lanes are pending datapath init, otherwise false
1198+
"""
1199+
pending = True
1200+
dpinit_pending_dict = api.get_dpinit_pending()
1201+
for lane in range(self.CMIS_NUM_CHANNELS):
1202+
if ((1 << lane) & channel) == 0:
1203+
continue
1204+
key = "DPInitPending{}".format(lane + 1)
1205+
if not dpinit_pending_dict[key]:
1206+
pending = False
1207+
break
1208+
1209+
return pending
1210+
11791211
def check_datapath_state(self, api, channel, states):
11801212
"""
11811213
Check if the CMIS datapath states are in the specified state
@@ -1458,7 +1490,9 @@ def task_worker(self):
14581490
# TODO: Make sure this doesn't impact other datapaths
14591491
api.set_lpmode(False)
14601492
self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_AP_CONF
1461-
self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=self.CMIS_DEF_EXPIRED)
1493+
dpDeinitDuration = self.get_cmis_dp_deinit_duration_secs(api)
1494+
self.log_notice("{} DpDeinit duration {} secs".format(lport, dpDeinitDuration))
1495+
self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=dpDeinitDuration)
14621496
elif state == self.CMIS_STATE_AP_CONF:
14631497
# TODO: Use fine grained time when the CMIS memory map is available
14641498
if not self.check_module_state(api, ['ModuleReady']):
@@ -1494,8 +1528,14 @@ def task_worker(self):
14941528
self.force_cmis_reinit(lport, retries + 1)
14951529
continue
14961530

1497-
# TODO: Use fine grained time when the CMIS memory map is available
1498-
self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=self.CMIS_DEF_EXPIRED)
1531+
if getattr(api, 'get_cmis_rev', None):
1532+
# Check datapath init pending on module that supports CMIS 5.x
1533+
majorRev = int(api.get_cmis_rev().split('.')[0])
1534+
if majorRev >= 5 and not self.check_datapath_init_pending(api, host_lanes):
1535+
self.log_notice("{}: datapath init not pending".format(lport))
1536+
self.force_cmis_reinit(lport, retries + 1)
1537+
continue
1538+
14991539
self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_INIT
15001540
elif state == self.CMIS_STATE_DP_INIT:
15011541
if not self.check_config_error(api, host_lanes, ['ConfigSuccess']):
@@ -1515,8 +1555,9 @@ def task_worker(self):
15151555

15161556
# D.1.3 Software Configuration and Initialization
15171557
api.set_datapath_init(host_lanes)
1518-
# TODO: Use fine grained timeout when the CMIS memory map is available
1519-
self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=self.CMIS_DEF_EXPIRED)
1558+
dpInitDuration = self.get_cmis_dp_init_duration_secs(api)
1559+
self.log_notice("{} DpInit duration {} secs".format(lport, dpInitDuration))
1560+
self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=dpInitDuration)
15201561
self.port_dict[lport]['cmis_state'] = self.CMIS_STATE_DP_TXON
15211562
elif state == self.CMIS_STATE_DP_TXON:
15221563
if not self.check_datapath_state(api, host_lanes, ['DataPathInitialized']):

0 commit comments

Comments
 (0)