diff --git a/sonic-xcvrd/tests/mock_swsscommon.py b/sonic-xcvrd/tests/mock_swsscommon.py index 0cfc1e5..6be4e03 100644 --- a/sonic-xcvrd/tests/mock_swsscommon.py +++ b/sonic-xcvrd/tests/mock_swsscommon.py @@ -36,6 +36,13 @@ def get(self, key): if key in self.mock_dict: return True, self.mock_dict[key] return False, None + + def hget(self, key, field): + if key in self.mock_dict: + for fv in self.mock_dict[key]: + if fv[0] == field: + return True, fv[1] + return False, None def get_size(self): return (len(self.mock_dict)) diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index 7e219f3..7758899 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -247,9 +247,11 @@ def test_CmisManagerTask_task_run_with_exception(self): @patch('xcvrd.xcvrd.get_cmis_application_desired', MagicMock(side_effect=KeyError)) @patch('xcvrd.xcvrd.log_exception_traceback') @patch('xcvrd.xcvrd.XcvrTableHelper.get_status_sw_tbl') + @patch('xcvrd.xcvrd.XcvrTableHelper.get_state_port_tbl') @patch('xcvrd.xcvrd.platform_chassis') - def test_CmisManagerTask_get_xcvr_api_exception(self, mock_platform_chassis, mock_get_status_sw_tbl, mock_log_exception_traceback): + def test_CmisManagerTask_get_xcvr_api_exception(self, mock_platform_chassis, mock_get_state_port_tbl, mock_get_status_sw_tbl, mock_log_exception_traceback): mock_get_status_sw_tbl = Table("STATE_DB", TRANSCEIVER_STATUS_SW_TABLE) + mock_get_state_port_tbl.return_value = Table("APPL_DB", 'PORT_TABLE') mock_sfp = MagicMock() mock_sfp.get_presence.return_value = True mock_platform_chassis.get_sfp = MagicMock(return_value=mock_sfp) @@ -257,13 +259,12 @@ def test_CmisManagerTask_get_xcvr_api_exception(self, mock_platform_chassis, moc stop_event = threading.Event() task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event) task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True]) - task.get_host_tx_status = MagicMock(return_value='true') - task.get_port_admin_status = MagicMock(return_value='up') task.get_cfg_port_tbl = MagicMock() task.xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE) task.xcvr_table_helper.get_status_sw_tbl.return_value = mock_get_status_sw_tbl port_change_event = PortChangeEvent('Ethernet0', 1, 0, PortChangeEvent.PORT_SET, - {'speed':'400000', 'lanes':'1,2,3,4,5,6,7,8'}) + {'speed':'400000', 'lanes':'1,2,3,4,5,6,7,8', + 'admin_status':'up', 'host_tx_status':'true'}) # Case 1: get_xcvr_api() raises an exception task.on_port_update_event(port_change_event) @@ -1053,14 +1054,13 @@ def test_del_port_sfp_dom_info_from_db(self): del_port_sfp_dom_info_from_db(logical_port_name, port_mapping, [init_tbl, dom_tbl, dom_threshold_tbl, pm_tbl, firmware_info_tbl]) assert dom_tbl.get_size() == 0 - @pytest.mark.parametrize("mock_found, mock_status_dict, expected_cmis_state", [ - (True, {'cmis_state': CMIS_STATE_INSERTED}, CMIS_STATE_INSERTED), - (False, {}, CMIS_STATE_UNKNOWN), - (True, {'other_key': 'some_value'}, CMIS_STATE_UNKNOWN) + @pytest.mark.parametrize("mock_found, mock_state, expected_cmis_state", [ + (True, CMIS_STATE_INSERTED, CMIS_STATE_INSERTED), + (False, None, CMIS_STATE_UNKNOWN) ]) - def test_get_cmis_state_from_state_db(self, mock_found, mock_status_dict, expected_cmis_state): + def test_get_cmis_state_from_state_db(self, mock_found, mock_state, expected_cmis_state): status_tbl = MagicMock() - status_tbl.get.return_value = (mock_found, mock_status_dict) + status_tbl.hget.return_value = (mock_found, mock_state) assert get_cmis_state_from_state_db("Ethernet0", status_tbl) == expected_cmis_state @patch('xcvrd.xcvrd_utilities.port_event_helper.PortMapping.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) @@ -2215,7 +2215,7 @@ def test_CmisManagerTask_get_configured_freq(self, mock_table_helper): stop_event = threading.Event() task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event) cfg_port_tbl = MagicMock() - cfg_port_tbl.get = MagicMock(return_value=(True, (('laser_freq', 193100),))) + cfg_port_tbl.hget = MagicMock(return_value=(True, 193100)) mock_table_helper.get_cfg_port_tbl = MagicMock(return_value=cfg_port_tbl) task.xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE) task.xcvr_table_helper.get_cfg_port_tbl = mock_table_helper.get_cfg_port_tbl @@ -2227,7 +2227,7 @@ def test_CmisManagerTask_get_configured_tx_power_from_db(self, mock_table_helper stop_event = threading.Event() task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event) cfg_port_tbl = MagicMock() - cfg_port_tbl.get = MagicMock(return_value=(True, (('tx_power', -10),))) + cfg_port_tbl.hget = MagicMock(return_value=(True, -10)) mock_table_helper.get_cfg_port_tbl = MagicMock(return_value=cfg_port_tbl) task.xcvr_table_helper = XcvrTableHelper(DEFAULT_NAMESPACE) task.xcvr_table_helper.get_cfg_port_tbl = mock_table_helper.get_cfg_port_tbl diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index 7132d3b..f0a8b32 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -358,10 +358,13 @@ def post_port_sfp_info_to_db(logical_port_name, port_mapping, table, transceiver ganged_member_num += 1 try: - port_info_dict = _wrapper_get_transceiver_info(physical_port) + if physical_port in transceiver_dict: + port_info_dict = transceiver_dict[physical_port] + else: + port_info_dict = _wrapper_get_transceiver_info(physical_port) + transceiver_dict[physical_port] = port_info_dict if port_info_dict is not None: is_replaceable = _wrapper_is_replaceable(physical_port) - transceiver_dict[physical_port] = port_info_dict # if cmis is supported by the module if 'cmis_rev' in port_info_dict: fvs = swsscommon.FieldValuePairs( @@ -437,11 +440,8 @@ def update_port_transceiver_status_table_sw(logical_port_name, status_sw_tbl, st status_sw_tbl.set(logical_port_name, fvs) def get_cmis_state_from_state_db(lport, status_sw_tbl): - found, transceiver_status_dict = status_sw_tbl.get(lport) - if found and 'cmis_state' in dict(transceiver_status_dict): - return dict(transceiver_status_dict)['cmis_state'] - else: - return CMIS_STATE_UNKNOWN + found, cmis_state = status_sw_tbl.hget(lport, 'cmis_state') + return cmis_state if found else CMIS_STATE_UNKNOWN # Delete port from SFP status table @@ -819,54 +819,38 @@ def check_datapath_state(self, api, host_lanes_mask, states): return done + def get_asic_id(self, lport): + return self.port_mapping.get_asic_id_for_logical_port(lport) + def get_configured_laser_freq_from_db(self, lport): """ Return the Tx power configured by user in CONFIG_DB's PORT table """ - freq = 0 - asic_index = self.port_mapping.get_asic_id_for_logical_port(lport) - port_tbl = self.xcvr_table_helper.get_cfg_port_tbl(asic_index) + port_tbl = self.xcvr_table_helper.get_cfg_port_tbl(self.get_asic_id(lport)) - found, port_info = port_tbl.get(lport) - if found and 'laser_freq' in dict(port_info): - freq = dict(port_info)['laser_freq'] - return int(freq) + found, laser_freq = port_tbl.hget(lport, 'laser_freq') + return int(laser_freq) if found else 0 def get_configured_tx_power_from_db(self, lport): """ Return the Tx power configured by user in CONFIG_DB's PORT table """ - power = 0 - asic_index = self.port_mapping.get_asic_id_for_logical_port(lport) - port_tbl = self.xcvr_table_helper.get_cfg_port_tbl(asic_index) + port_tbl = self.xcvr_table_helper.get_cfg_port_tbl(self.get_asic_id(lport)) - found, port_info = port_tbl.get(lport) - if found and 'tx_power' in dict(port_info): - power = dict(port_info)['tx_power'] - return float(power) + found, power = port_tbl.hget(lport, 'tx_power') + return float(power) if found else 0 def get_host_tx_status(self, lport): - host_tx_ready = 'false' - - asic_index = self.port_mapping.get_asic_id_for_logical_port(lport) - state_port_tbl = self.xcvr_table_helper.get_state_port_tbl(asic_index) + state_port_tbl = self.xcvr_table_helper.get_state_port_tbl(self.get_asic_id(lport)) - found, port_info = state_port_tbl.get(lport) - if found and 'host_tx_ready' in dict(port_info): - host_tx_ready = dict(port_info)['host_tx_ready'] - return host_tx_ready + found, host_tx_ready = state_port_tbl.hget(lport, 'host_tx_ready') + return host_tx_ready if found else 'false' def get_port_admin_status(self, lport): - admin_status = 'down' + cfg_port_tbl = self.xcvr_table_helper.get_cfg_port_tbl(self.get_asic_id(lport)) - asic_index = self.port_mapping.get_asic_id_for_logical_port(lport) - cfg_port_tbl = self.xcvr_table_helper.get_cfg_port_tbl(asic_index) - - found, port_info = cfg_port_tbl.get(lport) - if found: - # Check admin_status too ...just in case - admin_status = dict(port_info).get('admin_status', 'down') - return admin_status + found, admin_status = cfg_port_tbl.hget(lport, 'admin_status') + return admin_status if found else 'down' def configure_tx_output_power(self, api, lport, tx_power): min_p, max_p = api.get_supported_power_config() @@ -1465,16 +1449,21 @@ def _post_port_sfp_info_and_dom_thr_to_db_once(self, port_mapping, xcvr_table_he continue rc = post_port_sfp_info_to_db(logical_port_name, port_mapping, xcvr_table_helper.get_intf_tbl(asic_index), transceiver_dict, stop_event) if rc != SFP_EEPROM_NOT_READY: - self.dom_db_utils.post_port_dom_thresholds_to_db(logical_port_name) - # Read the VDM thresholds and post them to the DB - self.vdm_db_utils.post_port_vdm_thresholds_to_db(logical_port_name) - - # Do not notify media settings during warm reboot to avoid dataplane traffic impact if is_warm_start == False: media_settings_parser.notify_media_setting(logical_port_name, transceiver_dict, xcvr_table_helper, port_mapping) - transceiver_dict.clear() else: retry_eeprom_set.add(logical_port_name) + + dom_thresholds_cache = {} + vdm_thresholds_cache = {} + for logical_port_name in logical_port_list: + if stop_event.is_set(): + break + + if logical_port_name not in retry_eeprom_set: + self.dom_db_utils.post_port_dom_thresholds_to_db(logical_port_name, db_cache=dom_thresholds_cache) + # Read the VDM thresholds and post them to the DB + self.vdm_db_utils.post_port_vdm_thresholds_to_db(logical_port_name, db_cache=vdm_thresholds_cache) return retry_eeprom_set