From ac3e7f1230273ee5e8708917f6a970164f792377 Mon Sep 17 00:00:00 2001 From: vdahiya12 <67608553+vdahiya12@users.noreply.github.com> Date: Wed, 30 Mar 2022 16:17:47 -0700 Subject: [PATCH 01/11] [y_cable][Broadcom] update the BRCM y_cable driver to release 2.0 (#263) This release goes in sync with the following firmware version of Broadcom Y cable, which is consistent with release 8 version : { "nic": "D103.2_D208.3", "tor_a": "D308.3", "tor_b": "D308.3" } Description Basically a vendor specific implementation of abstract YCableBase class . detailed design discussion can be found https://github.com/Azure/SONiC/pull/757/files Motivation and Context to support the Y-Cable API required to support Broadcom's Y-Cable. How Has This Been Tested? put the changes in PMON, and all API's seem to run OK. Signed-off-by: vaibhav-dahiya --- sonic_y_cable/broadcom/y_cable_broadcom.py | 2643 +++++++++++++++++--- 1 file changed, 2347 insertions(+), 296 deletions(-) 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) + From 01512ecce4d6ce7272c0bbb7a5d47a1c02d92221 Mon Sep 17 00:00:00 2001 From: Kebo Liu Date: Tue, 5 Apr 2022 00:52:38 +0800 Subject: [PATCH 02/11] [SSD]Enhance ssd_generic with more error handling to avoid python crash #271 Signed-off-by: Kebo Liu kebol@nvidia.com Description Judge the self._parse_re return value, if it's N/A then stop further string slice handling to avoid a crash. Update the regular expression pattern for Innodisk SSD health, to handle the case that the output of the health section is different when its lifetime reaches the end. Motivation and Context Original code doesn't handle the case that self._parse_re returns N/A, it's assuming that self._parse_re will always return a none N/A value thus further handling the result w/o judge, which could in a crash. On Innodisk SSD, when the SSD remaining lifetime reaches the end, the output of the Health section will be a number w/o %, e.g. Health: 0.00 instead of Health: 95.0% in the normal case, need to update the regular expression to handle this case. How Has This Been Tested? UT test has been added. Tested the change on platforms with different types of SSD. --- sonic_platform_base/sonic_ssd/ssd_generic.py | 34 ++- tests/ssd_generic_test.py | 243 +++++++++++++++++++ 2 files changed, 271 insertions(+), 6 deletions(-) diff --git a/sonic_platform_base/sonic_ssd/ssd_generic.py b/sonic_platform_base/sonic_ssd/ssd_generic.py index f32e689f7..3f6a2bfe9 100644 --- a/sonic_platform_base/sonic_ssd/ssd_generic.py +++ b/sonic_platform_base/sonic_ssd/ssd_generic.py @@ -76,18 +76,40 @@ def fetch_generic_ssd_info(self, diskdev): def parse_generic_ssd_info(self): if "nvme" in self.dev: self.model = self._parse_re('Model Number:\s*(.+?)\n', self.ssd_info) - health_raw = self._parse_re('Percentage Used\s*(.+?)\n', self.ssd_info).split()[-1] - self.health = 100 - float(health_raw.strip('%')) - self.temperature = float(self._parse_re('Temperature\s*(.+?)\n', self.ssd_info).split()[-2]) + + health_raw = self._parse_re('Percentage Used\s*(.+?)\n', self.ssd_info) + if health_raw == NOT_AVAILABLE: + self.health = NOT_AVAILABLE + else: + health_raw = health_raw.split()[-1] + self.health = 100 - float(health_raw.strip('%')) + + temp_raw = self._parse_re('Temperature\s*(.+?)\n', self.ssd_info) + if temp_raw == NOT_AVAILABLE: + self.temperature = NOT_AVAILABLE + else: + temp_raw = temp_raw.split()[-2] + self.temperature = float(temp_raw) else: self.model = self._parse_re('Device Model:\s*(.+?)\n', self.ssd_info) - self.health = self._parse_re('Remaining_Lifetime_Perc\s*(.+?)\n', self.ssd_info).split()[-1] - self.temperature = self._parse_re('Temperature_Celsius\s*(.+?)\n', self.ssd_info).split()[-6] + + health_raw = self._parse_re('Remaining_Lifetime_Perc\s*(.+?)\n', self.ssd_info) + if health_raw == NOT_AVAILABLE: + self.health = NOT_AVAILABLE + else: + self.health = health_raw.split()[-1] + + temp_raw = self._parse_re('Temperature_Celsius\s*(.+?)\n', self.ssd_info) + if temp_raw == NOT_AVAILABLE: + self.temperature = NOT_AVAILABLE + else: + self.temperature = temp_raw.split()[-6] + self.serial = self._parse_re('Serial Number:\s*(.+?)\n', self.ssd_info) self.firmware = self._parse_re('Firmware Version:\s*(.+?)\n', self.ssd_info) def parse_innodisk_info(self): - self.health = self._parse_re('Health:\s*(.+?)%', self.vendor_ssd_info) + self.health = self._parse_re('Health:\s*(.+?)%?', self.vendor_ssd_info) self.temperature = self._parse_re('Temperature\s*\[\s*(.+?)\]', self.vendor_ssd_info) def parse_virtium_info(self): diff --git a/tests/ssd_generic_test.py b/tests/ssd_generic_test.py index 0e0c91727..5b6b82016 100644 --- a/tests/ssd_generic_test.py +++ b/tests/ssd_generic_test.py @@ -71,9 +71,205 @@ Num ErrCount SQId CmdId Status PELoc LBA NSID VS 0 5275 0 0x0001 0x0004 - 0 1 -""" +output_ssd = """smartctl 6.6 2017-11-05 r4594 [x86_64-linux-5.10.0-8-2-amd64] (local build) +Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org + +=== START OF INFORMATION SECTION === +Model Family: 3IE3/3ME3/3ME4 SSDs +Device Model: (S42) 3IE3 +Serial Number: BCA11712280210689 +LU WWN Device Id: 5 24693f 2ca215959 +Firmware Version: S16425i +User Capacity: 16,013,942,784 bytes [16.0 GB] +Sector Size: 512 bytes logical/physical +Rotation Rate: Solid State Device +Form Factor: 2.5 inches +Device is: In smartctl database [for details use: -P show] +ATA Version is: ATA8-ACS (minor revision not indicated) +SATA Version is: SATA 3.0, 6.0 Gb/s (current: 6.0 Gb/s) +Local Time is: Thu Mar 31 03:00:15 2022 UTC +SMART support is: Available - device has SMART capability. +SMART support is: Enabled + +=== START OF READ SMART DATA SECTION === +SMART overall-health self-assessment test result: PASSED + +General SMART Values: +Offline data collection status: (0x00) Offline data collection activity + was never started. + Auto Offline Data Collection: Disabled. +Total time to complete Offline +data collection: ( 32) seconds. +Offline data collection +capabilities: (0x00) Offline data collection not supported. +SMART capabilities: (0x0003) Saves SMART data before entering + power-saving mode. + Supports SMART auto save timer. +Error logging capability: (0x00) Error logging NOT supported. + No General Purpose Logging support. +SCT capabilities: (0x0039) SCT Status supported. + SCT Error Recovery Control supported. + SCT Feature Control supported. + SCT Data Table supported. + +SMART Attributes Data Structure revision number: 16 +Vendor Specific SMART Attributes with Thresholds: +ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE + 1 Raw_Read_Error_Rate 0x0000 000 000 000 Old_age Offline - 0 + 2 Throughput_Performance 0x0000 000 000 000 Old_age Offline - 0 + 3 Spin_Up_Time 0x0000 000 000 000 Old_age Offline - 0 + 5 Later_Bad_Block 0x0013 100 100 001 Pre-fail Always - 0 + 7 Seek_Error_Rate 0x0000 000 000 000 Old_age Offline - 0 + 8 Seek_Time_Performance 0x0000 000 000 000 Old_age Offline - 0 + 9 Power_On_Hours 0x0002 030 000 000 Old_age Always - 26142 + 10 Spin_Retry_Count 0x0000 000 000 000 Old_age Offline - 0 + 12 Power_Cycle_Count 0x0002 148 000 000 Old_age Always - 7828 +163 Total_Bad_Block_Count 0x0000 000 000 000 Old_age Offline - 8 +168 SATA_PHY_Error_Count 0x0000 000 000 000 Old_age Offline - 0 +169 Remaining_Lifetime_Perc 0x0000 095 000 000 Old_age Offline - 95 +175 Bad_Cluster_Table_Count 0x0000 000 000 000 Old_age Offline - 0 +192 Power-Off_Retract_Count 0x0000 000 000 000 Old_age Offline - 0 +194 Temperature_Celsius 0x0000 030 100 000 Old_age Offline - 30 (2 100 0 0 0) +197 Current_Pending_Sector 0x0012 000 100 000 Old_age Always - 0 +225 Data_Log_Write_Count 0x0000 000 029 000 Old_age Offline - 45712577 +240 Write_Head 0x0000 000 000 000 Old_age Offline - 0 +165 Max_Erase_Count 0x0002 220 001 000 Old_age Always - 988 +167 Average_Erase_Count 0x0002 213 001 000 Old_age Always - 981 +170 Spare_Block_Count 0x0003 100 001 000 Pre-fail Always - 146 +171 Program_Fail_Count 0x0002 000 001 000 Old_age Always - 0 +172 Erase_Fail_Count 0x0002 000 001 000 Old_age Always - 0 +176 RANGE_RECORD_Count 0x0000 100 001 000 Old_age Offline - 0 +187 Reported_Uncorrect 0x0002 000 001 000 Old_age Always - 0 +229 Flash_ID 0x0002 100 001 000 Old_age Always - 0x517693943a98 +232 Spares_Remaining_Perc 0x0003 100 001 000 Pre-fail Always - 0 +235 Later_Bad_Blk_Inf_R/W/E 0x0002 000 000 000 Old_age Always - 0 0 0 +241 Host_Writes_32MiB 0x0002 100 001 000 Old_age Always - 178564 +242 Host_Reads_32MiB 0x0002 100 001 000 Old_age Always - 760991 + +SMART Error Log not supported + +SMART Self-test Log not supported + +Selective Self-tests/Logging not supported""" + +output_Innodisk_ssd = """smartctl 6.6 2017-11-05 r4594 [x86_64-linux-4.19.0-12-2-amd64] (local build) +Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org + +=== START OF INFORMATION SECTION === +Model Family: Innodisk 1ME3/3ME/3SE SSDs +Device Model: InnoDisk Corp. - mSATA 3ME +Serial Number: 20171126AAAA11730156 +Firmware Version: S140714 +User Capacity: 32,017,047,552 bytes [32.0 GB] +Sector Size: 512 bytes logical/physical +Rotation Rate: Solid State Device +Form Factor: 2.5 inches +Device is: In smartctl database [for details use: -P show] +ATA Version is: ACS-2 (minor revision not indicated) +SATA Version is: SATA 3.0, 6.0 Gb/s (current: 6.0 Gb/s) +Local Time is: Thu Mar 31 08:24:17 2022 UTC +SMART support is: Available - device has SMART capability. +SMART support is: Enabled + +=== START OF READ SMART DATA SECTION === +SMART overall-health self-assessment test result: PASSED + +General SMART Values: +Offline data collection status: (0x00) Offline data collection activity + was never started. + Auto Offline Data Collection: Disabled. +Total time to complete Offline +data collection: ( 32) seconds. +Offline data collection +capabilities: (0x00) Offline data collection not supported. +SMART capabilities: (0x0003) Saves SMART data before entering + power-saving mode. + Supports SMART auto save timer. +Error logging capability: (0x00) Error logging NOT supported. + General Purpose Logging supported. +SCT capabilities: (0x0039) SCT Status supported. + SCT Error Recovery Control supported. + SCT Feature Control supported. + SCT Data Table supported. + +SMART Attributes Data Structure revision number: 16 +Vendor Specific SMART Attributes with Thresholds: +ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE + 1 Raw_Read_Error_Rate 0x0000 000 000 000 Old_age Offline - 0 + 2 Throughput_Performance 0x0000 000 000 000 Old_age Offline - 0 + 3 Spin_Up_Time 0x0000 000 000 000 Old_age Offline - 0 + 5 Reallocated_Sector_Ct 0x0002 100 100 000 Old_age Always - 0 + 7 Seek_Error_Rate 0x0000 000 000 000 Old_age Offline - 0 + 8 Seek_Time_Performance 0x0000 000 000 000 Old_age Offline - 0 + 9 Power_On_Hours 0x0002 100 100 000 Old_age Always - 32474 + 10 Spin_Retry_Count 0x0000 000 000 000 Old_age Offline - 0 + 12 Power_Cycle_Count 0x0002 100 100 000 Old_age Always - 297 +168 SATA_PHY_Error_Count 0x0000 000 000 000 Old_age Offline - 0 +169 Unknown_Innodisk_Attr 0x0000 000 000 000 Old_age Offline - 0x000000000000 +175 Bad_Cluster_Table_Count 0x0000 000 000 000 Old_age Offline - 0 +192 Power-Off_Retract_Count 0x0000 000 000 000 Old_age Offline - 0 + 1 Raw_Read_Error_Rate 0x0000 000 000 000 Old_age Offline - 2199023255552 +197 Current_Pending_Sector 0x0000 000 000 000 Old_age Offline - 0 +240 Write_Head 0x0000 000 000 000 Old_age Offline - 0 +225 Unknown_Innodisk_Attr 0x0000 000 000 000 Old_age Offline - 0 +170 Bad_Block_Count 0x0003 100 100 --- Pre-fail Always - 0 47 0 +173 Erase_Count 0x0002 100 100 --- Old_age Always - 0 7280 7192 +229 Flash_ID 0x0002 100 100 --- Old_age Always - 0x50769394de98 +236 Unstable_Power_Count 0x0002 100 100 --- Old_age Always - 0 +235 Later_Bad_Block 0x0002 100 000 --- Old_age Always - 0 +176 Uncorr_RECORD_Count 0x0000 100 000 --- Old_age Offline - 0 + +Read SMART Log Directory failed: scsi error badly formed scsi parameters + +SMART Error Log not supported + +SMART Self-test Log not supported + +Selective Self-tests/Logging not supported + +""" + +output_Innodisk_vendor_info = """******************************************************************************************** +* Innodisk iSMART V3.9.41 2018/05/25 * +******************************************************************************************** +Model Name: InnoDisk Corp. - mSATA 3ME +FW Version: S140714 +Serial Number: 20171126AAAA11730156 +Health: 0.00 +Capacity: 29.818199 GB +P/E Cycle: 3000 +Lifespan : 0 (Years : 0 Months : 0 Days : 0) +Write Protect: Disable +InnoRobust: Enable +-------------------------------------------------------------------------------------------- +ID SMART Attributes Value Raw Value +-------------------------------------------------------------------------------------------- +[09] Power On Hours [32474] [0902006464DA7E0000000000] +[0C] Power Cycle Count [ 297] [0C0200646429010000000000] +[AA] Total Bad Block Count [ 47] [AA0300646400002F00000000] +[AD] Erase Count Max. [ 7280] [AD02006464181C701C000000] +[AD] Erase Count Avg. [ 7192] [AD02006464181C701C000000] +[C2] Temperature [ 0] [000000000000000000000000] +[EB] Later Bad Block [ 0] [EB0200640000000000000000] +[EB] Read Block [ 0] [EB0200640000000000000000] +[EB] Write Block [ 0] [EB0200640000000000000000] +[EB] Erase Block [ 0] [EB0200640000000000000000] +[EC] Unstable Power Count [ 0] [EC0200646400000000000000] +""" + +output_lack_info_ssd = """smartctl 7.2 2020-12-30 r5155 [x86_64-linux-5.10.0-8-2-amd64] (local build) +Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools.org + +=== START OF INFORMATION SECTION === + +=== START OF SMART DATA SECTION === + + 0 5275 0 0x0001 0x0004 - 0 1 -""" + class TestSsdGeneric: @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_nvme_ssd)) def test_nvme_ssd(self): + # Test parsing nvme ssd info nvme_ssd = SsdUtil('/dev/nvme0n1') assert(nvme_ssd.get_health() == 100.0) assert(nvme_ssd.get_model() == 'SFPC020GM1EC2TO-I-5E-11P-STD') @@ -81,4 +277,51 @@ def test_nvme_ssd(self): assert(nvme_ssd.get_temperature() == 37) assert(nvme_ssd.get_serial() == "A0221030722410000027") + @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_lack_info_ssd)) + def test_nvme_ssd_with_na_path(self): + # Test parsing nvme ssd info which lack of expected sections + nvme_ssd = SsdUtil('/dev/nvme0n1') + assert(nvme_ssd.get_health() == 'N/A') + assert(nvme_ssd.get_model() == 'N/A') + assert(nvme_ssd.get_firmware() == "N/A") + assert(nvme_ssd.get_temperature() == "N/A") + assert(nvme_ssd.get_serial() == "N/A") + + @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_ssd)) + def test_ssd(self): + # Test parsing a normal ssd info + ssd = SsdUtil('/dev/sda') + assert(ssd.get_health() == '95') + assert(ssd.get_model() == '(S42) 3IE3') + assert(ssd.get_firmware() == 'S16425i') + assert(ssd.get_temperature() == '30') + assert(ssd.get_serial() == 'BCA11712280210689') + + @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_lack_info_ssd)) + def test_ssd_with_na_path(self): + # Test parsing normal ssd info which lack of expected sections + ssd = SsdUtil('/dev/sda') + assert(ssd.get_health() == 'N/A') + assert(ssd.get_model() == 'N/A') + assert(ssd.get_firmware() == "N/A") + assert(ssd.get_temperature() == "N/A") + assert(ssd.get_serial() == "N/A") + + @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_Innodisk_ssd)) + def test_Innodisk_ssd(self): + # Test parsing Innodisk ssd info + Innodisk_ssd = SsdUtil('/dev/sda') + assert(Innodisk_ssd.get_health() == 'N/A') + assert(Innodisk_ssd.get_model() == 'InnoDisk Corp. - mSATA 3ME') + assert(Innodisk_ssd.get_firmware() == "S140714") + assert(Innodisk_ssd.get_temperature() == 'N/A') + assert(Innodisk_ssd.get_serial() == "20171126AAAA11730156") + + Innodisk_ssd.vendor_ssd_info = output_Innodisk_vendor_info + Innodisk_ssd.parse_vendor_ssd_info('InnoDisk') + assert(Innodisk_ssd.get_health() == '0') + assert(Innodisk_ssd.get_model() == 'InnoDisk Corp. - mSATA 3ME') + assert(Innodisk_ssd.get_firmware() == "S140714") + assert(Innodisk_ssd.get_temperature() == '0') + assert(Innodisk_ssd.get_serial() == "20171126AAAA11730156") From b70e75979f704e980a3fb20732642ec99f32b0ee Mon Sep 17 00:00:00 2001 From: Kebo Liu Date: Mon, 11 Apr 2022 22:02:01 +0800 Subject: [PATCH 03/11] support new reboot-cause (#277) - Description Add some new reboot causes to cover followinging scenarios: BIOS - In case the BIOS upgrade process ended with failure and cause the switch to reset. CPU - Reset is initiated by SW on the CPU. it could be that SW encountered some catastrophic situation like a memory leak, eventually, the kernel reset the whole switch. Push button - Reset by pushing the reset button Reset from ASIC - Reset which is caused by ASIC. Motivation and Context Add more reboot causes to cover more scenarios. - How Has This Been Tested? UT is added with the code change. Run community reboot test to see the reboot cause checker can pass. Signed-off-by: Kebo Liu --- sonic_platform_base/chassis_base.py | 4 ++++ tests/chassis_base_test.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 tests/chassis_base_test.py diff --git a/sonic_platform_base/chassis_base.py b/sonic_platform_base/chassis_base.py index 96cec9e9e..e793a7bd1 100644 --- a/sonic_platform_base/chassis_base.py +++ b/sonic_platform_base/chassis_base.py @@ -24,6 +24,10 @@ class ChassisBase(device_base.DeviceBase): REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED = "Insufficient Fan Speed" REBOOT_CAUSE_WATCHDOG = "Watchdog" REBOOT_CAUSE_HARDWARE_OTHER = "Hardware - Other" + REBOOT_CAUSE_HARDWARE_BIOS = "BIOS" + REBOOT_CAUSE_HARDWARE_CPU = "CPU" + REBOOT_CAUSE_HARDWARE_BUTTON = "Push button" + REBOOT_CAUSE_HARDWARE_RESET_FROM_ASIC = "Reset from ASIC" REBOOT_CAUSE_NON_HARDWARE = "Non-Hardware" def __init__(self): diff --git a/tests/chassis_base_test.py b/tests/chassis_base_test.py new file mode 100644 index 000000000..c2f2e5f97 --- /dev/null +++ b/tests/chassis_base_test.py @@ -0,0 +1,18 @@ +from sonic_platform_base.chassis_base import ChassisBase + +class TestChassisBase: + + def test_reboot_cause(self): + chassis = ChassisBase() + assert(chassis.REBOOT_CAUSE_POWER_LOSS == "Power Loss") + assert(chassis.REBOOT_CAUSE_THERMAL_OVERLOAD_CPU == "Thermal Overload: CPU") + assert(chassis.REBOOT_CAUSE_THERMAL_OVERLOAD_ASIC == "Thermal Overload: ASIC") + assert(chassis.REBOOT_CAUSE_THERMAL_OVERLOAD_OTHER == "Thermal Overload: Other") + assert(chassis.REBOOT_CAUSE_INSUFFICIENT_FAN_SPEED == "Insufficient Fan Speed") + assert(chassis.REBOOT_CAUSE_WATCHDOG == "Watchdog") + assert(chassis.REBOOT_CAUSE_HARDWARE_OTHER == "Hardware - Other") + assert(chassis.REBOOT_CAUSE_HARDWARE_BIOS == "BIOS") + assert(chassis.REBOOT_CAUSE_HARDWARE_CPU == "CPU") + assert(chassis.REBOOT_CAUSE_HARDWARE_BUTTON == "Push button") + assert(chassis.REBOOT_CAUSE_HARDWARE_RESET_FROM_ASIC == "Reset from ASIC") + assert(chassis.REBOOT_CAUSE_NON_HARDWARE == "Non-Hardware") From 4e08440f13f0be6854b784e39e2865a5d2328d0b Mon Sep 17 00:00:00 2001 From: vdahiya12 <67608553+vdahiya12@users.noreply.github.com> Date: Thu, 14 Apr 2022 16:23:35 -0700 Subject: [PATCH 04/11] [Credo][Ycable] improve logging for Server Powered off/Faulty cables (#272) Signed-off-by: vaibhav-dahiya Signed-off-by: vaibhav-dahiya vdahiya@microsoft.com Cable could be powered off during which the i2c to the NIC MCU would not be able to respond with which side is active. For such cases the log needs to be improved. In case the cable is powered correctly but still the cable is not able to get the actve side, that would mean a faulty cable. Added/improved the appropriate logs Description Motivation and Context How Has This Been Tested? Improved logs only Additional Information (Optional) --- sonic_y_cable/credo/y_cable_credo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonic_y_cable/credo/y_cable_credo.py b/sonic_y_cable/credo/y_cable_credo.py index fd4aa67ca..e93c27866 100644 --- a/sonic_y_cable/credo/y_cable_credo.py +++ b/sonic_y_cable/credo/y_cable_credo.py @@ -617,7 +617,7 @@ def get_read_side(self): self.log_info("Reading from NIC side") return YCableBase.TARGET_NIC else: - self.log_error("Error: unknown status for checking which side regval = {} ".format(result)) + self.log_error("Error: Credo Y Cable unable to get the read side, Cable not plugged/Faulty Cable register value = {} ".format(result)) return YCableBase.TARGET_UNKNOWN @@ -675,7 +675,7 @@ def get_mux_direction(self): self.log_info("mux pointing to TOR B") return YCableBase.TARGET_TOR_B - self.log_error("Error: unknown status for mux direction regval = {} ".format(result)) + self.log_error("Error: Credo Y Cable unable to check the status mux direction, cable powered off/Faulty Cable register value = {}".format(result)) return YCableBase.TARGET_UNKNOWN def get_active_linked_tor_side(self): @@ -736,7 +736,7 @@ def get_active_linked_tor_side(self): self.log_info("Nothing linked for routing") return YCableBase.TARGET_NIC - self.log_error("Error: unknown status for active TOR regval = {} ".format(result)) + self.log_error("Error: Credo Y Cable unable to get active linked ToR side Cable powered off/Faulty Cable register value = {} ".format(result)) return YCableBase.TARGET_UNKNOWN def is_link_active(self, target): From f9181254bb750c3ce5b947fbfb62d66b1d4b097c Mon Sep 17 00:00:00 2001 From: dflynn-Nokia <60479697+dflynn-Nokia@users.noreply.github.com> Date: Mon, 2 May 2022 14:22:29 -0400 Subject: [PATCH 05/11] [syseeprom] Enable display of vendor extension TLV content (#270) Description The code that decodes the content of the ONIE syseeprom includes a flag to enable/disable displaying the content of the vendor extension TLV. This flag is currently set to 'disable'. Hence the 'show platform syseeprom' command shows the presence and size of the vendor extension TLV but does not show its content. This commit sets the flag to 'enable' so that the vendor extension TLV content is displayed. Motivation and Context The 'show platform syseeprom' command shows that the Vendor Extension TLV is present but does not show its content. Here's what that looks like on an example platform. --- sonic_platform_base/sonic_eeprom/eeprom_tlvinfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonic_platform_base/sonic_eeprom/eeprom_tlvinfo.py b/sonic_platform_base/sonic_eeprom/eeprom_tlvinfo.py index b7070d8a6..0961458cc 100644 --- a/sonic_platform_base/sonic_eeprom/eeprom_tlvinfo.py +++ b/sonic_platform_base/sonic_eeprom/eeprom_tlvinfo.py @@ -68,7 +68,7 @@ class TlvInfoDecoder(eeprom_base.EepromDecoder): _TLV_CODE_QUANTA_MODEL_NAME = _TLV_CODE_UNDEFINED # TLV Value Display Switch - _TLV_DISPLAY_VENDOR_EXT = False + _TLV_DISPLAY_VENDOR_EXT = True def __init__(self, path, start, status, ro, max_len=_TLV_INFO_MAX_LEN): From d62d3d6d86f8238b902b353b092d763a4c88998c Mon Sep 17 00:00:00 2001 From: Prince George <45705344+prgeor@users.noreply.github.com> Date: Wed, 4 May 2022 11:54:48 -0700 Subject: [PATCH 06/11] [CMIS]Fix low-power to high power mode transition (#268) * [CMIS]Fix low-power to high power mode transition * Remove python2 tests * Improve code coverage * Parametrize the test * Improve code coverage --- azure-pipelines.yml | 28 -- .../sonic_xcvr/api/public/cmis.py | 17 +- .../sonic_xcvr/mem_maps/public/cmis.py | 257 ++++-------------- tests/sonic_xcvr/test_cmis.py | 15 +- 4 files changed, 73 insertions(+), 244 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ece5dc2c5..b01a21c0f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -46,9 +46,6 @@ steps: - script: | set -xe - sudo pip2 install swsssdk-2.0.1-py2-none-any.whl - sudo pip2 install sonic_py_common-1.0-py2-none-any.whl - sudo pip2 install sonic_config_engine-1.0-py2-none-any.whl sudo pip3 install swsssdk-2.0.1-py3-none-any.whl sudo pip3 install sonic_py_common-1.0-py3-none-any.whl sudo pip3 install sonic_yang_mgmt-1.0-py3-none-any.whl @@ -66,31 +63,6 @@ steps: sudo apt-get install -y dotnet-sdk-5.0 displayName: "Install .NET CORE" -# Python 2 -- script: | - python2 setup.py test - displayName: 'Test Python 2' - -- task: PublishTestResults@2 - inputs: - testResultsFiles: '$(System.DefaultWorkingDirectory)/test-results.xml' - testRunTitle: Python 2 - failTaskOnFailedTests: true - condition: succeededOrFailed() - displayName: 'Publish Python 2 test results' - -- task: PublishCodeCoverageResults@1 - inputs: - codeCoverageTool: Cobertura - summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage.xml' - reportDirectory: '$(System.DefaultWorkingDirectory)/htmlcov/' - displayName: 'Publish Python 2 test coverage' - -- script: | - set -e - python2 setup.py bdist_wheel - displayName: 'Build Python 2 wheel' - # Python 3 - script: | python3 setup.py test diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index c47e20fa0..6b666987d 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -22,6 +22,8 @@ class CmisApi(XcvrApi): NUM_CHANNELS = 8 + LowPwrRequestSW = 4 + LowPwrAllowRequestHW = 6 def __init__(self, xcvr_eeprom): super(CmisApi, self).__init__(xcvr_eeprom) @@ -930,19 +932,20 @@ def set_lpmode(self, lpmode): lpmode_val = self.xcvr_eeprom.read(consts.MODULE_LEVEL_CONTROL) if lpmode_val is not None: if lpmode is True: - lpmode_val = lpmode_val | (1 << 4) + # Force module transition to LowPwr under SW control + lpmode_val = lpmode_val | (1 << CmisApi.LowPwrRequestSW) self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, lpmode_val) time.sleep(0.1) return self.get_lpmode() else: - lpmode_val = lpmode_val & ~(1 << 4) + # Force transition from LowPwr to HighPower state under SW control. + # This will transition LowPwrS signal to False. (see Table 6-12 CMIS v5.0) + lpmode_val = lpmode_val & ~(1 << CmisApi.LowPwrRequestSW) + lpmode_val = lpmode_val & ~(1 << CmisApi.LowPwrAllowRequestHW) self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, lpmode_val) time.sleep(1) - lpmode = self.xcvr_eeprom.read(consts.TRANS_MODULE_STATUS_FIELD) - if lpmode is not None: - if lpmode.get('ModuleState') == 'ModuleReady': - return True - return False + mstate = self.get_module_state() + return True if mstate == 'ModuleReady' else False return False def get_loopback_capability(self): diff --git a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py index bac7a7674..5d1c6dda9 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -53,118 +53,34 @@ def __init__(self, codes): CodeRegField(consts.CONNECTOR_FIELD, self.getaddr(0x0, 203), self.codes.CONNECTORS), RegGroupField(consts.APPLS_ADVT_FIELD, - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 1), self.getaddr(0x0, 86 + 4 * (1 - 1)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 2), self.getaddr(0x0, 86 + 4 * (2 - 1)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 3), self.getaddr(0x0, 86 + 4 * (3 - 1)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 4), self.getaddr(0x0, 86 + 4 * (4 - 1)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 5), self.getaddr(0x0, 86 + 4 * (5 - 1)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 6), self.getaddr(0x0, 86 + 4 * (6 - 1)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 7), self.getaddr(0x0, 86 + 4 * (7 - 1)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 8), self.getaddr(0x0, 86 + 4 * (8 - 1)), self.codes.HOST_ELECTRICAL_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 1), self.getaddr(0x0, 87 + 4 * (1 - 1)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 2), self.getaddr(0x0, 87 + 4 * (2 - 1)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 3), self.getaddr(0x0, 87 + 4 * (3 - 1)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 4), self.getaddr(0x0, 87 + 4 * (4 - 1)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 5), self.getaddr(0x0, 87 + 4 * (5 - 1)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 6), self.getaddr(0x0, 87 + 4 * (6 - 1)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 7), self.getaddr(0x0, 87 + 4 * (7 - 1)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 8), self.getaddr(0x0, 87 + 4 * (8 - 1)), self.codes.NM_850_MEDIA_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 1), self.getaddr(0x0, 87 + 4 * (1 - 1)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 2), self.getaddr(0x0, 87 + 4 * (2 - 1)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 3), self.getaddr(0x0, 87 + 4 * (3 - 1)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 4), self.getaddr(0x0, 87 + 4 * (4 - 1)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 5), self.getaddr(0x0, 87 + 4 * (5 - 1)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 6), self.getaddr(0x0, 87 + 4 * (6 - 1)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 7), self.getaddr(0x0, 87 + 4 * (7 - 1)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 8), self.getaddr(0x0, 87 + 4 * (8 - 1)), self.codes.SM_MEDIA_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 1), self.getaddr(0x0, 87 + 4 * (1 - 1)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 2), self.getaddr(0x0, 87 + 4 * (2 - 1)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 3), self.getaddr(0x0, 87 + 4 * (3 - 1)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 4), self.getaddr(0x0, 87 + 4 * (4 - 1)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 5), self.getaddr(0x0, 87 + 4 * (5 - 1)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 6), self.getaddr(0x0, 87 + 4 * (6 - 1)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 7), self.getaddr(0x0, 87 + 4 * (7 - 1)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 8), self.getaddr(0x0, 87 + 4 * (8 - 1)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 1), self.getaddr(0x0, 87 + 4 * (1 - 1)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 2), self.getaddr(0x0, 87 + 4 * (2 - 1)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 3), self.getaddr(0x0, 87 + 4 * (3 - 1)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 4), self.getaddr(0x0, 87 + 4 * (4 - 1)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 5), self.getaddr(0x0, 87 + 4 * (5 - 1)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 6), self.getaddr(0x0, 87 + 4 * (6 - 1)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 7), self.getaddr(0x0, 87 + 4 * (7 - 1)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 8), self.getaddr(0x0, 87 + 4 * (8 - 1)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 1), self.getaddr(0x0, 87 + 4 * (1 - 1)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 2), self.getaddr(0x0, 87 + 4 * (2 - 1)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 3), self.getaddr(0x0, 87 + 4 * (3 - 1)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 4), self.getaddr(0x0, 87 + 4 * (4 - 1)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 5), self.getaddr(0x0, 87 + 4 * (5 - 1)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 6), self.getaddr(0x0, 87 + 4 * (6 - 1)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 7), self.getaddr(0x0, 87 + 4 * (7 - 1)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 8), self.getaddr(0x0, 87 + 4 * (8 - 1)), self.codes.BASE_T_MEDIA_INTERFACE), - - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 1), self.getaddr(0x0, 88 + 4 * (1 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 2), self.getaddr(0x0, 88 + 4 * (2 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 3), self.getaddr(0x0, 88 + 4 * (3 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 4), self.getaddr(0x0, 88 + 4 * (4 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 5), self.getaddr(0x0, 88 + 4 * (5 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 6), self.getaddr(0x0, 88 + 4 * (6 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 7), self.getaddr(0x0, 88 + 4 * (7 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 8), self.getaddr(0x0, 88 + 4 * (8 - 1)), + *(CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, app), self.getaddr(0x0, 86 + 4 * (app - 1)), + self.codes.HOST_ELECTRICAL_INTERFACE) for app in range(1, 9)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, app), self.getaddr(0x0, 87 + 4 * (app- 1)), + self.codes.NM_850_MEDIA_INTERFACE) for app in range(1, 9)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, app), self.getaddr(0x0, 87 + 4 * (app - 1)), + self.codes.SM_MEDIA_INTERFACE) for app in range(1, 9)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, app), self.getaddr(0x0, 87 + 4 * (app - 1)), + self.codes.PASSIVE_COPPER_MEDIA_INTERFACE) for app in range(1, 9)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, app), self.getaddr(0x0, 87 + 4 * (app - 1)), + self.codes.ACTIVE_CABLE_MEDIA_INTERFACE) for app in range(1, 9)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, app), self.getaddr(0x0, 87 + 4 * (app - 1)), + self.codes.BASE_T_MEDIA_INTERFACE) for app in range(1, 9)), + + *(NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, lane), self.getaddr(0x0, 88 + 4 * (lane - 1)), *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 1), self.getaddr(0x0, 88 + 4 * (1 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 2), self.getaddr(0x0, 88 + 4 * (2 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 3), self.getaddr(0x0, 88 + 4 * (3 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 4), self.getaddr(0x0, 88 + 4 * (4 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 5), self.getaddr(0x0, 88 + 4 * (5 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 6), self.getaddr(0x0, 88 + 4 * (6 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 7), self.getaddr(0x0, 88 + 4 * (7 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 8), self.getaddr(0x0, 88 + 4 * (8 - 1)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), + ) for lane in range(1, 9)), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 1), self.getaddr(0x0, 89 + 4 * (1 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 2), self.getaddr(0x0, 89 + 4 * (2 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 3), self.getaddr(0x0, 89 + 4 * (3 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 4), self.getaddr(0x0, 89 + 4 * (4 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 5), self.getaddr(0x0, 89 + 4 * (5 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 6), self.getaddr(0x0, 89 + 4 * (6 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 7), self.getaddr(0x0, 89 + 4 * (7 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 8), self.getaddr(0x0, 89 + 4 * (8 - 1)), format="B", size=1), + *(NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, lane), self.getaddr(0x0, 88 + 4 * (lane - 1)), + *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) + ) for lane in range(1, 9)), + *(NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, lane), self.getaddr(0x0, 89 + 4 * (lane - 1)), + format="B", size=1) for lane in range(1, 9)), ), CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, self.getaddr(0x0, 86), self.codes.HOST_ELECTRICAL_INTERFACE), @@ -207,108 +123,37 @@ def __init__(self, codes): ), RegGroupField(consts.APPLS_ADVT_FIELD_PAGE01, - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 9), self.getaddr(0x1, 223 + 4 * (9 - 9)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 10), self.getaddr(0x1, 223 + 4 * (10 - 9)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 11), self.getaddr(0x1, 223 + 4 * (11 - 9)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 12), self.getaddr(0x1, 223 + 4 * (12 - 9)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 13), self.getaddr(0x1, 223 + 4 * (13 - 9)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 14), self.getaddr(0x1, 223 + 4 * (14 - 9)), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, 15), self.getaddr(0x1, 223 + 4 * (15 - 9)), self.codes.HOST_ELECTRICAL_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 9), self.getaddr(0x1, 224 + 4 * (9 - 9)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 10), self.getaddr(0x1, 224 + 4 * (10 - 9)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 11), self.getaddr(0x1, 224 + 4 * (11 - 9)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 12), self.getaddr(0x1, 224 + 4 * (12 - 9)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 13), self.getaddr(0x1, 224 + 4 * (13 - 9)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 14), self.getaddr(0x1, 224 + 4 * (14 - 9)), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, 15), self.getaddr(0x1, 224 + 4 * (15 - 9)), self.codes.NM_850_MEDIA_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 9), self.getaddr(0x1, 224 + 4 * (9 - 9)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 10), self.getaddr(0x1, 224 + 4 * (10 - 9)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 11), self.getaddr(0x1, 224 + 4 * (11 - 9)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 12), self.getaddr(0x1, 224 + 4 * (12 - 9)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 13), self.getaddr(0x1, 224 + 4 * (13 - 9)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 14), self.getaddr(0x1, 224 + 4 * (14 - 9)), self.codes.SM_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, 15), self.getaddr(0x1, 224 + 4 * (15 - 9)), self.codes.SM_MEDIA_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 9), self.getaddr(0x1, 224 + 4 * (9 - 9)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 10), self.getaddr(0x1, 224 + 4 * (10 - 9)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 11), self.getaddr(0x1, 224 + 4 * (11 - 9)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 12), self.getaddr(0x1, 224 + 4 * (12 - 9)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 13), self.getaddr(0x1, 224 + 4 * (13 - 9)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 14), self.getaddr(0x1, 224 + 4 * (14 - 9)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, 15), self.getaddr(0x1, 224 + 4 * (15 - 9)), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 9), self.getaddr(0x1, 224 + 4 * (9 - 9)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 10), self.getaddr(0x1, 224 + 4 * (10 - 9)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 11), self.getaddr(0x1, 224 + 4 * (11 - 9)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 12), self.getaddr(0x1, 224 + 4 * (12 - 9)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 13), self.getaddr(0x1, 224 + 4 * (13 - 9)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 14), self.getaddr(0x1, 224 + 4 * (14 - 9)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, 15), self.getaddr(0x1, 224 + 4 * (15 - 9)), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 9), self.getaddr(0x1, 224 + 4 * (9 - 9)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 10), self.getaddr(0x1, 224 + 4 * (10 - 9)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 11), self.getaddr(0x1, 224 + 4 * (11 - 9)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 12), self.getaddr(0x1, 224 + 4 * (12 - 9)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 13), self.getaddr(0x1, 224 + 4 * (13 - 9)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 14), self.getaddr(0x1, 224 + 4 * (14 - 9)), self.codes.BASE_T_MEDIA_INTERFACE), - CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, 15), self.getaddr(0x1, 224 + 4 * (15 - 9)), self.codes.BASE_T_MEDIA_INTERFACE), - - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 9), self.getaddr(0x1, 225 + 4 * (9 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 10), self.getaddr(0x1, 225 + 4 * (10 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 11), self.getaddr(0x1, 225 + 4 * (11 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 12), self.getaddr(0x1, 225 + 4 * (12 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 13), self.getaddr(0x1, 225 + 4 * (13 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 14), self.getaddr(0x1, 225 + 4 * (14 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), - NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, 15), self.getaddr(0x1, 225 + 4 * (15 - 9)), + *(CodeRegField("%s_%d" % (consts.HOST_ELECTRICAL_INTERFACE, app), self.getaddr(0x1, 223 + 4 * (app - 9)), + self.codes.HOST_ELECTRICAL_INTERFACE) for app in range(9, 16)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_850NM, app), self.getaddr(0x1, 224 + 4 * (app - 9)), + self.codes.NM_850_MEDIA_INTERFACE) for app in range(9, 16)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_SM, app), self.getaddr(0x1, 224 + 4 * (app - 9)), + self.codes.SM_MEDIA_INTERFACE) for app in range(9, 16)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, app), self.getaddr(0x1, 224 + 4 * (app - 9)), + self.codes.PASSIVE_COPPER_MEDIA_INTERFACE) for app in range(9, 16)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, app), self.getaddr(0x1, 224 + 4 * (app - 9)), + self.codes.ACTIVE_CABLE_MEDIA_INTERFACE) for app in range(9, 16)), + + *(CodeRegField("%s_%d" % (consts.MODULE_MEDIA_INTERFACE_BASE_T, app), self.getaddr(0x1, 224 + 4 * (app - 9)), + self.codes.BASE_T_MEDIA_INTERFACE) for app in range(9, 16)), + + *(NumberRegField("%s_%d" % (consts.MEDIA_LANE_COUNT, lane), self.getaddr(0x1, 225 + 4 * (lane - 9)), *(RegBitField("Bit%d" % (bit), bit) for bit in range (0, 4)) - ), + ) for lane in range(9, 16)), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 9), self.getaddr(0x1, 225 + 4 * (9 - 9)), + *(NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, lane), self.getaddr(0x1, 225 + 4 * (lane - 9)), *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 10), self.getaddr(0x1, 225 + 4 * (10 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 11), self.getaddr(0x1, 225 + 4 * (11 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 12), self.getaddr(0x1, 225 + 4 * (12 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 13), self.getaddr(0x1, 225 + 4 * (13 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 14), self.getaddr(0x1, 225 + 4 * (14 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), - NumberRegField("%s_%d" % (consts.HOST_LANE_COUNT, 15), self.getaddr(0x1, 225 + 4 * (15 - 9)), - *(RegBitField("Bit%d" % (bit), bit) for bit in range (4, 8)) - ), + ) for lane in range(9, 16)), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 9), self.getaddr(0x1, 226 + 4 * (9 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 10), self.getaddr(0x1, 226 + 4 * (10 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 11), self.getaddr(0x1, 226 + 4 * (11 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 12), self.getaddr(0x1, 226 + 4 * (12 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 13), self.getaddr(0x1, 226 + 4 * (13 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 14), self.getaddr(0x1, 226 + 4 * (14 - 1)), format="B", size=1), - NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, 15), self.getaddr(0x1, 226 + 4 * (15 - 1)), format="B", size=1), + *(NumberRegField("%s_%d" % (consts.HOST_LANE_ASSIGNMENT_OPTION, app), self.getaddr(0x1, 226 + 4 * (app - 1)), + format="B", size=1) for app in range(9, 16)), - *(NumberRegField("%s_%d" % (consts.MEDIA_LANE_ASSIGNMENT_OPTION, app), self.getaddr(0x1, 176 + (app - 1)), format="B", size=1) - for app in range(1, 16)) + *(NumberRegField("%s_%d" % (consts.MEDIA_LANE_ASSIGNMENT_OPTION, app), self.getaddr(0x1, 176 + (app - 1)), + format="B", size=1) for app in range(1, 16)) ) ) diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index a082eb243..f61a29832 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -837,12 +837,21 @@ def test_reset(self): assert kall is not None assert kall[0] == (consts.MODULE_LEVEL_CONTROL, 0x8) - def test_set_low_power(self): + @pytest.mark.parametrize("lpmode", [ + ([True], [False]) + ]) + def test_set_low_power(self, lpmode): + self.api.xcvr_eeprom.read = MagicMock() + self.api.xcvr_eeprom.read.return_value = True + self.api.xcvr_eeprom.write = MagicMock() + self.api.xcvr_eeprom.write.return_value = True self.api.is_flat_memory = MagicMock() self.api.is_flat_memory.return_value = False self.api.get_lpmode_support = MagicMock() - self.api.get_lpmode_support.return_value = False - self.api.set_lpmode(True) + self.api.get_lpmode_support.return_value = True + self.api.get_module_state = MagicMock() + self.api.get_module_state.return_value = "ModuleReady" + self.api.set_lpmode(lpmode) @pytest.mark.parametrize("mock_response, expected", [ ( From b0433720f8ec8987861eb68d02153159a0637b24 Mon Sep 17 00:00:00 2001 From: bill-nokia <104032696+bill-nokia@users.noreply.github.com> Date: Wed, 11 May 2022 02:41:20 -0400 Subject: [PATCH 07/11] [sonic_ssd] Nokia-7215: "show platform ssdhealth" not showing health percent (#279) Description The command is not showing the correct value for ssd health. admin@sonic:~$ show platform ssdhealth Device Model : M.2 (S42) 3IE4 Health : N/A Temperature : 25C Motivation and Context SSD health percentage not displayed on Nokia-7215 platform. How Has This Been Tested? "show platform ssdhealth" cli command Output after fix: admin@sonic:~$ show platform ssdhealth Device Model : M.2 (S42) 3IE4 Health : 100% Temperature : 25C --- sonic_platform_base/sonic_ssd/ssd_generic.py | 36 +++++--- tests/ssd_generic_test.py | 87 ++++++++++++++++++++ 2 files changed, 112 insertions(+), 11 deletions(-) diff --git a/sonic_platform_base/sonic_ssd/ssd_generic.py b/sonic_platform_base/sonic_ssd/ssd_generic.py index 3f6a2bfe9..610744127 100644 --- a/sonic_platform_base/sonic_ssd/ssd_generic.py +++ b/sonic_platform_base/sonic_ssd/ssd_generic.py @@ -20,6 +20,9 @@ NOT_AVAILABLE = "N/A" +# Set Vendor Specific IDs +INNODISK_HEALTH_ID = 169 +INNODISK_TEMPERATURE_ID = 194 class SsdUtil(SsdBase): """ @@ -109,24 +112,32 @@ def parse_generic_ssd_info(self): self.firmware = self._parse_re('Firmware Version:\s*(.+?)\n', self.ssd_info) def parse_innodisk_info(self): - self.health = self._parse_re('Health:\s*(.+?)%?', self.vendor_ssd_info) - self.temperature = self._parse_re('Temperature\s*\[\s*(.+?)\]', self.vendor_ssd_info) + if self.vendor_ssd_info: + self.health = self._parse_re('Health:\s*(.+?)%?', self.vendor_ssd_info) + self.temperature = self._parse_re('Temperature\s*\[\s*(.+?)\]', self.vendor_ssd_info) + else: + if self.health == NOT_AVAILABLE: + health_raw = self.parse_id_number(INNODISK_HEALTH_ID) + self.health = health_raw.split()[-1] + if self.temperature == NOT_AVAILABLE: + temp_raw = self.parse_id_number(INNODISK_TEMPERATURE_ID) + self.temperature = temp_raw.split()[-6] def parse_virtium_info(self): - self.temperature = self._parse_re('Temperature_Celsius\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info) - nand_endurance = self._parse_re('NAND_Endurance\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info) - avg_erase_count = self._parse_re('Average_Erase_Count\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info) - try: - self.health = 100 - (float(avg_erase_count) * 100 / float(nand_endurance)) - except ValueError: - pass + if self.vendor_ssd_info: + self.temperature = self._parse_re('Temperature_Celsius\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info) + nand_endurance = self._parse_re('NAND_Endurance\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info) + avg_erase_count = self._parse_re('Average_Erase_Count\s*\d*\s*(\d+?)\s+', self.vendor_ssd_info) + try: + self.health = 100 - (float(avg_erase_count) * 100 / float(nand_endurance)) + except (ValueError, ZeroDivisionError): + pass def fetch_vendor_ssd_info(self, diskdev, model): self.vendor_ssd_info = self._execute_shell(self.vendor_ssd_utility[model]["utility"].format(diskdev)) def parse_vendor_ssd_info(self, model): - if self.vendor_ssd_info: - self.vendor_ssd_utility[model]["parser"]() + self.vendor_ssd_utility[model]["parser"]() def get_health(self): """ @@ -183,3 +194,6 @@ def get_vendor_output(self): A string holding some vendor specific disk information """ return self.vendor_ssd_info + + def parse_id_number(self, id): + return self._parse_re('{}\s*(.+?)\n'.format(id), self.ssd_info) diff --git a/tests/ssd_generic_test.py b/tests/ssd_generic_test.py index 5b6b82016..980e0ce72 100644 --- a/tests/ssd_generic_test.py +++ b/tests/ssd_generic_test.py @@ -266,6 +266,84 @@ 0 5275 0 0x0001 0x0004 - 0 1 -""" +output_Innodisk_missing_names_ssd = """smartctl 6.6 2017-11-05 r4594 [armv7l-linux-4.19.0-12-2-armmp] (local build) +Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org + +=== START OF INFORMATION SECTION === +Model Family: Innodisk 3IE3/3ME3/3ME4 SSDs +Device Model: M.2 (S42) 3ME4 +Serial Number: YCA12003110020080 +LU WWN Device Id: 5 02b2a2 01d1c1b1a +Firmware Version: L17606 +User Capacity: 16,013,942,784 bytes [16.0 GB] +Sector Size: 512 bytes logical/physical +Rotation Rate: Solid State Device +Device is: In smartctl database [for details use: -P show] +ATA Version is: ACS-3 T13/2161-D revision 4 +SATA Version is: SATA 3.2, 6.0 Gb/s (current: 6.0 Gb/s) +Local Time is: Tue Apr 26 00:57:00 2022 UTC +SMART support is: Available - device has SMART capability. +SMART support is: Enabled + +=== START OF READ SMART DATA SECTION === +SMART overall-health self-assessment test result: PASSED + +General SMART Values: +Offline data collection status: (0x02) Offline data collection activity + was completed without error. + Auto Offline Data Collection: Disabled. +Total time to complete Offline +data collection: ( 32) seconds. +Offline data collection +capabilities: (0x00) Offline data collection not supported. +SMART capabilities: (0x0002) Does not save SMART data before + entering power-saving mode. + Supports SMART auto save timer. +Error logging capability: (0x00) Error logging NOT supported. + General Purpose Logging supported. + +SMART Attributes Data Structure revision number: 16 +Vendor Specific SMART Attributes with Thresholds: +ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE + 1 Raw_Read_Error_Rate 0x0000 000 000 000 Old_age Offline - 0 + 2 Throughput_Performance 0x0000 000 000 000 Old_age Offline - 0 + 5 Later_Bad_Block 0x0012 100 100 001 Old_age Always - 0 + 7 Seek_Error_Rate 0x0000 000 000 000 Old_age Offline - 0 + 8 Seek_Time_Performance 0x0000 000 000 000 Old_age Offline - 0 + 9 Power_On_Hours 0x0012 253 000 000 Old_age Always - 14151 + 10 Spin_Retry_Count 0x0000 000 000 000 Old_age Offline - 0 + 12 Power_Cycle_Count 0x0012 036 000 000 Old_age Always - 36 +163 Total_Bad_Block_Count 0x0000 000 000 000 Old_age Offline - 9 +168 SATA_PHY_Error_Count 0x0000 000 000 000 Old_age Offline - 0 +169 Unknown Attribute 0x0000 094 000 000 Old_age Offline - 94 +175 Bad_Cluster_Table_Count 0x0000 000 000 000 Old_age Offline - 0 +192 Power-Off_Retract_Count 0x0012 000 000 000 Old_age Always - 3 +194 Unknown Attribute 0x0002 039 100 000 Old_age Always - 39 (3 42 0 33 0) +197 Current_Pending_Sector 0x0000 000 000 000 Old_age Offline - 0 +225 Data_Log_Write_Count 0x0000 000 000 000 Old_age Offline - 0 +240 Write_Head 0x0000 000 000 000 Old_age Offline - 0 +165 Max_Erase_Count 0x0012 223 100 000 Old_age Always - 223 +167 Average_Erase_Count 0x0012 000 100 000 Old_age Always - 187 +170 Spare_Block_Count 0x0013 100 100 010 Pre-fail Always - 72 +171 Program_Fail_Count 0x0012 000 100 000 Old_age Always - 0 +172 Erase_Fail_Count 0x0012 000 100 000 Old_age Always - 0 +176 RANGE_RECORD_Count 0x0000 000 000 000 Old_age Offline - 0 +184 End-to-End_Error 0x0012 000 000 000 Old_age Always - 0 +187 Reported_Uncorrect 0x0012 000 000 000 Old_age Always - 0 +229 Flash_ID 0x0000 100 100 000 Old_age Offline - 0x51769394de98 +232 Spares_Remaining_Perc 0x0013 000 000 000 Pre-fail Always - 0 +235 Later_Bad_Blk_Inf_R/W/E 0x0002 000 000 000 Old_age Always - 0 0 0 +241 Host_Writes_32MiB 0x0002 100 100 000 Old_age Always - 14452 +242 Host_Reads_32MiB 0x0002 100 100 000 Old_age Always - 42566 + +SMART Error Log not supported + +SMART Self-test Log not supported + +Selective Self-tests/Logging not supported + +""" + class TestSsdGeneric: @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_nvme_ssd)) def test_nvme_ssd(self): @@ -325,3 +403,12 @@ def test_Innodisk_ssd(self): assert(Innodisk_ssd.get_temperature() == '0') assert(Innodisk_ssd.get_serial() == "20171126AAAA11730156") + @mock.patch('sonic_platform_base.sonic_ssd.ssd_generic.SsdUtil._execute_shell', mock.MagicMock(return_value=output_Innodisk_missing_names_ssd)) + def test_Innodisk_missing_names_ssd(self): + # Test parsing Innodisk ssd info + Innodisk_ssd = SsdUtil('/dev/sda') + Innodisk_ssd.vendor_ssd_info = '' + Innodisk_ssd.parse_vendor_ssd_info('InnoDisk') + assert(Innodisk_ssd.get_health() == '94') + assert(Innodisk_ssd.get_temperature() == '39') + From f575a401b83bbd5d6b6d68824ff22eae8647be16 Mon Sep 17 00:00:00 2001 From: vdahiya12 <67608553+vdahiya12@users.noreply.github.com> Date: Tue, 24 May 2022 15:12:40 -0700 Subject: [PATCH 08/11] [Credo][Ycable] changes for synchronizing executing Telemetry API's when mux toggle is inprogress (#280) In this PR, there is a support for adding a mux_toggle_status variable inside the base class for mux_cable. Using this variable the Derived classes for mux_cable can check this and return in case of a mux_toggle_status is in progress. From the higher layer this allows ycabled to synchronize the calls and not let mux_cable toggle to go in conjunction with some of the Telemetry calls. Signed-off-by: vaibhav-dahiya vdahiya@microsoft.com Description Motivation and Context To get the toggle time to a minimum/ not allow i2c to transactions on the cable to collide with each other How Has This Been Tested? Ran the changes on 7050cx3 arista testbed Signed-off-by: vaibhav-dahiya --- sonic_y_cable/credo/y_cable_credo.py | 23 +++++++++++++++++++++++ sonic_y_cable/y_cable_base.py | 10 ++++++++++ 2 files changed, 33 insertions(+) diff --git a/sonic_y_cable/credo/y_cable_credo.py b/sonic_y_cable/credo/y_cable_credo.py index e93c27866..7b5535b7d 100644 --- a/sonic_y_cable/credo/y_cable_credo.py +++ b/sonic_y_cable/credo/y_cable_credo.py @@ -695,6 +695,10 @@ def get_active_linked_tor_side(self): TARGET_TOR_B, if TOR B is actively linked and sending traffic. TARGET_UNKNOWN, if checking which side is linked and sending traffic API fails. """ + + if self.mux_toggle_status == self.MUX_TOGGLE_STATUS_INPROGRESS: + return YCableBase.TARGET_UNKNOWN + curr_offset = YCable.OFFSET_ACTIVE_TOR_INDICATOR if self.platform_chassis is not None: @@ -756,6 +760,10 @@ def is_link_active(self, target): a boolean, True if the link is active , False if the link is not active """ + + if self.mux_toggle_status == self.MUX_TOGGLE_STATUS_INPROGRESS: + return YCableBase.TARGET_UNKNOWN + curr_offset = YCable.OFFSET_CHECK_LINK_ACTIVE if self.platform_chassis is not None: @@ -825,6 +833,9 @@ def get_eye_heights(self, target): a list, with EYE values of lane 0 lane 1 lane 2 lane 3 with corresponding index """ + if self.mux_toggle_status == self.MUX_TOGGLE_STATUS_INPROGRESS: + return None + eye_result = [] if self.platform_chassis is not None: @@ -970,6 +981,9 @@ def get_switch_count_total(self, switch_count_type, clear_on_read=False): an integer, the number of times the Y-cable has been switched """ + if self.mux_toggle_status == self.MUX_TOGGLE_STATUS_INPROGRESS: + return 0 + count = 0 if self.platform_chassis is not None: @@ -1785,6 +1799,9 @@ def get_local_temperature(self): an Integer, the temperature of the local MCU """ + if self.mux_toggle_status == self.MUX_TOGGLE_STATUS_INPROGRESS: + return 0 + curr_offset = YCable.OFFSET_INTERNAL_TEMPERATURE if self.platform_chassis is not None: with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: @@ -1811,6 +1828,9 @@ def get_nic_voltage(self): a float, the voltage of the NIC MCU """ + if self.mux_toggle_status == self.MUX_TOGGLE_STATUS_INPROGRESS: + return 0 + if self.platform_chassis is not None: with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: if lock_status: @@ -1838,6 +1858,9 @@ def get_local_voltage(self): a float, the voltage of the local MCU """ + if self.mux_toggle_status == self.MUX_TOGGLE_STATUS_INPROGRESS: + return 0 + if self.platform_chassis is not None: with self.rlock.acquire_timeout(RLocker.ACQUIRE_LOCK_TIMEOUT) as lock_status: if lock_status: diff --git a/sonic_y_cable/y_cable_base.py b/sonic_y_cable/y_cable_base.py index 774c12db5..69892da36 100644 --- a/sonic_y_cable/y_cable_base.py +++ b/sonic_y_cable/y_cable_base.py @@ -78,6 +78,15 @@ class YCableBase(): FIRMWARE_DOWNLOAD_STATUS_FAILED = 2 + # Valid status values for mux togge + # The mux_toggle_status variable should be assigned/used + # one of these predefined values inside toggle/telemetry routine + # as to signify what is the current status of toggle in progress + + MUX_TOGGLE_STATUS_NOT_INITIATED_OR_FINISHED = 0 + MUX_TOGGLE_STATUS_INPROGRESS = 1 + + # definitions of PRBS run modes PRBS_DIRECTION_BOTH = 0 PRBS_DIRECTION_GENERATOR = 1 @@ -96,6 +105,7 @@ def __init__(self, port, logger): self.port = port self._logger = logger self.download_firmware_status = self.FIRMWARE_DOWNLOAD_STATUS_NOT_INITIATED_OR_FINISHED + self.mux_toggle_status = self.MUX_TOGGLE_STATUS_NOT_INITIATED_OR_FINISHED def log_warning(self, msg): From 04b08baab3b8231714fc80b001ce94c4513b60b0 Mon Sep 17 00:00:00 2001 From: Alexander Allen Date: Wed, 1 Jun 2022 16:58:34 -0400 Subject: [PATCH 09/11] [ssd_generic] Fix innodisk health regex (#287) Description The heath metric in ssd_generic for innodisk SSDs is too lazy. Fix to match the entire health number rather than just the first digit. How Has This Been Tested? Manual testing on Mellanox MSN2100 --- sonic_platform_base/sonic_ssd/ssd_generic.py | 2 +- tests/ssd_generic_test.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sonic_platform_base/sonic_ssd/ssd_generic.py b/sonic_platform_base/sonic_ssd/ssd_generic.py index 610744127..8d38d11e0 100644 --- a/sonic_platform_base/sonic_ssd/ssd_generic.py +++ b/sonic_platform_base/sonic_ssd/ssd_generic.py @@ -113,7 +113,7 @@ def parse_generic_ssd_info(self): def parse_innodisk_info(self): if self.vendor_ssd_info: - self.health = self._parse_re('Health:\s*(.+?)%?', self.vendor_ssd_info) + self.health = self._parse_re('Health:\s*(.+?)%', self.vendor_ssd_info) self.temperature = self._parse_re('Temperature\s*\[\s*(.+?)\]', self.vendor_ssd_info) else: if self.health == NOT_AVAILABLE: diff --git a/tests/ssd_generic_test.py b/tests/ssd_generic_test.py index 980e0ce72..73e89281c 100644 --- a/tests/ssd_generic_test.py +++ b/tests/ssd_generic_test.py @@ -235,7 +235,7 @@ Model Name: InnoDisk Corp. - mSATA 3ME FW Version: S140714 Serial Number: 20171126AAAA11730156 -Health: 0.00 +Health: 82.34% Capacity: 29.818199 GB P/E Cycle: 3000 Lifespan : 0 (Years : 0 Months : 0 Days : 0) @@ -397,7 +397,7 @@ def test_Innodisk_ssd(self): Innodisk_ssd.vendor_ssd_info = output_Innodisk_vendor_info Innodisk_ssd.parse_vendor_ssd_info('InnoDisk') - assert(Innodisk_ssd.get_health() == '0') + assert(Innodisk_ssd.get_health() == '82.34') assert(Innodisk_ssd.get_model() == 'InnoDisk Corp. - mSATA 3ME') assert(Innodisk_ssd.get_firmware() == "S140714") assert(Innodisk_ssd.get_temperature() == '0') From be04b801eb93b4408dd08f989bbf446910f6b864 Mon Sep 17 00:00:00 2001 From: "Marty Y. Lok" <76118573+mlok-nokia@users.noreply.github.com> Date: Thu, 9 Jun 2022 12:21:53 -0400 Subject: [PATCH 10/11] [multiasic][sfputil]Fix the sftpuitlhelper on mutilasic platform issue (#286) Signed-off-by: mlok --- sonic_platform_base/sonic_sfp/bcmshell.py | 8 +- .../sonic_sfp/sfputilhelper.py | 41 +++--- tests/0/port_config.ini | 7 ++ tests/1/port_config.ini | 8 ++ tests/platform_json/hwsku.json | 46 +++++++ tests/platform_json/platform.json | 117 ++++++++++++++++++ tests/port_config.ini | 28 ++--- tests/sfputilhelper_test.py | 104 +++++++++++++--- 8 files changed, 308 insertions(+), 51 deletions(-) create mode 100644 tests/0/port_config.ini create mode 100644 tests/1/port_config.ini create mode 100644 tests/platform_json/hwsku.json create mode 100644 tests/platform_json/platform.json diff --git a/sonic_platform_base/sonic_sfp/bcmshell.py b/sonic_platform_base/sonic_sfp/bcmshell.py index 244dfa672..99e8082f3 100644 --- a/sonic_platform_base/sonic_sfp/bcmshell.py +++ b/sonic_platform_base/sonic_sfp/bcmshell.py @@ -227,7 +227,7 @@ def getreg(self, reg, fields=False): # t = self.re_oneline.sub('', t) t = t.split('\n') - if t[-1] is '': + if t[-1] == '': t.pop() # get the results into a dict (module) of lists (array) of values/fields @@ -253,10 +253,10 @@ def __parse_reg__(text, fields=False): # now optimize the return # for I in iter(d): - if len(d[I]) is 1: + if len(d[I]) == 1: d[I] = d[I][0] - if len(d) is 1: + if len(d) == 1: return d.values()[0] else: return d @@ -319,7 +319,7 @@ def gettable(self, table, fields=False, start=None, entries=None): t = self.re_table_header.sub('', t) t = self.re_table_trailer.sub('', t) t = t.split('\n') - if t[-1] is '': + if t[-1] == '': t.pop() # parse the contents diff --git a/sonic_platform_base/sonic_sfp/sfputilhelper.py b/sonic_platform_base/sonic_sfp/sfputilhelper.py index f847a4370..7504729c7 100644 --- a/sonic_platform_base/sonic_sfp/sfputilhelper.py +++ b/sonic_platform_base/sonic_sfp/sfputilhelper.py @@ -13,7 +13,7 @@ from natsort import natsorted from portconfig import get_port_config - from sonic_py_common import device_info + from sonic_py_common import device_info, multi_asic from sonic_py_common.interface import backplane_prefix, inband_prefix, recirc_prefix except ImportError as e: @@ -22,6 +22,7 @@ # Global Variable PLATFORM_JSON = 'platform.json' PORT_CONFIG_INI = 'port_config.ini' +ASIC_NAME_PREFIX = 'asic' class SfpUtilHelper(object): # List to specify filter for sfp_ports @@ -52,7 +53,12 @@ def read_porttab_mappings(self, porttabfile, asic_inst=0): fp_port_index = 1 (platform, hwsku) = device_info.get_platform_and_hwsku() - ports, _, _ = get_port_config(hwsku, platform) + + asic_name = None + if multi_asic.is_multi_asic(): + asic_name = ASIC_NAME_PREFIX + str(asic_inst) + + ports, _, _ = get_port_config(hwsku, platform, asic_name=asic_name) if not ports: ports, _, _ = get_port_config(hwsku, platform, porttabfile) @@ -65,9 +71,9 @@ def read_porttab_mappings(self, porttabfile, asic_inst=0): logical_list.append(intf) # Ignore if this is an internal backplane interface and Inband interface - logical = [name for name in logical + logical = [name for name in logical_list if not name.startswith((backplane_prefix(), inband_prefix(), recirc_prefix()))] - logical = natsorted(logical_list, key=lambda y: y.lower()) + logical = natsorted(logical, key=lambda y: y.lower()) logical_to_physical, physical_to_logical = OrderedDict(), OrderedDict() for intf_name in logical: @@ -83,24 +89,25 @@ def read_porttab_mappings(self, porttabfile, asic_inst=0): # Mapping of logical port names available on a system to ASIC instance self.logical_to_asic[intf_name] = asic_inst - self.logical = logical - self.logical_to_physical = logical_to_physical - self.physical_to_logical = physical_to_logical + self.logical.extend(logical) + self.logical = list(set(self.logical)) + self.logical_to_physical.update(logical_to_physical) + self.physical_to_logical.update(physical_to_logical) return None def read_all_porttab_mappings(self, platform_dir, num_asic_inst): - # In multi asic scenario, get all the port_config files for different asics - for inst in range(num_asic_inst): - port_map_dir = os.path.join(platform_dir, str(inst)) - port_map_file = os.path.join(port_map_dir, PORT_CONFIG_INI) - if os.path.exists(port_map_file): - self.read_porttab_mappings(port_map_file, inst) - else: - port_json_file = os.path.join(port_map_dir, PLATFORM_JSON) - if os.path.exists(port_json_file): - self.read_porttab_mappings(port_json_file, inst) + # In multi asic scenario, get all the port_config files for different asic + for inst in range(num_asic_inst): + port_map_dir = os.path.join(platform_dir, str(inst)) + port_map_file = os.path.join(port_map_dir, PORT_CONFIG_INI) + if os.path.exists(port_map_file): + self.read_porttab_mappings(port_map_file, inst) + else: + port_json_file = os.path.join(platform_dir, PLATFORM_JSON) + if os.path.exists(port_json_file): + self.read_porttab_mappings(port_json_file, inst) def get_physical_to_logical(self, port_num): """Returns list of logical ports for the given physical port""" diff --git a/tests/0/port_config.ini b/tests/0/port_config.ini new file mode 100644 index 000000000..4fb083de5 --- /dev/null +++ b/tests/0/port_config.ini @@ -0,0 +1,7 @@ +# name lanes alias index +Ethernet0 29,30,31,32 fortyGigE0/0 1 +Ethernet4 25,26,27,28 fortyGigE0/4 2 +Ethernet8 37,38,39,40 fortyGigE0/8 3 +Ethernet12 33,34,35,36 fortyGigE0/12 4 +Ethernet16 41,42,43,44 fortyGigE0/16 5 +Ethernet20 45,46,47,48 fortyGigE0/20 6 diff --git a/tests/1/port_config.ini b/tests/1/port_config.ini new file mode 100644 index 000000000..01f154659 --- /dev/null +++ b/tests/1/port_config.ini @@ -0,0 +1,8 @@ +# name lanes alias index +Ethernet24 5,6,7,8 fortyGigE0/24 7 +Ethernet28 1,2,3,4 fortyGigE0/28 8 +Ethernet32 9,10,11,12 fortyGigE0/32 9 +Ethernet36 13,14,15,16 fortyGigE0/36 10 +Ethernet40 21,22,23,24 fortyGigE0/40 11 +Ethernet44 17,18,19,20 fortyGigE0/44 12 +Ethernet48 49,50,51,52 fortyGigE0/48 13 diff --git a/tests/platform_json/hwsku.json b/tests/platform_json/hwsku.json new file mode 100644 index 000000000..58bb6f1de --- /dev/null +++ b/tests/platform_json/hwsku.json @@ -0,0 +1,46 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet4": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet8": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet12": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet16": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet20": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet24": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet28": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet32": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet36": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet40": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet44": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet48": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + }, + "Ethernet52": { + "default_brkout_mode": "1x200G[100G,50G,40G,25G,10G,1G]" + } + } +} diff --git a/tests/platform_json/platform.json b/tests/platform_json/platform.json new file mode 100644 index 000000000..8f436859a --- /dev/null +++ b/tests/platform_json/platform.json @@ -0,0 +1,117 @@ +{ + "chassis": { + "name": "", + "components": [], + "fans": [], + "fan_drawers": [], + "psus": [], + "thermals": [], + "sfps": [] + }, + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "29,30,31,32", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp1"], + "2x100G[50G,25G,10G,1G]": ["etp1a", "etp1b"] + } + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "25,26,27,28", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp2"], + "2x100G[50G,25G,10G,1G]": ["etp2a", "etp2b"] + } + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "37,38,39,40", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp3"], + "2x100G[50G,25G,10G,1G]": ["etp3a", "etp3b"] + } + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "33,34,35,36", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp4"], + "2x100G[50G,25G,10G,1G]": ["etp4a", "etp4b"] + } + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "41,42,43,44", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp5"], + "2x100G[50G,25G,10G,1G]": ["etp5a", "etp5b"] + } + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "44,46,47,48", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp6"], + "2x100G[50G,25G,10G,1G]": ["etp6a", "etp6b"] + } + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "5,6,7,8", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp7"], + "2x100G[50G,25G,10G,1G]": ["etp7a", "etp7b"] + } + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "1,2,3,4", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp8"], + "2x100G[50G,25G,10G,1G]": ["etp8a", "etp8b"] + } + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "9,10,11,12", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp9"], + "2x100G[50G,25G,10G,1G]": ["etp9a", "etp9b"] + } + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "13,14,15,16", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp10"], + "2x100G[50G,25G,10G,1G]": ["etp10a", "etp10b"] + } + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "21,22,23,24", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp11"], + "2x100G[50G,25G,10G,1G]": ["etp11a", "etp11b"] + } + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "17,18,19,20", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp12"], + "2x100G[50G,25G,10G,1G]": ["etp12a", "etp12b"] + } + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "49,50,51,51", + "breakout_modes": { + "1x200G[100G,50G,40G,25G,10G,1G]": ["etp13"], + "2x100G[50G,25G,10G,1G]": ["etp13a", "etp13b"] + } + } + } +} diff --git a/tests/port_config.ini b/tests/port_config.ini index ed03fa85c..923cab7cf 100644 --- a/tests/port_config.ini +++ b/tests/port_config.ini @@ -1,14 +1,14 @@ -# name lanes alias -Ethernet0 29,30,31,32 fortyGigE0/0 -Ethernet4 25,26,27,28 fortyGigE0/4 -Ethernet8 37,38,39,40 fortyGigE0/8 -Ethernet12 33,34,35,36 fortyGigE0/12 -Ethernet16 41,42,43,44 fortyGigE0/16 -Ethernet20 45,46,47,48 fortyGigE0/20 -Ethernet24 5,6,7,8 fortyGigE0/24 -Ethernet28 1,2,3,4 fortyGigE0/28 -Ethernet32 9,10,11,12 fortyGigE0/32 -Ethernet36 13,14,15,16 fortyGigE0/36 -Ethernet40 21,22,23,24 fortyGigE0/40 -Ethernet44 17,18,19,20 fortyGigE0/44 -Ethernet48 49,50,51,52 fortyGigE0/48 +# name lanes alias index +Ethernet0 29,30,31,32 fortyGigE0/0 1 +Ethernet4 25,26,27,28 fortyGigE0/4 2 +Ethernet8 37,38,39,40 fortyGigE0/8 3 +Ethernet12 33,34,35,36 fortyGigE0/12 4 +Ethernet16 41,42,43,44 fortyGigE0/16 5 +Ethernet20 45,46,47,48 fortyGigE0/20 6 +Ethernet24 5,6,7,8 fortyGigE0/24 7 +Ethernet28 1,2,3,4 fortyGigE0/28 8 +Ethernet32 9,10,11,12 fortyGigE0/32 9 +Ethernet36 13,14,15,16 fortyGigE0/36 10 +Ethernet40 21,22,23,24 fortyGigE0/40 11 +Ethernet44 17,18,19,20 fortyGigE0/44 12 +Ethernet48 49,50,51,52 fortyGigE0/48 13 diff --git a/tests/sfputilhelper_test.py b/tests/sfputilhelper_test.py index 49342e561..e81280912 100644 --- a/tests/sfputilhelper_test.py +++ b/tests/sfputilhelper_test.py @@ -4,36 +4,75 @@ import pytest from sonic_platform_base.sonic_sfp import sfputilhelper +from unittest import mock +PORT_LIST = [ + "Ethernet0", + "Ethernet4", + "Ethernet8", + "Ethernet12", + "Ethernet16", + "Ethernet20", + "Ethernet24", + "Ethernet28", + "Ethernet32", + "Ethernet36", + "Ethernet40", + "Ethernet44", + "Ethernet48" +] + +LOGICAL_TO_PHYSICAL ={ + 'Ethernet0': [1], + 'Ethernet4': [2], + 'Ethernet8': [3], + 'Ethernet12': [4], + 'Ethernet16': [5], + 'Ethernet20': [6], + 'Ethernet24': [7], + 'Ethernet28': [8], + 'Ethernet32': [9], + 'Ethernet36': [10], + 'Ethernet40': [11], + 'Ethernet44': [12], + 'Ethernet48': [13] +} + +PHYSICAL_TO_LOGICAL = { + 1: ['Ethernet0'], + 2: ['Ethernet4'], + 3: ['Ethernet8'], + 4: ['Ethernet12'], + 5: ['Ethernet16'], + 6: ['Ethernet20'], + 7: ['Ethernet24'], + 8: ['Ethernet28'], + 9: ['Ethernet32'], + 10: ['Ethernet36'], + 11: ['Ethernet40'], + 12: ['Ethernet44'], + 13: ['Ethernet48'] +} + +test_dir = os.path.dirname(os.path.realpath(__file__)) +hwsku_json_file = os.path.join(test_dir, 'platform_json', 'hwsku.json') @pytest.fixture(scope="class") def setup_class(request): # Configure the setup - test_dir = os.path.dirname(os.path.realpath(__file__)) request.cls.port_config_file = os.path.join(test_dir, 'port_config.ini') + request.cls.platform_dir = os.path.dirname(os.path.realpath(__file__)) + request.cls.platform_json_dir = os.path.join(test_dir, 'platform_json') @pytest.mark.usefixtures("setup_class") class TestSfpUtilHelper(object): port_config_file = None + platform_dir = None + platform_json_dir = None def test_read_port_mappings(self): - PORT_LIST = [ - "Ethernet0", - "Ethernet4", - "Ethernet8", - "Ethernet12", - "Ethernet16", - "Ethernet20", - "Ethernet24", - "Ethernet28", - "Ethernet32", - "Ethernet36", - "Ethernet40", - "Ethernet44", - "Ethernet48" - ] sfputil_helper = sfputilhelper.SfpUtilHelper() sfputil_helper.read_porttab_mappings(self.port_config_file, 0) @@ -43,3 +82,36 @@ def test_read_port_mappings(self): for logical_port_name in logical_port_list: assert logical_port_name in PORT_LIST + + + @mock.patch('portconfig.get_hwsku_file_name', mock.MagicMock(return_value=hwsku_json_file)) + def test_read_all_port_mappings(self): + + sfputil_helper = sfputilhelper.SfpUtilHelper() + sfputil_helper.logical = [] + sfputil_helper.logical_to_physical = {} + sfputil_helper.physical_to_logica = {} + sfputil_helper.read_all_porttab_mappings(self.platform_dir, 2) + logical_port_list = sfputil_helper.logical + + assert len(logical_port_list) == len(PORT_LIST) + for logical_port_name in logical_port_list: + assert logical_port_name in PORT_LIST + assert sfputil_helper.logical_to_physical == LOGICAL_TO_PHYSICAL + assert sfputil_helper.physical_to_logical == PHYSICAL_TO_LOGICAL + + # test platform.json case + + sfputil_helper.logical = [] + sfputil_helper.logical_to_physical = {} + sfputil_helper.physical_to_logica = {} + sfputil_helper.read_all_porttab_mappings(self.platform_json_dir, 2) + logical_port_list = sfputil_helper.logical + + assert len(logical_port_list) == len(PORT_LIST) + + for logical_port_name in logical_port_list: + assert logical_port_name in PORT_LIST + + assert sfputil_helper.logical_to_physical == LOGICAL_TO_PHYSICAL + assert sfputil_helper.physical_to_logical == PHYSICAL_TO_LOGICAL From 0d45adb62f48637a575e09da7c61c58a7020e40e Mon Sep 17 00:00:00 2001 From: Prince George <45705344+prgeor@users.noreply.github.com> Date: Mon, 13 Jun 2022 15:23:59 -0700 Subject: [PATCH 11/11] Skip CDB and VDM for flat memory modules (#281) * Skip CDB and VDM for flat memory modules * Improve code coverage * Fix test failure * Fix test failure * Fix test failure --- .../sonic_xcvr/api/public/cmis.py | 20 ++++++++++++++++--- tests/sonic_xcvr/test_cmisCDB.py | 17 ++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index 6b666987d..4d0a9fea4 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -27,8 +27,8 @@ class CmisApi(XcvrApi): def __init__(self, xcvr_eeprom): super(CmisApi, self).__init__(xcvr_eeprom) - self.vdm = CmisVdmApi(xcvr_eeprom) - self.cdb = CmisCdbApi(xcvr_eeprom) + self.vdm = CmisVdmApi(xcvr_eeprom) if not self.is_flat_memory() else None + self.cdb = CmisCdbApi(xcvr_eeprom) if not self.is_flat_memory() else None def get_model(self): ''' @@ -1015,7 +1015,7 @@ def get_vdm(self): ''' This function returns all the VDM items, including real time monitor value, threholds and flags ''' - vdm = self.vdm.get_vdm_allpage() if not self.is_flat_memory() else {} + vdm = self.vdm.get_vdm_allpage() if self.vdm is not None else {} return vdm def get_module_firmware_fault_state_changed(self): @@ -1116,6 +1116,9 @@ def get_module_fw_mgmt_feature(self, verbose = False): the following upgrade with depend on these parameters. """ txt = '' + if self.cdb is None: + return {'status': False, 'info': "CDB Not supported", 'result': None} + # get fw upgrade features (CMD 0041h) starttime = time.time() autopaging = self.xcvr_eeprom.read(consts.AUTO_PAGING_SUPPORT) @@ -1166,6 +1169,10 @@ def get_module_fw_info(self): Validity Status: 1 = invalid, 0 = valid """ txt = '' + + if self.cdb is None: + return {'status': False, 'info': "CDB Not supported", 'result': None} + # get fw info (CMD 0100h) rpllen, rpl_chkcode, rpl = self.cdb.get_fw_info() # password issue @@ -1250,6 +1257,8 @@ def module_fw_run(self, mode = 0x01): """ # run module FW (CMD 0109h) txt = '' + if self.cdb is None: + return False, "CDB NOT supported on this module" starttime = time.time() fw_run_status = self.cdb.run_fw_image(mode) if fw_run_status == 1: @@ -1280,6 +1289,8 @@ def module_fw_commit(self): Otherwise it will return False. """ txt = '' + if self.cdb is None: + return False, "CDB NOT supported on this module" # commit module FW (CMD 010Ah) starttime = time.time() fw_commit_status= self.cdb.commit_fw_image() @@ -1337,6 +1348,9 @@ def module_fw_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin This function returns True if download successfully completes. Otherwise it will return False where it fails. """ txt = '' + if self.cdb is None: + return False, "CDB NOT supported on this module" + # start fw download (CMD 0101h) starttime = time.time() try: diff --git a/tests/sonic_xcvr/test_cmisCDB.py b/tests/sonic_xcvr/test_cmisCDB.py index b0a7396ac..6973e0245 100644 --- a/tests/sonic_xcvr/test_cmisCDB.py +++ b/tests/sonic_xcvr/test_cmisCDB.py @@ -1,5 +1,6 @@ from mock import MagicMock import pytest +from sonic_platform_base.sonic_xcvr.api.public.cmis import CmisApi from sonic_platform_base.sonic_xcvr.api.public.cmisCDB import CmisCdbApi from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom @@ -13,6 +14,18 @@ class TestCDB(object): eeprom = XcvrEeprom(reader, writer, mem_map) api = CmisCdbApi(eeprom) + def test_cdb_is_none(self): + api = CmisApi(self.eeprom) + api.cdb = None + print(api) + print(api.get_module_fw_mgmt_feature()) + assert False == api.get_module_fw_mgmt_feature()['status'] + assert False == api.get_module_fw_info()['status'] + assert False == api.module_fw_run()[0] + assert False == api.module_fw_commit()[0] + assert False == api.module_fw_download(None, None, None, None, None, None)[0] + + @pytest.mark.parametrize("mock_response, expected", [ (64, False), (0, True) @@ -101,7 +114,7 @@ def test_get_fw_management_features(self, mock_response, expected): self.api.cdb1_chkstatus = MagicMock() self.api.cdb1_chkstatus.return_value = mock_response[0] self.api.read_cdb = MagicMock() - self.api.read_cdb.return_value = mock_response[1] + self.api.read_cdb.return_value = mock_response[1] result = self.api.get_fw_management_features() assert result == expected @@ -185,7 +198,7 @@ def test_run_fw_image(self, mock_response, expected): self.api.cdb1_chkstatus.return_value = mock_response result = self.api.run_fw_image() assert result == expected - + @pytest.mark.parametrize("mock_response, expected", [ (1, 1), (64, 64),