diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index 4e4f4b721..400b72fdc 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -1677,6 +1677,29 @@ def get_host_lane_assignment_option_side_effect(app): appl = get_cmis_application_desired(mock_xcvr_api, host_lane_count, speed) assert task.get_cmis_host_lanes_mask(mock_xcvr_api, appl, host_lane_count, subport) == expected + @patch('swsscommon.swsscommon.FieldValuePairs') + def test_CmisManagerTask_post_port_active_apsel_to_db_error_cases(self, mock_field_value_pairs): + mock_xcvr_api = MagicMock() + mock_xcvr_api.get_active_apsel_hostlane = MagicMock() + mock_xcvr_api.get_application_advertisement = MagicMock() + + port_mapping = PortMapping() + stop_event = threading.Event() + task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event) + lport = "Ethernet0" + host_lanes_mask = 0xff + + # Case: table does not exist + task.xcvr_table_helper.get_intf_tbl = MagicMock(return_value=None) + task.post_port_active_apsel_to_db(mock_xcvr_api, lport, host_lanes_mask) + assert mock_field_value_pairs.call_count == 0 + + # Case: lport is not in the table + int_tbl = MagicMock() + int_tbl.get = MagicMock(return_value=(False, dict)) + task.xcvr_table_helper.get_intf_tbl = MagicMock(return_value=int_tbl) + task.post_port_active_apsel_to_db(mock_xcvr_api, lport, host_lanes_mask) + assert mock_field_value_pairs.call_count == 0 def test_CmisManagerTask_post_port_active_apsel_to_db(self): mock_xcvr_api = MagicMock() @@ -1719,6 +1742,7 @@ def test_CmisManagerTask_post_port_active_apsel_to_db(self): ]) int_tbl = Table("STATE_DB", TRANSCEIVER_INFO_TABLE) + int_tbl.get = MagicMock(return_value=(True, dict)) port_mapping = PortMapping() stop_event = threading.Event() diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 31a11d120..d69e5ce30 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -478,30 +478,20 @@ def post_port_sfp_info_to_db(logical_port_name, port_mapping, table, transceiver if 'media_interface_code' in port_info_dict else 'N/A'), ('host_electrical_interface', port_info_dict['host_electrical_interface'] if 'host_electrical_interface' in port_info_dict else 'N/A'), - ('host_lane_count', str(port_info_dict['host_lane_count']) - if 'host_lane_count' in port_info_dict else 'N/A'), - ('media_lane_count', str(port_info_dict['media_lane_count']) - if 'media_lane_count' in port_info_dict else 'N/A'), + ('host_lane_count', 'N/A'), + ('media_lane_count', 'N/A'), ('host_lane_assignment_option', str(port_info_dict['host_lane_assignment_option']) if 'host_lane_assignment_option' in port_info_dict else 'N/A'), ('media_lane_assignment_option', str(port_info_dict['media_lane_assignment_option']) if 'media_lane_assignment_option' in port_info_dict else 'N/A'), - ('active_apsel_hostlane1', str(port_info_dict['active_apsel_hostlane1']) - if 'active_apsel_hostlane1' in port_info_dict else 'N/A'), - ('active_apsel_hostlane2', str(port_info_dict['active_apsel_hostlane2']) - if 'active_apsel_hostlane2' in port_info_dict else 'N/A'), - ('active_apsel_hostlane3', str(port_info_dict['active_apsel_hostlane3']) - if 'active_apsel_hostlane3' in port_info_dict else 'N/A'), - ('active_apsel_hostlane4', str(port_info_dict['active_apsel_hostlane4']) - if 'active_apsel_hostlane4' in port_info_dict else 'N/A'), - ('active_apsel_hostlane5', str(port_info_dict['active_apsel_hostlane5']) - if 'active_apsel_hostlane5' in port_info_dict else 'N/A'), - ('active_apsel_hostlane6', str(port_info_dict['active_apsel_hostlane6']) - if 'active_apsel_hostlane6' in port_info_dict else 'N/A'), - ('active_apsel_hostlane7', str(port_info_dict['active_apsel_hostlane7']) - if 'active_apsel_hostlane7' in port_info_dict else 'N/A'), - ('active_apsel_hostlane8', str(port_info_dict['active_apsel_hostlane8']) - if 'active_apsel_hostlane8' in port_info_dict else 'N/A'), + ('active_apsel_hostlane1', 'N/A'), + ('active_apsel_hostlane2', 'N/A'), + ('active_apsel_hostlane3', 'N/A'), + ('active_apsel_hostlane4', 'N/A'), + ('active_apsel_hostlane5', 'N/A'), + ('active_apsel_hostlane6', 'N/A'), + ('active_apsel_hostlane7', 'N/A'), + ('active_apsel_hostlane8', 'N/A'), ('media_interface_technology', port_info_dict['media_interface_technology'] if 'media_interface_technology' in port_info_dict else 'N/A'), ('supported_max_tx_power', str(port_info_dict['supported_max_tx_power']) @@ -1278,6 +1268,13 @@ def post_port_active_apsel_to_db(self, api, lport, host_lanes_mask): asic_index = self.port_mapping.get_asic_id_for_logical_port(lport) intf_tbl = self.xcvr_table_helper.get_intf_tbl(asic_index) + if not intf_tbl: + helper_logger.log_warning("Active ApSel db update: TRANSCEIVER_INFO table not found for {}".format(lport)) + return + found, _ = intf_tbl.get(lport) + if not found: + helper_logger.log_warning("Active ApSel db update: {} not found in INTF_TABLE".format(lport)) + return fvs = swsscommon.FieldValuePairs(tuple_list) intf_tbl.set(lport, fvs) self.log_notice("{}: updated TRANSCEIVER_INFO_TABLE {}".format(lport, tuple_list)) @@ -1504,6 +1501,12 @@ def task_worker(self): if not need_update: # No application updates + # As part of xcvrd restart, the TRANSCEIVER_INFO table is deleted and + # created with default value of 'N/A' for all the active apsel fields. + # The below (post_port_active_apsel_to_db) will ensure that the + # active apsel fields are updated correctly in the DB since + # the CMIS state remains unchanged during xcvrd restart + self.post_port_active_apsel_to_db(api, lport, host_lanes_mask) self.log_notice("{}: no CMIS application update required...READY".format(lport)) self.update_port_transceiver_status_table_sw_cmis_state(lport, CMIS_STATE_READY) continue