diff --git a/sonic-xcvrd/tests/test_xcvrd.py b/sonic-xcvrd/tests/test_xcvrd.py index 724b01e7bae9..fbc9b0f7a7ce 100644 --- a/sonic-xcvrd/tests/test_xcvrd.py +++ b/sonic-xcvrd/tests/test_xcvrd.py @@ -69,7 +69,7 @@ def test_xcvrd_helper_class_run(self): def test_post_port_dom_info_to_db(self): logical_port_name = "Ethernet0" stop_event = threading.Event() - dom_tbl = Table("state_db", "dom_info_tbl") + dom_tbl = Table("STATE_DB", TRANSCEIVER_DOM_SENSOR_TABLE) post_port_dom_info_to_db(logical_port_name, dom_tbl, stop_event) @patch('xcvrd.xcvrd.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) @@ -77,8 +77,8 @@ def test_post_port_dom_info_to_db(self): def test_del_port_sfp_dom_info_from_db(self): logical_port_name = "Ethernet0" stop_event = threading.Event() - dom_tbl = Table("state_db", "dom_info_tbl") - init_tbl = Table("state_db", "init_info_tbl") + dom_tbl = Table("STATE_DB", TRANSCEIVER_DOM_SENSOR_TABLE) + init_tbl = Table("STATE_DB", TRANSCEIVER_INFO_TABLE) del_port_sfp_dom_info_from_db(logical_port_name, init_tbl, dom_tbl) @patch('xcvrd.xcvrd.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) @@ -106,7 +106,7 @@ def test_del_port_sfp_dom_info_from_db(self): def test_post_port_dom_threshold_info_to_db(self): logical_port_name = "Ethernet0" stop_event = threading.Event() - dom_tbl = Table("state_db", "dom_info_tbl") + dom_tbl = Table("STATE_DB", TRANSCEIVER_DOM_SENSOR_TABLE) post_port_dom_threshold_info_to_db(logical_port_name, dom_tbl, stop_event) @patch('xcvrd.xcvrd.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) @@ -132,7 +132,7 @@ def test_post_port_dom_threshold_info_to_db(self): def test_post_port_sfp_info_to_db(self): logical_port_name = "Ethernet0" stop_event = threading.Event() - dom_tbl = Table("state_db", "dom_info_tbl") + dom_tbl = Table("STATE_DB", TRANSCEIVER_DOM_SENSOR_TABLE) transceiver_dict = {} post_port_sfp_info_to_db(logical_port_name, dom_tbl, transceiver_dict, stop_event) @@ -215,3 +215,103 @@ def test_post_port_sfp_dom_info_to_db(self): def test_init_port_sfp_status_tbl(self): stop_event = threading.Event() init_port_sfp_status_tbl(stop_event) + + @patch('xcvrd.xcvrd_utilities.y_cable_helper.y_cable_platform_sfputil', MagicMock(return_value=[0])) + @patch('y_cable_helper.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) + @patch('y_cable_helper._wrapper_get_presence', MagicMock(return_value=True)) + @patch('y_cable_helper.get_muxcable_info', MagicMock(return_value={'tor_active': 'self', + 'mux_direction': 'self', + 'manual_switch_count': '7', + 'auto_switch_count': '71', + 'link_status_self': 'up', + 'link_status_peer': 'up', + 'link_status_nic': 'up', + 'nic_lane1_active': 'True', + 'nic_lane2_active': 'True', + 'nic_lane3_active': 'True', + 'nic_lane4_active': 'True', + 'self_eye_height_lane1': '500', + 'self_eye_height_lane2': '510', + 'peer_eye_height_lane1': '520', + 'peer_eye_height_lane2': '530', + 'nic_eye_height_lane1': '742', + 'nic_eye_height_lane2': '750', + 'internal_temperature': '28', + 'internal_voltage': '3.3', + 'nic_temperature': '20', + 'nic_voltage': '2.7', + 'build_slot1_nic': 'MS', + 'build_slot2_nic': 'MS', + 'version_slot1_nic': '1.7', + 'version_slot2_nic': '1.7', + 'run_slot1_nic': 'True', + 'run_slot2_nic': 'False', + 'commit_slot1_nic': 'True', + 'commit_slot2_nic': 'False', + 'empty_slot1_nic': 'True', + 'empty_slot2_nic': 'False', + 'build_slot1_tor1': 'MS', + 'build_slot2_tor1': 'MS', + 'version_slot1_tor1': '1.7', + 'version_slot2_tor1': '1.7', + 'run_slot1_tor1': 'True', + 'run_slot2_tor1': 'False', + 'commit_slot1_tor1': 'True', + 'commit_slot2_tor1': 'False', + 'empty_slot1_tor1': 'True', + 'empty_slot2_tor1': 'False', + 'build_slot1_tor2': 'MS', + 'build_slot2_tor2': 'MS', + 'version_slot1_tor2': '1.7', + 'version_slot2_tor2': '1.7', + 'run_slot1_tor2': 'True', + 'run_slot2_tor2': 'False', + 'commit_slot1_tor2': 'True', + 'commit_slot2_tor2': 'False', + 'empty_slot1_tor2': 'True', + 'empty_slot2_tor2': 'False'})) + def test_post_port_mux_info_to_db(self): + logical_port_name = "Ethernet0" + mux_tbl = Table("STATE_DB", y_cable_helper.MUX_CABLE_INFO_TABLE) + rc = post_port_mux_info_to_db(logical_port_name, mux_tbl) + assert(rc != -1) + + @patch('xcvrd.xcvrd_utilities.y_cable_helper.y_cable_platform_sfputil', MagicMock(return_value=[0])) + @patch('y_cable_helper.logical_port_name_to_physical_port_list', MagicMock(return_value=[0])) + @patch('y_cable_helper._wrapper_get_presence', MagicMock(return_value=True)) + @patch('y_cable_helper.get_muxcable_static_info', MagicMock(return_value={'read_side': 'self', + 'nic_lane1_precursor1': '1', + 'nic_lane1_precursor2': '-7', + 'nic_lane1_maincursor': '-1', + 'nic_lane1_postcursor1': '11', + 'nic_lane1_postcursor2': '11', + 'nic_lane2_precursor1': '12', + 'nic_lane2_precursor2': '7', + 'nic_lane2_maincursor': '7', + 'nic_lane2_postcursor1': '7', + 'nic_lane2_postcursor2': '7', + 'tor_self_lane1_precursor1': '17', + 'tor_self_lane1_precursor2': '17', + 'tor_self_lane1_maincursor': '17', + 'tor_self_lane1_postcursor1': '17', + 'tor_self_lane1_postcursor2': '17', + 'tor_self_lane2_precursor1': '7', + 'tor_self_lane2_precursor2': '7', + 'tor_self_lane2_maincursor': '7', + 'tor_self_lane2_postcursor1': '7', + 'tor_self_lane2_postcursor2': '7', + 'tor_peer_lane1_precursor1': '7', + 'tor_peer_lane1_precursor2': '7', + 'tor_peer_lane1_maincursor': '17', + 'tor_peer_lane1_postcursor1': '7', + 'tor_peer_lane1_postcursor2': '17', + 'tor_peer_lane2_precursor1': '7', + 'tor_peer_lane2_precursor2': '7', + 'tor_peer_lane2_maincursor': '17', + 'tor_peer_lane2_postcursor1': '7', + 'tor_peer_lane2_postcursor2': '17'})) + def test_post_port_mux_static_info_to_db(self): + logical_port_name = "Ethernet0" + mux_tbl = Table("STATE_DB", y_cable_helper.MUX_CABLE_STATIC_INFO_TABLE) + rc = post_port_mux_static_info_to_db(logical_port_name, mux_tbl) + assert(rc != -1) diff --git a/sonic-xcvrd/xcvrd/xcvrd.py b/sonic-xcvrd/xcvrd/xcvrd.py index fa45779bc384..fdac852416b8 100644 --- a/sonic-xcvrd/xcvrd/xcvrd.py +++ b/sonic-xcvrd/xcvrd/xcvrd.py @@ -832,11 +832,12 @@ def __init__(self): self.task_thread = None self.task_stopping_event = threading.Event() - def task_worker(self): + def task_worker(self, y_cable_presence): helper_logger.log_info("Start DOM monitoring loop") # Connect to STATE_DB and create transceiver dom info table state_db, dom_tbl, status_tbl = {}, {}, {} + mux_tbl = {} # Get the namespaces in the platform namespaces = multi_asic.get_front_end_namespaces() @@ -859,14 +860,16 @@ def task_worker(self): if not detect_port_in_error_status(logical_port_name, status_tbl[asic_index]): post_port_dom_info_to_db(logical_port_name, dom_tbl[asic_index], self.task_stopping_event) post_port_dom_threshold_info_to_db(logical_port_name, dom_tbl[asic_index], self.task_stopping_event) + if y_cable_presence[0] is True: + y_cable_helper.check_identifier_presence_and_update_mux_info_entry(state_db, mux_tbl, asic_index, logical_port_name) helper_logger.log_info("Stop DOM monitoring loop") - def task_run(self): + def task_run(self, y_cable_presence): if self.task_stopping_event.is_set(): return - self.task_thread = threading.Thread(target=self.task_worker) + self.task_thread = threading.Thread(target=self.task_worker, args=(y_cable_presence,)) self.task_thread.start() def task_stop(self): @@ -1325,7 +1328,7 @@ def run(self): # Start the dom sensor info update thread dom_info_update = DomInfoUpdateTask() - dom_info_update.task_run() + dom_info_update.task_run(self.y_cable_presence) # Start the sfp state info update process sfp_state_update = SfpStateUpdateTask() diff --git a/sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py b/sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py index a729fc289531..96424f6f37a7 100644 --- a/sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py +++ b/sonic-xcvrd/xcvrd/xcvrd_utilities/y_cable_helper.py @@ -3,15 +3,13 @@ helper utlities configuring y_cable for xcvrd daemon """ -try: - import threading +import threading +import time - from sonic_py_common import daemon_base, logger - from sonic_py_common import multi_asic - from sonic_y_cable import y_cable - from swsscommon import swsscommon -except ImportError as e: - raise ImportError(str(e) + " - required module not found") +from sonic_py_common import daemon_base, logger +from sonic_py_common import multi_asic +from sonic_y_cable import y_cable +from swsscommon import swsscommon SELECT_TIMEOUT = 1000 @@ -54,6 +52,9 @@ Y_CABLE_STATUS_TORB_ACTIVE } +MUX_CABLE_STATIC_INFO_TABLE = "MUX_CABLE_STATIC_INFO" +MUX_CABLE_INFO_TABLE = "MUX_CABLE_INFO" + # Find out the underneath physical port list by logical name @@ -79,7 +80,8 @@ def _wrapper_get_presence(physical_port): # Delete port from Y cable status table def delete_port_from_y_cable_table(logical_port_name, y_cable_tbl): - y_cable_tbl._del(logical_port_name) + if y_cable_tbl is not None: + y_cable_tbl._del(logical_port_name) def update_table_mux_status_for_response_tbl(table_name, status, logical_port_name): @@ -269,7 +271,7 @@ def read_y_cable_and_update_statedb_port_tbl(logical_port_name, mux_config_tbl): "Error: Retreived multiple ports for a Y cable port {}".format(logical_port_name)) -def check_identifier_presence_and_update_mux_table_entry(state_db, port_tbl, y_cable_tbl, asic_index, logical_port_name, y_cable_presence): +def check_identifier_presence_and_update_mux_table_entry(state_db, port_tbl, y_cable_tbl, static_tbl, mux_tbl, asic_index, logical_port_name, y_cable_presence): (status, fvs) = port_tbl[asic_index].get(logical_port_name) if status is False: @@ -285,10 +287,14 @@ def check_identifier_presence_and_update_mux_table_entry(state_db, port_tbl, y_c if val == "true": y_cable_asic_table = y_cable_tbl.get(asic_index, None) - if y_cable_presence[0] is True and y_cable_asic_table is not None: + mux_asic_table = mux_tbl.get(asic_index, None) + static_mux_asic_table = static_tbl.get(asic_index, None) + if y_cable_presence[0] is True and y_cable_asic_table is not None and mux_asic_table is not None and static_mux_asic_table is not None: # fill in the newly found entry read_y_cable_and_update_statedb_port_tbl( logical_port_name, y_cable_tbl[asic_index]) + post_port_mux_info_to_db(logical_port_name, mux_tbl[asic_index]) + post_port_mux_static_info_to_db(logical_port_name, static_tbl[asic_index]) else: # first create the state db y cable table and then fill in the entry @@ -301,14 +307,19 @@ def check_identifier_presence_and_update_mux_table_entry(state_db, port_tbl, y_c "STATE_DB", namespace) y_cable_tbl[asic_id] = swsscommon.Table( state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME) + static_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_STATIC_INFO_TABLE) + mux_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_INFO_TABLE) # fill the newly found entry read_y_cable_and_update_statedb_port_tbl( logical_port_name, y_cable_tbl[asic_index]) + post_port_mux_info_to_db(logical_port_name, mux_tbl[asic_index]) + post_port_mux_static_info_to_db(logical_port_name, static_tbl[asic_index]) def check_identifier_presence_and_delete_mux_table_entry(state_db, port_tbl, asic_index, logical_port_name, y_cable_presence, delete_change_event): y_cable_tbl = {} + static_tbl, mux_tbl = {}, {} # if there is No Y cable do not do anything here if y_cable_presence[0] is False: @@ -334,9 +345,15 @@ def check_identifier_presence_and_delete_mux_table_entry(state_db, port_tbl, asi "STATE_DB", namespace) y_cable_tbl[asic_id] = swsscommon.Table( state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME) + static_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_STATIC_INFO_TABLE) + mux_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_INFO_TABLE) # fill the newly found entry delete_port_from_y_cable_table( logical_port_name, y_cable_tbl[asic_index]) + delete_port_from_y_cable_table( + logical_port_name, static_tbl[asic_index]) + delete_port_from_y_cable_table( + logical_port_name, mux_tbl[asic_index]) delete_change_event[:] = [True] @@ -345,6 +362,7 @@ def init_ports_status_for_y_cable(platform_sfp, platform_chassis, y_cable_presen global y_cable_platform_chassis # Connect to CONFIG_DB and create port status table inside state_db config_db, state_db, port_tbl, y_cable_tbl = {}, {}, {}, {} + static_tbl, mux_tbl = {}, {} port_table_keys = {} y_cable_platform_sfputil = platform_sfp @@ -374,7 +392,7 @@ def init_ports_status_for_y_cable(platform_sfp, platform_chassis, y_cable_presen if logical_port_name in port_table_keys[asic_index]: check_identifier_presence_and_update_mux_table_entry( - state_db, port_tbl, y_cable_tbl, asic_index, logical_port_name, y_cable_presence) + state_db, port_tbl, y_cable_tbl, static_tbl, mux_tbl, asic_index, logical_port_name, y_cable_presence) else: # This port does not exist in Port table of config but is present inside # logical_ports after loading the port_mappings from port_config_file @@ -386,6 +404,7 @@ def init_ports_status_for_y_cable(platform_sfp, platform_chassis, y_cable_presen def change_ports_status_for_y_cable_change_event(port_dict, y_cable_presence, stop_event=threading.Event()): # Connect to CONFIG_DB and create port status table inside state_db config_db, state_db, port_tbl, y_cable_tbl = {}, {}, {}, {} + static_tbl, mux_tbl = {}, {} port_table_keys = {} delete_change_event = [False] @@ -400,6 +419,8 @@ def change_ports_status_for_y_cable_change_event(port_dict, y_cable_presence, st # Init PORT_STATUS table if ports are on Y cable and an event is received for key, value in port_dict.items(): + if stop_event.is_set(): + break logical_port_list = y_cable_platform_sfputil.get_physical_to_logical(int(key)) if logical_port_list is None: helper_logger.log_warning("Got unknown FP port index {}, ignored".format(key)) @@ -417,7 +438,7 @@ def change_ports_status_for_y_cable_change_event(port_dict, y_cable_presence, st if value == SFP_STATUS_INSERTED: helper_logger.log_info("Got SFP inserted event") check_identifier_presence_and_update_mux_table_entry( - state_db, port_tbl, y_cable_tbl, asic_index, logical_port_name, y_cable_presence) + state_db, port_tbl, y_cable_tbl, static_tbl, mux_tbl, asic_index, logical_port_name, y_cable_presence) elif value == SFP_STATUS_REMOVED or value in errors_block_eeprom_reading: check_identifier_presence_and_delete_mux_table_entry( state_db, port_tbl, asic_index, logical_port_name, y_cable_presence, delete_change_event) @@ -446,6 +467,7 @@ def delete_ports_status_for_y_cable(): state_db, port_tbl, y_cable_tbl = {}, {}, {} y_cable_tbl_keys = {} + static_tbl, mux_tbl = {}, {} namespaces = multi_asic.get_front_end_namespaces() for namespace in namespaces: asic_id = multi_asic.get_asic_index_from_namespace(namespace) @@ -453,6 +475,8 @@ def delete_ports_status_for_y_cable(): y_cable_tbl[asic_id] = swsscommon.Table( state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME) y_cable_tbl_keys[asic_id] = y_cable_tbl[asic_id].getKeys() + static_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_STATIC_INFO_TABLE) + mux_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_INFO_TABLE) # delete PORTS on Y cable table if ports on Y cable logical_port_list = y_cable_platform_sfputil.logical @@ -468,6 +492,532 @@ def delete_ports_status_for_y_cable(): if logical_port_name in y_cable_tbl_keys[asic_index]: delete_port_from_y_cable_table( logical_port_name, y_cable_tbl[asic_index]) + delete_port_from_y_cable_table( + logical_port_name, static_tbl[asic_index]) + delete_port_from_y_cable_table( + logical_port_name, mux_tbl[asic_index]) + + +def check_identifier_presence_and_update_mux_info_entry(state_db, mux_tbl, asic_index, logical_port_name): + + # Get the namespaces in the platform + config_db, port_tbl = {}, {} + namespaces = multi_asic.get_front_end_namespaces() + for namespace in namespaces: + asic_id = multi_asic.get_asic_index_from_namespace(namespace) + config_db[asic_id] = daemon_base.db_connect("CONFIG_DB", namespace) + port_tbl[asic_id] = swsscommon.Table(config_db[asic_id], "PORT") + + (status, fvs) = port_tbl[asic_index].get(logical_port_name) + + if status is False: + helper_logger.log_warning( + "Could not retreive fieldvalue pairs for {}, inside config_db".format(logical_port_name)) + return + + else: + # Convert list of tuples to a dictionary + mux_table_dict = dict(fvs) + if "mux_cable" in mux_table_dict: + val = mux_table_dict.get("mux_cable", None) + if val == "true": + + if mux_tbl.get(asic_index, None) is not None: + # fill in the newly found entry + post_port_mux_info_to_db(logical_port_name, mux_tbl[asic_index]) + + else: + # first create the state db y cable table and then fill in the entry + namespaces = multi_asic.get_front_end_namespaces() + for namespace in namespaces: + asic_id = multi_asic.get_asic_index_from_namespace( + namespace) + mux_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_INFO_TABLE) + # fill the newly found entry + post_port_mux_info_to_db(logical_port_name, mux_tbl[asic_index]) + + +def get_firmware_dict(physical_port, target, side, mux_info_dict): + + result = y_cable.get_firmware_version(physical_port, target) + + if result is not None and isinstance(result, dict): + mux_info_dict[("build_slot1_{}".format(side))] = result.get("build_slot1", None) + mux_info_dict[("version_slot1_{}".format(side))] = result.get("version_slot1", None) + mux_info_dict[("build_slot2_{}".format(side))] = result.get("build_slot2", None) + mux_info_dict[("version_slot2_{}".format(side))] = result.get("version_slot2", None) + mux_info_dict[("run_slot1_{}".format(side))] = result.get("run_slot1", None) + mux_info_dict[("run_slot2_{}".format(side))] = result.get("run_slot2", None) + mux_info_dict[("commit_slot1_{}".format(side))] = result.get("commit_slot1", None) + mux_info_dict[("commit_slot2_{}".format(side))] = result.get("commit_slot2", None) + mux_info_dict[("empty_slot1_{}".format(side))] = result.get("empty_slot1", None) + mux_info_dict[("empty_slot2_{}".format(side))] = result.get("empty_slot2", None) + else: + mux_info_dict[("build_slot1_{}".format(side))] = "N/A" + mux_info_dict[("version_slot1_{}".format(side))] = "N/A" + mux_info_dict[("build_slot2_{}".format(side))] = "N/A" + mux_info_dict[("version_slot2_{}".format(side))] = "N/A" + mux_info_dict[("run_slot1_{}".format(side))] = "N/A" + mux_info_dict[("run_slot2_{}".format(side))] = "N/A" + mux_info_dict[("commit_slot1_{}".format(side))] = "N/A" + mux_info_dict[("commit_slot2_{}".format(side))] = "N/A" + mux_info_dict[("empty_slot1_{}".format(side))] = "N/A" + mux_info_dict[("empty_slot2_{}".format(side))] = "N/A" + + +def get_muxcable_info(physical_port, logical_port_name): + + mux_info_dict = {} + y_cable_tbl, state_db = {}, {} + + namespaces = multi_asic.get_front_end_namespaces() + for namespace in namespaces: + asic_id = multi_asic.get_asic_index_from_namespace(namespace) + state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace) + y_cable_tbl[asic_id] = swsscommon.Table( + state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME) + + asic_index = y_cable_platform_sfputil.get_asic_id_for_logical_port( + logical_port_name) + if asic_index is None: + helper_logger.log_warning( + "Got invalid asic index for {}, ignored".format(logical_port_name)) + return -1 + + (status, fvs) = y_cable_tbl[asic_index].get(logical_port_name) + if status is False: + helper_logger.log_warning("Could not retreive fieldvalue pairs for {}, inside state_db table {}".format( + logical_port_name, y_cable_tbl[asic_index])) + return -1 + + mux_port_dict = dict(fvs) + read_side = int(mux_port_dict.get("read_side")) + + active_side = y_cable.check_active_linked_tor_side(physical_port) + + if active_side is None or active_side == y_cable.EEPROM_ERROR: + tor_active = 'unknown' + elif read_side == active_side and (active_side == 1 or active_side == 2): + tor_active = 'active' + elif read_side != active_side and (active_side == 1 or active_side == 2): + tor_active = 'standby' + else: + tor_active = 'unknown' + + mux_info_dict["tor_active"] = tor_active + + mux_dir_val = y_cable.check_mux_direction(physical_port) + if mux_dir_val is None or mux_dir_val == y_cable.EEPROM_ERROR: + mux_direction = 'unknown' + elif read_side == mux_dir_val and (active_side == 1 or active_side == 2): + mux_direction = 'self' + elif read_side != mux_dir_val and (active_side == 1 or active_side == 2): + mux_direction = 'peer' + else: + mux_direction = 'unknown' + + mux_info_dict["mux_direction"] = mux_direction + + manual_switch_cnt = y_cable.get_switch_count(physical_port, y_cable.SWITCH_COUNT_MANUAL) + auto_switch_cnt = y_cable.get_switch_count(physical_port, y_cable.SWITCH_COUNT_AUTO) + + if manual_switch_cnt is not y_cable.EEPROM_ERROR: + mux_info_dict["manual_switch_count"] = manual_switch_cnt + else: + mux_info_dict["manual_switch_count"] = "N/A" + + if auto_switch_cnt is not y_cable.EEPROM_ERROR: + mux_info_dict["auto_switch_count"] = auto_switch_cnt + else: + mux_info_dict["auto_switch_count"] = "N/A" + + lane_active = y_cable.check_if_nic_lanes_active(physical_port) + + if lane_active is not y_cable.EEPROM_ERROR: + if (lane_active & 0x1): + mux_info_dict["nic_lane1_active"] = "True" + else: + mux_info_dict["nic_lane1_active"] = "False" + + if ((lane_active >> 1) & 0x1): + mux_info_dict["nic_lane2_active"] = "True" + else: + mux_info_dict["nic_lane2_active"] = "False" + + if ((lane_active >> 2) & 0x1): + mux_info_dict["nic_lane3_active"] = "True" + else: + mux_info_dict["nic_lane3_active"] = "False" + + if ((lane_active >> 3) & 0x1): + mux_info_dict["nic_lane4_active"] = "True" + else: + mux_info_dict["nic_lane4_active"] = "False" + else: + mux_info_dict["nic_lane1_active"] = "N/A" + mux_info_dict["nic_lane2_active"] = "N/A" + mux_info_dict["nic_lane3_active"] = "N/A" + mux_info_dict["nic_lane4_active"] = "N/A" + + if read_side == 1: + eye_result_self = y_cable.get_eye_info(physical_port, 1) + eye_result_peer = y_cable.get_eye_info(physical_port, 2) + else: + eye_result_self = y_cable.get_eye_info(physical_port, 2) + eye_result_peer = y_cable.get_eye_info(physical_port, 1) + + eye_result_nic = y_cable.get_eye_info(physical_port, 3) + + if eye_result_self is not None and eye_result_self is not y_cable.EEPROM_ERROR and isinstance(eye_result_self, list): + mux_info_dict["self_eye_height_lane1"] = eye_result_self[0] + mux_info_dict["self_eye_height_lane2"] = eye_result_self[1] + else: + mux_info_dict["self_eye_height_lane1"] = "N/A" + mux_info_dict["self_eye_height_lane2"] = "N/A" + + if eye_result_peer is not None and eye_result_peer is not y_cable.EEPROM_ERROR and isinstance(eye_result_peer, list): + mux_info_dict["peer_eye_height_lane1"] = eye_result_peer[0] + mux_info_dict["peer_eye_height_lane2"] = eye_result_peer[1] + else: + mux_info_dict["peer_eye_height_lane1"] = "N/A" + mux_info_dict["peer_eye_height_lane2"] = "N/A" + + if eye_result_nic is not None and eye_result_nic is not y_cable.EEPROM_ERROR and isinstance(eye_result_nic, list): + mux_info_dict["nic_eye_height_lane1"] = eye_result_nic[0] + mux_info_dict["nic_eye_height_lane2"] = eye_result_nic[1] + else: + mux_info_dict["nic_eye_height_lane1"] = "N/A" + mux_info_dict["nic_eye_height_lane2"] = "N/A" + + if read_side == 1: + if y_cable.check_if_link_is_active_for_torA(physical_port): + mux_info_dict["link_status_self"] = "up" + else: + mux_info_dict["link_status_self"] = "down" + if y_cable.check_if_link_is_active_for_torB(physical_port): + mux_info_dict["link_status_peer"] = "up" + else: + mux_info_dict["link_status_peer"] = "down" + else: + if y_cable.check_if_link_is_active_for_torB(physical_port): + mux_info_dict["link_status_self"] = "up" + else: + mux_info_dict["link_status_self"] = "down" + if y_cable.check_if_link_is_active_for_torA(physical_port): + mux_info_dict["link_status_peer"] = "up" + else: + mux_info_dict["link_status_peer"] = "down" + + if y_cable.check_if_link_is_active_for_NIC(physical_port): + mux_info_dict["link_status_nic"] = "up" + else: + mux_info_dict["link_status_nic"] = "down" + + get_firmware_dict(physical_port, 0, "nic", mux_info_dict) + get_firmware_dict(physical_port, 1, "tor1", mux_info_dict) + get_firmware_dict(physical_port, 2, "tor2", mux_info_dict) + + res = y_cable.get_internal_voltage_temp(physical_port) + + if res is not y_cable.EEPROM_ERROR and isinstance(res, tuple): + mux_info_dict["internal_temperature"] = res[0] + mux_info_dict["internal_voltage"] = res[1] + else: + mux_info_dict["internal_temperature"] = "N/A" + mux_info_dict["internal_voltage"] = "N/A" + + res = y_cable.get_nic_voltage_temp(physical_port) + + if res is not y_cable.EEPROM_ERROR and isinstance(res, tuple): + mux_info_dict["nic_temperature"] = res[0] + mux_info_dict["nic_voltage"] = res[1] + else: + mux_info_dict["nic_temperature"] = "N/A" + mux_info_dict["nic_voltage"] = "N/A" + + return mux_info_dict + + +def get_muxcable_static_info(physical_port, logical_port_name): + + mux_static_info_dict = {} + y_cable_tbl, state_db = {}, {} + + namespaces = multi_asic.get_front_end_namespaces() + for namespace in namespaces: + asic_id = multi_asic.get_asic_index_from_namespace(namespace) + state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace) + y_cable_tbl[asic_id] = swsscommon.Table( + state_db[asic_id], swsscommon.STATE_HW_MUX_CABLE_TABLE_NAME) + + asic_index = y_cable_platform_sfputil.get_asic_id_for_logical_port( + logical_port_name) + if asic_index is None: + helper_logger.log_warning( + "Got invalid asic index for {}, ignored".format(logical_port_name)) + return -1 + + (status, fvs) = y_cable_tbl[asic_index].get(logical_port_name) + if status is False: + helper_logger.log_warning("Could not retreive fieldvalue pairs for {}, inside state_db table {}".format( + logical_port_name, y_cable_tbl[asic_index])) + return -1 + mux_port_dict = dict(fvs) + read_side = int(mux_port_dict.get("read_side")) + + if read_side == 1: + mux_static_info_dict["read_side"] = "tor1" + else: + mux_static_info_dict["read_side"] = "tor2" + + dummy_list = ["N/A", "N/A", "N/A", "N/A", "N/A"] + cursor_nic_values = [] + cursor_tor1_values = [] + cursor_tor2_values = [] + for i in range(1, 3): + cursor_values_nic = y_cable.get_target_cursor_values(physical_port, i, y_cable.TARGET_NIC) + if cursor_values_nic is not None and cursor_values_nic is not y_cable.EEPROM_ERROR and isinstance(cursor_values_nic, list): + cursor_nic_values.append(cursor_values_nic) + else: + cursor_nic_values.append(dummy_list) + cursor_values_tor1 = y_cable.get_target_cursor_values(physical_port, i, y_cable.TARGET_TOR1) + if cursor_values_tor1 is not None and cursor_values_tor1 is not y_cable.EEPROM_ERROR and isinstance(cursor_values_tor1, list): + cursor_tor1_values.append(cursor_values_tor1) + else: + cursor_tor1_values.append(dummy_list) + + cursor_values_tor2 = y_cable.get_target_cursor_values(physical_port, i, y_cable.TARGET_TOR2) + if cursor_values_tor2 is not None and cursor_values_tor2 is not y_cable.EEPROM_ERROR and isinstance(cursor_values_tor2, list): + cursor_tor2_values.append(cursor_values_tor2) + else: + cursor_tor2_values.append(dummy_list) + + for i in range(1, 3): + mux_static_info_dict[("nic_lane{}_precursor1".format(i))] = cursor_nic_values[i-1][0] + mux_static_info_dict[("nic_lane{}_precursor2".format(i))] = cursor_nic_values[i-1][1] + mux_static_info_dict[("nic_lane{}_maincursor".format(i))] = cursor_nic_values[i-1][2] + mux_static_info_dict[("nic_lane{}_postcursor1".format(i))] = cursor_nic_values[i-1][3] + mux_static_info_dict[("nic_lane{}_postcursor2".format(i))] = cursor_nic_values[i-1][4] + + if read_side == 1: + for i in range(1, 3): + mux_static_info_dict[("tor_self_lane{}_precursor1".format(i))] = cursor_tor1_values[i-1][0] + mux_static_info_dict[("tor_self_lane{}_precursor2".format(i))] = cursor_tor1_values[i-1][1] + mux_static_info_dict[("tor_self_lane{}_maincursor".format(i))] = cursor_tor1_values[i-1][2] + mux_static_info_dict[("tor_self_lane{}_postcursor1".format(i))] = cursor_tor1_values[i-1][3] + mux_static_info_dict[("tor_self_lane{}_postcursor2".format(i))] = cursor_tor1_values[i-1][4] + + for i in range(1, 3): + mux_static_info_dict[("tor_peer_lane{}_precursor1".format(i))] = cursor_tor2_values[i-1][0] + mux_static_info_dict[("tor_peer_lane{}_precursor2".format(i))] = cursor_tor2_values[i-1][1] + mux_static_info_dict[("tor_peer_lane{}_maincursor".format(i))] = cursor_tor2_values[i-1][2] + mux_static_info_dict[("tor_peer_lane{}_postcursor1".format(i))] = cursor_tor2_values[i-1][3] + mux_static_info_dict[("tor_peer_lane{}_postcursor2".format(i))] = cursor_tor2_values[i-1][4] + else: + for i in range(1, 3): + mux_static_info_dict[("tor_self_lane{}_precursor1".format(i))] = cursor_tor2_values[i-1][0] + mux_static_info_dict[("tor_self_lane{}_precursor2".format(i))] = cursor_tor2_values[i-1][1] + mux_static_info_dict[("tor_self_lane{}_maincursor".format(i))] = cursor_tor2_values[i-1][2] + mux_static_info_dict[("tor_self_lane{}_postcursor1".format(i))] = cursor_tor2_values[i-1][3] + mux_static_info_dict[("tor_self_lane{}_postcursor2".format(i))] = cursor_tor2_values[i-1][4] + + for i in range(1, 3): + mux_static_info_dict[("tor_peer_lane{}_precursor1".format(i))] = cursor_tor1_values[i-1][0] + mux_static_info_dict[("tor_peer_lane{}_precursor2".format(i))] = cursor_tor1_values[i-1][1] + mux_static_info_dict[("tor_peer_lane{}_maincursor".format(i))] = cursor_tor1_values[i-1][2] + mux_static_info_dict[("tor_peer_lane{}_postcursor1".format(i))] = cursor_tor1_values[i-1][3] + mux_static_info_dict[("tor_peer_lane{}_postcursor2".format(i))] = cursor_tor1_values[i-1][4] + + return mux_static_info_dict + + +def post_port_mux_info_to_db(logical_port_name, table): + + physical_port_list = logical_port_name_to_physical_port_list(logical_port_name) + if physical_port_list is None: + helper_logger.log_error("No physical ports found for logical port '{}'".format(logical_port_name)) + return -1 + + if len(physical_port_list) > 1: + helper_logger.log_warning( + "Error: Retreived multiple ports for a Y cable port {}".format(logical_port_name)) + return -1 + + for physical_port in physical_port_list: + + if not _wrapper_get_presence(physical_port): + helper_logger.log_warning( + "Error: trying to post mux info without presence of port {}".format(logical_port_name)) + continue + + mux_info_dict = get_muxcable_info(physical_port, logical_port_name) + if mux_info_dict is not None and mux_info_dict is not -1: + #transceiver_dict[physical_port] = port_info_dict + fvs = swsscommon.FieldValuePairs( + [('tor_active', mux_info_dict["tor_active"]), + ('mux_direction', str(mux_info_dict["mux_direction"])), + ('manual_switch_count', str(mux_info_dict["manual_switch_count"])), + ('auto_switch_count', str(mux_info_dict["auto_switch_count"])), + ('link_status_self', mux_info_dict["link_status_self"]), + ('link_status_peer', mux_info_dict["link_status_peer"]), + ('link_status_nic', mux_info_dict["link_status_nic"]), + ('nic_lane1_active', mux_info_dict["nic_lane1_active"]), + ('nic_lane2_active', mux_info_dict["nic_lane2_active"]), + ('nic_lane3_active', mux_info_dict["nic_lane3_active"]), + ('nic_lane4_active', mux_info_dict["nic_lane4_active"]), + ('self_eye_height_lane1', str(mux_info_dict["self_eye_height_lane1"])), + ('self_eye_height_lane2', str(mux_info_dict["self_eye_height_lane2"])), + ('peer_eye_height_lane1', str(mux_info_dict["peer_eye_height_lane1"])), + ('peer_eye_height_lane2', str(mux_info_dict["peer_eye_height_lane1"])), + ('nic_eye_height_lane1', str(mux_info_dict["nic_eye_height_lane1"])), + ('nic_eye_height_lane2', str(mux_info_dict["nic_eye_height_lane2"])), + ('internal_temperature', str(mux_info_dict["internal_temperature"])), + ('internal_voltage', str(mux_info_dict["internal_voltage"])), + ('nic_temperature', str(mux_info_dict["nic_temperature"])), + ('nic_voltage', str(mux_info_dict["nic_voltage"])), + ('build_slot1_nic', str(mux_info_dict["build_slot1_nic"])), + ('build_slot2_nic', str(mux_info_dict["build_slot2_nic"])), + ('version_slot1_nic', str(mux_info_dict["version_slot1_nic"])), + ('version_slot2_nic', str(mux_info_dict["version_slot2_nic"])), + ('run_slot1_nic', str(mux_info_dict["run_slot1_nic"])), + ('run_slot2_nic', str(mux_info_dict["run_slot2_nic"])), + ('commit_slot1_nic', str(mux_info_dict["commit_slot1_nic"])), + ('commit_slot2_nic', str(mux_info_dict["commit_slot2_nic"])), + ('empty_slot1_nic', str(mux_info_dict["empty_slot1_nic"])), + ('empty_slot2_nic', str(mux_info_dict["empty_slot2_nic"])), + ('build_slot1_tor1', str(mux_info_dict["build_slot1_tor1"])), + ('build_slot2_tor1', str(mux_info_dict["build_slot2_tor1"])), + ('version_slot1_tor1', str(mux_info_dict["version_slot1_tor1"])), + ('version_slot2_tor1', str(mux_info_dict["version_slot2_tor1"])), + ('run_slot1_tor1', str(mux_info_dict["run_slot1_tor1"])), + ('run_slot2_tor1', str(mux_info_dict["run_slot2_tor1"])), + ('commit_slot1_tor1', str(mux_info_dict["commit_slot1_tor1"])), + ('commit_slot2_tor1', str(mux_info_dict["commit_slot2_tor1"])), + ('empty_slot1_tor1', str(mux_info_dict["empty_slot1_tor1"])), + ('empty_slot2_tor1', str(mux_info_dict["empty_slot2_tor1"])), + ('build_slot1_tor2', str(mux_info_dict["build_slot1_tor2"])), + ('build_slot2_tor2', str(mux_info_dict["build_slot2_tor2"])), + ('version_slot1_tor2', str(mux_info_dict["version_slot1_tor2"])), + ('version_slot2_tor2', str(mux_info_dict["version_slot2_tor2"])), + ('run_slot1_tor2', str(mux_info_dict["run_slot1_tor2"])), + ('run_slot2_tor2', str(mux_info_dict["run_slot2_tor2"])), + ('commit_slot1_tor2', str(mux_info_dict["commit_slot1_tor2"])), + ('commit_slot2_tor2', str(mux_info_dict["commit_slot2_tor2"])), + ('empty_slot1_tor2', str(mux_info_dict["empty_slot1_tor2"])), + ('empty_slot2_tor2', str(mux_info_dict["empty_slot2_tor2"])) + ]) + table.set(logical_port_name, fvs) + else: + return -1 + + +def post_port_mux_static_info_to_db(logical_port_name, static_table): + + physical_port_list = logical_port_name_to_physical_port_list(logical_port_name) + if physical_port_list is None: + helper_logger.log_error("No physical ports found for logical port '{}'".format(logical_port_name)) + return -1 + + if len(physical_port_list) > 1: + helper_logger.log_warning( + "Error: Retreived multiple ports for a Y cable port {}".format(logical_port_name)) + return -1 + + for physical_port in physical_port_list: + + if not _wrapper_get_presence(physical_port): + continue + + mux_static_info_dict = get_muxcable_static_info(physical_port, logical_port_name) + + if mux_static_info_dict is not None and mux_static_info_dict is not -1: + #transceiver_dict[physical_port] = port_info_dict + fvs = swsscommon.FieldValuePairs( + [('read_side', mux_static_info_dict["read_side"]), + ('nic_lane1_precursor1', str(mux_static_info_dict["nic_lane1_precursor1"])), + ('nic_lane1_precursor2', str(mux_static_info_dict["nic_lane1_precursor2"])), + ('nic_lane1_maincursor', str(mux_static_info_dict["nic_lane1_maincursor"])), + ('nic_lane1_postcursor1', str(mux_static_info_dict["nic_lane1_postcursor1"])), + ('nic_lane1_postcursor2', str(mux_static_info_dict["nic_lane1_postcursor2"])), + ('nic_lane2_precursor1', str(mux_static_info_dict["nic_lane2_precursor1"])), + ('nic_lane2_precursor2', str(mux_static_info_dict["nic_lane2_precursor2"])), + ('nic_lane2_maincursor', str(mux_static_info_dict["nic_lane2_maincursor"])), + ('nic_lane2_postcursor1', str(mux_static_info_dict["nic_lane2_postcursor1"])), + ('nic_lane2_postcursor2', str(mux_static_info_dict["nic_lane2_postcursor2"])), + ('tor_self_lane1_precursor1', str(mux_static_info_dict["tor_self_lane1_precursor1"])), + ('tor_self_lane1_precursor2', str(mux_static_info_dict["tor_self_lane1_precursor2"])), + ('tor_self_lane1_maincursor', str(mux_static_info_dict["tor_self_lane1_maincursor"])), + ('tor_self_lane1_postcursor1', str(mux_static_info_dict["tor_self_lane1_postcursor1"])), + ('tor_self_lane1_postcursor2', str(mux_static_info_dict["tor_self_lane1_postcursor2"])), + ('tor_self_lane2_precursor1', str(mux_static_info_dict["tor_self_lane2_precursor1"])), + ('tor_self_lane2_precursor2', str(mux_static_info_dict["tor_self_lane2_precursor2"])), + ('tor_self_lane2_maincursor', str(mux_static_info_dict["tor_self_lane2_maincursor"])), + ('tor_self_lane2_postcursor1', str(mux_static_info_dict["tor_self_lane2_postcursor1"])), + ('tor_self_lane2_postcursor2', str(mux_static_info_dict["tor_self_lane2_postcursor2"])), + ('tor_peer_lane1_precursor1', str(mux_static_info_dict["tor_peer_lane1_precursor1"])), + ('tor_peer_lane1_precursor2', str(mux_static_info_dict["tor_peer_lane1_precursor2"])), + ('tor_peer_lane1_maincursor', str(mux_static_info_dict["tor_peer_lane1_maincursor"])), + ('tor_peer_lane1_postcursor1', str(mux_static_info_dict["tor_peer_lane1_postcursor1"])), + ('tor_peer_lane1_postcursor2', str(mux_static_info_dict["tor_peer_lane1_postcursor2"])), + ('tor_peer_lane2_precursor1', str(mux_static_info_dict["tor_peer_lane2_precursor1"])), + ('tor_peer_lane2_precursor2', str(mux_static_info_dict["tor_peer_lane2_precursor2"])), + ('tor_peer_lane2_maincursor', str(mux_static_info_dict["tor_peer_lane2_maincursor"])), + ('tor_peer_lane2_postcursor1', str(mux_static_info_dict["tor_peer_lane2_postcursor1"])), + ('tor_peer_lane2_postcursor2', str(mux_static_info_dict["tor_peer_lane2_postcursor2"])) + ]) + static_table.set(logical_port_name, fvs) + else: + return -1 + + +def post_mux_static_info_to_db(is_warm_start, stop_event=threading.Event()): + # Connect to STATE_DB and create transceiver mux/static info tables + state_db, static_tbl = {}, {} + + # Get the namespaces in the platform + namespaces = multi_asic.get_front_end_namespaces() + for namespace in namespaces: + asic_id = multi_asic.get_asic_index_from_namespace(namespace) + state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace) + static_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_STATIC_INFO_TABLE) + + # Post all the current interface dom/sfp info to STATE_DB + logical_port_list = y_cable_platform_sfputil.logical + for logical_port_name in logical_port_list: + if stop_event.is_set(): + break + + # Get the asic to which this port belongs + asic_index = y_cable_platform_sfputil.get_asic_id_for_logical_port(logical_port_name) + if asic_index is None: + logger.log_warning("Got invalid asic index for {}, ignored".format(logical_port_name)) + continue + post_port_mux_static_info_to_db(logical_port_name, mux_tbl[asic_index]) + + +def post_mux_info_to_db(is_warm_start, stop_event=threading.Event()): + # Connect to STATE_DB and create transceiver mux/static info tables + state_db, mux_tbl, static_tbl = {}, {}, {} + + # Get the namespaces in the platform + namespaces = multi_asic.get_front_end_namespaces() + for namespace in namespaces: + asic_id = multi_asic.get_asic_index_from_namespace(namespace) + state_db[asic_id] = daemon_base.db_connect("STATE_DB", namespace) + mux_tbl[asic_id] = swsscommon.Table(state_db[asic_id], MUX_CABLE_INFO_TABLE) + + # Post all the current interface dom/sfp info to STATE_DB + logical_port_list = y_cable_platform_sfputil.logical + for logical_port_name in logical_port_list: + if stop_event.is_set(): + break + + # Get the asic to which this port belongs + asic_index = y_cable_platform_sfputil.get_asic_id_for_logical_port(logical_port_name) + if asic_index is None: + logger.log_warning("Got invalid asic index for {}, ignored".format(logical_port_name)) + continue + post_port_mux_info_to_db(logical_port_name, mux_tbl[asic_index]) # Thread wrapper class to update y_cable status periodically @@ -511,6 +1061,12 @@ def task_worker(self): while True: # Use timeout to prevent ignoring the signals we want to handle # in signal_handler() (e.g. SIGTERM for graceful shutdown) + + # A brief sleep appears necessary in this loop or any spawned + # update threads will get stuck. Appears to be due to the sel.select() call. + # TODO: Eliminate the need for this sleep. + time.sleep(0.1) + (state, selectableObj) = sel.select(SELECT_TIMEOUT) if state == swsscommon.Select.TIMEOUT: