Skip to content

Commit

Permalink
Moved update_port_transceiver_status_table_sw_cmis_state to CmisManag…
Browse files Browse the repository at this point in the history
…erTask class
  • Loading branch information
mihirpat1 committed Mar 19, 2024
1 parent f88117c commit 6ac293e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 63 deletions.
37 changes: 16 additions & 21 deletions sonic-xcvrd/tests/test_xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,27 +357,6 @@ def test_del_port_sfp_dom_info_from_db(self):
firmware_info_tbl = Table("STATE_DB", TRANSCEIVER_FIRMWARE_INFO_TABLE)
del_port_sfp_dom_info_from_db(logical_port_name, port_mapping, init_tbl, dom_tbl, dom_threshold_tbl, pm_tbl, firmware_info_tbl)

def test_update_port_transceiver_status_table_sw_cmis_state(self):
mock_xcvr_table_helper = MagicMock()
mock_get_status_tbl = MagicMock()
mock_get_status_tbl.set = MagicMock()
mock_xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
port_mapping = PortMapping()
update_port_transceiver_status_table_sw_cmis_state("Ethernet0", None, port_mapping, CMIS_STATE_INSERTED)
assert mock_get_status_tbl.set.call_count == 0

update_port_transceiver_status_table_sw_cmis_state("Ethernet0", mock_xcvr_table_helper, None, CMIS_STATE_INSERTED)
assert mock_get_status_tbl.set.call_count == 0

port_mapping.get_asic_id_for_logical_port = MagicMock(return_value=0)
mock_xcvr_table_helper.get_status_tbl.return_value = None
update_port_transceiver_status_table_sw_cmis_state("Ethernet0", mock_xcvr_table_helper, port_mapping, CMIS_STATE_INSERTED)
assert mock_get_status_tbl.set.call_count == 0

mock_xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
update_port_transceiver_status_table_sw_cmis_state("Ethernet0", mock_xcvr_table_helper, port_mapping, CMIS_STATE_INSERTED)
assert mock_get_status_tbl.set.call_count == 1

@pytest.mark.parametrize("mock_found, mock_status_dict, expected_cmis_state", [
(True, {'cmis_state': CMIS_STATE_INSERTED}, CMIS_STATE_INSERTED),
(False, {}, CMIS_STATE_UNKNOWN),
Expand Down Expand Up @@ -1340,6 +1319,22 @@ def test_SffManagerTask_task_worker(self, mock_chassis):
assert mock_xcvr_api.tx_disable_channel.call_count == 2
mock_sfp.get_presence = MagicMock(return_value=True)

def test_update_port_transceiver_status_table_sw_cmis_state(self):
port_mapping = PortMapping()
stop_event = threading.Event()
task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event)
port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET)
task.on_port_update_event(port_change_event)

task.xcvr_table_helper.get_status_tbl = MagicMock(return_value=None)
task.update_port_transceiver_status_table_sw_cmis_state("Ethernet0", CMIS_STATE_INSERTED)

mock_get_status_tbl = MagicMock()
mock_get_status_tbl.set = MagicMock()
task.xcvr_table_helper.get_status_tbl.return_value = mock_get_status_tbl
task.update_port_transceiver_status_table_sw_cmis_state("Ethernet0", CMIS_STATE_INSERTED)
assert mock_get_status_tbl.set.call_count == 1

