diff --git a/sonic_y_cable/broadcom/y_cable_broadcom.py b/sonic_y_cable/broadcom/y_cable_broadcom.py index 57b2d4714..43a2d0edd 100644 --- a/sonic_y_cable/broadcom/y_cable_broadcom.py +++ b/sonic_y_cable/broadcom/y_cable_broadcom.py @@ -13,12 +13,16 @@ import array import math import os + import re + import string import threading + import shelve from ctypes import c_int16 from datetime import datetime from contextlib import contextmanager #import chassis + import platform #from chassis import chassis import sonic_platform.platform #from sonic_py_common import logger @@ -34,6 +38,11 @@ # strut definitions used in fw related functions +class func_name_args(): + def __init__(self, length, name, desc): + self.arg_len = length + self.func = name + self.description = desc class cable_image_version_s(object): @@ -141,6 +150,73 @@ def __init__(self): self.exp_stack = array.array('I', []) + +class cable_mcu_event_log_s(object): + + def __init__(self): + self.event_type = None + self.timestamp = 0 + self.run_no = 0 + self.event_source = 0 + +class cable_phy_chip_event_log_s(object): + + def __init__(self): + self.in_fault = None + self.out_fault = None + self.timestamp = 0 + self.run_no = 0 + + +class pcsfec_dump_status_short_s(object): + + def __init__(self): + self.fec_type = 0 + self.func_mode = 0 + self.pcs_sts = pcsrx_status_short_s() # PCS Rx status for port based on fec_type/direction/func_mode + self.fec_sts = fecrx_status_short_s() # FEC Rx status for port based on fec_type/direction/func_mode + self.no_clr_on_rd = 0 + +class fecrx_status_short_s(object): + + def __init__(self): + self.am_lolock_sticky = 0 + self.dgbox_clsn_sticky = 0 + self.hi_ser_sticky = 0 + self.xdec_err_sticky = 0 + self.fec_link_stat = 0 + self.fec_link_stat_sticky = 0 + self.tot_frame_rev_cnt = 0 + self.tot_frame_corr_cnt = 0 + self.tot_frame_uncorr_cnt = 0 + self.tot_symbols_corr_cnt = 0 + self.tot_bits_corr_cnt = [] + self.tot_frames_err_cnt = [] + + +class pcsrx_status_short_s(object): + + def __init__(self): + self.pcs_status_phylane = [] + self.pcs_dskw_align_stat = 0 + self.pcs_dskw_align_loss_sticky = 0 + self.pcs_hiber_stat = 0 + self.pcs_hiber_sticky = 0 + self.pcs_ber_cnt = 0 + self.pcs_link_stat = 0 + self.pcs_link_stat_sticky = 0 + +class pcsrx_status_phylane_short_s(object): + + def __init__(self): + self.pcs_block_lock_stat = 0 + self.pcs_block_lolock_sticky = 0 + self.pcs_am_lock_stat = 0 + self.pcs_am_lolock_sticky = 0 + self.pcs_dskw_error_sticky = 0 + self.pcs_bip_err_cnt = [] + + ENABLE_DBG_PRINT = False @@ -204,6 +280,33 @@ def release(self): class YCable(YCableBase): + + CAPI_FEC_TYPE_PCS = 0 + FEC_TOT_FRAMES_ERR_NUM_SHORT = 8 + port_func_mode_description = [ + "", + "MILLENIO_CAPI_MODE_400", + "MILLENIO_CAPI_MODE_200", + "MILLENIO_CAPI_MODE_100", + "MILLENIO_CAPI_MODE_50G", + "MILLENIO_CAPI_MODE_40G", + "MILLENIO_CAPI_MODE_25G", + "MILLENIO_CAPI_MODE_10G", + "MILLENIO_CAPI_MODE_1G "] + + port_fec_type_description = [ + "MILLENIO_CAPI_FEC_TYPE_PCS", + "MILLENIO_CAPI_FEC_TYPE_FC_FEC", + "MILLENIO_CAPI_FEC_TYPE_RS528", + "MILLENIO_CAPI_FEC_TYPE_RS544", + "INVALID_FEC", + "MILLENIO_CAPI_FEC_TYPE_NA"] + + + CAPI_MODE_NONE = 0 #**< No suitable func mode */ + CAPI_MODE_100G = 3 #**< 100G mode */ + CAPI_MODE_50G = 4 #**< 50G mode */ + WARMBOOT = 0 COLDBOOT = 1 @@ -216,7 +319,7 @@ class YCable(YCableBase): PRBS_DIRECTION_GENERATOR = 1 PRBS_DIRECTION_CHECKER = 2 - BCM_API_VERSION = "1.3" + BCM_API_VERSION = "2.0" CONSOLE_PRINT = False # Log levels @@ -247,13 +350,25 @@ class YCable(YCableBase): PORT_LOCK_TIMEOUT = 30 # in seconds + # Rollback states + PERFORM_ROLLBACK = 1 + ALREADY_ROLLED_BACK = 2 + CANNOT_ROLLBACK = 3 + + # Activate states + PERFORM_ACTIVATE = 1 + ALREADY_ACTIVATED = 2 + CANNOT_ACTIVATE = 3 + # Register absolute addresses QSFP28_LP_3_TX_RX_LOSS = 0x00000003 QSFP28_LP_5_TX_RX_CDR_LOL = 0x00000005 + QSFP28_LP_6_TEMP_WARN = 0x00000006 QSFP28_LOS_LOL_SEC = 0x0000004A QSFP28_LINK_DOWN = 0x0000004B QSFP28_LINK_FAULT = 0x0000004C QSFP28_MESC_FAULT = 0x0000004D + QSFP28_INSERT_ERR_FAULT = 0x0000004F QSFP28_BIP_CW_ERR_FAULT = 0x00000050 QSFP28_LP_22_TEMP_MSB = 0x00000016 QSFP_SQL_STATUS = 0x0000004E @@ -267,6 +382,8 @@ class YCable(YCableBase): QSFP28_BIP_UNCORR_MASK = 0x00007F65 QSFP28_UP0_148_VENDOR_NAME_0 = 0x00000094 QSFP28_UP0_168_PN_1 = 0x000000a8 + QSFP28_UP0_168_SN_1 = 0x000000c4 + QSFP28_UP0_DATE_CODE = 0x000000d4 QSFP28_UP0_224_SPECIFIC_1_RSV = 0x000000e0 QSFP_BRCM_CABLE_CMD = 0x00000013 QSFP_BRCM_CABLE_CTRL_CMD_STS = 0x00000014 @@ -346,6 +463,14 @@ class YCable(YCableBase): CABLE_CMD_ID_GET_TO_TORB_AUT_SWT_CNT_CLR = 0x32 CABLE_CMD_ID_READ_MCU_RAM = 0x33 CABLE_CMD_ID_CLEAR_CRASH = 0x34 + CABLE_CMD_GET_PHY_CHIP_EVENT_LOG = 0x35 + CABLE_CMD_GET_MCU_EVENT_LOG = 0x36 + CABLE_CMD_SET_PHY_CHIP_DEBUG_MODE = 0x37 + CABLE_CMD_GET_PHY_CHIP_DEBUG_MODE = 0x38 + CABLE_CMD_GET_PCSFEC_STATS = 0x39 + CABLE_CMD_ENABLE_WATCHDOG = 0x40 + CABLE_CMD_DISABLE_WATCHDOG = 0x41 + # Download commands FW_CMD_START = 1 @@ -361,6 +486,8 @@ class YCable(YCableBase): FW_CMD_WARM_BOOT = 13 FW_CMD_BOOT_STATUS = 14 + FW_CMD_BL_WR_UNPR = 15 + FW_CMD_BL_WR_PR = 16 # destination values TOR_MCU = 0x01 @@ -395,13 +522,17 @@ class YCable(YCableBase): QSFP_BRCM_FW_UPGRADE_HEADER_24_31 = 0x85 QSFP_BRCM_FW_UPGRADE_BOOT_STATUS = 0x9A + # Bootloader + QSFP_BRCM_FW_UPGRADE_BL_SUPPORT_0_7 = 0xAD + # The Qsfp page for broadcom firmware version support QSFP_BRCM_FW_VERSION_PAGE = 0x83 QSFP_BRCM_FW_VERSION_CTRL_CMD = 0x80 - QSFP_BRCM_FW_VERSION_CMD_STS = 0x81 + QSFP_BRCM_FW_VERSION_CMD_STS = 0x81 QSFP_BRCM_FW_VERSION_HEADER_24_31 = 0x85 QSFP_BRCM_FW_VERSION_CURRENT_BANK = 0x86 + # muxchip return codes RR_ERROR = -1 # -255 # Error Category RR_ERROR_SYSTEM_UNAVAILABLE = -250 # System Unavailable Error @@ -479,14 +610,65 @@ class YCable(YCableBase): CMD_REG_DUMP = "reg_dump" CMD_INTR_STATUS = "intr_status" + NIC_NO_SIG_DETECT_LANE0 = 0x1 + NIC_NO_SIG_DETECT_LANE1 = 0x2 + NIC_NO_SIG_DETECT_LANE2 = 0x4 + NIC_NO_SIG_DETECT_LANE3 = 0x8 + TORA_NO_SIG_DETECT_LANE0 = 0x10 + TORA_NO_SIG_DETECT_LANE1 = 0x20 + TORA_NO_SIG_DETECT_LANE2 = 0x40 + TORA_NO_SIG_DETECT_LANE3 = 0x80 + + NIC_CDR_LOCK_LOSS_LANE0 = 0x1 + NIC_CDR_LOCK_LOSS_LANE1 = 0x2 + NIC_CDR_LOCK_LOSS_LANE2 = 0x4 + NIC_CDR_LOCK_LOSS_LANE3 = 0x8 + TORA_CDR_LOCK_LOSS_LANE0 = 0x10 + TORA_CDR_LOCK_LOSS_LANE1 = 0x20 + TORA_CDR_LOCK_LOSS_LANE2 = 0x40 + TORA_CDR_LOCK_LOSS_LANE3 = 0x80 + + TORB_CDR_LOCK_LOSS_LANE0 = 0x1 + TORB_CDR_LOCK_LOSS_LANE1 = 0x2 + TORB_CDR_LOCK_LOSS_LANE2 = 0x4 + TORB_CDR_LOCK_LOSS_LANE3 = 0x8 + TORB_NO_SIG_DETECT_LANE0 = 0x10 + TORB_NO_SIG_DETECT_LANE1 = 0x20 + TORB_NO_SIG_DETECT_LANE2 = 0x40 + TORB_NO_SIG_DETECT_LANE3 = 0x80 + + PHY_CHIP_WATCHDOG = 0x1 + PHY_CHIP_MEM_SINGLE_BIT_ERROR = 0x2 + PHY_CHIP_MEM_DUAL_BIT_ERROR = 0x4 + TORA_CRASH = 0x8 + TORB_CRASH = 0x10 + NIC_CRASH = 0x20 + AVS_FAILURE = 0x40 + MUX_DIRECTION_CHANGE = 0x80 + + TORA_SOUTHBOUND_FECPCS_LINK_DOWN = 0x1 + TORB_SOUTHBOUND_FECPCS_LINK_DOWN = 0x2 + ACTIVE_SOUTHBOUND_TOR_LINK_FAULT = 0x4 + TORA_NORTHBOUND_LINK_FAULT = 0x8 + TORB_NORTHBOUND_LINK_FAULT = 0x10 + TORA_BIP_UNCORRECTABLE = 0x20 + TORB_BIP_UNCORRECTABLE = 0x40 + + LEN_OF_SET_CURSOR_VALUES = 7 + def __init__(self, port, logger1): self.port = port self.platform_chassis = None + self.debug_dump_list = {} self.sfp = None self.lock = PortLock(port) self.fp_lock = PortLock(port) self.dl_lock = PortLock(port) + self.ev_lock = PortLock(port) + + # add functions for CLI execution + self.init_cli_functions() self.logger = logger1 self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_NOT_INITIATED_OR_FINISHED super(YCable, self).__init__(port, logger1) @@ -499,6 +681,122 @@ def __init__(self, port, logger1): except Exception as e: logger1.log_warning("Failed to load chassis due to {}".format(repr(e))) + def init_cli_functions(self): + self.debug_dump_list["reg_dump"] = func_name_args(0, "reg_dump", "It will dump all registers with meaningful values, Function has no arguments") + self.debug_dump_list["intr_status"] = func_name_args(0, "cable_get_intr_status", "It will read cable interrupt status, Function has no arguments") + + ## TXFIR cmds + self.debug_dump_list["set_target_cursor_values"] = func_name_args(3, "set_target_cursor_values", "Function sets the target cursor values, ARG_1. lane_mask, ARG_2. cursor_values_list, ARG_3.target") + self.debug_dump_list["get_target_cursor_values"] = func_name_args(2, "get_target_cursor_values", "Function reads the cable target cursor values, ARG_1. lane_mask, ARG_2.target") + + ## LINK ACTIVE + self.debug_dump_list["is_link_active"] = func_name_args(1, "is_link_active", "Function checks if NIC, TOR_A and TOR_B of the Y cable's link is active, ARG_1. target") + + ## TOGGLE + self.debug_dump_list["toggle_mux_to_tora"] = func_name_args(0, "toggle_mux_to_tor_a", "does a hard switch toggle of the Y cable's MUX regardless of link state to TOR A on the port this is called for, Function has no arguments") + self.debug_dump_list["toggle_mux_to_torb"] = func_name_args(0, "toggle_mux_to_tor_b", "does a hard switch toggle of the Y cable's MUX regardless of link state to TOR B on the port this is called for, Function has no arguments") + + self.debug_dump_list["get_active_linked_tor_side"] = func_name_args(0, "get_active_linked_tor_side", "checks which side of the Y cable is actively linked and sending traffic and returns either TOR A or TOR B, Function has no arguments") + + self.debug_dump_list["mux_direction"] = func_name_args(0, "get_mux_direction", "checks which side of the Y cable mux is currently point to and returns either TOR A or TOR B, Function has no arguments") + self.debug_dump_list["read_side"] = func_name_args(0, "get_read_side", "checks which side of the Y cable the reads are actually getting performed from, Function has no arguments") + + ## SQUELCH + self.debug_dump_list["set_squelch"] = func_name_args(4, "cable_set_squelch", "checks which side of the Y cable the reads are actually getting performed from, Function has 4 arguments 1.target, 2.lane_map, 3.enable, 4.direction") + self.debug_dump_list["get_squelch"] = func_name_args(0, "cable_get_squelch", "specifically returns the Rx squelch and Tx squelch status on TOR and NIC, Function has no arguments") + + ## PRBS + self.debug_dump_list["enable_prbs"] = func_name_args(3, "enable_prbs_mode", "configures and enables the PRBS mode/type depending upon the mode_value the user provides, Function has 3 arguments 1.target, 2.mode_value, 3.lane_mask, 4.direction=PRBS_DIRECTION_BOTH") + self.debug_dump_list["disable_prbs"] = func_name_args(1, "disable_prbs_mode", "configures and disables the PRBS mode/type depending upon the mode_value the user provides, Function has 1 arguments 1.target, 2.direction=PRBS_DIRECTION_BOTH") + self.debug_dump_list["check_prbs"] = func_name_args(3, "cable_check_prbs", "specifically provides PRBS lock status and error count for the given prbs_type, lane_mask and target side, Function has 1 arguments 1.target, 2.mode_value, 3.lane_mask") + + ## MODE + self.debug_dump_list["set_mode"] = func_name_args(1, "cable_set_mode", "specifically set the cable mode on the port user provides, Function has 1 argument 1.cable_mode") + self.debug_dump_list["get_mode"] = func_name_args(0, "cable_get_mode", "specifically set the cable mode on the port user provides, Function has no arguments") + self.debug_dump_list["set_fec_mode"] = func_name_args(1, "set_fec_mode", "specifically set the cable mode on the port user provides, Function has 1 arguments 1. fec_mode") + self.debug_dump_list["get_fec_mode"] = func_name_args(0, "get_fec_mode", "specifically get the cable mode on the port user provides, Function has no arguments") + + ## SWITCHING MODE + self.debug_dump_list["get_switching_mode"] = func_name_args(0, "get_switching_mode", "returns which type of switching mode the cable is set to auto/manual, Function has no arguments") + self.debug_dump_list["set_switching_mode"] = func_name_args(1, "set_switching_mode", "enables the auto switching or manual switching feature on the Y-Cable, Function has 1 arguments 1.mode") + + ## LOOPBACK + self.debug_dump_list["enable_loopback"] = func_name_args(3, "enable_loopback_mode", "configures and enables the Loopback mode on the port user provides, Function has 3 arguments 1.target 2.lane_map 3.mode ") + self.debug_dump_list["disable_loopback"] = func_name_args(1, "disable_loopback_mode", "disables the Loopback mode on the port user provides, Function has 1 argument 1.target") + self.debug_dump_list["get_loopback"] = func_name_args(1, "get_loopback_mode", "returns the Loopback mode on the port which it has been configured, Function has 1 argument 1.target") + + ## ANLT + self.debug_dump_list["set_anlt"] = func_name_args(2, "set_anlt", "enables/disables the cable auto-negotiation + link training (AN/LT), Function has 2 arguments 1.enable 2.target") + self.debug_dump_list["get_anlt"] = func_name_args(1, "get_anlt", "enables/disables the cable auto-negotiation + link training (AN/LT), Function has 2 arguments 1.target") + self.debug_dump_list["get_anlt_stats"] = func_name_args(1, "get_anlt_stats", "returns auto-negotiation + link training (AN/LT) mode statistics, Function has 1 arguments 1.target") + self.debug_dump_list["restart_anlt"] = func_name_args(1, "restart_anlt", "restarts auto-negotiation + link training (AN/LT) mode, Function has 1 arguments 1.target") + + ## SWITCH COUNT + self.debug_dump_list["switch_count_total"] = func_name_args(2, "get_switch_count_total", "returns the total switch count to change the Active TOR which has been done manually/automatic by the user, Function has 3 arguments 1.switch_count_type 2.clear_on_read") + self.debug_dump_list["switch_count_tor_a"] = func_name_args(1, "get_switch_count_tor_a", "returns the switch count to change the Active TOR which has been done manually by the user initiated from ToR A, Function has 1 arguments 1.clear_on_read") + self.debug_dump_list["switch_count_tor_b"] = func_name_args(1, "get_switch_count_tor_b", "returns the switch count to change the Active TOR which has been done manually by the user initiated from ToR A, Function has 1 arguments 1.clear_on_read") + self.debug_dump_list["switch_count_target"] = func_name_args(3, "get_switch_count_target", "returns the total number of times the Active TOR has been done manually/automaticlly toggled towards a target, Function has 3 arguments 1.switch_count_type, 2.target, 3.clear_on_read") + + ## LOCAL VLOLATAGE and TEMP + self.debug_dump_list["local_voltage"] = func_name_args(0, "get_local_voltage", "returns local ToR voltage of the physical port for which this API is called, Function has no arguments") + self.debug_dump_list["local_temperature"] = func_name_args(0, "get_local_temperature", "returns local ToR temperature of the physical port for which this API is called, Function has no arguments") + self.debug_dump_list["nic_temperature"] = func_name_args(0, "get_nic_temperature", "returns nic temperature of the physical port for which this API is called, Function has no arguments") + + ## Read / Write Register + self.debug_dump_list["read_register"] = func_name_args(2, "rd_reg_ex", "specifically used to read the register values, Function has 2 arguments 1. reg_addr, 2. lane_map ") + self.debug_dump_list["write_register"] = func_name_args(3, "wr_reg_ex", "specifically used to write the register values, Function has 3 arguments 1. reg_addr, 2. reg_value, 3. lane_map ") + + ## reset + self.debug_dump_list["reset_nic"] = func_name_args(1, "reset", "resets the MCU to which this API is called for, Function has 1 arguments 1. target ") + self.debug_dump_list["reset_tora"] = func_name_args(1, "reset", "resets the MCU to which this API is called for, Function has 1 arguments 1. target ") + self.debug_dump_list["reset_torb"] = func_name_args(1, "reset", "resets the MCU to which this API is called for, Function has 1 arguments 1. target ") + + ## ALIVE STATUS + self.debug_dump_list["alive_status"] = func_name_args(0, "get_alive_status", "checks if cable is connected to all the ports and is healthy, Function has no arguments ") + + ## EYE_HEIGHTS + self.debug_dump_list["eye_heights"] = func_name_args(1, "get_eye_heights", "returns the EYE height value for a specfic port, Function has 1 argument 1. target ") + self.debug_dump_list["internal_eye_heights"] = func_name_args(1, "internal_get_eye_heights", "returns the EYE height value for a specfic port, Functionn has 1 argument 1.target") + + self.debug_dump_list["get_snr"] = func_name_args(0, "cable_get_snr", "returns the SNR value, Function has no arguments ") + self.debug_dump_list["ber_info"] = func_name_args(1, "get_ber_info", "returns the BER (Bit error rate) value for a specfic port, Function has 1 arguments 1. target ") + self.debug_dump_list["get_speed"] = func_name_args(0, "get_speed", "gets the mode of the cable for corresponding lane configuration, Function has no arguments ") + + ## AUTOSWITCH HYSTERESIS + self.debug_dump_list["set_hysteresis_timer"] = func_name_args(1, "set_autoswitch_hysteresis_timer", "sets the hysteresis timer of the cable. the time in auto-switch mode which the mux has to wait after toggling it once, before again toggling the mux to a different ToR, Function has 1 arguments 1. timer ") + self.debug_dump_list["get_hysteresis_timer"] = func_name_args(0, "get_autoswitch_hysteresis_timer", "gets the hysteresis timer of the cable, Function has no arguments ") + + ## SET/GET INTR STATUS + self.debug_dump_list["set_intr_mask"] = func_name_args(1, "cable_set_intr_mask", "sets the Lane interupt mask,Chip interupt mask and Port interupt mask on torA, torB and NIC. Function has 1 arguments 1. intr_mask") + self.debug_dump_list["get_intr_mask"] = func_name_args(0, "cable_get_intr_mask", "gets the Lane interupt mask,Chip interupt mask and Port interupt mask on torA, torB and NIC. Function has no arguments ") + + ## intr active status + self.debug_dump_list["intr_active_status"] = func_name_args(0, "cable_check_intr_active_status", "gets the active interupt mask, Functionn has no arguments ") + + self.debug_dump_list["create_port"] = func_name_args(5, "create_port", "sets the mode of the cable/port for corresponding lane/fec etc. configuration as specified, Functionn has 5 arguments 1.speed, 2.fec_mode_tor=FEC_MODE_NONE, 3.fec_mode_nic=FEC_MODE_NONE, 4.anlt_tor=False, 5.anlt_nic=False ") + + ## SET / GET DEBUG MODE + self.debug_dump_list["set_debug"] = func_name_args(1, "set_debug_mode", "enables/disables a debug mode that the port is now, Functionn has 1 arguments 1.debug_mode ") + self.debug_dump_list["get_debug"] = func_name_args(0, "get_debug_mode", "enables/disables a debug mode that the port is now, Functionn has no arguments") + self.debug_dump_list["event_log"] = func_name_args(0, "get_event_log", "returns the event log of the cable, Functionn has no arguments") + + ## PHY CHIP + self.debug_dump_list["enadis_phy_chip_idle_loop"] = func_name_args(1, "cable_set_enadis_phy_chip_idle_loop", "cable_set_enadis_phy_chip_idle_loop, Functionn has 1 argument 1.disable") + + ## WATCHDOG + self.debug_dump_list["watchdog_self"] = func_name_args(1, "enable_disable_watchdog_tor", "enable or disable the watchdog tor self, Functionn has 1 argument 1.disable") + self.debug_dump_list["watchdog_peer"] = func_name_args(1, "enable_disable_watchdog_peer_tor", "enable or disable the watchdog tor peer, Functionn has 1 argument 1.disable") + self.debug_dump_list["watchdog_nic"] = func_name_args(1, "cable_enable_disable_watchdog_nic", "enable or disable the watchdog nic, Functionn has 1 argument 1.disable") + + self.debug_dump_list["util_print_ctx_debug"] = func_name_args(0, "util_print_ctx_debug", "print, Functionn has no argument") + + ## CRASH DUMP + self.debug_dump_list["nic_mcu_dump"] = func_name_args(0, "cable_print_nic_mcu_dump", "gets the nic crash, Functionn has no argument") + self.debug_dump_list["clear_nic_mcu_dump"] = func_name_args(0, "cable_clear_nic_mcu_dump", "clears the nic crash, Functionn has no argument") + self.debug_dump_list["tor_mcu_dump"] = func_name_args(0, "cable_print_tor_mcu_dump", "gets the tor crash, Functionn has no argument") + self.debug_dump_list["clear_tor_mcu_dump"] = func_name_args(0, "cable_clear_tor_mcu_dump", "clears the tor crash, Functionn has no argument") + + ############################################################################################# ### Broadcom internal/debug/utility functions ### ############################################################################################# @@ -573,6 +871,8 @@ def __util_convert_to_phyinfo_details(self, target, lane_map): if read_side == 1: is_torA = True + elif read_side == 0 and target == self.EYE_PRBS_LOOPBACK_TARGET_LOCAL: + core_ip = self.CORE_IP_NIC if (target == self.EYE_PRBS_LOOPBACK_TARGET_LOCAL): target = read_side @@ -581,7 +881,8 @@ def __util_convert_to_phyinfo_details(self, target, lane_map): if (target == self.TARGET_TOR_B or target == self.EYE_PRBS_LOOPBACK_TARGET_TOR_B) and read_side == self.TARGET_TOR_A: is_torA = False # if check is on TOR-A and read side is TOR-B, make is_torA False - elif (target == self.TARGET_TOR_A or target == self.EYE_PRBS_LOOPBACK_TARGET_TOR_A) and read_side == self.TARGET_TOR_B: + elif (((target == self.TARGET_TOR_A or target == self.EYE_PRBS_LOOPBACK_TARGET_TOR_A) and read_side == self.TARGET_TOR_B) or + ((target == self.TARGET_TOR_A or target == self.EYE_PRBS_LOOPBACK_TARGET_TOR_A) and read_side == self.TARGET_NIC)): is_torA = True #lane_mask = lane_map @@ -620,6 +921,8 @@ def __util_convert_to_loopback_phyinfo(self, target, lane_map, lb_mode): if read_side == self.TARGET_TOR_A: is_torA = True + elif read_side == 0 and target == self.EYE_PRBS_LOOPBACK_TARGET_LOCAL: + core_ip = self.CORE_IP_NIC if (target == self.EYE_PRBS_LOOPBACK_TARGET_LOCAL): target = read_side @@ -628,7 +931,8 @@ def __util_convert_to_loopback_phyinfo(self, target, lane_map, lb_mode): if (target == self.TARGET_TOR_B or target == self.EYE_PRBS_LOOPBACK_TARGET_TOR_B) and read_side == self.TARGET_TOR_A: is_torA = False # if target is TOR-A but read_side is TOR-B, make is_torA True - elif (target == self.TARGET_TOR_A or target == self.EYE_PRBS_LOOPBACK_TARGET_TOR_A) and read_side == self.TARGET_TOR_B: + elif (((target == self.TARGET_TOR_A or target == self.EYE_PRBS_LOOPBACK_TARGET_TOR_A) and read_side == self.TARGET_TOR_B) or + ((target == self.TARGET_TOR_A or target == self.EYE_PRBS_LOOPBACK_TARGET_TOR_A) and read_side == self.TARGET_NIC)): is_torA = True #lane_mask = lane_map @@ -641,6 +945,7 @@ def __util_convert_to_loopback_phyinfo(self, target, lane_map, lb_mode): mode = self.CABLE_NIC_RLOOPBACK_MODE else: self.log(self.LOG_ERROR, "Incorrect mode value") + return self.ERROR_INVALID_INPUT else: if is_torA is False: @@ -651,6 +956,7 @@ def __util_convert_to_loopback_phyinfo(self, target, lane_map, lb_mode): mode = self.CABLE_TOR_RLOOPBACK_MODE else: self.log(self.LOG_ERROR, "Incorrect mode value") + return self.ERROR_INVALID_INPUT else: lane_mask = lane_map if lb_mode == self.LOOPBACK_MODE_FAR_END: @@ -659,6 +965,7 @@ def __util_convert_to_loopback_phyinfo(self, target, lane_map, lb_mode): mode = self.CABLE_TOR_RLOOPBACK_MODE else: self.log(self.LOG_ERROR, "Incorrect mode value") + return self.ERROR_INVALID_INPUT if core_ip == self.CORE_IP_TOR: core_ip = self.CORE_IP_CLIENT @@ -753,8 +1060,7 @@ def __cable_cmd_execute(self, command_id, cmd_hdr, cmd_req_body): # skip sending cmd_hdr for SET_HMUX_CONTEXT_PRI and SET_HMUX_CONTEXT_SEC if ((command_id < self.CABLE_CMD_ID_SET_HMUX_CONTEXT_PRI) or - (command_id == self.CABLE_CMD_ID_READ_MCU_RAM) or - (command_id == self.CABLE_CMD_ID_CLEAR_CRASH)): + (command_id >= self.CABLE_CMD_ID_READ_MCU_RAM)): curr_offset = self.QSFP_VEN_FE_130_BRCM_DATA_LENGHT_LSB result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 5, cmd_hdr) if result is False: @@ -932,6 +1238,58 @@ def get_part_number(self): return part_number + def get_serial_number(self): + """ + This API specifically returns the serial number of the Y cable for a specfic port. + + Args: + None + + Returns: + a string, with part number + """ + + if self.sfp is not None: + curr_offset = self.QSFP28_UP0_168_SN_1 + sn_result = self.sfp.read_eeprom(curr_offset, 15) + else: + self.log(self.LOG_ERROR, "platform_chassis is not loaded, failed to get vendor name and sn_number") + return self.ERROR_PLATFORM_NOT_LOADED + + if self.__validate_read_data(sn_result, 15, "get serial_number") == self.EEPROM_READ_DATA_INVALID: + return self.EEPROM_ERROR + + sn_number = str(sn_result.decode()) + self.log(self.LOG_DEBUG, "Serial number = {}".format(sn_number)) + + return sn_number + + def get_date_code(self): + """ + This API specifically returns the date code of the Y cable for a specfic port. + + Args: + None + + Returns: + a string, with part number + """ + + if self.sfp is not None: + curr_offset = self.QSFP28_UP0_DATE_CODE + dcode_result = self.sfp.read_eeprom(curr_offset, 7) + else: + self.log(self.LOG_ERROR, "platform_chassis is not loaded, failed to date code") + return self.ERROR_PLATFORM_NOT_LOADED + + if self.__validate_read_data(dcode_result, 7, "get date_code") == self.EEPROM_READ_DATA_INVALID: + return self.EEPROM_ERROR + + dt_code = str(dcode_result.decode()) + self.log(self.LOG_DEBUG, "Date Code = {}".format(dt_code)) + + return dt_code + def get_vendor(self): """ This API returns the vendor name of the Y cable for a specfic port. @@ -975,8 +1333,8 @@ def get_read_side(self): TARGET_UNKNOWN, if reading the Y cable API fails. """ - start_ts = datetime.utcnow() - ts = self.log_timestamp(start_ts, " get_read_side() start") + #start_ts = datetime.utcnow() + #ts = self.log_timestamp(start_ts, " get_read_side() start") if self.platform_chassis is not None: curr_offset = self.QSFP28_UP0_224_SPECIFIC_1_RSV @@ -988,7 +1346,7 @@ def get_read_side(self): if self.__validate_read_data(result, 1, "read side") == self.EEPROM_READ_DATA_INVALID: return self.EEPROM_ERROR read_side = struct.unpack("> 8) & 0xFF) + curr_offset = ((self.QSFP_BRCM_FW_UPGRADE_PAGE*128) + self.QSFP_BRCM_FW_UPGRADE_BL_SUPPORT_0_7) + + if self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, dat) is False: + return self.ERROR_WR_EEPROM_FAILED + ts = self.log_timestamp(ts, "compression header sent") # Send request firmware upgrad to START @@ -3353,7 +3834,7 @@ def get_nic_temperature(self): return temperature - def get_eye_heights(self, target): + def internal_get_eye_heights(self, target): """ This API returns the EYE height value for a specfic port. The target could be local side, TOR_A, TOR_B, NIC etc. @@ -3368,6 +3849,7 @@ def get_eye_heights(self, target): Returns: a list, with EYE values of lane 0 lane 1 lane 2 lane 3 with corresponding index """ + if target == self.EYE_PRBS_LOOPBACK_TARGET_NIC or target == self.TARGET_NIC: self.log(self.LOG_WARN, "Get eye heights not supported for NIC target ") return None @@ -3414,8 +3896,8 @@ def get_eye_heights(self, target): l += 1 j += 1 for i in range(0, 4): - #lrud_val = (format(eye_heights[i][0]) + " " + format(eye_heights[i][1]) + " " + format(eye_heights[i][2]) + " " + format(eye_heights[i][3])) - lrud_val = eye_heights[i][2] + eye_heights[i][3] + lrud_val = (format(eye_heights[i][0]) + " " + format(eye_heights[i][1]) + " " + format(eye_heights[i][2]) + " " + format(eye_heights[i][3])) + #lrud_val = eye_heights[i][2] + eye_heights[i][3] lrud_list.append(lrud_val) if lane_mask == 0xF0: @@ -3428,8 +3910,8 @@ def get_eye_heights(self, target): j += 1 k = 0 for i in range(4, 8): - #lrud_val = (format(eye_heights[k][0]) + " " + format(eye_heights[k][1]) + " " + format(eye_heights[k][2]) + " " + format(eye_heights[k][3])) - lrud_val = eye_heights[k][2] + eye_heights[k][3] + lrud_val = (format(eye_heights[k][0]) + " " + format(eye_heights[k][1]) + " " + format(eye_heights[k][2]) + " " + format(eye_heights[k][3])) + #lrud_val = eye_heights[k][2] + eye_heights[k][3] lrud_list.append(lrud_val) k += 1 @@ -3439,33 +3921,120 @@ def get_eye_heights(self, target): self.log(self.LOG_ERROR, "Command execute failed ret_val: {}".format(ret_val)) return None - def get_ber_info(self, target): + def get_eye_heights(self, target): """ - This API returns the BER (Bit error rate) value for a specfic port. + This API returns the EYE height value for a specfic port. The target could be local side, TOR_A, TOR_B, NIC etc. The port on which this API is called for can be referred using self.port. Args: target: - One of the following predefined constants, the target on which to get the BER: + One of the following predefined constants, the target on which to get the eye: EYE_PRBS_LOOPBACK_TARGET_LOCAL -> local side, EYE_PRBS_LOOPBACK_TARGET_TOR_A -> TOR A EYE_PRBS_LOOPBACK_TARGET_TOR_B -> TOR B EYE_PRBS_LOOPBACK_TARGET_NIC -> NIC Returns: - a list, with BER values of lane 0 lane 1 lane 2 lane 3 with corresponding index + a list, with EYE values of lane 0 lane 1 lane 2 lane 3 with corresponding index """ - if (target != self.EYE_PRBS_LOOPBACK_TARGET_LOCAL and target != self.EYE_PRBS_LOOPBACK_TARGET_TOR_A and - target != self.EYE_PRBS_LOOPBACK_TARGET_TOR_B and target != self.EYE_PRBS_LOOPBACK_TARGET_NIC): - self.log(self.LOG_ERROR, "Invalid Traget : {}".format(target)) + if target == self.EYE_PRBS_LOOPBACK_TARGET_NIC or target == self.TARGET_NIC: + self.log(self.LOG_WARN, "Get eye heights not supported for NIC target ") + return None + elif (target != self.EYE_PRBS_LOOPBACK_TARGET_TOR_A) and (target != self.EYE_PRBS_LOOPBACK_TARGET_TOR_B) and \ + (target != self.EYE_PRBS_LOOPBACK_TARGET_LOCAL): + self.log(self.LOG_ERROR, "Invalid target : {}".format(target)) return self.ERROR_INVALID_TARGET - mode_value = 0xff - lane = 0x0f - ber_result = [] - ret_val, lock_sts, err_cnt_list = self.cable_check_prbs(target, mode_value, lane) - if ret_val != 0: - return False + core_ip, lane_mask = self.__util_convert_to_phyinfo_details(target, 0X0F) + + cmd_hdr = bytearray(10) + cmd_req_body = bytearray(self.MAX_REQ_PARAM_LEN) + + cmd_hdr[0] = 0 + cmd_hdr[1] = 0x40 + cmd_hdr[2] = lane_mask if (core_ip == self.CORE_IP_CLIENT) else 0 + cmd_hdr[3] = 0 + #cmd_hdr[3] = lane_mask if (core_ip == self.CORE_IP_LW) else 0 + cmd_hdr[4] = self.CORE_IP_CLIENT + + ret_val, cmd_rsp_body = self.__cable_cmd_execute(self.CABLE_CMD_ID_GET_EYE_MARGIN, cmd_hdr, cmd_req_body) + + if ret_val == 0: + eye_heights = [[] for i in range(4)] + values = [] + lrud_list = [] + ind = 0 + for i in range(0, 32): + #values.append(struct.unpack("h", cmd_rsp_body[ind:ind+2])) + byte_list = [] + for j in range(0, 2): + byte_list.append(cmd_rsp_body[ind + j]) + byte_array = bytearray(byte_list) + values.append(struct.unpack("h", byte_array)[0]) + + ind += 2 + + if lane_mask == 0x0F: + j = 0 + l = 0 + for i in range(0, 4): + for k in range(0, 4): + eye_heights[j].append(values[l]) + l += 1 + j += 1 + for i in range(0, 4): + #lrud_val = (format(eye_heights[i][0]) + " " + format(eye_heights[i][1]) + " " + format(eye_heights[i][2]) + " " + format(eye_heights[i][3])) + lrud_val = eye_heights[i][2] + eye_heights[i][3] + lrud_list.append(lrud_val) + + if lane_mask == 0xF0: + j = 0 + l = 16 + for i in range(0, 4): + for k in range(0, 4): + eye_heights[j].append(values[l]) + l += 1 + j += 1 + k = 0 + for i in range(4, 8): + #lrud_val = (format(eye_heights[k][0]) + " " + format(eye_heights[k][1]) + " " + format(eye_heights[k][2]) + " " + format(eye_heights[k][3])) + lrud_val = eye_heights[k][2] + eye_heights[k][3] + lrud_list.append(lrud_val) + + k += 1 + + return lrud_list + else: + self.log(self.LOG_ERROR, "Command execute failed ret_val: {}".format(ret_val)) + return None + + def get_ber_info(self, target): + """ + This API returns the BER (Bit error rate) value for a specfic port. + The target could be local side, TOR_A, TOR_B, NIC etc. + The port on which this API is called for can be referred using self.port. + Args: + target: + One of the following predefined constants, the target on which to get the BER: + EYE_PRBS_LOOPBACK_TARGET_LOCAL -> local side, + EYE_PRBS_LOOPBACK_TARGET_TOR_A -> TOR A + EYE_PRBS_LOOPBACK_TARGET_TOR_B -> TOR B + EYE_PRBS_LOOPBACK_TARGET_NIC -> NIC + Returns: + a list, with BER values of lane 0 lane 1 lane 2 lane 3 with corresponding index + """ + + if (target != self.EYE_PRBS_LOOPBACK_TARGET_LOCAL and target != self.EYE_PRBS_LOOPBACK_TARGET_TOR_A and + target != self.EYE_PRBS_LOOPBACK_TARGET_TOR_B and target != self.EYE_PRBS_LOOPBACK_TARGET_NIC): + self.log(self.LOG_ERROR, "Invalid Traget : {}".format(target)) + return self.ERROR_INVALID_TARGET + + mode_value = 0xff + lane = 0x0f + ber_result = [] + ret_val, lock_sts, err_cnt_list = self.cable_check_prbs(target, mode_value, lane) + if ret_val != 0: + return False time.sleep(1) @@ -3503,7 +4072,8 @@ def get_target_cursor_values(self, lane, target): """ # validate lane number - if lane < 1 or lane > 4: + if ((type(lane) is not int) or + (lane < 1 or lane > 4)): self.log(self.LOG_ERROR, "Invalid lane = {} valid lane is 1 to 4".format(lane)) return self.ERROR_INVALID_INPUT @@ -3533,7 +4103,7 @@ def get_target_cursor_values(self, lane, target): if ret_val == 0: txfir = [] ind = 0 - for i in range(0, 7): + for _ in range(0, 7): txfir.append(struct.unpack("h", cmd_rsp_body[ind:ind+2])[0]) ind += 2 @@ -3573,7 +4143,13 @@ def set_target_cursor_values(self, lane, cursor_values, target): , False if cursor values setting is not successful """ - if lane < 1 or lane > 4: + # check length of argument + if(self.LEN_OF_SET_CURSOR_VALUES != len(cursor_values)): + self.log(self.LOG_ERROR, "Wrong No of cursor values passed to function set_target_cursor_values") + return self.ERROR_INVALID_INPUT + + if ((type(lane) is not int) or + (lane < 1 or lane > 4)): self.log(self.LOG_ERROR, "Invalid lane = {} valid lane is 1 to 4".format(lane)) return self.ERROR_INVALID_INPUT @@ -3634,6 +4210,10 @@ def download_firmware(self, fwfile): ERROR_GET_VERSION_FAILED : Failed to get fw version from MCU """ + if (os.path.isfile(fwfile) != True): + self.log(self.LOG_ERROR, "ERROR : Fwfile {} is not present".format(fwfile)) + return self.RR_ERROR + self.log(self.LOG_DEBUG, "download_firmware() start...") read_side = self.get_read_side() if read_side == self.TARGET_NIC: @@ -3824,7 +4404,7 @@ def activate_firmware(self, fwfile=None, hitless=False): Args: boot_type: an Integer, one of the follwing predefine constants defines the boot type - WARMBOOT = 0 + WARMBOOT = 0 COLDBOOT = 1 fwfile (optional): @@ -3853,9 +4433,11 @@ def activate_firmware(self, fwfile=None, hitless=False): """ #ret_val = self.ERROR_FW_ACTIVATE_FAILURE - nic_ret_val = self.RR_SUCCESS - self_ret_val = self.RR_SUCCESS - peer_ret_val = self.RR_SUCCESS + + if((fwfile is not None) and + (os.path.isfile(fwfile) != True)): + self.log(self.LOG_ERROR, "ERROR : Fwfile {} is not present".format(fwfile)) + return self.RR_ERROR if hitless == True: boot_type = self.WARMBOOT @@ -4026,6 +4608,9 @@ def activate_firmware(self, fwfile=None, hitless=False): (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank1_info.image_fw_version.image_version_minor == upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): + activate_tor_peer = self.PERFORM_ACTIVATE + self.log(self.LOG_INFO, "Activate TOR-PEER - eligible") + if boot_type == self.WARMBOOT: self.log(self.LOG_INFO, "Toggle TOR-PEER MCU - warm boot") ret_val = self.__cable_fw_warm_boot(upgrade_info[self.TOR_MCU_PEER - 1]) @@ -4050,12 +4635,14 @@ def activate_firmware(self, fwfile=None, hitless=False): (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank2_info.image_fw_version.image_version_minor == upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor)))): - self.log(self.LOG_INFO, "TOR-PEER MCU FW Version already active") - peer_ret_val = self.WARNING_FW_ALREADY_ACTIVE + activate_tor_peer = self.ALREADY_ACTIVATED + self.log(self.LOG_INFO, "Activate TOR-PEER MCU - already activated") else: - self.log(self.LOG_ERROR, "ERROR: cannot activate due to fw version mismatch") - peer_ret_val = self.RR_ERROR + activate_tor_peer = self.CANNOT_ACTIVATE + self.log(self.LOG_ERROR, "ERROR: TOR-PEER cannot activate due to fw version mismatch") + #if ret_val != self.RR_ERROR: + #peer_ret_val = self.RR_ERROR # Check if NIC MCU and MUX chip needs activation self.log(self.LOG_INFO, "NIC MCU activation:") @@ -4098,6 +4685,9 @@ def activate_firmware(self, fwfile=None, hitless=False): (upgrade_info[self.MUX_CHIP - 1].status_info.bank1_info.image_fw_version.image_version_minor == upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor)))))): + activate_nic = self.PERFORM_ACTIVATE + self.log(self.LOG_INFO, "Activate NIC MCU - eligible") + if boot_type == self.WARMBOOT: self.log(self.LOG_INFO, "Toggle NIC MCU - warm boot") ret_val = self.__cable_fw_warm_boot(upgrade_info[self.NIC_MCU - 1]) @@ -4130,12 +4720,12 @@ def activate_firmware(self, fwfile=None, hitless=False): (upgrade_info[self.MUX_CHIP - 1].status_info.bank2_info.image_fw_version.image_version_minor == upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): - self.log(self.LOG_INFO, "NIC MCU FW Version already active") - nic_ret_val = self.WARNING_FW_ALREADY_ACTIVE + activate_nic = self.ALREADY_ACTIVATED + self.log(self.LOG_INFO, "ACTIVATE NIC MCU - already activated") else: - self.log(self.LOG_ERROR, "ERROR: cannot activate due to fw version mismatch") - nic_ret_val = self.RR_ERROR + activate_nic = self.CANNOT_ACTIVATE + self.log(self.LOG_ERROR, "ERROR: NIC/MUX cannot activate due to fw version mismatch") # Check if TOR SELF MCU needs activation self.log(self.LOG_INFO, "TOR SELF activation:") @@ -4162,6 +4752,9 @@ def activate_firmware(self, fwfile=None, hitless=False): (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank1_info.image_fw_version.image_version_minor == upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): + activate_tor_self = self.PERFORM_ACTIVATE + self.log(self.LOG_INFO, "Activate TOR-SELF MCU - eligible") + if boot_type == self.WARMBOOT: self.log(self.LOG_INFO, "Toggle TOR-SELF MCU - warm boot") ret_val = self.__cable_fw_warm_boot(upgrade_info[self.TOR_MCU_SELF - 1]) @@ -4186,24 +4779,32 @@ def activate_firmware(self, fwfile=None, hitless=False): (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank2_info.image_fw_version.image_version_minor == upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor)))): - self.log(self.LOG_INFO, "TOR-SELF MCU FW Version already active") - self_ret_val = self.WARNING_FW_ALREADY_ACTIVE + activate_tor_self = self.ALREADY_ACTIVATED + self.log(self.LOG_INFO, "Activate TOR-SELF MCU - already activated") else: - self.log(self.LOG_ERROR, "ERROR: cannot activate due to fw version mismatch") - self_ret_val = self.RR_ERROR + activate_tor_self = self.CANNOT_ACTIVATE + self.log(self.LOG_ERROR, "ERROR: TOR-SELF cannot activate due to fw version mismatch") + #if ret_val != self.RR_ERROR: + #self_ret_val = self.RR_ERROR + else: self.log(self.LOG_ERROR, "DL Port lock timed-out!") #ret_val = self.ERROR_PORT_LOCK_TIMEOUT return self.ERROR_PORT_LOCK_TIMEOUT - if peer_ret_val == self.RR_ERROR or self_ret_val == self.RR_ERROR or nic_ret_val == self.RR_ERROR: - return self.RR_ERROR - elif peer_ret_val == self.WARNING_FW_ALREADY_ACTIVE and self_ret_val == self.WARNING_FW_ALREADY_ACTIVE and nic_ret_val == self.WARNING_FW_ALREADY_ACTIVE: - return self.WARNING_FW_ALREADY_ACTIVE - else: + if activate_nic == self.PERFORM_ACTIVATE or activate_tor_self == self.PERFORM_ACTIVATE or activate_tor_peer == self.PERFORM_ACTIVATE: + self.log(self.LOG_INFO, "Activate performed one or all MCUs!") return self.RR_SUCCESS + elif activate_nic == self.ALREADY_ACTIVATED and activate_tor_self == self.ALREADY_ACTIVATED and activate_tor_peer == self.ALREADY_ACTIVATED: + self.log(self.LOG_INFO, "Already activated!") + return self.WARNING_FW_ALREADY_ACTIVE + + elif activate_nic == self.CANNOT_ACTIVATE or activate_tor_self == self.CANNOT_ACTIVATE or activate_tor_peer == self.CANNOT_ACTIVATE: + self.log(self.LOG_ERROR, "ERROR: Cannot activate!") + return self.RR_ERROR + def rollback_firmware(self, fwfile=None): """ This routine should rollback the firmware to the previous version @@ -4214,7 +4815,7 @@ def rollback_firmware(self, fwfile=None): Args: boot_type: an Integer, one of the follwing predefine constants defines the boot type - WARMBOOT + WARMBOOT COLDBOOT fwfile (optional): a string, a path to the file which contains the firmware image. @@ -4244,12 +4845,17 @@ def rollback_firmware(self, fwfile=None): """ #ret_val = self.ERROR_FW_ROLLBACK_FAILURE - nic_ret_val = self.RR_SUCCESS - self_ret_val = self.RR_SUCCESS - peer_ret_val = self.RR_SUCCESS + rollback_nic = self.CANNOT_ROLLBACK + rollback_tor_self = self.CANNOT_ROLLBACK + rollback_tor_peer = self.CANNOT_ROLLBACK boot_type = self.COLDBOOT + if((fwfile is not None) and + (os.path.isfile(fwfile) != True)): + self.log(self.LOG_ERROR, "ERROR : Fwfile {} is not present".format(fwfile)) + return self.RR_ERROR + upgrade_head = [] upgrade_head.append(cable_upgrade_head_s()) upgrade_head.append(cable_upgrade_head_s()) @@ -4292,8 +4898,7 @@ def rollback_firmware(self, fwfile=None): if(self. cable_fw_get_status(upgrade_info[i], True) != self.RR_SUCCESS): return self.RR_ERROR - # First make sure there was a successful download_firmware prior to activate - # Check that all the ends of the cable have at least one bank matching the firmware version in fwfile + # Check that all the ends of the cable have at least one bank matching the firmware version in fwfile if fwfile is not None: if not (( (((upgrade_info[self.NIC_MCU - 1].status_info.bank1_info.image_fw_version.image_version_major == @@ -4329,7 +4934,7 @@ def rollback_firmware(self, fwfile=None): upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_major) and (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank2_info.image_fw_version.image_version_minor == upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): - self.log(self.LOG_ERROR, "Error: Could not find for each end of the cable at least one bank matching the firmware version in the file. Please make sure to download the firmware in the file for each end") + self.log(self.LOG_ERROR, "Error: Could not find for each end of the cable at least one bank matching the firmware version in the file.") return self.ERROR_NO_MATCHING_FW else: @@ -4431,6 +5036,9 @@ def rollback_firmware(self, fwfile=None): (upgrade_info[self.MUX_CHIP - 1].status_info.bank1_info.image_fw_version.image_version_minor != upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor)))))): + rollback_nic = self.PERFORM_ROLLBACK + self.log(self.LOG_INFO, "Rollback NIC MCU - eligible") + if boot_type == self.WARMBOOT: self.log(self.LOG_INFO, "Rollback NIC MCU - warm boot") ret_val = self.__cable_fw_warm_boot(upgrade_info[self.NIC_MCU - 1]) @@ -4444,32 +5052,52 @@ def rollback_firmware(self, fwfile=None): self.log(self.LOG_ERROR, "ERROR: while rollback NIC MCU firwmware") return self.ERROR_TOGGLE_FAILED - elif(((upgrade_info[self.NIC_MCU - 1].status_info.current_bank == 1) and - (((upgrade_info[self.NIC_MCU - 1].status_info.bank1_info.image_fw_version.image_version_major != - upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_major) or - (upgrade_info[self.NIC_MCU - 1].status_info.bank1_info.image_fw_version.image_version_minor != - upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) and - ((upgrade_info[self.MUX_CHIP - 1].status_info.bank1_info.image_fw_version.image_version_major != - upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_major) or - (upgrade_info[self.MUX_CHIP - 1].status_info.bank1_info.image_fw_version.image_version_minor != - upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor)))) - or - ((upgrade_info[self.NIC_MCU - 1].status_info.current_bank == 2) and - (((upgrade_info[self.NIC_MCU - 1].status_info.bank2_info.image_fw_version.image_version_major != - upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_major) or - (upgrade_info[self.NIC_MCU - 1].status_info.bank2_info.image_fw_version.image_version_minor != - upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_minor))and - ((upgrade_info[self.MUX_CHIP - 1].status_info.bank2_info.image_fw_version.image_version_major != - upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_major) or - (upgrade_info[self.MUX_CHIP - 1].status_info.bank2_info.image_fw_version.image_version_minor != - upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): - - self.log(self.LOG_INFO, "NIC/MUX Previous version already rolled back") - nic_ret_val = self.WARNING_FW_ALREADY_ROLLEDBACK + # if rollback_ver == inactive_bank && rollback_ver != active_bank + elif(( + (((upgrade_info[self.NIC_MCU - 1].status_info.current_bank == 2) and + (((upgrade_info[self.NIC_MCU - 1].status_info.bank1_info.image_fw_version.image_version_major == + upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_major) and + (upgrade_info[self.NIC_MCU - 1].status_info.bank1_info.image_fw_version.image_version_minor == + upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) or + ((upgrade_info[self.MUX_CHIP - 1].status_info.bank1_info.image_fw_version.image_version_major == + upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_major) and + (upgrade_info[self.MUX_CHIP - 1].status_info.bank1_info.image_fw_version.image_version_minor == + upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor))) + and + (((upgrade_info[self.NIC_MCU - 1].status_info.bank2_info.image_fw_version.image_version_major != + upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_major) or + (upgrade_info[self.NIC_MCU - 1].status_info.bank2_info.image_fw_version.image_version_minor != + upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) or + ((upgrade_info[self.MUX_CHIP - 1].status_info.bank2_info.image_fw_version.image_version_major != + upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_major) or + (upgrade_info[self.MUX_CHIP - 1].status_info.bank2_info.image_fw_version.image_version_minor != + upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor)))) + or + ((upgrade_info[self.NIC_MCU - 1].status_info.current_bank == 1) and + (((upgrade_info[self.NIC_MCU - 1].status_info.bank2_info.image_fw_version.image_version_major == + upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_major) and + (upgrade_info[self.NIC_MCU - 1].status_info.bank2_info.image_fw_version.image_version_minor == + upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) or + ((upgrade_info[self.MUX_CHIP - 1].status_info.bank2_info.image_fw_version.image_version_major == + upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_major) and + (upgrade_info[self.MUX_CHIP - 1].status_info.bank2_info.image_fw_version.image_version_minor == + upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor))) + and + (((upgrade_info[self.NIC_MCU - 1].status_info.bank1_info.image_fw_version.image_version_major != + upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_major) or + (upgrade_info[self.NIC_MCU - 1].status_info.bank1_info.image_fw_version.image_version_minor != + upgrade_head[self.NIC_MCU - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) or + ((upgrade_info[self.MUX_CHIP - 1].status_info.bank1_info.image_fw_version.image_version_major != + upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_major) or + (upgrade_info[self.MUX_CHIP - 1].status_info.bank1_info.image_fw_version.image_version_minor != + upgrade_head[self.MUX_CHIP - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))))): + + rollback_nic = self.ALREADY_ROLLED_BACK + self.log(self.LOG_INFO, "Rollback NIC MCU - already rolled-back") else: + rollback_nic = self.CANNOT_ROLLBACK self.log(self.LOG_ERROR, "ERROR: NIC/MUX cannot rollback: no previous version found to rollback") - nic_ret_val = self.RR_ERROR # Check TOR SELF MCU needs rollback self.log(self.LOG_INFO, "TOR SELF MCU rollback:") @@ -4495,6 +5123,8 @@ def rollback_firmware(self, fwfile=None): (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank1_info.image_fw_version.image_version_minor != upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): + rollback_tor_self = self.PERFORM_ROLLBACK + self.log(self.LOG_INFO, "Rollback TOR-SELF MCU - eligible") if boot_type == self.WARMBOOT: self.log(self.LOG_INFO, "Rollback TOR-SELF MCU - warm boot") ret_val = self.__cable_fw_warm_boot(upgrade_info[self.TOR_MCU_SELF - 1]) @@ -4508,25 +5138,35 @@ def rollback_firmware(self, fwfile=None): self.log(self.LOG_ERROR, "ERROR: while rollback TOR-SELF firwmware") return self.ERROR_TOGGLE_FAILED - elif(((upgrade_info[self.TOR_MCU_SELF - 1].status_info.current_bank == 1) and - ((upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank1_info.image_fw_version.image_version_major != - upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_major) or - (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank1_info.image_fw_version.image_version_minor != - upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor))) or - ((upgrade_info[self.TOR_MCU_SELF - 1].status_info.current_bank == 2) and - ((upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank2_info.image_fw_version.image_version_major != - upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_major) or - (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank2_info.image_fw_version.image_version_minor != - upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor)))): + # if rollback_ver == inactive_bank && rollback_ver != active_bank + elif( + (((upgrade_info[self.TOR_MCU_SELF - 1].status_info.current_bank == 2) and + ((upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank1_info.image_fw_version.image_version_major == + upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_major) and + (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank1_info.image_fw_version.image_version_minor == + upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) and + ((upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank2_info.image_fw_version.image_version_major != + upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_major) or + (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank2_info.image_fw_version.image_version_minor != + upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor))) or + ((upgrade_info[self.TOR_MCU_SELF - 1].status_info.current_bank == 1) and + ((upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank2_info.image_fw_version.image_version_major == + upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_major) and + (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank2_info.image_fw_version.image_version_minor == + upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) and + ((upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank1_info.image_fw_version.image_version_major != + upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_major) or + (upgrade_info[self.TOR_MCU_SELF - 1].status_info.bank1_info.image_fw_version.image_version_minor != + upgrade_head[self.TOR_MCU_SELF - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): - self.log(self.LOG_INFO, "TOR-SELF Previous version already rolled back") - if ret_val != self.WARNING_FW_ALREADY_ROLLEDBACK: - self_ret_val = self.WARNING_FW_ALREADY_ROLLEDBACK + rollback_tor_self = self.ALREADY_ROLLED_BACK + self.log(self.LOG_INFO, "Rollback TOR-SELF MCU - already rolled-back") else: + rollback_tor_self = self.CANNOT_ROLLBACK self.log(self.LOG_ERROR, "ERROR: TOR-SELF cannot rollback: no previous version found to rollback") - if ret_val != self.RR_ERROR: - self_ret_val = self.RR_ERROR + #if ret_val != self.RR_ERROR: + #self_ret_val = self.RR_ERROR # Check TOR PEER MCU needs rollback self.log(self.LOG_INFO, "TOR PEER MCU rollback:") @@ -4552,6 +5192,9 @@ def rollback_firmware(self, fwfile=None): (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank1_info.image_fw_version.image_version_minor != upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): + rollback_tor_peer = self.PERFORM_ROLLBACK + self.log(self.LOG_INFO, "Rollback TOR-PEER MCU - eligible") + if boot_type == self.WARMBOOT: self.log(self.LOG_INFO, "Toggle TOR-PEER MCU - warm boot") ret_val = self.__cable_fw_warm_boot(upgrade_info[self.TOR_MCU_PEER - 1]) @@ -4565,37 +5208,52 @@ def rollback_firmware(self, fwfile=None): self.log(self.LOG_ERROR, "ERROR: while rollback TOR-PEER firwmware") return self.ERROR_TOGGLE_FAILED - elif(((upgrade_info[self.TOR_MCU_PEER - 1].status_info.current_bank == 1) and - ((upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank1_info.image_fw_version.image_version_major != - upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_major) or - (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank1_info.image_fw_version.image_version_minor != - upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor))) or - ((upgrade_info[self.TOR_MCU_PEER - 1].status_info.current_bank == 2) and - ((upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank2_info.image_fw_version.image_version_major != - upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_major) or - (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank2_info.image_fw_version.image_version_minor != - upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor)))): + # if rollback_ver == inactive_bank && rollback_ver != active_bank + elif( + (((upgrade_info[self.TOR_MCU_PEER - 1].status_info.current_bank == 2) and + ((upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank1_info.image_fw_version.image_version_major == + upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_major) and + (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank1_info.image_fw_version.image_version_minor == + upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) and + ((upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank2_info.image_fw_version.image_version_major != + upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_major) or + (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank2_info.image_fw_version.image_version_minor != + upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor))) or + ((upgrade_info[self.TOR_MCU_PEER - 1].status_info.current_bank == 1) and + ((upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank2_info.image_fw_version.image_version_major == + upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_major) and + (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank2_info.image_fw_version.image_version_minor == + upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor)) and + ((upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank1_info.image_fw_version.image_version_major != + upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_major) or + (upgrade_info[self.TOR_MCU_PEER - 1].status_info.bank1_info.image_fw_version.image_version_minor != + upgrade_head[self.TOR_MCU_PEER - 1].cable_up_info.image_info.image_fw_version.image_version_minor))))): - self.log(self.LOG_INFO, "TOR-PEER Previous version already rolled back") - if ret_val != self.WARNING_FW_ALREADY_ROLLEDBACK: - peer_ret_val = self.WARNING_FW_ALREADY_ROLLEDBACK + rollback_tor_peer = self.ALREADY_ROLLED_BACK + self.log(self.LOG_INFO, "Rollback TOR-PEER MCU - already rolled back") else: + rollback_tor_peer = self.CANNOT_ROLLBACK self.log(self.LOG_ERROR, "ERROR: TOR-PEER cannot rollback: no previous version found to rollback") - if ret_val != self.RR_ERROR: - peer_ret_val = self.RR_ERROR + #if ret_val != self.RR_ERROR: + #peer_ret_val = self.RR_ERROR else: self.log(self.LOG_ERROR, "DL Port lock timed-out!") #ret_val = self.ERROR_PORT_LOCK_TIMEOUT return self.ERROR_PORT_LOCK_TIMEOUT - if peer_ret_val == self.RR_ERROR or self_ret_val == self.RR_ERROR or nic_ret_val == self.RR_ERROR: - return self.RR_ERROR - elif peer_ret_val == self.WARNING_FW_ALREADY_ROLLEDBACK and self_ret_val == self.WARNING_FW_ALREADY_ROLLEDBACK and nic_ret_val == self.WARNING_FW_ALREADY_ROLLEDBACK: - return self.WARNING_FW_ALREADY_ROLLEDBACK - else: + if rollback_nic == self.PERFORM_ROLLBACK or rollback_tor_self == self.PERFORM_ROLLBACK or rollback_tor_peer == self.PERFORM_ROLLBACK: + self.log(self.LOG_INFO, "Rollback performed one or all MCUs!") return self.RR_SUCCESS + elif rollback_nic == self.ALREADY_ROLLED_BACK and rollback_tor_self == self.ALREADY_ROLLED_BACK and rollback_tor_peer == self.ALREADY_ROLLED_BACK: + self.log(self.LOG_INFO, "Already rolled back!") + return self.WARNING_FW_ALREADY_ROLLEDBACK + + elif rollback_nic == self.CANNOT_ROLLBACK and rollback_tor_self == self.CANNOT_ROLLBACK and rollback_tor_peer == self.CANNOT_ROLLBACK: + self.log(self.LOG_ERROR, "ERROR: Cannot rollback!") + return self.RR_ERROR + def set_switching_mode(self, mode): """ This API enables the auto switching or manual switching feature on the Y-Cable, @@ -5110,6 +5768,7 @@ def get_fec_mode(self, target=None): FEC_MODE_FC """ mode_select = self.cable_get_mode() + if (mode_select < 0): self.log(self.LOG_ERROR, "get_mode failed ret_code: {}".format(mode_select)) return self.ERROR_GET_FEC_MODE_FAILED @@ -5133,6 +5792,7 @@ def set_anlt(self, enable, target): a boolean, True if the auto-negotiation + link training (AN/LT) enable/disable specified is configured , False if the auto-negotiation + link training (AN/LT) enable/disable specified is not configured """ + if (target != self.TARGET_TOR_A) and (target != self.TARGET_TOR_B) and (target != self.TARGET_NIC) and (target != self.EYE_PRBS_LOOPBACK_TARGET_LOCAL): self.log(self.LOG_ERROR, "Invalid target : {}".format(target)) return self.ERROR_INVALID_INPUT @@ -5175,6 +5835,7 @@ def get_anlt(self, target): a boolean, True if auto-negotiation + link training (AN/LT) is enabled , False if auto-negotiation + link training (AN/LT) is not enabled """ + if (target != self.TARGET_TOR_A) and (target != self.TARGET_TOR_B) and (target != self.TARGET_NIC) and (target != self.EYE_PRBS_LOOPBACK_TARGET_LOCAL): self.log(self.LOG_ERROR, "Invalid target : {}".format(target)) return self.ERROR_INVALID_INPUT @@ -5209,6 +5870,49 @@ def get_anlt(self, target): self.log(self.LOG_ERROR, "Get AN/LT get mode command execution failed") return False + def sort_logs(self, sorted_logs, event_logs): + + for idx in range(len(event_logs)): + event_obj = event_logs[idx] + + # if sorted_logs is empty, simply add the log + if len(sorted_logs) == 0: + sorted_logs.append(event_obj) + #print("[case-0] adding run_no {} timestamp {}".format(event_obj.run_no, event_obj.timestamp)) + else: + #match_run_list_found = False + added_to_list = False + # add the event_obj in run_no & timestamp order + for sidx in range(len(sorted_logs)): + tmp_obj = sorted_logs[sidx] + + if tmp_obj.run_no > event_obj.run_no: + sorted_logs.insert(sidx, event_obj) + #print("[case-1] adding run_no {} timestamp {} at index {}".format(event_obj.run_no, event_obj.timestamp, sidx)) + #print("[case-1] tmp_obj run_no {} timestamp {} at index {}".format(tmp_obj.run_no, tmp_obj.timestamp, sidx)) + added_to_list = True + break + elif tmp_obj.run_no == event_obj.run_no: + if tmp_obj.timestamp > event_obj.timestamp: + sorted_logs.insert(sidx, event_obj) + #print("[case-2] adding run_no {} timestamp {} at index {}".format(event_obj.run_no, event_obj.timestamp, sidx)) + added_to_list = True + break + + if added_to_list == False: + #print("[case-3] adding run_no {} timestamp {} after index {}".format(event_obj.run_no, event_obj.timestamp, sidx)) + sorted_logs.append(event_obj) + + def convert_to_hhmmss(self, millis): + mil = millis%1000 + seconds = (millis/1000)%60 + minutes = (millis/(1000*60))%60 + hours = (millis/(1000*60*60))%24 + + out = ("%02d:%02d:%02d.%03d" % (hours, minutes, seconds, mil)) + + return out + def get_event_log(self, clear_on_read=False): """ This API returns the event log of the cable @@ -5221,8 +5925,107 @@ def get_event_log(self, clear_on_read=False): list: a list of strings which correspond to the event logs of the cable """ - - return None + all_logs_list = [] + phy_logs = [] + mcu_logs = [] + sorted_phy_nic_logs = [] + sorted_tor_self_logs = [] + sorted_tor_peer_logs = [] + + all_logs_list.append("Run No : Timestamp : Source : Event ") + all_logs_list.append("------ : --------- : ------ : ----- ") + phy_logs = self.cable_get_phy_chip_event_log() + + # sort phy logs first + self.sort_logs(sorted_phy_nic_logs, phy_logs) + + tmp_list = [] + + # fetch event_logs for each event source and add them to tmp_list + # sort the tmp_list into combined sorted_phy_nic_logs[] + for event_source in range(1, 5): + mcu_logs = self.cable_get_nic_mcu_event_log(event_source) + if mcu_logs: + for j in range(len(mcu_logs)): + event_obj = mcu_logs[j] + event_type = struct.unpack(" 0: + self.sort_logs(sorted_phy_nic_logs, tmp_list) + + log_item = 0 + for evt in range(len(sorted_phy_nic_logs)): + if (type(sorted_phy_nic_logs[evt]) == cable_phy_chip_event_log_s): + tmp_phy_str_list = self.convert_to_phy_chip_event_log_str_list(sorted_phy_nic_logs[evt], log_item) + log_item += 1 + for i in range(len(tmp_phy_str_list)): + all_logs_list.append(tmp_phy_str_list[i]) + elif (type(sorted_phy_nic_logs[evt]) == cable_mcu_event_log_s): + tstamp = self.convert_to_hhmmss(sorted_phy_nic_logs[evt].timestamp) + + #evt_str = self.get_mcu_event_type_str(int.from_bytes(sorted_phy_nic_logs[evt].event_type, "big")) + evt_type = struct.unpack(" 0: + self.sort_logs(sorted_tor_self_logs, tmp_list1) + + for evt in range(len(sorted_tor_self_logs)): + tstamp = self.convert_to_hhmmss(sorted_tor_self_logs[evt].timestamp) + #evt_str = self.get_mcu_event_type_str(int.from_bytes(sorted_tor_self_logs[evt].event_type, "big")) + evt_type = struct.unpack(" 0: + self.sort_logs(sorted_tor_peer_logs, tmp_list1) + + for evt in range(len(sorted_tor_peer_logs)): + tstamp = self.convert_to_hhmmss(sorted_tor_peer_logs[evt].timestamp) + #evt_str = self.get_mcu_event_type_str(int.from_bytes(sorted_tor_peer_logs[evt].event_type, "big")) + evt_type = struct.unpack(" 1)): + break + + output_str += "\n Lane {} Status =============".format(lane) + output_str += "\n Block Lock Live Status = {}".format(hex(src_ptr.pcs_sts.pcs_status_phylane[lane].pcs_block_lock_stat)) + output_str += "\n Block LoLock Sticky Status = {} ".format(hex(src_ptr.pcs_sts.pcs_status_phylane[lane].pcs_block_lolock_sticky)) + output_str += "\n AM Lock Live Status = {} ".format(hex(src_ptr.pcs_sts.pcs_status_phylane[lane].pcs_am_lock_stat)) + output_str += "\n AM LoLock Sticky Status = {} ".format(hex(src_ptr.pcs_sts.pcs_status_phylane[lane].pcs_am_lolock_sticky)) + output_str += "\n Deskew Error Sticky Status = {} ".format(hex(src_ptr.pcs_sts.pcs_status_phylane[lane].pcs_dskw_error_sticky)) + + output_str += "\n BIP Error Count ========== " + for sublane in range(5): + pcsl = 5 * lane + sublane + output_str += "\n sublane@{} (pcsl @ {}) = hex( {} ) | dec( {} ) ; ".format(sublane, pcsl, hex(src_ptr.pcs_sts.pcs_status_phylane[lane].pcs_bip_err_cnt[sublane]), src_ptr.pcs_sts.pcs_status_phylane[lane].pcs_bip_err_cnt[sublane]) + + output_str += "\n" + + output_str += "\n*** Per Port Status *** \n" + output_str += "\n dskw alignment live status = {} ".format(src_ptr.pcs_sts.pcs_dskw_align_stat) + output_str += "\n dskw loss of alignment sticky status = {} \n".format(src_ptr.pcs_sts.pcs_dskw_align_loss_sticky) + + output_str += "\n high ber live status = {} \n".format(src_ptr.pcs_sts.pcs_hiber_stat) + output_str += "\n high ber sticky status = {} \n".format(src_ptr.pcs_sts.pcs_hiber_sticky) + + output_str += "\n pcs ber count = hex( {} ) | dec( {} ) \n".format(hex(src_ptr.pcs_sts.pcs_ber_cnt), src_ptr.pcs_sts.pcs_ber_cnt) + + output_str += "\n live link status = {} \n".format(src_ptr.pcs_sts.pcs_link_stat) + output_str += "\n sticky link status = {} \n".format(src_ptr.pcs_sts.pcs_link_stat_sticky) + + return output_str def get_fec_stats(self, target): """ @@ -5255,8 +6174,106 @@ def get_fec_stats(self, target): a dictionary: a detailed format agreed upon by vendors """ + output_dict = {} + + if (target != self.TARGET_TOR_A) and (target != self.TARGET_TOR_B): + self.log(self.LOG_ERROR, "Invalid target : {}".format(target)) + output_dict["error_messgae"] = "Invalid target : {}".format(target) + return output_dict + #return self.ERROR_INVALID_INPUT + + mode_select = self.get_fec_mode() + if (mode_select < 0): + self.log(self.LOG_ERROR, "get_mode failed ret_code: {}".format(mode_select)) + output_dict["error_messgae"] = "get_mode failed ret_code: {}".format(mode_select) + return output_dict + #return self.ERROR_GET_FEC_MODE_FAILED + + if mode_select != self.FEC_MODE_RS: + output_dict["error_message"] = "get_fec_stats() on PCS mode not allowed!" + return output_dict + + status = bytearray(121) + lane_mask = 0xF + no_clr_on_rd = 0 + src_ptr = pcsfec_dump_status_short_s() + + status = self.cable_get_pcsfec_stats(target, lane_mask, no_clr_on_rd) + if status is None: + self.log(self.LOG_ERROR, "ERROR: failed to get pcs/fec stats!") + output_dict["error_message"] = "ERROR: failed to get pcs/fec stats!" + return output_dict + #return self.RR_ERROR + + # get fec_type and func_mode + src_ptr.fec_type = status[0] + src_ptr.func_mode = status[1] + + + # FEC + if src_ptr.fec_type != self.CAPI_FEC_TYPE_PCS: + fecrx_status = fecrx_status_short_s() + start_idx = 2 # skip first two bytes, fec_type and func_mode + + fecrx_status.am_lolock_sticky = status[start_idx] + fecrx_status.dgbox_clsn_sticky = status[start_idx+1] + fecrx_status.hi_ser_sticky = status[start_idx+2] + fecrx_status.xdec_err_sticky = status[start_idx+3] + fecrx_status.fec_link_stat = status[start_idx+4] + fecrx_status.fec_link_stat_sticky= status[start_idx+5] + + fecrx_status.tot_frame_rev_cnt = struct.unpack_from(" 0b'0011 , means running on lane0 and lane1 enable: - an Integer,specifies SQUELCH or UNSQUELCH + an Integer,specifies SQUELCH or UNSQUELCH SQUELCh -> 1 UNSQUELCH -> 0 direction: @@ -6640,9 +7950,15 @@ def cable_set_squelch(self, target, lane_map, enable, direction): if (target != self.TARGET_TOR_A) and (target != self.TARGET_TOR_B) and (target != self.TARGET_NIC) and (target != self.EYE_PRBS_LOOPBACK_TARGET_LOCAL): self.log(self.LOG_ERROR, "Invalid target : {}".format(target)) return self.ERROR_INVALID_TARGET - elif lane_map & 0xF == 0: + elif (type(lane_map) is not int) or (lane_map & 0xF == 0): self.log(self.LOG_ERROR, "Invalid Lane map {}".format(lane_map)) return self.ERROR_INVALID_INPUT + elif (enable != 0) and (enable != 1): + self.log(self.LOG_ERROR, "Invalid Squelch {}".format(enable)) + return self.ERROR_INVALID_INPUT + elif (direction != 0) and (direction != 1): + self.log(self.LOG_ERROR, "Invalid direction {}".format(direction)) + return self.ERROR_INVALID_INPUT ret_val = self.__util_convert_to_phyinfo_details(target, lane_map) core_ip = ret_val[0] @@ -6916,7 +8232,7 @@ def cable_set_intr_mask(self, intr_mask): 1 torB to nic pcs fec link 7-2 reserved Args: - list of intr mask in the below order : + list of intr mask in the below order : nic_torA_loss_lock_intr_mask torB_cdr_loss_lock_torB_loss_intr_mask torA_loss_nic_loss_intr_mask @@ -6964,6 +8280,9 @@ def cable_set_intr_mask(self, intr_mask): return True def cable_check_intr_active_status(self): + """ + This API returns the active interrupt + """ curr_offset = self.QSFP28_LP_QSFP28_LP_2_STATUS_CR result = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) @@ -7122,7 +8441,7 @@ def cable_print_nic_mcu_dump(self): if value != 0xDEADBEEF: self.log(self.LOG_WARN, "No new crash on NIC") break - # elif i == 1: + #elif i == 1: #value = struct.unpack("\n") + else: + self.log(self.LOG_INFO, "peer tor pcs/fec statistics---------------------->\n") + + cmd_hdr[0] = 0x1 # len of comnd request + cmd_hdr[1] = 0x3C # len of cmd response + cmd_hdr[2] = lane_mask if (core_ip == self.CORE_IP_CLIENT) else 0 # client lanemask + cmd_hdr[3] = lane_mask if (core_ip == self.CORE_IP_LW) else 0 # Line lanemask + cmd_hdr[4] = core_ip # NIC | TOR + + if no_clr_on_rd: + cmd_req_body[0] = 0x10 + else: + cmd_req_body[0] = 0x0 + + ret_val, cmd_rsp_body = self.__cable_cmd_execute(self.CABLE_CMD_GET_PCSFEC_STATS, cmd_hdr, cmd_req_body) + + if ret_val == 0: + dump_status_buff = cmd_rsp_body + + cmd_req_body[0] = 0x01 + ret_val, cmd_rsp_body = self.__cable_cmd_execute(self.CABLE_CMD_GET_PCSFEC_STATS, cmd_hdr, cmd_req_body) + if ret_val == 0: + for i in range(len(cmd_rsp_body)): + dump_status_buff.append(cmd_rsp_body[i]) + return dump_status_buff + + return None + + def cable_set_enadis_phy_chip_idle_loop(self, disable): + """ + This API enable or disable the phy chip idle loop + The port on which this API is called for can be referred using self.port. + Args: + disable: + an integer, + 1 - disable + 0 - enable + + Returns: + integer: + 0 on success and -1 on failure + + """ + + cmd_hdr = bytearray(5) + cmd_req_body = bytearray(self.MAX_REQ_PARAM_LEN) + + cmd_hdr[0] = 0 + cmd_hdr[1] = 0 + cmd_hdr[2] = 0 + cmd_hdr[3] = 0 + cmd_hdr[4] = 0 + + cmd_id = self.CABLE_CMD_ID_DISABLE_PHY_CHIP if disable else self.CABLE_CMD_ID_ENABLE_PHY_CHIP + ret_val, cmd_rsp_body = self.__cable_cmd_execute(cmd_id, cmd_hdr, cmd_req_body) + + if ret_val == 0: + return ret_val + + return None + + def enable_disable_watchdog_tor(self, disable): + """ + This API enable or disable the watchdog tor + The port on which this API is called for can be referred using self.port. + Args: + disable: + an integer, + 1 - disable + 0 - enable + + Returns: + integer: + 0 on success and -1 on failure + + """ + + curr_offset = ((0xFD * 128) + 180) + buffer1 = bytearray(1) + buffer1[0] = disable + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, buffer1) + if result is False: + return self.ERROR_WR_EEPROM_FAILED, None + + return self.RR_SUCCESS + + def enable_disable_watchdog_peer_tor(self, disable): + """ + This API enable or disable the watchdog tor peer + The port on which this API is called for can be referred using self.port. + Args: + disable: + an integer, + 1 - disable + 0 - enable + + Returns: + integer: + 0 on success and -1 on failure + + """ + + curr_offset = ((0xFC * 128) + 0x80) + command = bytearray(1) + command[0] = 0x8 if disable else 0x4 + result = self.platform_chassis.get_sfp(self.port).write_eeprom(curr_offset, 1, command) + if result is False: + return self.ERROR_WR_EEPROM_FAILED, None + + curr_offset = (0xFC * 128) + 0x80 + for _ in range(0, 30): + rd_done_status = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + if rd_done_status is None: + self.log(self.LOG_ERROR, "read status failed") + return self.EEPROM_ERROR + if rd_done_status[0] == 0: + break + + curr_offset = (0xFC * 128) + 0x82 + rd_err_st = self.platform_chassis.get_sfp(self.port).read_eeprom(curr_offset, 1) + if rd_err_st is None: + self.log(self.LOG_ERROR, "read error status failed") + return self.EEPROM_ERROR + + if rd_err_st[0] == 0: + return self.RR_SUCCESS + else: + return self.RR_ERROR + + def cable_enable_disable_watchdog_nic(self, disable): + """ + This API enable or disable the phy chip idle loop + The port on which this API is called for can be referred using self.port. + Args: + disable: + an integer, + 1 - disable + 0 - enable + + Returns: + integer: + 0 on success and -1 on failure + + """ + + cmd_hdr = bytearray(5) + cmd_req_body = bytearray(self.MAX_REQ_PARAM_LEN) + + cmd_hdr[0] = 0 + cmd_hdr[1] = 0 + cmd_hdr[2] = 0 + cmd_hdr[3] = 0 + cmd_hdr[4] = 0 + + cmd_id = self.CABLE_CMD_DISABLE_WATCHDOG if disable else self.CABLE_CMD_ENABLE_WATCHDOG + ret_val, cmd_rsp_body = self.__cable_cmd_execute(cmd_id, cmd_hdr, cmd_req_body) + + if ret_val == 0: + return ret_val + + return self.RR_ERROR + + def internal_pre_cmd_check(self, upgrade_info): + """ + This API calls the internal __pre_cmd_check function + """ + return self.__pre_cmd_check(upgrade_info) + + def internal_handle_cmd(self, upgrade_info, cmd_handle): + """ + This API calls the internal __handle_cmd function + """ + return self.__handle_cmd(upgrade_info, cmd_handle) +