diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index 2581c7a0d..6123bef39 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -764,6 +764,89 @@ def get_host_lane_assignment_option_side_effect(app): appl = task.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 + def test_CmisManagerTask_post_port_active_apsel_to_db(self): + mock_xcvr_api = MagicMock() + mock_xcvr_api.get_active_apsel_hostlane = MagicMock(side_effect=[ + { + 'ActiveAppSelLane1': 1, + 'ActiveAppSelLane2': 1, + 'ActiveAppSelLane3': 1, + 'ActiveAppSelLane4': 1, + 'ActiveAppSelLane5': 1, + 'ActiveAppSelLane6': 1, + 'ActiveAppSelLane7': 1, + 'ActiveAppSelLane8': 1 + }, + { + 'ActiveAppSelLane1': 2, + 'ActiveAppSelLane2': 2, + 'ActiveAppSelLane3': 2, + 'ActiveAppSelLane4': 2, + 'ActiveAppSelLane5': 2, + 'ActiveAppSelLane6': 2, + 'ActiveAppSelLane7': 2, + 'ActiveAppSelLane8': 2 + }, + NotImplementedError + ]) + mock_xcvr_api.get_application_advertisement = MagicMock(side_effect=[ + { + 1: { + 'media_lane_count': 4, + 'host_lane_count': 8 + } + }, + { + 2: { + 'media_lane_count': 1, + 'host_lane_count': 2 + } + } + ]) + + int_tbl = Table("STATE_DB", TRANSCEIVER_INFO_TABLE) + + port_mapping = PortMapping() + stop_event = threading.Event() + task = CmisManagerTask(DEFAULT_NAMESPACE, port_mapping, stop_event) + task.xcvr_table_helper.get_intf_tbl = MagicMock(return_value=int_tbl) + + # case: partial lanes update + lport = "Ethernet0" + host_lanes_mask = 0xc + ret = task.post_port_active_apsel_to_db(mock_xcvr_api, lport, host_lanes_mask) + assert int_tbl.getKeys() == ["Ethernet0"] + assert dict(int_tbl.mock_dict["Ethernet0"]) == {'active_apsel_hostlane3': '1', + 'active_apsel_hostlane4': '1', + 'host_lane_count': '8', + 'media_lane_count': '4'} + # case: full lanes update + lport = "Ethernet8" + host_lanes_mask = 0xff + task.post_port_active_apsel_to_db(mock_xcvr_api, lport, host_lanes_mask) + assert int_tbl.getKeys() == ["Ethernet0", "Ethernet8"] + assert dict(int_tbl.mock_dict["Ethernet0"]) == {'active_apsel_hostlane3': '1', + 'active_apsel_hostlane4': '1', + 'host_lane_count': '8', + 'media_lane_count': '4'} + assert dict(int_tbl.mock_dict["Ethernet8"]) == {'active_apsel_hostlane1': '2', + 'active_apsel_hostlane2': '2', + 'active_apsel_hostlane3': '2', + 'active_apsel_hostlane4': '2', + 'active_apsel_hostlane5': '2', + 'active_apsel_hostlane6': '2', + 'active_apsel_hostlane7': '2', + 'active_apsel_hostlane8': '2', + 'host_lane_count': '2', + 'media_lane_count': '1'} + + # case: NotImplementedError + int_tbl = Table("STATE_DB", TRANSCEIVER_INFO_TABLE) # a new empty table + lport = "Ethernet0" + host_lanes_mask = 0xf + ret = task.post_port_active_apsel_to_db(mock_xcvr_api, lport, host_lanes_mask) + assert int_tbl.getKeys() == [] + @patch('xcvrd.xcvrd.platform_chassis') @patch('xcvrd.xcvrd_utilities.port_mapping.subscribe_port_update_event', MagicMock(return_value=(None, None))) @patch('xcvrd.xcvrd_utilities.port_mapping.handle_port_update_event', MagicMock()) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index f59cf6433..8a273e062 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -1335,6 +1335,36 @@ def configure_laser_frequency(self, api, lport, freq, grid=75): self.log_error("{} Tuning in progress, subport selection may fail!".format(lport)) return api.set_laser_freq(freq, grid) + def post_port_active_apsel_to_db(self, api, lport, host_lanes_mask): + try: + act_apsel = api.get_active_apsel_hostlane() + appl_advt = api.get_application_advertisement() + except NotImplementedError: + helper_logger.log_error("Required feature is not implemented") + return + + tuple_list = [] + for lane in range(self.CMIS_MAX_HOST_LANES): + if ((1 << lane) & host_lanes_mask) == 0: + continue + act_apsel_lane = act_apsel.get('ActiveAppSelLane{}'.format(lane + 1), 'N/A') + tuple_list.append(('active_apsel_hostlane{}'.format(lane + 1), + str(act_apsel_lane))) + + # also update host_lane_count and media_lane_count + if len(tuple_list) > 0: + appl_advt_act = appl_advt.get(act_apsel_lane) + host_lane_count = appl_advt_act.get('host_lane_count', 'N/A') if appl_advt_act else 'N/A' + tuple_list.append(('host_lane_count', str(host_lane_count))) + media_lane_count = appl_advt_act.get('media_lane_count', 'N/A') if appl_advt_act else 'N/A' + tuple_list.append(('media_lane_count', str(media_lane_count))) + + asic_index = self.port_mapping.get_asic_id_for_logical_port(lport) + intf_tbl = self.xcvr_table_helper.get_intf_tbl(asic_index) + fvs = swsscommon.FieldValuePairs(tuple_list) + intf_tbl.set(lport, fvs) + self.log_notice("{}: updated TRANSCEIVER_INFO_TABLE {}".format(lport, tuple_list)) + def wait_for_port_config_done(self, namespace): # Connect to APPL_DB and subscribe to PORT table notifications appl_db = daemon_base.db_connect("APPL_DB", namespace=namespace) @@ -1641,6 +1671,7 @@ def task_worker(self): self.log_notice("{}: READY".format(lport)) self.port_dict[lport]['cmis_state'] = self.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))