@patch('xcvrd.xcvrd._wrapper_get_sfp_type', MagicMock(return_value='QSFP_DD'))
def test_CmisManagerTask_handle_port_change_event(self):
port_mapping = PortMapping()
Expand Down
74 changes: 32 additions & 42 deletions sonic-xcvrd/xcvrd/xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,27 +714,6 @@ def update_port_transceiver_status_table_sw(logical_port_name, status_tbl, statu
fvs = swsscommon.FieldValuePairs([('status', status), ('error', error_descriptions)])
status_tbl.set(logical_port_name, fvs)

def update_port_transceiver_status_table_sw_cmis_state(lport, xcvr_table_helper, port_mapping, cmis_state_to_set):
if xcvr_table_helper is None:
helper_logger.log_error("xcvr_table_helper is None while updating "
"sw CMIS state for lport {}".format(lport))
return

if port_mapping is None:
helper_logger.log_error("port_mapping is None while updating "
"sw CMIS state for lport {}".format(lport))
return

asic_index = port_mapping.get_asic_id_for_logical_port(lport)
status_table = xcvr_table_helper.get_status_tbl(asic_index)
if status_table is None:
helper_logger.log_error("status_table is None while updating "
"sw CMIS state for lport {}".format(lport))
return

fvs = swsscommon.FieldValuePairs([('cmis_state', cmis_state_to_set)])
status_table.set(lport, fvs)

def get_cmis_state_from_state_db(lport, status_tbl):
found, transceiver_status_dict = status_tbl.get(lport)
if found and 'cmis_state' in dict(transceiver_status_dict):
Expand Down Expand Up @@ -834,6 +813,17 @@ def log_notice(self, message):
def log_error(self, message):
helper_logger.log_error("CMIS: {}".format(message))

def update_port_transceiver_status_table_sw_cmis_state(self, lport, cmis_state_to_set):
asic_index = self.port_mapping.get_asic_id_for_logical_port(lport)
status_table = self.xcvr_table_helper.get_status_tbl(asic_index)
if status_table is None:
helper_logger.log_error("status_table is None while updating "
"sw CMIS state for lport {}".format(lport))
return

fvs = swsscommon.FieldValuePairs([('cmis_state', cmis_state_to_set)])
status_table.set(lport, fvs)

def on_port_update_event(self, port_change_event):
if port_change_event.event_type not in [port_change_event.PORT_SET, port_change_event.PORT_DEL]:
return
Expand Down Expand Up @@ -885,7 +875,7 @@ def on_port_update_event(self, port_change_event):

self.force_cmis_reinit(lport, 0)
else:
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_REMOVED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_REMOVED)

def get_cmis_dp_init_duration_secs(self, api):
return api.get_datapath_init_duration()/1000
Expand Down Expand Up @@ -1033,7 +1023,7 @@ def force_cmis_reinit(self, lport, retries=0):
"""
Try to force the restart of CMIS state machine
"""
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_INSERTED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_INSERTED)
self.port_dict[lport]['cmis_retries'] = retries
self.port_dict[lport]['cmis_expired'] = None # No expiration

Expand Down Expand Up @@ -1307,27 +1297,27 @@ def task_worker(self):
# double-check the HW presence before moving forward
sfp = platform_chassis.get_sfp(pport)
if not sfp.get_presence():
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_REMOVED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_REMOVED)
continue

try:
# Skip if XcvrApi is not supported
api = sfp.get_xcvr_api()
if api is None:
self.log_error("{}: skipping CMIS state machine since no xcvr api!!!".format(lport))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_READY)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
continue

# Skip if it's not a paged memory device
if api.is_flat_memory():
self.log_notice("{}: skipping CMIS state machine for flat memory xcvr".format(lport))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_READY)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
continue

# Skip if it's not a CMIS module
type = api.get_module_type_abbreviation()
if (type is None) or (type not in self.CMIS_MODULE_TYPES):
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_READY)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
continue

if api.is_coherent_module():
Expand All @@ -1337,7 +1327,7 @@ def task_worker(self):
self.port_dict[lport]['laser_freq'] = self.get_configured_laser_freq_from_db(lport)
except AttributeError:
# Skip if these essential routines are not available
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_READY)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
continue

# CMIS expiration and retries
Expand All @@ -1353,15 +1343,15 @@ def task_worker(self):
if state != CMIS_STATE_INSERTED and (host_lanes_mask <= 0 or appl < 1):
self.log_error("{}: Unexpected value for host_lanes_mask {} or appl {} in "
"{} state".format(lport, host_lanes_mask, appl, state))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_FAILED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_FAILED)
continue

self.log_notice("{}: {}G, lanemask=0x{:x}, state={}, appl {} host_lane_count {} "
"retries={}".format(lport, int(speed/1000), host_lanes_mask,
state, appl, host_lane_count, retries))
if retries > self.CMIS_MAX_RETRIES:
self.log_error("{}: FAILED".format(lport))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_FAILED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_FAILED)
continue

try:
Expand All @@ -1371,7 +1361,7 @@ def task_worker(self):
if self.port_dict[lport]['appl'] is None:
self.log_error("{}: no suitable app for the port appl {} host_lane_count {} "
"host_speed {}".format(lport, appl, host_lane_count, host_speed))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_FAILED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_FAILED)
continue
appl = self.port_dict[lport]['appl']
self.log_notice("{}: Setting appl={}".format(lport, appl))
Expand All @@ -1381,7 +1371,7 @@ def task_worker(self):
if self.port_dict[lport]['host_lanes_mask'] <= 0:
self.log_error("{}: Invalid lane mask received - host_lane_count {} subport {} "
"appl {}!".format(lport, host_lane_count, subport, appl))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_FAILED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_FAILED)
continue
host_lanes_mask = self.port_dict[lport]['host_lanes_mask']
self.log_notice("{}: Setting host_lanemask=0x{:x}".format(lport, host_lanes_mask))
Expand All @@ -1396,7 +1386,7 @@ def task_worker(self):
self.log_error("{}: Invalid media lane mask received - media_lane_count {} "
"media_lane_assignment_options {} subport {}"
" appl {}!".format(lport, media_lane_count, media_lane_assignment_options, subport, appl))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_FAILED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_FAILED)
continue
media_lanes_mask = self.port_dict[lport]['media_lanes_mask']
self.log_notice("{}: Setting media_lanemask=0x{:x}".format(lport, media_lanes_mask))
Expand All @@ -1406,7 +1396,7 @@ def task_worker(self):
self.log_notice("{} Forcing Tx laser OFF".format(lport))
# Force DataPath re-init
api.tx_disable_channel(media_lanes_mask, True)
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_READY)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
continue
# Configure the target output power if ZR module
if api.is_coherent_module():
Expand All @@ -1431,10 +1421,10 @@ def task_worker(self):
if not need_update:
# No application updates
self.log_notice("{}: no CMIS application update required...READY".format(lport))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_READY)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
continue
self.log_notice("{}: force Datapath reinit".format(lport))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_DP_DEINIT)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_DP_DEINIT)
elif state == CMIS_STATE_DP_DEINIT:
# D.2.2 Software Deinitialization
api.set_datapath_deinit(host_lanes_mask)
Expand All @@ -1448,7 +1438,7 @@ def task_worker(self):

#Sets module to high power mode and doesn't impact datapath if module is already in high power mode
api.set_lpmode(False)
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_AP_CONF)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_AP_CONF)
dpDeinitDuration = self.get_cmis_dp_deinit_duration_secs(api)
modulePwrUpDuration = self.get_cmis_module_power_up_duration_secs(api)
self.log_notice("{}: DpDeinit duration {} secs, modulePwrUp duration {} secs".format(lport, dpDeinitDuration, modulePwrUpDuration))
Expand Down Expand Up @@ -1513,7 +1503,7 @@ def task_worker(self):
self.force_cmis_reinit(lport, retries + 1)
continue

update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_DP_INIT)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_DP_INIT)
elif state == CMIS_STATE_DP_INIT:
if not self.check_config_error(api, host_lanes_mask, ['ConfigSuccess']):
if (expired is not None) and (expired <= now):
Expand Down Expand Up @@ -1543,7 +1533,7 @@ def task_worker(self):
dpInitDuration = self.get_cmis_dp_init_duration_secs(api)
self.log_notice("{}: DpInit duration {} secs".format(lport, dpInitDuration))
self.port_dict[lport]['cmis_expired'] = now + datetime.timedelta(seconds=dpInitDuration)
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_DP_TXON)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_DP_TXON)
elif state == CMIS_STATE_DP_TXON:
if not self.check_datapath_state(api, host_lanes_mask, ['DataPathInitialized']):
if (expired is not None) and (expired <= now):
Expand All @@ -1555,7 +1545,7 @@ def task_worker(self):
media_lanes_mask = self.port_dict[lport]['media_lanes_mask']
api.tx_disable_channel(media_lanes_mask, False)
self.log_notice("{}: Turning ON tx power".format(lport))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_DP_ACTIVATE)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_DP_ACTIVATE)
elif state == CMIS_STATE_DP_ACTIVATE:
if not self.check_datapath_state(api, host_lanes_mask, ['DataPathActivated']):
if (expired is not None) and (expired <= now):
Expand All @@ -1564,12 +1554,12 @@ def task_worker(self):
continue

self.log_notice("{}: READY".format(lport))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_READY)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY)
self.post_port_active_apsel_to_db(api, lport, host_lanes_mask)

except (NotImplementedError, AttributeError) as e:
self.log_error("{}: internal errors due to {}".format(lport, e))
update_port_transceiver_status_table_sw_cmis_state(lport, self.xcvr_table_helper, self.port_mapping, CMIS_STATE_FAILED)
self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_FAILED)

self.log_notice("Stopped")

Expand Down

0 comments on commit 6ac293e

Please sign in to comment.