From bbabcc4c0d05cdbdae50c6eadbf2ba159fbfbb20 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Mon, 30 Aug 2021 10:43:28 -0700 Subject: [PATCH 01/16] 400zr integration, add to state_db --- .../sonic_xcvr/api/public/cmis.py | 430 +++++++++++++++++- .../sonic_xcvr/codes/public/sff8024.py | 270 +++++++++++ .../sonic_xcvr/fields/consts.py | 148 +++++- .../sonic_xcvr/mem_maps/public/cmis.py | 140 +++++- 4 files changed, 966 insertions(+), 22 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index f8ce14857..5b6c02175 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -6,15 +6,443 @@ from ...fields import consts from ..xcvr_api import XcvrApi - +import time +BYTELENGTH = 8 class CmisApi(XcvrApi): NUM_CHANNELS = 8 def __init__(self, xcvr_eeprom): super(CmisApi, self).__init__(xcvr_eeprom) + # Transceiver Information def get_model(self): return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD) + def get_vendor_rev(self): + return self.xcvr_eeprom.read(consts.VENDOR_REV) + + def get_vendor_serial(self): + return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO) + + def get_vendor_name(self): + return self.xcvr_eeprom.read(consts.VENDOR_NAME_FIELD) + + def get_module_type(self): + return self.xcvr_eeprom.read(consts.ID_FIELD) + + def get_vendor_OUI(self): + return self.xcvr_eeprom.read(consts.VENDOR_OUI_FIELD) + + def get_vendor_date(self): + return self.xcvr_eeprom.read(consts.VENDOR_DATE) + + def get_connector_type(self): + return self.xcvr_eeprom.read(consts.CONNECTOR_TYPE) + + def get_module_media_type(self): + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_TYPE) + + def get_host_electrical_interface(self): + return self.xcvr_eeprom.read(consts.HOST_ELECTRICAL_INTERFACE) + + def get_module_media_interface(self): + media_type = self.get_module_media_type() + if media_type == 'Multimode Fiber (MMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM) + elif media_type == 'Single Mode Fiber (SMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_SM) + elif media_type == 'Passive Copper Cable': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER) + elif media_type == 'Active Cable Assembly': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE) + elif media_type == 'BASE-T': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_BASE_T) + else: + return 'Unknown media interface' + + def get_host_lane_count(self): + lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) + return (lane_count >> 4) & 0xf + + def get_media_lane_count(self): + lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) + return (lane_count) & 0xf + + def get_host_lane_assignment_option(self): + return self.xcvr_eeprom.read(consts.HOST_LANE_ASSIGNMENT_OPTION) + + def get_media_lane_assignment_option(self): + return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION) + + def get_active_apsel_hostlane1(self): + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_1) + return (result >> 4) & 0xf + + def get_active_apsel_hostlane2(self): + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_2) + return (result >> 4) & 0xf + + def get_active_apsel_hostlane3(self): + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_3) + return (result >> 4) & 0xf + + def get_active_apsel_hostlane4(self): + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_4) + return (result >> 4) & 0xf + + def get_active_apsel_hostlane5(self): + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_5) + return (result >> 4) & 0xf + + def get_active_apsel_hostlane6(self): + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_6) + return (result >> 4) & 0xf + + def get_active_apsel_hostlane7(self): + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_7) + return (result >> 4) & 0xf + + def get_active_apsel_hostlane8(self): + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_8) + return (result >> 4) & 0xf + + def get_media_interface_technology(self): + return self.xcvr_eeprom.read(consts.MEDIA_INTERFACE_TECH) + + def get_module_hardware_revision(self): + hw_major_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) + hw_minor_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) + hw_rev = [str(num) for num in [hw_major_rev, hw_minor_rev]] + return '.'.join(hw_rev) + + def get_cmis_rev(self): + cmis = self.xcvr_eeprom.read(consts.CMIS_REVISION) + cmis_major = (cmis >> 4) & 0xf + cmis_minor = (cmis) & 0xf + cmis_rev = [str(num) for num in [cmis_major, cmis_minor]] + return '.'.join(cmis_rev) + + def get_module_active_firmware(self): + active_fw_major = self.xcvr_eeprom.read(consts.ACTIVE_FW_MAJOR_REV) + active_fw_minor = self.xcvr_eeprom.read(consts.ACTIVE_FW_MINOR_REV) + active_fw = [str(num) for num in [active_fw_major, active_fw_minor]] + return '.'.join(active_fw) + + def get_module_inactive_firmware(self): + inactive_fw_major = self.xcvr_eeprom.read(consts.INACTIVE_FW_MAJOR_REV) + inactive_fw_minor = self.xcvr_eeprom.read(consts.INACTIVE_FW_MINOR_REV) + inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]] + return '.'.join(inactive_fw) + + # Transceiver DOM + def get_module_temperature(self): + return self.xcvr_eeprom.read(consts.CASE_TEMP) + + def get_module_voltage(self): + return self.xcvr_eeprom.read(consts.VOLTAGE) + + def get_rxpower1(self): + return self.xcvr_eeprom.read(consts.RX_POW1) + + def get_rxpower2(self): + return self.xcvr_eeprom.read(consts.RX_POW2) + + def get_rxpower3(self): + return self.xcvr_eeprom.read(consts.RX_POW3) + + def get_rxpower4(self): + return self.xcvr_eeprom.read(consts.RX_POW4) + + def get_txbias1(self): + return self.xcvr_eeprom.read(consts.TX_BIAS1) + + def get_txbias2(self): + return self.xcvr_eeprom.read(consts.TX_BIAS2) + + def get_txbias3(self): + return self.xcvr_eeprom.read(consts.TX_BIAS3) + + def get_txbias4(self): + return self.xcvr_eeprom.read(consts.TX_BIAS4) + + def get_freq_grid(self): + freq_grid = self.xcvr_eeprom.read(consts.GRID_SPACING) >> 4 + if freq_grid == 7: + return 75 + elif freq_grid == 6: + return 33 + elif freq_grid == 5: + return 100 + elif freq_grid == 4: + return 50 + elif freq_grid == 3: + return 25 + elif freq_grid == 2: + return 12.5 + elif freq_grid == 1: + return 6.25 + elif freq_grid == 0: + return 3.125 + + def get_laser_config_freq(self): + freq_grid = self.get_freq_grid() + channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) + if freq_grid == 75: + config_freq = 193100000 + channel * freq_grid/3*1000 + else: + config_freq = 193100000 + channel * freq_grid + return config_freq + + def get_current_laser_freq(self): + return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ) + + def get_TX_config_power(self): + return self.xcvr_eeprom.read(consts.TX_CONFIG_POWER) + + def get_media_output_loopback(self): + result = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) + return result == 1 + + def get_media_input_loopback(self): + result = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) + return result == 1 + + def get_host_output_loopback(self): + result = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) + loopback_status = [] + for bitpos in range(BYTELENGTH): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status + + def get_host_input_loopback(self): + result = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) + loopback_status = [] + for bitpos in range(BYTELENGTH): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status + + def get_aux_mon_type(self): + result = self.xcvr_eeprom.read(consts.AUX_MON_TYPE) + aux1_mon_type = result & 0x1 + aux2_mon_type = (result >> 1) & 0x1 + aux3_mon_type = (result >> 2) & 0x1 + return aux1_mon_type, aux2_mon_type, aux3_mon_type + + def get_laser_temp(self): + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + LASER_TEMP_SCALE = 256.0 + if aux2_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE + elif aux2_mon_type == 1 and aux3_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX3_MON)/LASER_TEMP_SCALE + else: + return None + return laser_temp + + def get_PM(self): + self.xcvr_eeprom.write(consts.FREEZE_REQUEST, 128) + time.sleep(1) + PM_dict = dict() + + rx_bits_pm = self.xcvr_eeprom.read(consts.RX_BITS_PM) + rx_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_BITS_SUB_INTERVAL_PM) + rx_corr_bits_pm = self.xcvr_eeprom.read(consts.RX_CORR_BITS_PM) + rx_min_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_CORR_BITS_SUB_INTERVAL_PM) + rx_max_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MAX_CORR_BITS_SUB_INTERVAL_PM) + + if (rx_bits_subint_pm != 0) and (rx_bits_pm != 0): + PM_dict['preFEC_BER_cur'] = rx_corr_bits_pm*1.0/rx_bits_pm + PM_dict['preFEC_BER_min'] = rx_min_corr_bits_subint_pm*1.0/rx_bits_subint_pm + PM_dict['preFEC_BER_max'] = rx_max_corr_bits_subint_pm*1.0/rx_bits_subint_pm + + rx_frames_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_PM) + rx_frames_subint_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_SUB_INTERVAL_PM) + rx_frames_uncorr_err_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_UNCORR_ERR_PM) + rx_min_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) + rx_max_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) + + if (rx_frames_subint_pm != 0) and (rx_frames_pm != 0): + PM_dict['preFEC_uncorr_frame_ratio_cur'] = rx_frames_uncorr_err_pm*1.0/rx_frames_subint_pm + PM_dict['preFEC_uncorr_frame_ratio_min'] = rx_min_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm + PM_dict['preFEC_uncorr_frame_ratio_max'] = rx_max_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm + + PM_dict['rx_cd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_CD_PM) + PM_dict['rx_cd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_CD_PM) + PM_dict['rx_cd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_CD_PM) + + PM_dict['rx_dgd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_DGD_PM) + PM_dict['rx_dgd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_DGD_PM) + PM_dict['rx_dgd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_DGD_PM) + + PM_dict['rx_sopmd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SOPMD_PM) + PM_dict['rx_sopmd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SOPMD_PM) + PM_dict['rx_sopmd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SOPMD_PM) + + PM_dict['rx_pdl_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_PDL_PM) + PM_dict['rx_pdl_min'] = self.xcvr_eeprom.read(consts.RX_MIN_PDL_PM) + PM_dict['rx_pdl_max'] = self.xcvr_eeprom.read(consts.RX_MAX_PDL_PM) + + PM_dict['rx_osnr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_OSNR_PM) + PM_dict['rx_osnr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_OSNR_PM) + PM_dict['rx_osnr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_OSNR_PM) + + PM_dict['rx_esnr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_ESNR_PM) + PM_dict['rx_esnr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_ESNR_PM) + PM_dict['rx_esnr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_ESNR_PM) + + PM_dict['rx_cfo_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_CFO_PM) + PM_dict['rx_cfo_min'] = self.xcvr_eeprom.read(consts.RX_MIN_CFO_PM) + PM_dict['rx_cfo_max'] = self.xcvr_eeprom.read(consts.RX_MAX_CFO_PM) + + PM_dict['rx_evm_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_EVM_PM) + PM_dict['rx_evm_min'] = self.xcvr_eeprom.read(consts.RX_MIN_EVM_PM) + PM_dict['rx_evm_max'] = self.xcvr_eeprom.read(consts.RX_MAX_EVM_PM) + + PM_dict['tx_power_avg'] = self.xcvr_eeprom.read(consts.TX_AVG_POWER_PM) + PM_dict['tx_power_min'] = self.xcvr_eeprom.read(consts.TX_MIN_POWER_PM) + PM_dict['tx_power_max'] = self.xcvr_eeprom.read(consts.TX_MAX_POWER_PM) + + PM_dict['rx_power_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_POWER_PM) + PM_dict['rx_power_min'] = self.xcvr_eeprom.read(consts.RX_MIN_POWER_PM) + PM_dict['rx_power_max'] = self.xcvr_eeprom.read(consts.RX_MAX_POWER_PM) + + PM_dict['rx_sigpwr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SIG_POWER_PM) + PM_dict['rx_sigpwr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SIG_POWER_PM) + PM_dict['rx_sigpwr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SIG_POWER_PM) + + PM_dict['rx_soproc_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SOPROC_PM) + PM_dict['rx_soproc_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SOPROC_PM) + PM_dict['rx_soproc_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SOPROC_PM) + + PM_dict['rx_mer_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_MER_PM) + PM_dict['rx_mer_min'] = self.xcvr_eeprom.read(consts.RX_MIN_MER_PM) + PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM) + + self.xcvr_eeprom.write(consts.FREEZE_REQUEST, 0) + return PM_dict + + def get_module_state(self): + result = self.xcvr_eeprom.read(consts.MODULE_STATE) >> 1 + DICT = self.xcvr_eeprom.mem_map.codes.MODULE_STATE + return DICT.get(result, "Unknown") + + def get_module_firmware_fault_state_changed(self): + result = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) + datapath_firmware_fault = bool((result >> 2) & 0x1) + module_firmware_fault = bool((result >> 1) & 0x1) + module_state_changed = bool(result & 0x1) + return datapath_firmware_fault, module_firmware_fault, module_state_changed + + def get_datapath_state(self): + result = self.xcvr_eeprom.read(consts.DATAPATH_STATE) + dp_lane7 = (result >> 0) & 0xf + dp_lane8 = (result >> 4) & 0xf + dp_lane5 = (result >> 8) & 0xf + dp_lane6 = (result >> 12) & 0xf + dp_lane3 = (result >> 16) & 0xf + dp_lane4 = (result >> 20) & 0xf + dp_lane1 = (result >> 24) & 0xf + dp_lane2 = (result >> 28) & 0xf + dp_state_raw = [dp_lane1, dp_lane2, dp_lane3, dp_lane4, dp_lane5, dp_lane6, dp_lane7, dp_lane8] + DICT = self.xcvr_eeprom.mem_map.codes.DATAPATH_STATE + dp_state = [DICT.get(dp_lane, "Unknown") for dp_lane in dp_state_raw] + return dp_state + + def get_tx_output_status(self): + result = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) + tx_output_status = [] + for bitpos in range(BYTELENGTH): + tx_output_status.append(bool((result >> bitpos) & 0x1)) + return tx_output_status + + def get_rx_output_status(self): + result = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) + rx_output_status = [] + for bitpos in range(BYTELENGTH): + rx_output_status.append(bool((result >> bitpos) & 0x1)) + return rx_output_status + + def get_tx_fault(self): + result = self.xcvr_eeprom.read(consts.TX_FAULT_FLAG) + tx_fault = [] + for bitpos in range(BYTELENGTH): + tx_fault.append(bool((result >> bitpos) & 0x1)) + return tx_fault + + def get_tx_los(self): + result = self.xcvr_eeprom.read(consts.TX_LOS_FLAG) + tx_los = [] + for bitpos in range(BYTELENGTH): + tx_los.append(bool((result >> bitpos) & 0x1)) + return tx_los + + def get_tx_cdr_lol(self): + result = self.xcvr_eeprom.read(consts.TX_CDR_LOL) + tx_lol = [] + for bitpos in range(BYTELENGTH): + tx_lol.append(bool((result >> bitpos) & 0x1)) + return tx_lol + + def get_rx_los(self): + result = self.xcvr_eeprom.read(consts.RX_LOS_FLAG) + rx_los = [] + for bitpos in range(BYTELENGTH): + rx_los.append(bool((result >> bitpos) & 0x1)) + return rx_los + + def get_rx_cdr_lol(self): + result = self.xcvr_eeprom.read(consts.RX_CDR_LOL) + rx_lol = [] + for bitpos in range(BYTELENGTH): + rx_lol.append(bool((result >> bitpos) & 0x1)) + return rx_lol + + def get_config_lane_status(self): + result = self.xcvr_eeprom.read(consts.CONFIG_LANE_STATUS) + config_status_lane7 = (result >> 0) & 0xf + config_status_lane8 = (result >> 4) & 0xf + config_status_lane5 = (result >> 8) & 0xf + config_status_lane6 = (result >> 12) & 0xf + config_status_lane3 = (result >> 16) & 0xf + config_status_lane4 = (result >> 20) & 0xf + config_status_lane1 = (result >> 24) & 0xf + config_status_lane2 = (result >> 28) & 0xf + config_status_raw = [config_status_lane1, config_status_lane2, config_status_lane3, config_status_lane4, + config_status_lane5, config_status_lane6, config_status_lane7, config_status_lane8] + DICT = self.xcvr_eeprom.mem_map.codes.CONFIG_STATUS + config_status = [DICT.get(config_lane, "Unknown") for config_lane in config_status_raw] + return config_status + + def get_dpinit_pending(self): + result = self.xcvr_eeprom.read(consts.DPINIT_PENDING) + dpinit_pending = [] + for bitpos in range(BYTELENGTH): + dpinit_pending.append(bool((result >> bitpos) & 0x1)) + return dpinit_pending + + def get_tuning_in_progress(self): + return bool(self.xcvr_eeprom.read(consts.TUNING_IN_PROGRESS)) + + def get_wavelength_unlocked(self): + return bool(self.xcvr_eeprom.read(consts.WAVELENGTH_UNLOCKED)) + + def get_laser_tuning_summary(self): + result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) + laser_tuning_summary = [] + if (result >> 5) & 0x1: + laser_tuning_summary.append("TargetOutputPowerOOR") + if (result >> 4) & 0x1: + laser_tuning_summary.append("FineTuningOutOfRange") + if (result >> 3) & 0x1: + laser_tuning_summary.append("TuningNotAccepted") + if (result >> 2) & 0x1: + laser_tuning_summary.append("InvalidChannel") + if (result >> 1) & 0x1: + laser_tuning_summary.append("WavelengthUnlocked") + if (result >> 0) & 0x1: + laser_tuning_summary.append("TuningComplete") + return laser_tuning_summary + + # TODO: other XcvrApi methods diff --git a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py index 5948b1af2..216348c53 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py @@ -41,4 +41,274 @@ class Sff8024(XcvrCodes): 30: 'QSFP+ or later with CMIS' } + CONNECTOR_TYPE = { + 0: 'Unknown or unspecified', + 1: 'SC', + 2: 'FC Style 1 copper connector', + 3: 'FC Style 2 copper connector', + 4: 'BNC/TNC', + 5: 'FC coax headers', + 6: 'Fiberjack', + 7: 'LC', + 8: 'MT-RJ', + 9: 'MU', + 10: 'SG', + 11: 'Optical Pigtail', + 12: 'MPO 1x12', + 13: 'MPO 2x16', + 32: 'HSSDC II', + 33: 'Copper pigtail', + 34: 'RJ45', + 35: 'No separable connector', + 36: 'MXC 2x16', + 37: 'CS optical connector', + 38: 'SN optical connector', + 39: 'MPO 2x12', + 40: 'MPO 1x16', + } + + + MODULE_MEDIA_TYPE = { + 0: 'Undefined', + 1: 'Multimode Fiber (MMF)', + 2: 'Single Mode Fiber (SMF)', + 3: 'Passive Copper Cable', + 4: 'Active Cable Assembly', + 5: 'BASE-T', + } + + HOST_ELECTRICAL_INTERFACE = { + 0: 'Undefined', + 1: '1000BASE -CX(Clause 39)', + 2: 'XAUI(Clause 47)', + 3: 'XFI (SFF INF-8071i)', + 4: 'SFI (SFF-8431)', + 5: '25GAUI C2M (Annex 109B)', + 6: 'XLAUI C2M (Annex 83B)', + 7: 'XLPPI (Annex 86A)', + 8: 'LAUI-2 C2M (Annex 135C)', + 9: '50GAUI-2 C2M (Annex 135E)', + 10: '50GAUI-1 C2M (Annex 135G)', + 11: 'CAUI-4 C2M (Annex 83E)', + 12: '100GAUI-4 C2M (Annex 135E)', + 13: '100GAUI-2 C2M (Annex 135G)', + 14: '200GAUI-8 C2M (Annex 120C)', + 15: '200GAUI-4 C2M (Annex 120E)', + 16: '400GAUI-16 C2M (Annex 120C)', + 17: '400GAUI-8 C2M (Annex 120E)', + 19: '10GBASE-CX4 (Clause 54)', + 20: '25GBASE-CR CA-L (Clause 110)', + 21: '25GBASE-CR CA-S (Clause 110)', + 22: '25GBASE-CR CA-N (Clause 110)', + 23: '40GBASE-CR4 (Clause 85)', + 24: '50GBASE-CR (Clause 126)', + 25: '100GBASE-CR10 (Clause 85)', + 26: '100GBASE-CR4 (Clause 92)', + 27: '100GBASE-CR2 (Clause 136)', + 28: '200GBASE-CR4 (Clause 136)', + 29: '400G CR8', + 30: '1000BASE-T (Clause 40)', + 31: '2.5GBASE-T (Clause 126)', + 32: '5GBASE-T (Clause 126)', + 33: '10GBASE-T (Clause 55)', + 34: '25GBASE-T (Clause 113)', + 35: '40GBASE-T (Clause 113)', + 36: '50GBASE-T (Placeholder)', + 37: '8GFC (FC-PI-4)', + 38: '10GFC (10GFC)', + 39: '16GFC (FC-PI-5)', + 40: '32GFC (FC-PI-6)', + 41: '64GFC (FC-PI-7)', + 42: '128GFC (FC-PI-6P)', + 43: '256GFC (FC-PI-7P)', + 44: 'IB SDR (Arch.Spec.Vol.2)', + 45: 'IB DDR (Arch.Spec.Vol.2)', + 46: 'IB QDR (Arch.Spec.Vol.2)', + 47: 'IB FDR (Arch.Spec.Vol.2)', + 48: 'IB EDR (Arch.Spec.Vol.2)', + 49: 'IB HDR (Arch.Spec.Vol.2)', + 50: 'IB NDR', + 51: 'E.96 (CPRI Specification V7.0)', + 52: 'E.99 (CPRI Specification V7.0)', + 53: 'E.119 (CPRI Specification V7.0)', + 54: 'E.238 (CPRI Specification V7.0)', + 55: 'OTL3.4 (ITU-T G.709/Y.1331 G.Sup58)', + 56: 'OTL4.10 (ITU-T G.709/Y.1331 G.Sup58)', + 57: 'OTL4.4 (ITU-T G.709/Y.1331 G.Sup58)', + 58: 'OTLC.4 (ITU-T G.709.1/Y.1331 G.Sup58)', + 59: 'FOIC1.4 (ITU-T G.709.1/Y.1331 G.Sup58)', + 60: 'FOIC1.2 (ITU-T G.709.1/Y.1331 G.Sup58)', + 61: 'FOIC2.8 (ITU-T G.709.1/Y.1331 G.Sup58)', + 62: 'FOIC2.4 (ITU-T G.709.1/Y.1331 G.Sup58)', + 63: 'FOIC4.16 (ITU-T G.709.1 G.Sup58)', + 64: 'FOIC4.8 (ITU-T G.709.1 G.Sup58)', + } + + NM_850_MEDIA_INTERFACE = { + 0: 'Undefined', + 1: '10GBASE-SW (Clause 52)', + 2: '10GBASE-SR (Clause 52)', + 3: '25GBASE-SR (Clause 112)', + 4: '40GBASE-SR4 (Clause 86)', + 5: '40GE SWDM4 MSA Spec', + 6: '40GE BiDi', + 7: '50GBASE-SR (Clause 138)', + 8: '100GBASE-SR10 (Clause 86)', + 9: '100GBASE-SR4 (Clause 95)', + 10: '100GE SWDM4 MSA Spec', + 11: '100GE BiDi', + 12: '100GBASE-SR2 (Clause 138)', + 13: '100G-SR (Placeholder)', + 14: '200GBASE-SR4 (Clause 138)', + 15: '400GBASE-SR16 (Clause 123)', + 16: '400GBASE-SR8 (Clause 138)', + 17: '400G-SR4 (Placeholder)', + 18: '800G-SR8 (Placeholder)', + 26: '400GBASE-SR4.2 (Clause 150) (400GE BiDi)', + 19: '8GFC-MM (FC-PI-4)', + 20: '10GFC-MM (10GFC)', + 21: '16GFC-MM (FC-PI-5)', + 22: '32GFC-MM (FC-PI-6)', + 23: '64GFC-MM (FC-PI 7)', + 24: '128GFC-MM4 (FC-PI-6P)', + 25: '256GFC-MM4 (FC-PI-7P)', + } + + SM_MEDIA_INTERFACE = { + 0: 'Undefined', + 1: '10GBASE-LW (Cl 52)', + 2: '10GBASE-EW (Cl 52)', + 3: '10G-ZW', + 4: '10GBASE-LR (Cl 52)', + 5: '10GBASE-ER (Cl 52)', + 6: '10G-ZR', + 7: '25GBASE-LR (Cl 114)', + 8: '25GBASE-ER (Cl 114)', + 9: '40GBASE-LR4 (Cl 87)', + 10: '40GBASE-FR (Cl 89)', + 11: '50GBASE-FR (Cl 139)', + 12: '50GBASE-LR (Cl 139)', + 13: '100GBASE-LR4 (Cl 88)', + 14: '100GBASE-ER4 (Cl 88)', + 15: '100G PSM4 MSA Spec', + 16: '100G CWDM4 MSA Spec', + 17: '100G 4WDM-10 MSA Spec', + 18: '100G 4WDM-20 MSA Spec', + 19: '100G 4WDM-40 MSA Spec', + 20: '100GBASE-DR (Cl 140)', + 21: '100G-FR/100GBASE-FR1 (Cl 140)', + 22: '100G-LR/100GBASE-LR1 (Cl 140)', + 23: '200GBASE-DR4 (Cl 121)', + 24: '200GBASE-FR4 (Cl 122)', + 25: '200GBASE-LR4 (Cl 122)', + 26: '400GBASE-FR8 (Cl 122)', + 27: '400GBASE-LR8 (Cl 122)', + 28: '400GBASE-DR4 (Cl 124)', + 29: '400G-FR4/400GBASE-FR4 (Cl 151)', + 30: '400G-LR4-10', + 31: '8GFC-SM (FC-PI-4)', + 32: '10GFC-SM (10GFC)', + 33: '16GFC-SM (FC-PI-5)', + 34: '32GFC-SM (FC-PI-6)', + 35: '64GFC-SM (FC-PI-7)', + 36: '128GFC-PSM4 (FC-PI-6P)', + 37: '256GFC-PSM4 (FC-PI-7P)', + 38: '128GFC-CWDM4 (FC-PI-6P)', + 39: '256GFC-CWDM4 (FC-PI-7P)', + 44: '4I1-9D1F (G.959.1)', + 45: '4L1-9C1F (G.959.1)', + 46: '4L1-9D1F (G.959.1)', + 47: 'C4S1-9D1F (G.695)', + 48: 'C4S1-4D1F (G.695)', + 49: '4I1-4D1F (G.959.1)', + 50: '8R1-4D1F (G.959.1)', + 51: '8I1-4D1F (G.959.1)', + 56: '10G-SR', + 57: '10G-LR', + 58: '25G-SR', + 59: '25G-LR', + 60: '10G-LR-BiDi', + 61: '25G-LR-BiDi', + 62: '400ZR, DWDM, amplified', + 63: '400ZR, Single Wavelength, Unamplified', + 70: 'ZR400-OFEC-16QAM', + 71: 'ZR300-OFEC-8QAM', + 72: 'ZR200-OFEC-QPSK', + 73: 'ZR100-OFEC-QPSK', + } + + PASSIVE_COPPER_MEDIA_INTERFACE = { + '00': 'Undefined', + '01': 'Copper cable', + '02': 'Passive Loopback module', + } + + ACTIVE_CABLE_MEDIA_INTERFACE = { + '00': 'Undefined', + '01': 'Active Cable assembly with BER < 10^-12', + '02': 'Active Cable assembly with BER < 5x10^-5', + '03': 'Active Cable assembly with BER < 2.6x10^-4', + '04': 'Active Cable assembly with BER < 10^-6', + 'bf': 'Active Loopback module', + } + + BASE_T_MEDIA_INTERFACE = { + '00': 'Undefined', + '01': '1000BASE-T (Clause 40)', + '02': '2.5GBASE-T (Clause 126)', + '03': '5GBASE-T (Clause 126)', + '04': '10GBASE-T (Clause 55)', + } + + MEDIA_INTERFACE_TECH = { + 0: '850 nm VCSEL', + 1: '1310 nm VCSEL', + 2: '1550 nm VCSEL', + 3: '1310 nm FP', + 4: '1310 nm DFB', + 5: '1550 nm DFB', + 6: '1310 nm EML', + 7: '1550 nm EML', + 8: 'Others', + 9: '1490 nm DFB', + 10: 'Copper cable unequalized', + 11: 'Copper cable passive equalized', + 12: 'Copper cable, near and far end limiting active equalizers', + 13: 'Copper cable, far end limiting active equalizers', + 14: 'Copper cable, near end limiting active equalizers', + 15: 'Copper cable, linear active equalizers', + 16: 'C-band tunable laser', + 17: 'L-band tunable laser', + } + + MODULE_STATE = { + 1: 'ModuleLowPwr', + 2: 'ModulePwrUp', + 3: 'ModuleReady', + 4: 'ModulePwrDn', + 5: 'ModuleFault', + } + + DATAPATH_STATE = { + 1: 'DataPathDeactivated', + 2: 'DataPathInit', + 3: 'DataPathDeinit', + 4: 'DataPathActivated', + 5: 'DataPathTxTurnOn', + 6: 'DataPathTxTurnOff', + 7: 'DataPathInitialized', + } + + CONFIG_STATUS = { + 0: 'ConfigUndefined', + 1: 'ConfigSuccess', + 2: 'ConfigRejected', + 3: 'ConfigRejectedInvalidAppSel', + 4: 'ConfigRejectedInvalidDataPath', + 5: 'ConfigRejectedInvalidSI', + 6: 'ConfigRejectedLaneInUse', + 7: 'ConfigRejectedPartialDataPath', + 12: 'ConfigInProgress', + } + # TODO: Add other codes diff --git a/sonic_platform_base/sonic_xcvr/fields/consts.py b/sonic_platform_base/sonic_xcvr/fields/consts.py index 088b8ad10..535dd1b20 100644 --- a/sonic_platform_base/sonic_xcvr/fields/consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/consts.py @@ -1,27 +1,149 @@ # COMMON - +ADMIN_INFO_FIELD = "AdminInfo" ID_FIELD = "Identifier" - VENDOR_NAME_FIELD = "VendorName" VENDOR_OUI_FIELD = "VendorOUI" VENDOR_PART_NO_FIELD = "VendorPN" +VENDOR_REV = "VendorRev" +VENDOR_SERIAL_NO = "VendorSN" +VENDOR_DATE = "DateCode" +CONNECTOR_TYPE = "ConnectorType" +MODULE_MEDIA_TYPE = "ModuleMediaType" +HOST_ELECTRICAL_INTERFACE = "HostElectricalInterfaceID" +MODULE_MEDIA_INTERFACE_850NM = "ModuleMediaInterface850nm" +MODULE_MEDIA_INTERFACE_SM = "ModuleMediaInterfaceSM" +MODULE_MEDIA_INTERFACE_PASSIVE_COPPER = "ModuleMediaInterfacePassiveCopper" +MODULE_MEDIA_INTERFACE_ACTIVE_CABLE = "ModuleMediaInterfaceActiveCable" +MODULE_MEDIA_INTERFACE_BASE_T = "ModuleMediaInterfaceBaseT" +LANE_COUNT = "LaneCount" +HOST_LANE_ASSIGNMENT_OPTION = "HostLaneAssignmentOptions" +MEDIA_LANE_ASSIGNMENT_OPTION = "MediaLaneAssignmentOptions" +ACTIVE_APSEL_HOSTLANE_1 = "ActiveSetLane1" +ACTIVE_APSEL_HOSTLANE_2 = "ActiveSetLane2" +ACTIVE_APSEL_HOSTLANE_3 = "ActiveSetLane3" +ACTIVE_APSEL_HOSTLANE_4 = "ActiveSetLane4" +ACTIVE_APSEL_HOSTLANE_5 = "ActiveSetLane5" +ACTIVE_APSEL_HOSTLANE_6 = "ActiveSetLane6" +ACTIVE_APSEL_HOSTLANE_7 = "ActiveSetLane7" +ACTIVE_APSEL_HOSTLANE_8 = "ActiveSetLane8" +MEDIA_INTERFACE_TECH = "MediaInterfaceTechnology" +HW_MAJOR_REV = "ModuleHardwareMajorRevision" +HW_MINOR_REV = "ModuleHardwareMinorRevision" +CMIS_REVISION = "CmisRevision" +ACTIVE_FW_MAJOR_REV = "ModuleActiveFirmwareMajorRevision" +ACTIVE_FW_MINOR_REV = "ModuleActiveFirmwareMinorRevision" +INACTIVE_FW_MAJOR_REV = "ModuleInactiveFirmwareMajorRevision" +INACTIVE_FW_MINOR_REV = "ModuleInactiveFirmwareMinorRevision" -# SFF-8436 +# DOM +TRANS_DOM_FIELD = "TransceiverDom" +CASE_TEMP = "ModuleTemp" +VOLTAGE = "Supply3V3" +RX_POW1 = "Rx1Power" +RX_POW2 = "Rx2Power" +RX_POW3 = "Rx3Power" +RX_POW4 = "Rx4Power" +TX_BIAS1 = "Tx1Bias" +TX_BIAS2 = "Tx2Bias" +TX_BIAS3 = "Tx3Bias" +TX_BIAS4 = "Tx4Bias" +GRID_SPACING = "Tx1SelectedGridSpacing" +LASER_CONFIG_CHANNEL = "Tx1ChannelNumber" +LASER_CURRENT_FREQ = "Tx1CurrentLaserFrequency" +TX_CONFIG_POWER = "Tx1TargetOutputPower" +MEDIA_OUTPUT_LOOPBACK = "MediaSideOutputLoopbackEnable" +MEDIA_INPUT_LOOPBACK = "MediaSideInputLoopbackEnable" +HOST_OUTPUT_LOOPBACK = "HostSideOutputLoopbackEnable" +HOST_INPUT_LOOPBACK = "HostSideLoopbackEnable" +AUX_MON_TYPE = "AuxMonitorType" +AUX1_MON = "Aux1MonValue" +AUX2_MON = "Aux2MonValue" +AUX3_MON = "Aux3MonValue" -# CMIS +# Status +TRANS_STATUS_FIELD = "TransceiverStatus" +MODULE_STATE = "ModuleState" +MODULE_FIRMWARE_FAULT_INFO = "FirmwareFault" +DATAPATH_STATE= "DataPathStateHostLane" +TX_OUTPUT_STATUS = "TxOutputStatus" +RX_OUTPUT_STATUS = "RxOutputStatus" +TX_FAULT_FLAG = "TxFault" +TX_LOS_FLAG = "TxLOS" +TX_CDR_LOL = "TxCDRLOL" +RX_LOS_FLAG = "RxLOS" +RX_CDR_LOL = "RxCDRLOL" +CONFIG_LANE_STATUS = "ConfigStatusLane" +DPINIT_PENDING = "DPInitPending" +TUNING_IN_PROGRESS = "TxTuningInProgress" +WAVELENGTH_UNLOCKED = "TxWavelengthUnlocked" +LASER_TUNING_DETAIL = "TxTuningDetail" -ADMIN_INFO_FIELD = "AdminInfo" # C-CMIS ## Media Lane FEC Performance Monitoring -MEDIA_LANE_FEC_PM_FIELD = "Media Lane FEC Performance Monitoring" -MEDIA_LANE_LINK_PM_FIELD = "Media Lane Link Performance Monitoring" -RX_BITS_PM_FIELD = "rxBitsPm" -RX_BITS_SUB_INT_PM_FIELD = "rxBitsSubIntPm" ## Media Lane Link Performance Monitoring -RX_AVG_CD_PM_FIELD = "rxAvgCdPm" -RX_MIN_CD_PM_FIELD = "rxMinCdPm" -RX_MAX_CD_PM_FIELD = "rxMaxCdPm" -RX_AVG_DGD_PM_FIELD = "rxAvgDgdPm" +# PM +TRANS_PM_FIELD = "TransceiverPm" +FREEZE_REQUEST = "FreezeRequest" +MEDIA_LANE_FEC_PM = "Media Lane FEC Performance Monitoring" +MEDIA_LANE_LINK_PM = "Media Lane Link Performance Monitoring" +RX_BITS_PM = "rxBitsPm" +RX_BITS_SUB_INTERVAL_PM = "rxBitsSubIntPm" +RX_CORR_BITS_PM = "rxCorrBitsPm" +RX_MIN_CORR_BITS_SUB_INTERVAL_PM = "rxMinCorrBitsSubIntPm" +RX_MAX_CORR_BITS_SUB_INTERVAL_PM = "rxMaxCorrBitsSubIntPm" +RX_FRAMES_PM = "rxFramesPm" +RX_FRAMES_SUB_INTERVAL_PM = "rxFramsSubIntPm" +RX_FRAMES_UNCORR_ERR_PM = "rxFramesUncorrErrPm" +RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM = "rxMinFramesUncorrErrSubintPm" +RX_MAX_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM = "rxMaxFramesUncorrErrSubintPm" + +RX_AVG_CD_PM = "rxAvgCdPm" +RX_MIN_CD_PM = "rxMinCdPm" +RX_MAX_CD_PM = "rxMaxCdPm" +RX_AVG_DGD_PM = "rxAvgDgdPm" +RX_MIN_DGD_PM = "rxMinDgdPm" +RX_MAX_DGD_PM = "rxMaxDgdPm" +RX_AVG_SOPMD_PM = "rxAvgSopmdPm" +RX_MIN_SOPMD_PM = "rxMinSopmdPm" +RX_MAX_SOPMD_PM = "rxMaxSopmdPm" +RX_AVG_PDL_PM = "rxAvgPdlPm" +RX_MIN_PDL_PM = "rxMinPdlPm" +RX_MAX_PDL_PM = "rxMaxPdlPm" +RX_AVG_OSNR_PM = "rxAvgOsnrPm" +RX_MIN_OSNR_PM = "rxMinOsnrPm" +RX_MAX_OSNR_PM = "rxMaxOsnrPm" +RX_AVG_ESNR_PM = "rxAvgEsnrPm" +RX_MIN_ESNR_PM = "rxMinEsnrPm" +RX_MAX_ESNR_PM = "rxMaxEsnrPm" +RX_AVG_CFO_PM = "rxAvgCfoPm" +RX_MAX_CFO_PM = "rxMinCfoPm" +RX_MIN_CFO_PM = "rxMaxCfoPm" +RX_AVG_EVM_PM = "rxAvgEvmPm" +RX_MIN_EVM_PM = "rxMinEvmPm" +RX_MAX_EVM_PM = "rxMaxEvmPm" +TX_AVG_POWER_PM = "txAvgPowerPm" +TX_MIN_POWER_PM = "txMinPowerPm" +TX_MAX_POWER_PM = "txMaxPowerPm" +RX_AVG_POWER_PM = "rxAvgPowerPm" +RX_MIN_POWER_PM = "rxMinPowerPm" +RX_MAX_POWER_PM = "rxMaxPowerPm" +RX_AVG_POWER_PM = "rxAvgPowerPm" +RX_MIN_POWER_PM = "rxMinPowerPm" +RX_MAX_POWER_PM = "rxMaxPowerPm" +RX_AVG_SIG_POWER_PM = "rxAvgSigPowerPm" +RX_MIN_SIG_POWER_PM = "rxMinSigPowerPm" +RX_MAX_SIG_POWER_PM = "rxMaxSigPowerPm" +RX_AVG_SOPROC_PM = "rxAvgSigSoprocPm" +RX_MIN_SOPROC_PM = "rxMinSigSoprocPm" +RX_MAX_SOPROC_PM = "rxMaxSigSoprocPm" +RX_AVG_MER_PM = "rxAvgMerPm" +RX_MIN_MER_PM = "rxMinMerPm" +RX_MAX_MER_PM = "rxMaxMerPm" + + + + + 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 8f7275fc9..88413277a 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -11,6 +11,7 @@ NumberRegField, RegGroupField, StringRegField, + RegBitField, ) from ...fields import consts @@ -28,20 +29,143 @@ def __init__(self, codes): StringRegField(consts.VENDOR_NAME_FIELD, get_addr(0x0, 129), size=16), HexRegField(consts.VENDOR_OUI_FIELD, get_addr(0x0, 145), size=3), StringRegField(consts.VENDOR_PART_NO_FIELD, get_addr(0x0, 148), size=16), + StringRegField(consts.VENDOR_REV, get_addr(0x0, 164), size=2), + StringRegField(consts.VENDOR_SERIAL_NO, get_addr(0x0, 166), size=16), + StringRegField(consts.VENDOR_DATE,get_addr(0x0,182), size = 8), + CodeRegField(consts.CONNECTOR_TYPE, get_addr(0x0, 203), self.codes.CONNECTOR_TYPE), + CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, get_addr(0x0, 86), self.codes.HOST_ELECTRICAL_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_TYPE, get_addr(0x0, 85), self.codes.MODULE_MEDIA_TYPE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, get_addr(0x0, 87), self.codes.NM_850_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_SM, get_addr(0x0, 87), self.codes.SM_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, get_addr(0x0, 87), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, get_addr(0x0, 87), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, get_addr(0x0, 87), self.codes.BASE_T_MEDIA_INTERFACE), + NumberRegField(consts.LANE_COUNT, get_addr(0x0, 88), format="B", size=1), + NumberRegField(consts.HOST_LANE_ASSIGNMENT_OPTION, get_addr(0x0, 89), format="B", size=1), + NumberRegField(consts.MEDIA_LANE_ASSIGNMENT_OPTION, get_addr(0x1, 176), format="B", size=1), + NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_1, get_addr(0x11, 206), format="B", size=1), + NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_2, get_addr(0x11, 207), format="B", size=1), + NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_3, get_addr(0x11, 208), format="B", size=1), + NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_4, get_addr(0x11, 209), format="B", size=1), + NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_5, get_addr(0x11, 210), format="B", size=1), + NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_6, get_addr(0x11, 211), format="B", size=1), + NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_7, get_addr(0x11, 212), format="B", size=1), + NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_8, get_addr(0x11, 213), format="B", size=1), + CodeRegField(consts.MEDIA_INTERFACE_TECH, get_addr(0x0, 212), self.codes.MEDIA_INTERFACE_TECH), + NumberRegField(consts.HW_MAJOR_REV, get_addr(0x1, 130), size=1), + NumberRegField(consts.HW_MINOR_REV, get_addr(0x1, 131), size=1), + NumberRegField(consts.CMIS_REVISION, get_addr(0x0, 1), format="B", size=1), + NumberRegField(consts.ACTIVE_FW_MAJOR_REV, get_addr(0x0, 39), format="B", size=1), + NumberRegField(consts.ACTIVE_FW_MINOR_REV, get_addr(0x0, 40), format="B", size=1), + NumberRegField(consts.INACTIVE_FW_MAJOR_REV, get_addr(0x1, 128), format="B", size=1), + NumberRegField(consts.INACTIVE_FW_MINOR_REV, get_addr(0x1, 129), format="B", size=1), # TODO: add remaining admin fields ) - self.MEDIA_LANE_FEC_PM = RegGroupField(consts.MEDIA_LANE_FEC_PM_FIELD, - NumberRegField(consts.RX_BITS_PM_FIELD, get_addr(0x34, 128), format=">Q", size=8), - NumberRegField(consts.RX_BITS_SUB_INT_PM_FIELD, get_addr(0x34, 136), format=">Q", size=8), + self.TRANS_DOM = RegGroupField(consts.TRANS_DOM_FIELD, + NumberRegField(consts.CASE_TEMP, get_addr(0x0, 14), format=">h", size=2, scale=256.0), + NumberRegField(consts.VOLTAGE, get_addr(0x0, 16), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POW1, get_addr(0x11, 186), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POW2, get_addr(0x11, 188), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POW3, get_addr(0x11, 190), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POW4, get_addr(0x11, 192), format=">H", size=2, scale=10000.0), + NumberRegField(consts.TX_BIAS1, get_addr(0x11, 170), format=">H", size=2, scale=500.0), + NumberRegField(consts.TX_BIAS2, get_addr(0x11, 172), format=">H", size=2, scale=500.0), + NumberRegField(consts.TX_BIAS3, get_addr(0x11, 174), format=">H", size=2, scale=500.0), + NumberRegField(consts.TX_BIAS4, get_addr(0x11, 176), format=">H", size=2, scale=500.0), + NumberRegField(consts.GRID_SPACING, get_addr(0x12, 128), size=1), + NumberRegField(consts.LASER_CONFIG_CHANNEL, get_addr(0x12, 136), format=">h", size=2), + NumberRegField(consts.LASER_CURRENT_FREQ, get_addr(0x12, 168), format=">L", size=4), + NumberRegField(consts.TX_CONFIG_POWER, get_addr(0x12, 200), format=">h", size=2,scale=100.0), + RegBitField(consts.MEDIA_OUTPUT_LOOPBACK, offset=get_addr(0x13, 180), bitpos=0), + RegBitField(consts.MEDIA_INPUT_LOOPBACK, offset=get_addr(0x13, 181), bitpos=0), + NumberRegField(consts.HOST_OUTPUT_LOOPBACK, get_addr(0x13, 182), size=1), + NumberRegField(consts.HOST_INPUT_LOOPBACK, get_addr(0x13, 183), size=1), + NumberRegField(consts.AUX_MON_TYPE, get_addr(0x1, 145), size=1), + NumberRegField(consts.AUX1_MON, get_addr(0x0, 18), format=">h", size=2), + NumberRegField(consts.AUX2_MON, get_addr(0x0, 20), format=">h", size=2), + NumberRegField(consts.AUX3_MON, get_addr(0x0, 22), format=">h", size=2), + ) + + self.TRANS_STATUS = RegGroupField(consts.TRANS_STATUS_FIELD, + NumberRegField(consts.MODULE_STATE, get_addr(0x0, 3), size=1), + NumberRegField(consts.MODULE_FIRMWARE_FAULT_INFO, get_addr(0x0, 8), size=1), + NumberRegField(consts.DATAPATH_STATE, get_addr(0x11, 128), format = '>I', size=4), + NumberRegField(consts.RX_OUTPUT_STATUS, get_addr(0x11, 132), size=1), + NumberRegField(consts.TX_OUTPUT_STATUS, get_addr(0x11, 133), size=1), + NumberRegField(consts.TX_FAULT_FLAG, get_addr(0x11, 135), size=1), + NumberRegField(consts.TX_LOS_FLAG, get_addr(0x11, 136), size=1), + NumberRegField(consts.TX_CDR_LOL, get_addr(0x11, 137), size=1), + NumberRegField(consts.RX_LOS_FLAG, get_addr(0x11, 147), size=1), + NumberRegField(consts.RX_CDR_LOL, get_addr(0x11, 148), size=1), + NumberRegField(consts.CONFIG_LANE_STATUS, get_addr(0x11, 202), format=">I", size=4), + NumberRegField(consts.DPINIT_PENDING, get_addr(0x11, 235), size=1), + RegBitField(consts.TUNING_IN_PROGRESS, offset=get_addr(0x12, 222), bitpos=1), + RegBitField(consts.WAVELENGTH_UNLOCKED, offset=get_addr(0x12, 222), bitpos=0), + NumberRegField(consts.LASER_TUNING_DETAIL, get_addr(0x12, 231), size=1), + ) + + self.TRANS_PM = RegGroupField(consts.TRANS_PM_FIELD, + NumberRegField(consts.FREEZE_REQUEST, get_addr(0x2f, 144), size=1, ro=False), + ) + + self.MEDIA_LANE_FEC_PM = RegGroupField(consts.MEDIA_LANE_FEC_PM, + NumberRegField(consts.RX_BITS_PM, get_addr(0x34, 128), format=">Q", size=8), + NumberRegField(consts.RX_BITS_SUB_INTERVAL_PM, get_addr(0x34, 136), format=">Q", size=8), + NumberRegField(consts.RX_CORR_BITS_PM, get_addr(0x34, 144), format=">Q", size=8), + NumberRegField(consts.RX_MIN_CORR_BITS_SUB_INTERVAL_PM, get_addr(0x34, 152), format=">Q", size=8), + NumberRegField(consts.RX_MAX_CORR_BITS_SUB_INTERVAL_PM, get_addr(0x34, 160), format=">Q", size=8), + NumberRegField(consts.RX_FRAMES_PM, get_addr(0x34, 168), format=">I", size=4), + NumberRegField(consts.RX_FRAMES_SUB_INTERVAL_PM, get_addr(0x34, 172), format=">I", size=4), + NumberRegField(consts.RX_FRAMES_UNCORR_ERR_PM, get_addr(0x34, 176), format=">I", size=4), + NumberRegField(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM, get_addr(0x34, 180), format=">I", size=4), + NumberRegField(consts.RX_MAX_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM, get_addr(0x34, 184), format=">I", size=4), # TODO: add other PMs... ) - self.MEDIA_LANE_LINK_PM = RegGroupField(consts.MEDIA_LANE_LINK_PM_FIELD, - NumberRegField(consts.RX_AVG_CD_PM_FIELD, get_addr(0x35, 128), format=">i", size=4), - NumberRegField(consts.RX_MIN_CD_PM_FIELD, get_addr(0x35, 132), format=">i", size=4), - NumberRegField(consts.RX_MAX_CD_PM_FIELD, get_addr(0x35, 136), format=">i", size=4), - NumberRegField(consts.RX_AVG_DGD_PM_FIELD, get_addr(0x35, 140), format=">H", size=2, scale=100) + self.MEDIA_LANE_LINK_PM = RegGroupField(consts.MEDIA_LANE_LINK_PM, + NumberRegField(consts.RX_AVG_CD_PM, get_addr(0x35, 128), format=">i", size=4), + NumberRegField(consts.RX_MIN_CD_PM, get_addr(0x35, 132), format=">i", size=4), + NumberRegField(consts.RX_MAX_CD_PM, get_addr(0x35, 136), format=">i", size=4), + NumberRegField(consts.RX_AVG_DGD_PM, get_addr(0x35, 140), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_DGD_PM, get_addr(0x35, 142), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_DGD_PM, get_addr(0x35, 144), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_SOPMD_PM, get_addr(0x35, 146), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_SOPMD_PM, get_addr(0x35, 148), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_SOPMD_PM, get_addr(0x35, 150), format=">H", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_PDL_PM, get_addr(0x35, 152), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MIN_PDL_PM, get_addr(0x35, 154), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MAX_PDL_PM, get_addr(0x35, 156), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_AVG_OSNR_PM, get_addr(0x35, 158), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MIN_OSNR_PM, get_addr(0x35, 160), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MAX_OSNR_PM, get_addr(0x35, 162), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_AVG_ESNR_PM, get_addr(0x35, 164), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MIN_ESNR_PM, get_addr(0x35, 166), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MAX_ESNR_PM, get_addr(0x35, 168), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_AVG_CFO_PM, get_addr(0x35, 170), format=">h", size=2), + NumberRegField(consts.RX_MIN_CFO_PM, get_addr(0x35, 172), format=">h", size=2), + NumberRegField(consts.RX_MAX_CFO_PM, get_addr(0x35, 174), format=">h", size=2), + NumberRegField(consts.RX_AVG_EVM_PM, get_addr(0x35, 176), format=">H", size=2, scale=655.35), + NumberRegField(consts.RX_MIN_EVM_PM, get_addr(0x35, 178), format=">H", size=2, scale=655.35), + NumberRegField(consts.RX_MAX_EVM_PM, get_addr(0x35, 180), format=">H", size=2, scale=655.35), + NumberRegField(consts.TX_AVG_POWER_PM, get_addr(0x35,182), format=">h", size=2, scale=100.0), + NumberRegField(consts.TX_MIN_POWER_PM, get_addr(0x35,184), format=">h", size=2, scale=100.0), + NumberRegField(consts.TX_MAX_POWER_PM, get_addr(0x35,186), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_POWER_PM, get_addr(0x35,188), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_POWER_PM, get_addr(0x35,190), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_POWER_PM, get_addr(0x35,192), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_POWER_PM, get_addr(0x35,188), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_POWER_PM, get_addr(0x35,190), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_POWER_PM, get_addr(0x35,192), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_SIG_POWER_PM, get_addr(0x35,194), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MIN_SIG_POWER_PM, get_addr(0x35,196), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_MAX_SIG_POWER_PM, get_addr(0x35,198), format=">h", size=2, scale=100.0), + NumberRegField(consts.RX_AVG_SOPROC_PM, get_addr(0x35,200), format=">H", size=2), + NumberRegField(consts.RX_MIN_SOPROC_PM, get_addr(0x35,202), format=">H", size=2), + NumberRegField(consts.RX_MAX_SOPROC_PM, get_addr(0x35,204), format=">H", size=2), + NumberRegField(consts.RX_AVG_MER_PM, get_addr(0x35,206), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MIN_MER_PM, get_addr(0x35,208), format=">H", size=2, scale=10.0), + NumberRegField(consts.RX_MAX_MER_PM, get_addr(0x35,210), format=">H", size=2, scale=10.0), # TODO: add others PMs... ) From 4cd63f487b56ea7e0028e523666ae7676b901756 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Wed, 1 Sep 2021 10:38:29 -0700 Subject: [PATCH 02/16] add to config_db --- .../sonic_xcvr/api/public/cmis.py | 67 ++++++++++++++++++- .../sonic_xcvr/fields/consts.py | 4 ++ .../sonic_xcvr/fields/xcvr_field.py | 4 +- .../sonic_xcvr/mem_maps/public/cmis.py | 19 ++++-- 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index 5b6c02175..792370d08 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -241,7 +241,8 @@ def get_laser_temp(self): def get_PM(self): self.xcvr_eeprom.write(consts.FREEZE_REQUEST, 128) - time.sleep(1) + time.sleep(5) + self.xcvr_eeprom.write(consts.FREEZE_REQUEST, 0) PM_dict = dict() rx_bits_pm = self.xcvr_eeprom.read(consts.RX_BITS_PM) @@ -318,7 +319,7 @@ def get_PM(self): PM_dict['rx_mer_min'] = self.xcvr_eeprom.read(consts.RX_MIN_MER_PM) PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM) - self.xcvr_eeprom.write(consts.FREEZE_REQUEST, 0) + return PM_dict def get_module_state(self): @@ -443,6 +444,68 @@ def get_laser_tuning_summary(self): laser_tuning_summary.append("TuningComplete") return laser_tuning_summary + def set_low_power(self, AssertLowPower): + low_power_control = AssertLowPower << 6 + self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control) + + def set_laser_freq(self, freq): + freq_grid = 0x70 + self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) + channel_number = int(round((freq - 193.1)/0.025)) + assert channel_number % 3 == 0 + self.set_low_power(True) + time.sleep(5) + self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) + time.sleep(1) + self.set_low_power(False) + time.sleep(1) + + def set_TX_power(self, TX_power): + self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, TX_power) + time.sleep(1) + + def get_loopback_capability(self): + allowed_loopback_result = self.xcvr_eeprom.read(consts.LOOPBACK_CAPABILITY) + loopback_capability = dict() + loopback_capability['simultaneous_host_media_loopback_supported'] = bool((allowed_loopback_result >> 6) & 0x1) + loopback_capability['per_lane_media_loopback_supported'] = bool((allowed_loopback_result >> 5) & 0x1) + loopback_capability['per_lane_host_loopback_supported'] = bool((allowed_loopback_result >> 4) & 0x1) + loopback_capability['host_side_input_loopback_supported'] = bool((allowed_loopback_result >> 3) & 0x1) + loopback_capability['host_side_output_loopback_supported'] = bool((allowed_loopback_result >> 2) & 0x1) + loopback_capability['media_side_input_loopback_supported'] = bool((allowed_loopback_result >> 1) & 0x1) + loopback_capability['media_side_output_loopback_supported'] = bool((allowed_loopback_result >> 0) & 0x1) + return loopback_capability + + def set_loopback_mode(self, loopback_mode): + ''' + Loopback mode has to be one of the five: + 1. "none" (default) + 2. "host-side-input" + 3. "host-side-output" + 4. "media-side-input" + 5. "media-side-output" + The function will look at 13h:128 to check advertized loopback capabilities. + ''' + loopback_capability = self.get_loopback_capability() + if loopback_mode == 'none': + self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0) + elif loopback_mode == 'host-side-input': + assert loopback_capability['host_side_input_loopback_supported'] + self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0xff) + elif loopback_mode == 'host-side-output': + assert loopback_capability['host_side_output_loopback_supported'] + self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0xff) + elif loopback_mode == 'media-side-input': + assert loopback_capability['media_side_input_loopback_supported'] + self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0x1) + elif loopback_mode == 'media-side-output': + assert loopback_capability['media_side_output_loopback_supported'] + self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0x1) + # TODO: other XcvrApi methods + diff --git a/sonic_platform_base/sonic_xcvr/fields/consts.py b/sonic_platform_base/sonic_xcvr/fields/consts.py index 535dd1b20..49131fbf5 100644 --- a/sonic_platform_base/sonic_xcvr/fields/consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/consts.py @@ -78,6 +78,10 @@ WAVELENGTH_UNLOCKED = "TxWavelengthUnlocked" LASER_TUNING_DETAIL = "TxTuningDetail" +# CONFIG +TRANS_CONFIG_FIELD = "TransceriverConfig" +MODULE_LEVEL_CONTROL = "ModuleControl" +LOOPBACK_CAPABILITY = "LoopbackCapability" # C-CMIS diff --git a/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py b/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py index 178bf8934..6391f756b 100644 --- a/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py +++ b/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py @@ -151,8 +151,8 @@ def decode(self, raw_data): def encode(self, val, raw_state=None): assert not self.ro if self.scale is not None: - return bytearray(struct.pack(self.format, val * self.scale)) - return bytearray(struct.pack(self.format, val)) + return bytearray(struct.pack(self.format, int(val * self.scale))) + return bytearray(struct.pack(self.format, int(val))) class StringRegField(RegField): """ 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 88413277a..e56404cb0 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -73,14 +73,15 @@ def __init__(self, codes): NumberRegField(consts.TX_BIAS2, get_addr(0x11, 172), format=">H", size=2, scale=500.0), NumberRegField(consts.TX_BIAS3, get_addr(0x11, 174), format=">H", size=2, scale=500.0), NumberRegField(consts.TX_BIAS4, get_addr(0x11, 176), format=">H", size=2, scale=500.0), - NumberRegField(consts.GRID_SPACING, get_addr(0x12, 128), size=1), - NumberRegField(consts.LASER_CONFIG_CHANNEL, get_addr(0x12, 136), format=">h", size=2), + NumberRegField(consts.GRID_SPACING, get_addr(0x12, 128), size=1, ro=False), + NumberRegField(consts.LASER_CONFIG_CHANNEL, get_addr(0x12, 136), format=">h", size=2, ro=False), NumberRegField(consts.LASER_CURRENT_FREQ, get_addr(0x12, 168), format=">L", size=4), - NumberRegField(consts.TX_CONFIG_POWER, get_addr(0x12, 200), format=">h", size=2,scale=100.0), - RegBitField(consts.MEDIA_OUTPUT_LOOPBACK, offset=get_addr(0x13, 180), bitpos=0), - RegBitField(consts.MEDIA_INPUT_LOOPBACK, offset=get_addr(0x13, 181), bitpos=0), - NumberRegField(consts.HOST_OUTPUT_LOOPBACK, get_addr(0x13, 182), size=1), - NumberRegField(consts.HOST_INPUT_LOOPBACK, get_addr(0x13, 183), size=1), + NumberRegField(consts.TX_CONFIG_POWER, get_addr(0x12, 200), format=">h", size=2, scale=100.0, ro=False), + NumberRegField(consts.LOOPBACK_CAPABILITY, get_addr(0x13, 128), size=1), + RegBitField(consts.MEDIA_OUTPUT_LOOPBACK, offset=get_addr(0x13, 180), bitpos=0, ro=False), + RegBitField(consts.MEDIA_INPUT_LOOPBACK, offset=get_addr(0x13, 181), bitpos=0, ro=False), + NumberRegField(consts.HOST_OUTPUT_LOOPBACK, get_addr(0x13, 182), size=1, ro=False), + NumberRegField(consts.HOST_INPUT_LOOPBACK, get_addr(0x13, 183), size=1, ro=False), NumberRegField(consts.AUX_MON_TYPE, get_addr(0x1, 145), size=1), NumberRegField(consts.AUX1_MON, get_addr(0x0, 18), format=">h", size=2), NumberRegField(consts.AUX2_MON, get_addr(0x0, 20), format=">h", size=2), @@ -169,4 +170,8 @@ def __init__(self, codes): # TODO: add others PMs... ) + self.TRANS_CONFIG = RegGroupField(consts.TRANS_CONFIG_FIELD, + NumberRegField(consts.MODULE_LEVEL_CONTROL, get_addr(0x0, 26), size=1, ro=False), + ) + # TODO: add remaining fields From 9165e0961d8f91c7314bbadd1313e6801e2cad91 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Wed, 22 Sep 2021 23:26:24 -0700 Subject: [PATCH 03/16] Address PR comments: 1. add descriptions to api functions; 2. open c_cmis.py file for ZR application only; 3. separate two dictionaries - sff8024 and cmis_code; --- .../sonic_xcvr/api/public/c_cmis.py | 955 ++++++++++++++++++ .../sonic_xcvr/codes/public/cmis_code.py | 60 ++ 2 files changed, 1015 insertions(+) create mode 100644 sonic_platform_base/sonic_xcvr/api/public/c_cmis.py create mode 100644 sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py new file mode 100644 index 000000000..017bc0b96 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -0,0 +1,955 @@ +""" + c-cmis.py + + Implementation of XcvrApi that corresponds to C-CMIS +""" +from ...fields import consts +from ..xcvr_api import XcvrApi +import time +BYTELENGTH = 8 +class CCmisApi(XcvrApi): + NUM_CHANNELS = 8 + + def __init__(self, xcvr_eeprom): + super(CCmisApi, self).__init__(xcvr_eeprom) + + # Transceiver Information + def get_model(self): + ''' + This function returns the part number of the module + ''' + return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD) + + def get_vendor_rev(self): + ''' + This function returns the revision level for part number provided by vendor + ''' + return self.xcvr_eeprom.read(consts.VENDOR_REV) + + def get_vendor_serial(self): + ''' + This function returns the serial number of the module + ''' + return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO) + + def get_vendor_name(self): + ''' + This function returns the vendor name of the module + ''' + return self.xcvr_eeprom.read(consts.VENDOR_NAME_FIELD) + + def get_module_type(self): + ''' + This function returns the SFF8024Identifier (module type / form-factor). Table 4-1 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.ID_FIELD) + + def get_vendor_OUI(self): + ''' + This function returns the vendor IEEE company ID + ''' + return self.xcvr_eeprom.read(consts.VENDOR_OUI_FIELD) + + def get_vendor_date(self): + ''' + This function returns the module manufacture date. It returns YYMMDDXX. XX is the lot code. + ''' + return self.xcvr_eeprom.read(consts.VENDOR_DATE) + + def get_connector_type(self): + ''' + This function returns module connector. Table 4-3 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.CONNECTOR_TYPE) + + def get_module_media_type(self): + ''' + This function returns module media type: MMF, SMF, Passive Copper Cable, Active Cable Assembly or Base-T. + ''' + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_TYPE) + + def get_host_electrical_interface(self): + ''' + This function returns module host electrical interface. Table 4-5 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.HOST_ELECTRICAL_INTERFACE) + + def get_module_media_interface(self): + ''' + This function returns module media electrical interface. Table 4-6 ~ 4-10 in SFF-8024 Rev4.6 + ''' + media_type = self.get_module_media_type() + if media_type == 'Multimode Fiber (MMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM) + elif media_type == 'Single Mode Fiber (SMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_SM) + elif media_type == 'Passive Copper Cable': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER) + elif media_type == 'Active Cable Assembly': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE) + elif media_type == 'BASE-T': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_BASE_T) + else: + return 'Unknown media interface' + + def get_host_lane_count(self): + ''' + This function returns number of host lanes + ''' + lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) + return (lane_count >> 4) & 0xf + + def get_media_lane_count(self): + ''' + This function returns number of media lanes + ''' + lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) + return (lane_count) & 0xf + + def get_host_lane_assignment_option(self): + ''' + This function returns the host lane that the application begins on + ''' + return self.xcvr_eeprom.read(consts.HOST_LANE_ASSIGNMENT_OPTION) + + def get_media_lane_assignment_option(self): + ''' + This function returns the media lane that the application is allowed to begin on + ''' + return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION) + + def get_active_apsel_hostlane(self): + ''' + This function returns the application select code that each host lane has + ''' + apsel_dict = dict() + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_1) + apsel_dict['hostlane1'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_2) + apsel_dict['hostlane2'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_3) + apsel_dict['hostlane3'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_4) + apsel_dict['hostlane4'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_5) + apsel_dict['hostlane5'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_6) + apsel_dict['hostlane6'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_7) + apsel_dict['hostlane7'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_8) + apsel_dict['hostlane8'] = (result >> 4) & 0xf + return apsel_dict + + def get_media_interface_technology(self): + ''' + This function returns the media lane technology + ''' + return self.xcvr_eeprom.read(consts.MEDIA_INTERFACE_TECH) + + def get_module_hardware_revision(self): + ''' + This function returns the module hardware revision + ''' + hw_major_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) + hw_minor_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) + hw_rev = [str(num) for num in [hw_major_rev, hw_minor_rev]] + return '.'.join(hw_rev) + + def get_cmis_rev(self): + ''' + This function returns the CMIS version the module complies to + ''' + cmis = self.xcvr_eeprom.read(consts.CMIS_REVISION) + cmis_major = (cmis >> 4) & 0xf + cmis_minor = (cmis) & 0xf + cmis_rev = [str(num) for num in [cmis_major, cmis_minor]] + return '.'.join(cmis_rev) + + def get_module_active_firmware(self): + ''' + This function returns the active firmware version + ''' + active_fw_major = self.xcvr_eeprom.read(consts.ACTIVE_FW_MAJOR_REV) + active_fw_minor = self.xcvr_eeprom.read(consts.ACTIVE_FW_MINOR_REV) + active_fw = [str(num) for num in [active_fw_major, active_fw_minor]] + return '.'.join(active_fw) + + def get_module_inactive_firmware(self): + ''' + This function returns the inactive firmware version + ''' + inactive_fw_major = self.xcvr_eeprom.read(consts.INACTIVE_FW_MAJOR_REV) + inactive_fw_minor = self.xcvr_eeprom.read(consts.INACTIVE_FW_MINOR_REV) + inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]] + return '.'.join(inactive_fw) + + # Transceiver DOM + def get_module_temperature(self): + ''' + This function returns the module case temperature and its thresholds. Unit in deg C + ''' + case_temp_dict = dict() + case_temp = self.xcvr_eeprom.read(consts.CASE_TEMP) + case_temp_high_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_ALARM) + case_temp_low_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_ALARM) + case_temp_high_warn = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_WARN) + case_temp_low_warn = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_WARN) + case_temp_dict = {'monitor value': case_temp, + 'high alarm': case_temp_high_alarm, + 'low alarm': case_temp_low_alarm, + 'high warn': case_temp_high_warn, + 'low warn': case_temp_low_warn} + return case_temp_dict + + def get_module_voltage(self): + ''' + This function returns the monitored value of the 3.3-V supply voltage and its thresholds. + Unit in V + ''' + voltage_dict = dict() + voltage = self.xcvr_eeprom.read(consts.VOLTAGE) + voltage_high_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_ALARM) + voltage_low_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_ALARM) + voltage_high_warn = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_WARN) + voltage_low_warn = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_WARN) + voltage_dict = {'monitor value': voltage, + 'high alarm': voltage_high_alarm, + 'low alarm': voltage_low_alarm, + 'high warn': voltage_high_warn, + 'low warn': voltage_low_warn} + return voltage_dict + + def get_txpower(self): + ''' + This function returns the TX output power. Unit in mW + ''' + tx_power_dict = dict() + tx_power = self.xcvr_eeprom.read(consts.TX_POW) + tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM) + tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM) + tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN) + tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN) + tx_power_dict = {'monitor value lane1': tx_power, + 'high alarm': tx_power_high_alarm, + 'low alarm': tx_power_low_alarm, + 'high warn': tx_power_high_warn, + 'low warn': tx_power_low_warn} + return tx_power_dict + + def get_rxpower(self): + ''' + This function returns the RX input power. Unit in mW + ''' + rx_power_dict = dict() + rx_power = self.xcvr_eeprom.read(consts.RX_POW) + rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM) + rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM) + rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN) + rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN) + rx_power_dict = {'monitor value lane1': rx_power, + 'high alarm': rx_power_high_alarm, + 'low alarm': rx_power_low_alarm, + 'high warn': rx_power_high_warn, + 'low warn': rx_power_low_warn} + return rx_power_dict + + def get_txbias(self): + ''' + This function returns the TX laser bias current. Unit in mA + ''' + tx_bias_current_dict = dict() + tx_bias_current = self.xcvr_eeprom.read(consts.TX_BIAS) + tx_bias_current_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_ALARM) + tx_bias_current_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_ALARM) + tx_bias_current_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_WARN) + tx_bias_current_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_WARN) + tx_bias_current_dict = {'monitor value lane1': tx_bias_current, + 'high alarm': tx_bias_current_high_alarm, + 'low alarm': tx_bias_current_low_alarm, + 'high warn': tx_bias_current_high_warn, + 'low warn': tx_bias_current_low_warn} + return tx_bias_current_dict + + def get_freq_grid(self): + ''' + This function returns the configured frequency grid. Unit in GHz + ''' + freq_grid = self.xcvr_eeprom.read(consts.GRID_SPACING) >> 4 + if freq_grid == 7: + return 75 + elif freq_grid == 6: + return 33 + elif freq_grid == 5: + return 100 + elif freq_grid == 4: + return 50 + elif freq_grid == 3: + return 25 + elif freq_grid == 2: + return 12.5 + elif freq_grid == 1: + return 6.25 + elif freq_grid == 0: + return 3.125 + + def get_laser_config_freq(self): + ''' + This function returns the configured laser frequency. Unit in MHz + ''' + freq_grid = self.get_freq_grid() + channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) + if freq_grid == 75: + config_freq = 193100000 + channel * freq_grid/3*1000 + else: + config_freq = 193100000 + channel * freq_grid + return config_freq + + def get_current_laser_freq(self): + ''' + This function returns the monitored laser frequency. Unit in MHz + ''' + return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ) + + def get_TX_config_power(self): + ''' + This function returns the configured TX output power. Unit in dBm + ''' + return self.xcvr_eeprom.read(consts.TX_CONFIG_POWER) + + def get_media_output_loopback(self): + ''' + This function returns the media output loopback status + ''' + result = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) + return result == 1 + + def get_media_input_loopback(self): + ''' + This function returns the media input loopback status + ''' + result = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) + return result == 1 + + def get_host_output_loopback(self): + ''' + This function returns the host output loopback status + ''' + result = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) + loopback_status = [] + for bitpos in range(BYTELENGTH): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status + + def get_host_input_loopback(self): + ''' + This function returns the host input loopback status + ''' + result = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) + loopback_status = [] + for bitpos in range(BYTELENGTH): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status + + def get_aux_mon_type(self): + ''' + This function returns the aux monitor types + ''' + result = self.xcvr_eeprom.read(consts.AUX_MON_TYPE) + aux1_mon_type = result & 0x1 + aux2_mon_type = (result >> 1) & 0x1 + aux3_mon_type = (result >> 2) & 0x1 + return aux1_mon_type, aux2_mon_type, aux3_mon_type + + def get_laser_temperature(self): + ''' + This function returns the laser temperature monitor value + ''' + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + LASER_TEMP_SCALE = 256.0 + laser_temp_dict = dict() + if aux2_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE + laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEMP_SCALE + laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEMP_SCALE + laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEMP_SCALE + laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEMP_SCALE + elif aux2_mon_type == 1 and aux3_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX3_MON)/LASER_TEMP_SCALE + laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX3_HIGH_ALARM)/LASER_TEMP_SCALE + laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX3_LOW_ALARM)/LASER_TEMP_SCALE + laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX3_HIGH_WARN)/LASER_TEMP_SCALE + laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX3_LOW_WARN)/LASER_TEMP_SCALE + else: + return None + laser_temp_dict = {'monitor value': laser_temp, + 'high alarm': laser_temp_high_alarm, + 'low alarm': laser_temp_low_alarm, + 'high warn': laser_temp_high_warn, + 'low warn': laser_temp_low_warn} + return laser_temp_dict + + def get_laser_TEC_current(self): + ''' + This function returns the laser TEC current monitor value + ''' + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + LASER_TEC_CURRENT_SCALE = 32767.0 + laser_tec_current_dict = dict() + if aux1_mon_type == 1: + laser_tec_current = self.xcvr_eeprom.read(consts.AUX1_MON)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX1_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX1_LOW_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX1_HIGH_WARN)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX1_LOW_WARN)/LASER_TEC_CURRENT_SCALE + elif aux1_mon_type == 0 and aux2_mon_type == 1: + laser_tec_current = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEC_CURRENT_SCALE + else: + return None + laser_tec_current_dict = {'monitor value': laser_tec_current, + 'high alarm': laser_tec_current_high_alarm, + 'low alarm': laser_tec_current_low_alarm, + 'high warn': laser_tec_current_high_warn, + 'low warn': laser_tec_current_low_warn} + return laser_tec_current_dict + + def get_custom_field(self, signed = False, scale = 1.0): + ''' + This function returns the custom monitor field + ''' + result = self.xcvr_eeprom.read(consts.CUSTOM_MON) + if signed: + result -= 2**15 + result /= scale + return result + + + def get_PM(self): + ''' + This function returns the PMs reported in Page 34h and 35h in OIF C-CMIS document + CD: unit in ps/nm + DGD: unit in ps + SOPMD: unit in ps^2 + PDL: unit in dB + OSNR: unit in dB + ESNR: unit in dB + CFO: unit in MHz + TXpower:unit in dBm + RXpower:unit in dBm + RX sig power: unit in dBm + SOPROC: unit in krad/s + MER: unit in dB + ''' + self.xcvr_eeprom.write(consts.VDM_CONTROL, 128) + time.sleep(5) + self.xcvr_eeprom.write(consts.VDM_CONTROL, 0) + PM_dict = dict() + + rx_bits_pm = self.xcvr_eeprom.read(consts.RX_BITS_PM) + rx_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_BITS_SUB_INTERVAL_PM) + rx_corr_bits_pm = self.xcvr_eeprom.read(consts.RX_CORR_BITS_PM) + rx_min_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_CORR_BITS_SUB_INTERVAL_PM) + rx_max_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MAX_CORR_BITS_SUB_INTERVAL_PM) + + if (rx_bits_subint_pm != 0) and (rx_bits_pm != 0): + PM_dict['preFEC_BER_cur'] = rx_corr_bits_pm*1.0/rx_bits_pm + PM_dict['preFEC_BER_min'] = rx_min_corr_bits_subint_pm*1.0/rx_bits_subint_pm + PM_dict['preFEC_BER_max'] = rx_max_corr_bits_subint_pm*1.0/rx_bits_subint_pm + + rx_frames_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_PM) + rx_frames_subint_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_SUB_INTERVAL_PM) + rx_frames_uncorr_err_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_UNCORR_ERR_PM) + rx_min_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) + rx_max_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) + + if (rx_frames_subint_pm != 0) and (rx_frames_pm != 0): + PM_dict['preFEC_uncorr_frame_ratio_cur'] = rx_frames_uncorr_err_pm*1.0/rx_frames_subint_pm + PM_dict['preFEC_uncorr_frame_ratio_min'] = rx_min_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm + PM_dict['preFEC_uncorr_frame_ratio_max'] = rx_max_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm + + PM_dict['rx_cd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_CD_PM) + PM_dict['rx_cd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_CD_PM) + PM_dict['rx_cd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_CD_PM) + + PM_dict['rx_dgd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_DGD_PM) + PM_dict['rx_dgd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_DGD_PM) + PM_dict['rx_dgd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_DGD_PM) + + PM_dict['rx_sopmd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SOPMD_PM) + PM_dict['rx_sopmd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SOPMD_PM) + PM_dict['rx_sopmd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SOPMD_PM) + + PM_dict['rx_pdl_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_PDL_PM) + PM_dict['rx_pdl_min'] = self.xcvr_eeprom.read(consts.RX_MIN_PDL_PM) + PM_dict['rx_pdl_max'] = self.xcvr_eeprom.read(consts.RX_MAX_PDL_PM) + + PM_dict['rx_osnr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_OSNR_PM) + PM_dict['rx_osnr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_OSNR_PM) + PM_dict['rx_osnr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_OSNR_PM) + + PM_dict['rx_esnr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_ESNR_PM) + PM_dict['rx_esnr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_ESNR_PM) + PM_dict['rx_esnr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_ESNR_PM) + + PM_dict['rx_cfo_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_CFO_PM) + PM_dict['rx_cfo_min'] = self.xcvr_eeprom.read(consts.RX_MIN_CFO_PM) + PM_dict['rx_cfo_max'] = self.xcvr_eeprom.read(consts.RX_MAX_CFO_PM) + + PM_dict['rx_evm_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_EVM_PM) + PM_dict['rx_evm_min'] = self.xcvr_eeprom.read(consts.RX_MIN_EVM_PM) + PM_dict['rx_evm_max'] = self.xcvr_eeprom.read(consts.RX_MAX_EVM_PM) + + PM_dict['tx_power_avg'] = self.xcvr_eeprom.read(consts.TX_AVG_POWER_PM) + PM_dict['tx_power_min'] = self.xcvr_eeprom.read(consts.TX_MIN_POWER_PM) + PM_dict['tx_power_max'] = self.xcvr_eeprom.read(consts.TX_MAX_POWER_PM) + + PM_dict['rx_power_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_POWER_PM) + PM_dict['rx_power_min'] = self.xcvr_eeprom.read(consts.RX_MIN_POWER_PM) + PM_dict['rx_power_max'] = self.xcvr_eeprom.read(consts.RX_MAX_POWER_PM) + + PM_dict['rx_sigpwr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SIG_POWER_PM) + PM_dict['rx_sigpwr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SIG_POWER_PM) + PM_dict['rx_sigpwr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SIG_POWER_PM) + + PM_dict['rx_soproc_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SOPROC_PM) + PM_dict['rx_soproc_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SOPROC_PM) + PM_dict['rx_soproc_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SOPROC_PM) + + PM_dict['rx_mer_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_MER_PM) + PM_dict['rx_mer_min'] = self.xcvr_eeprom.read(consts.RX_MIN_MER_PM) + PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM) + return PM_dict + + + # Transceiver status + def get_module_state(self): + ''' + This function returns the module state + ''' + result = self.xcvr_eeprom.read(consts.MODULE_STATE) >> 1 + DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].MODULE_STATE + return DICT.get(result, "Unknown") + + def get_module_firmware_fault_state_changed(self): + ''' + This function returns datapath firmware fault state, module firmware fault state + and whether module state changed + ''' + result = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) + datapath_firmware_fault = bool((result >> 2) & 0x1) + module_firmware_fault = bool((result >> 1) & 0x1) + module_state_changed = bool(result & 0x1) + return datapath_firmware_fault, module_firmware_fault, module_state_changed + + def get_module_level_flag(self): + ''' + This function returns teh module level flags, including + - 3.3 V voltage supply flags + - Case temperature flags + - Aux 1 flags + - Aux 2 flags + - Aux 3 flags + - Custom field flags + ''' + module_flag_byte1 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE1) + module_flag_byte2 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE2) + module_flag_byte3 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE3) + + voltage_high_alarm_flag = bool((module_flag_byte1 >> 4) & 0x1) + voltage_low_alarm_flag = bool((module_flag_byte1 >> 5) & 0x1) + voltage_high_warn_flag = bool((module_flag_byte1 >> 6) & 0x1) + voltage_low_warn_flag = bool((module_flag_byte1 >> 7) & 0x1) + voltage_flags = {'voltage_high_alarm_flag': voltage_high_alarm_flag, + 'voltage_low_alarm_flag': voltage_low_alarm_flag, + 'voltage_high_warn_flag': voltage_high_warn_flag, + 'voltage_low_warn_flag': voltage_low_warn_flag} + + case_temp_high_alarm_flag = bool((module_flag_byte1 >> 0) & 0x1) + case_temp_low_alarm_flag = bool((module_flag_byte1 >> 1) & 0x1) + case_temp_high_warn_flag = bool((module_flag_byte1 >> 2) & 0x1) + case_temp_low_warn_flag = bool((module_flag_byte1 >> 3) & 0x1) + case_temp_flags = {'case_temp_high_alarm_flag': case_temp_high_alarm_flag, + 'case_temp_low_alarm_flag': case_temp_low_alarm_flag, + 'case_temp_high_warn_flag': case_temp_high_warn_flag, + 'case_temp_low_warn_flag': case_temp_low_warn_flag} + + aux2_high_alarm_flag = bool((module_flag_byte2 >> 4) & 0x1) + aux2_low_alarm_flag = bool((module_flag_byte2 >> 5) & 0x1) + aux2_high_warn_flag = bool((module_flag_byte2 >> 6) & 0x1) + aux2_low_warn_flag = bool((module_flag_byte2 >> 7) & 0x1) + aux2_flags = {'aux2_high_alarm_flag': aux2_high_alarm_flag, + 'aux2_low_alarm_flag': aux2_low_alarm_flag, + 'aux2_high_warn_flag': aux2_high_warn_flag, + 'aux2_low_warn_flag': aux2_low_warn_flag} + + aux1_high_alarm_flag = bool((module_flag_byte2 >> 0) & 0x1) + aux1_low_alarm_flag = bool((module_flag_byte2 >> 1) & 0x1) + aux1_high_warn_flag = bool((module_flag_byte2 >> 2) & 0x1) + aux1_low_warn_flag = bool((module_flag_byte2 >> 3) & 0x1) + aux1_flags = {'aux1_high_alarm_flag': aux1_high_alarm_flag, + 'aux1_low_alarm_flag': aux1_low_alarm_flag, + 'aux1_high_warn_flag': aux1_high_warn_flag, + 'aux1_low_warn_flag': aux1_low_warn_flag} + + custom_mon_high_alarm_flag = bool((module_flag_byte3 >> 4) & 0x1) + custom_mon_low_alarm_flag = bool((module_flag_byte3 >> 5) & 0x1) + custom_mon_high_warn_flag = bool((module_flag_byte3 >> 6) & 0x1) + custom_mon_low_warn_flag = bool((module_flag_byte3 >> 7) & 0x1) + custom_mon_flags = {'custom_mon_high_alarm_flag': custom_mon_high_alarm_flag, + 'custom_mon_low_alarm_flag': custom_mon_low_alarm_flag, + 'custom_mon_high_warn_flag': custom_mon_high_warn_flag, + 'custom_mon_low_warn_flag': custom_mon_low_warn_flag} + + aux3_high_alarm_flag = bool((module_flag_byte3 >> 0) & 0x1) + aux3_low_alarm_flag = bool((module_flag_byte3 >> 1) & 0x1) + aux3_high_warn_flag = bool((module_flag_byte3 >> 2) & 0x1) + aux3_low_warn_flag = bool((module_flag_byte3 >> 3) & 0x1) + aux3_flags = {'aux3_high_alarm_flag': aux3_high_alarm_flag, + 'aux3_low_alarm_flag': aux3_low_alarm_flag, + 'aux3_high_warn_flag': aux3_high_warn_flag, + 'aux3_low_warn_flag': aux3_low_warn_flag} + + module_flag = {'voltage_flags': voltage_flags, + 'case_temp_flags': case_temp_flags, + 'aux1_flags': aux1_flags, + 'aux2_flags': aux2_flags, + 'aux3_flags': aux3_flags, + 'custom_mon_flags': custom_mon_flags} + return module_flag + + def get_datapath_state(self): + ''' + This function returns the eight datapath states + ''' + result = self.xcvr_eeprom.read(consts.DATAPATH_STATE) + dp_lane7 = (result >> 0) & 0xf + dp_lane8 = (result >> 4) & 0xf + dp_lane5 = (result >> 8) & 0xf + dp_lane6 = (result >> 12) & 0xf + dp_lane3 = (result >> 16) & 0xf + dp_lane4 = (result >> 20) & 0xf + dp_lane1 = (result >> 24) & 0xf + dp_lane2 = (result >> 28) & 0xf + DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].DATAPATH_STATE + dp_state_dict = {'dp_lane1': DICT.get(dp_lane1, "Unknown"), + 'dp_lane2': DICT.get(dp_lane2, "Unknown"), + 'dp_lane3': DICT.get(dp_lane3, "Unknown"), + 'dp_lane4': DICT.get(dp_lane4, "Unknown"), + 'dp_lane5': DICT.get(dp_lane5, "Unknown"), + 'dp_lane6': DICT.get(dp_lane6, "Unknown"), + 'dp_lane7': DICT.get(dp_lane7, "Unknown"), + 'dp_lane8': DICT.get(dp_lane8, "Unknown") + } + return dp_state_dict + + def get_tx_output_status(self): + ''' + This function returns whether TX output signals are valid + ''' + result = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) + tx_output_status_dict = dict() + for bitpos in range(BYTELENGTH): + tx_output_status_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_output_status_dict + + def get_rx_output_status(self): + ''' + This function returns whether RX output signals are valid + ''' + result = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) + rx_output_status_dict = dict() + for bitpos in range(BYTELENGTH): + rx_output_status_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return rx_output_status_dict + + def get_tx_fault(self): + ''' + This function returns TX failure flag + ''' + result = self.xcvr_eeprom.read(consts.TX_FAULT_FLAG) + tx_fault_dict = dict() + for bitpos in range(BYTELENGTH): + tx_fault_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_fault_dict + + def get_tx_los(self): + ''' + This function returns TX LOS flag + ''' + result = self.xcvr_eeprom.read(consts.TX_LOS_FLAG) + tx_los_dict = dict() + for bitpos in range(BYTELENGTH): + tx_los_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_los_dict + + def get_tx_cdr_lol(self): + ''' + This function returns TX CDR LOL flag + ''' + result = self.xcvr_eeprom.read(consts.TX_CDR_LOL) + tx_lol_dict = dict() + for bitpos in range(BYTELENGTH): + tx_lol_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_lol_dict + + def get_tx_power_flag(self): + ''' + This function returns TX power out of range flag + ''' + tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM_FLAG) + tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM_FLAG) + tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN_FLAG) + tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN_FLAG) + tx_power_high_alarm_dict = dict() + tx_power_low_alarm_dict = dict() + tx_power_high_warn_dict = dict() + tx_power_low_warn_dict = dict() + for bitpos in range(BYTELENGTH): + tx_power_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_alarm >> bitpos) & 0x1) + tx_power_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_alarm >> bitpos) & 0x1) + tx_power_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_warn >> bitpos) & 0x1) + tx_power_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_warn >> bitpos) & 0x1) + + tx_power_flag_dict = {'tx_power_high_alarm': tx_power_high_alarm_dict, + 'tx_power_low_alarm': tx_power_low_alarm_dict, + 'tx_power_high_warn': tx_power_high_warn_dict, + 'tx_power_low_warn': tx_power_low_warn_dict,} + return tx_power_flag_dict + + def get_tx_bias_flag(self): + ''' + This function returns TX bias out of range flag + ''' + tx_bias_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_ALARM_FLAG) + tx_bias_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_ALARM_FLAG) + tx_bias_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_WARN_FLAG) + tx_bias_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_WARN_FLAG) + tx_bias_high_alarm_dict = dict() + tx_bias_low_alarm_dict = dict() + tx_bias_high_warn_dict = dict() + tx_bias_low_warn_dict = dict() + for bitpos in range(BYTELENGTH): + tx_bias_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_alarm >> bitpos) & 0x1) + tx_bias_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_alarm >> bitpos) & 0x1) + tx_bias_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_warn >> bitpos) & 0x1) + tx_bias_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_warn >> bitpos) & 0x1) + + tx_bias_flag_dict = {'tx_bias_high_alarm': tx_bias_high_alarm_dict, + 'tx_bias_low_alarm': tx_bias_low_alarm_dict, + 'tx_bias_high_warn': tx_bias_high_warn_dict, + 'tx_bias_low_warn': tx_bias_low_warn_dict,} + return tx_bias_flag_dict + + def get_rx_power_flag(self): + ''' + This function returns RX power out of range flag + ''' + rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM_FLAG) + rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM_FLAG) + rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN_FLAG) + rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN_FLAG) + rx_power_high_alarm_dict = dict() + rx_power_low_alarm_dict = dict() + rx_power_high_warn_dict = dict() + rx_power_low_warn_dict = dict() + for bitpos in range(BYTELENGTH): + rx_power_high_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_alarm >> bitpos) & 0x1) + rx_power_low_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_alarm >> bitpos) & 0x1) + rx_power_high_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_warn >> bitpos) & 0x1) + rx_power_low_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_warn >> bitpos) & 0x1) + + rx_power_flag_dict = {'rx_power_high_alarm': rx_power_high_alarm_dict, + 'rx_power_low_alarm': rx_power_low_alarm_dict, + 'rx_power_high_warn': rx_power_high_warn_dict, + 'rx_power_low_warn': rx_power_low_warn_dict,} + return rx_power_flag_dict + + def get_rx_los(self): + ''' + This function returns RX LOS flag + ''' + result = self.xcvr_eeprom.read(consts.RX_LOS_FLAG) + rx_los_dict = dict() + for bitpos in range(BYTELENGTH): + rx_los_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return rx_los_dict + + def get_rx_cdr_lol(self): + ''' + This function returns RX CDR LOL flag + ''' + result = self.xcvr_eeprom.read(consts.RX_CDR_LOL) + rx_lol_dict = dict() + for bitpos in range(BYTELENGTH): + rx_lol_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return rx_lol_dict + + def get_config_datapath_hostlane_status(self): + ''' + This function returns configuration command execution + / result status for the datapath of each host lane + ''' + result = self.xcvr_eeprom.read(consts.CONFIG_LANE_STATUS) + config_status_lane7 = (result >> 0) & 0xf + config_status_lane8 = (result >> 4) & 0xf + config_status_lane5 = (result >> 8) & 0xf + config_status_lane6 = (result >> 12) & 0xf + config_status_lane3 = (result >> 16) & 0xf + config_status_lane4 = (result >> 20) & 0xf + config_status_lane1 = (result >> 24) & 0xf + config_status_lane2 = (result >> 28) & 0xf + config_status_raw = [config_status_lane1, config_status_lane2, config_status_lane3, config_status_lane4, + config_status_lane5, config_status_lane6, config_status_lane7, config_status_lane8] + DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].CONFIG_STATUS + config_status_dict = {'config_DP_status_hostlane1': DICT.get(config_status_lane1, "Unknown"), + 'config_DP_status_hostlane2': DICT.get(config_status_lane2, "Unknown"), + 'config_DP_status_hostlane3': DICT.get(config_status_lane3, "Unknown"), + 'config_DP_status_hostlane4': DICT.get(config_status_lane4, "Unknown"), + 'config_DP_status_hostlane5': DICT.get(config_status_lane5, "Unknown"), + 'config_DP_status_hostlane6': DICT.get(config_status_lane6, "Unknown"), + 'config_DP_status_hostlane7': DICT.get(config_status_lane7, "Unknown"), + 'config_DP_status_hostlane8': DICT.get(config_status_lane8, "Unknown") + } + return config_status_dict + + def get_dpinit_pending(self): + ''' + This function returns datapath init pending status. + 0 means datapath init not pending. + 1 means datapath init pending. DPInit not yet executed after successful ApplyDPInit. + Hence the active control set content may deviate from the actual hardware config + ''' + result = self.xcvr_eeprom.read(consts.DPINIT_PENDING) + dpinit_pending_dict = dict() + for bitpos in range(BYTELENGTH): + dpinit_pending_dict['hostlane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return dpinit_pending_dict + + def get_tuning_in_progress(self): + ''' + This function returns tunning in progress status. + 0 means tuning not in progress + 1 means tuning in progress + ''' + return bool(self.xcvr_eeprom.read(consts.TUNING_IN_PROGRESS)) + + def get_wavelength_unlocked(self): + ''' + This function returns wavelength unlocked status. + 0 means wavelength locked + 1 means wavelength unlocked + ''' + return bool(self.xcvr_eeprom.read(consts.WAVELENGTH_UNLOCKED)) + + def get_laser_tuning_summary(self): + ''' + This function returns laser tuning status summary + ''' + result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) + laser_tuning_summary = [] + if (result >> 5) & 0x1: + laser_tuning_summary.append("TargetOutputPowerOOR") + if (result >> 4) & 0x1: + laser_tuning_summary.append("FineTuningOutOfRange") + if (result >> 3) & 0x1: + laser_tuning_summary.append("TuningNotAccepted") + if (result >> 2) & 0x1: + laser_tuning_summary.append("InvalidChannel") + if (result >> 1) & 0x1: + laser_tuning_summary.append("WavelengthUnlocked") + if (result >> 0) & 0x1: + laser_tuning_summary.append("TuningComplete") + return laser_tuning_summary + + def set_low_power(self, AssertLowPower): + ''' + This function sets the module to low power state. + AssertLowPower being 0 means "set to high power" + AssertLowPower being 1 means "set to low power" + ''' + low_power_control = AssertLowPower << 6 + self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control) + + def set_laser_freq(self, freq): + ''' + This function sets the laser frequency. Unit in THz + ZR application will not support fine tuning of the laser + ''' + GridSupported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) + GridSupported_75GHz = (GridSupported >> 7) & 0x1 + assert GridSupported_75GHz + freq_grid = 0x70 + self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) + channel_number = int(round((freq - 193.1)/0.025)) + assert channel_number % 3 == 0 + low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) + hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) + if channel_number > hi_ch_num or channel_number < low_ch_num: + raise ValueError('Provisioned frequency out of range. Max Freq: 196.1; Min Freq: 191.3 THz.') + self.set_low_power(True) + time.sleep(5) + self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) + time.sleep(1) + self.set_low_power(False) + time.sleep(1) + + def set_TX_power(self, TX_power): + ''' + This function sets the TX output power. Unit in dBm + ''' + min_prog_tx_output_power = self.xcvr_eeprom.read(consts.MIN_PROG_OUTPUT_POWER) + max_prog_tx_output_power = self.xcvr_eeprom.read(consts.MAX_PROG_OUTPUT_POWER) + if TX_power > max_prog_tx_output_power or TX_power < min_prog_tx_output_power: + raise ValueError('Provisioned TX power out of range. Max: %.1f; Min: %.1f dBm.' + %(max_prog_tx_output_power, min_prog_tx_output_power)) + self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, TX_power) + time.sleep(1) + + def get_loopback_capability(self): + ''' + This function returns the module loopback capability as advertised + ''' + allowed_loopback_result = self.xcvr_eeprom.read(consts.LOOPBACK_CAPABILITY) + loopback_capability = dict() + loopback_capability['simultaneous_host_media_loopback_supported'] = bool((allowed_loopback_result >> 6) & 0x1) + loopback_capability['per_lane_media_loopback_supported'] = bool((allowed_loopback_result >> 5) & 0x1) + loopback_capability['per_lane_host_loopback_supported'] = bool((allowed_loopback_result >> 4) & 0x1) + loopback_capability['host_side_input_loopback_supported'] = bool((allowed_loopback_result >> 3) & 0x1) + loopback_capability['host_side_output_loopback_supported'] = bool((allowed_loopback_result >> 2) & 0x1) + loopback_capability['media_side_input_loopback_supported'] = bool((allowed_loopback_result >> 1) & 0x1) + loopback_capability['media_side_output_loopback_supported'] = bool((allowed_loopback_result >> 0) & 0x1) + return loopback_capability + + def set_loopback_mode(self, loopback_mode): + ''' + This function sets the module loopback mode. + Loopback mode has to be one of the five: + 1. "none" (default) + 2. "host-side-input" + 3. "host-side-output" + 4. "media-side-input" + 5. "media-side-output" + The function will look at 13h:128 to check advertized loopback capabilities. + ''' + loopback_capability = self.get_loopback_capability() + if loopback_mode == 'none': + self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0) + elif loopback_mode == 'host-side-input': + assert loopback_capability['host_side_input_loopback_supported'] + self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0xff) + elif loopback_mode == 'host-side-output': + assert loopback_capability['host_side_output_loopback_supported'] + self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0xff) + elif loopback_mode == 'media-side-input': + assert loopback_capability['media_side_input_loopback_supported'] + self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0x1) + elif loopback_mode == 'media-side-output': + assert loopback_capability['media_side_output_loopback_supported'] + self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0x1) \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py b/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py new file mode 100644 index 000000000..1cf8d5220 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py @@ -0,0 +1,60 @@ +""" + cmis_code.py + + Implementation of dictionaries used in CMIS +""" +from ..xcvr_codes import XcvrCodes + +class CmisCode(XcvrCodes): + MEDIA_INTERFACE_TECH = { + 0: '850 nm VCSEL', + 1: '1310 nm VCSEL', + 2: '1550 nm VCSEL', + 3: '1310 nm FP', + 4: '1310 nm DFB', + 5: '1550 nm DFB', + 6: '1310 nm EML', + 7: '1550 nm EML', + 8: 'Others', + 9: '1490 nm DFB', + 10: 'Copper cable unequalized', + 11: 'Copper cable passive equalized', + 12: 'Copper cable, near and far end limiting active equalizers', + 13: 'Copper cable, far end limiting active equalizers', + 14: 'Copper cable, near end limiting active equalizers', + 15: 'Copper cable, linear active equalizers', + 16: 'C-band tunable laser', + 17: 'L-band tunable laser', + } + + MODULE_STATE = { + 1: 'ModuleLowPwr', + 2: 'ModulePwrUp', + 3: 'ModuleReady', + 4: 'ModulePwrDn', + 5: 'ModuleFault', + } + + DATAPATH_STATE = { + 1: 'DataPathDeactivated', + 2: 'DataPathInit', + 3: 'DataPathDeinit', + 4: 'DataPathActivated', + 5: 'DataPathTxTurnOn', + 6: 'DataPathTxTurnOff', + 7: 'DataPathInitialized', + } + + CONFIG_STATUS = { + 0: 'ConfigUndefined', + 1: 'ConfigSuccess', + 2: 'ConfigRejected', + 3: 'ConfigRejectedInvalidAppSel', + 4: 'ConfigRejectedInvalidDataPath', + 5: 'ConfigRejectedInvalidSI', + 6: 'ConfigRejectedLaneInUse', + 7: 'ConfigRejectedPartialDataPath', + 12: 'ConfigInProgress', + } + + # TODO: Add other codes \ No newline at end of file From 405688b72eeb955709e661827ab62cd645ff3838 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Wed, 22 Sep 2021 23:33:07 -0700 Subject: [PATCH 04/16] Address PR comments --- .../sonic_xcvr/api/public/cmis.py | 492 ------------------ .../sonic_xcvr/codes/public/sff8024.py | 51 -- .../sonic_xcvr/fields/consts.py | 87 +++- .../sonic_xcvr/mem_maps/public/cmis.py | 108 +++- .../sonic_xcvr/xcvr_api_factory.py | 7 +- 5 files changed, 159 insertions(+), 586 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index 792370d08..2d1bd8246 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -14,498 +14,6 @@ class CmisApi(XcvrApi): def __init__(self, xcvr_eeprom): super(CmisApi, self).__init__(xcvr_eeprom) - # Transceiver Information - def get_model(self): - return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD) - - def get_vendor_rev(self): - return self.xcvr_eeprom.read(consts.VENDOR_REV) - - def get_vendor_serial(self): - return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO) - - def get_vendor_name(self): - return self.xcvr_eeprom.read(consts.VENDOR_NAME_FIELD) - - def get_module_type(self): - return self.xcvr_eeprom.read(consts.ID_FIELD) - - def get_vendor_OUI(self): - return self.xcvr_eeprom.read(consts.VENDOR_OUI_FIELD) - - def get_vendor_date(self): - return self.xcvr_eeprom.read(consts.VENDOR_DATE) - - def get_connector_type(self): - return self.xcvr_eeprom.read(consts.CONNECTOR_TYPE) - - def get_module_media_type(self): - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_TYPE) - - def get_host_electrical_interface(self): - return self.xcvr_eeprom.read(consts.HOST_ELECTRICAL_INTERFACE) - - def get_module_media_interface(self): - media_type = self.get_module_media_type() - if media_type == 'Multimode Fiber (MMF)': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM) - elif media_type == 'Single Mode Fiber (SMF)': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_SM) - elif media_type == 'Passive Copper Cable': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER) - elif media_type == 'Active Cable Assembly': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE) - elif media_type == 'BASE-T': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_BASE_T) - else: - return 'Unknown media interface' - - def get_host_lane_count(self): - lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) - return (lane_count >> 4) & 0xf - - def get_media_lane_count(self): - lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) - return (lane_count) & 0xf - - def get_host_lane_assignment_option(self): - return self.xcvr_eeprom.read(consts.HOST_LANE_ASSIGNMENT_OPTION) - - def get_media_lane_assignment_option(self): - return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION) - - def get_active_apsel_hostlane1(self): - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_1) - return (result >> 4) & 0xf - - def get_active_apsel_hostlane2(self): - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_2) - return (result >> 4) & 0xf - - def get_active_apsel_hostlane3(self): - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_3) - return (result >> 4) & 0xf - - def get_active_apsel_hostlane4(self): - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_4) - return (result >> 4) & 0xf - - def get_active_apsel_hostlane5(self): - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_5) - return (result >> 4) & 0xf - - def get_active_apsel_hostlane6(self): - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_6) - return (result >> 4) & 0xf - - def get_active_apsel_hostlane7(self): - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_7) - return (result >> 4) & 0xf - - def get_active_apsel_hostlane8(self): - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_8) - return (result >> 4) & 0xf - - def get_media_interface_technology(self): - return self.xcvr_eeprom.read(consts.MEDIA_INTERFACE_TECH) - - def get_module_hardware_revision(self): - hw_major_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) - hw_minor_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) - hw_rev = [str(num) for num in [hw_major_rev, hw_minor_rev]] - return '.'.join(hw_rev) - - def get_cmis_rev(self): - cmis = self.xcvr_eeprom.read(consts.CMIS_REVISION) - cmis_major = (cmis >> 4) & 0xf - cmis_minor = (cmis) & 0xf - cmis_rev = [str(num) for num in [cmis_major, cmis_minor]] - return '.'.join(cmis_rev) - - def get_module_active_firmware(self): - active_fw_major = self.xcvr_eeprom.read(consts.ACTIVE_FW_MAJOR_REV) - active_fw_minor = self.xcvr_eeprom.read(consts.ACTIVE_FW_MINOR_REV) - active_fw = [str(num) for num in [active_fw_major, active_fw_minor]] - return '.'.join(active_fw) - - def get_module_inactive_firmware(self): - inactive_fw_major = self.xcvr_eeprom.read(consts.INACTIVE_FW_MAJOR_REV) - inactive_fw_minor = self.xcvr_eeprom.read(consts.INACTIVE_FW_MINOR_REV) - inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]] - return '.'.join(inactive_fw) - - # Transceiver DOM - def get_module_temperature(self): - return self.xcvr_eeprom.read(consts.CASE_TEMP) - - def get_module_voltage(self): - return self.xcvr_eeprom.read(consts.VOLTAGE) - - def get_rxpower1(self): - return self.xcvr_eeprom.read(consts.RX_POW1) - - def get_rxpower2(self): - return self.xcvr_eeprom.read(consts.RX_POW2) - - def get_rxpower3(self): - return self.xcvr_eeprom.read(consts.RX_POW3) - - def get_rxpower4(self): - return self.xcvr_eeprom.read(consts.RX_POW4) - - def get_txbias1(self): - return self.xcvr_eeprom.read(consts.TX_BIAS1) - - def get_txbias2(self): - return self.xcvr_eeprom.read(consts.TX_BIAS2) - - def get_txbias3(self): - return self.xcvr_eeprom.read(consts.TX_BIAS3) - - def get_txbias4(self): - return self.xcvr_eeprom.read(consts.TX_BIAS4) - - def get_freq_grid(self): - freq_grid = self.xcvr_eeprom.read(consts.GRID_SPACING) >> 4 - if freq_grid == 7: - return 75 - elif freq_grid == 6: - return 33 - elif freq_grid == 5: - return 100 - elif freq_grid == 4: - return 50 - elif freq_grid == 3: - return 25 - elif freq_grid == 2: - return 12.5 - elif freq_grid == 1: - return 6.25 - elif freq_grid == 0: - return 3.125 - - def get_laser_config_freq(self): - freq_grid = self.get_freq_grid() - channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) - if freq_grid == 75: - config_freq = 193100000 + channel * freq_grid/3*1000 - else: - config_freq = 193100000 + channel * freq_grid - return config_freq - - def get_current_laser_freq(self): - return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ) - - def get_TX_config_power(self): - return self.xcvr_eeprom.read(consts.TX_CONFIG_POWER) - - def get_media_output_loopback(self): - result = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) - return result == 1 - - def get_media_input_loopback(self): - result = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) - return result == 1 - - def get_host_output_loopback(self): - result = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) - loopback_status = [] - for bitpos in range(BYTELENGTH): - loopback_status.append(bool((result >> bitpos) & 0x1)) - return loopback_status - - def get_host_input_loopback(self): - result = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) - loopback_status = [] - for bitpos in range(BYTELENGTH): - loopback_status.append(bool((result >> bitpos) & 0x1)) - return loopback_status - - def get_aux_mon_type(self): - result = self.xcvr_eeprom.read(consts.AUX_MON_TYPE) - aux1_mon_type = result & 0x1 - aux2_mon_type = (result >> 1) & 0x1 - aux3_mon_type = (result >> 2) & 0x1 - return aux1_mon_type, aux2_mon_type, aux3_mon_type - - def get_laser_temp(self): - aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() - LASER_TEMP_SCALE = 256.0 - if aux2_mon_type == 0: - laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE - elif aux2_mon_type == 1 and aux3_mon_type == 0: - laser_temp = self.xcvr_eeprom.read(consts.AUX3_MON)/LASER_TEMP_SCALE - else: - return None - return laser_temp - - def get_PM(self): - self.xcvr_eeprom.write(consts.FREEZE_REQUEST, 128) - time.sleep(5) - self.xcvr_eeprom.write(consts.FREEZE_REQUEST, 0) - PM_dict = dict() - - rx_bits_pm = self.xcvr_eeprom.read(consts.RX_BITS_PM) - rx_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_BITS_SUB_INTERVAL_PM) - rx_corr_bits_pm = self.xcvr_eeprom.read(consts.RX_CORR_BITS_PM) - rx_min_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_CORR_BITS_SUB_INTERVAL_PM) - rx_max_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MAX_CORR_BITS_SUB_INTERVAL_PM) - - if (rx_bits_subint_pm != 0) and (rx_bits_pm != 0): - PM_dict['preFEC_BER_cur'] = rx_corr_bits_pm*1.0/rx_bits_pm - PM_dict['preFEC_BER_min'] = rx_min_corr_bits_subint_pm*1.0/rx_bits_subint_pm - PM_dict['preFEC_BER_max'] = rx_max_corr_bits_subint_pm*1.0/rx_bits_subint_pm - - rx_frames_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_PM) - rx_frames_subint_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_SUB_INTERVAL_PM) - rx_frames_uncorr_err_pm = self.xcvr_eeprom.read(consts.RX_FRAMES_UNCORR_ERR_PM) - rx_min_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) - rx_max_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) - - if (rx_frames_subint_pm != 0) and (rx_frames_pm != 0): - PM_dict['preFEC_uncorr_frame_ratio_cur'] = rx_frames_uncorr_err_pm*1.0/rx_frames_subint_pm - PM_dict['preFEC_uncorr_frame_ratio_min'] = rx_min_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm - PM_dict['preFEC_uncorr_frame_ratio_max'] = rx_max_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm - - PM_dict['rx_cd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_CD_PM) - PM_dict['rx_cd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_CD_PM) - PM_dict['rx_cd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_CD_PM) - - PM_dict['rx_dgd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_DGD_PM) - PM_dict['rx_dgd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_DGD_PM) - PM_dict['rx_dgd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_DGD_PM) - - PM_dict['rx_sopmd_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SOPMD_PM) - PM_dict['rx_sopmd_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SOPMD_PM) - PM_dict['rx_sopmd_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SOPMD_PM) - - PM_dict['rx_pdl_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_PDL_PM) - PM_dict['rx_pdl_min'] = self.xcvr_eeprom.read(consts.RX_MIN_PDL_PM) - PM_dict['rx_pdl_max'] = self.xcvr_eeprom.read(consts.RX_MAX_PDL_PM) - - PM_dict['rx_osnr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_OSNR_PM) - PM_dict['rx_osnr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_OSNR_PM) - PM_dict['rx_osnr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_OSNR_PM) - - PM_dict['rx_esnr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_ESNR_PM) - PM_dict['rx_esnr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_ESNR_PM) - PM_dict['rx_esnr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_ESNR_PM) - - PM_dict['rx_cfo_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_CFO_PM) - PM_dict['rx_cfo_min'] = self.xcvr_eeprom.read(consts.RX_MIN_CFO_PM) - PM_dict['rx_cfo_max'] = self.xcvr_eeprom.read(consts.RX_MAX_CFO_PM) - - PM_dict['rx_evm_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_EVM_PM) - PM_dict['rx_evm_min'] = self.xcvr_eeprom.read(consts.RX_MIN_EVM_PM) - PM_dict['rx_evm_max'] = self.xcvr_eeprom.read(consts.RX_MAX_EVM_PM) - - PM_dict['tx_power_avg'] = self.xcvr_eeprom.read(consts.TX_AVG_POWER_PM) - PM_dict['tx_power_min'] = self.xcvr_eeprom.read(consts.TX_MIN_POWER_PM) - PM_dict['tx_power_max'] = self.xcvr_eeprom.read(consts.TX_MAX_POWER_PM) - - PM_dict['rx_power_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_POWER_PM) - PM_dict['rx_power_min'] = self.xcvr_eeprom.read(consts.RX_MIN_POWER_PM) - PM_dict['rx_power_max'] = self.xcvr_eeprom.read(consts.RX_MAX_POWER_PM) - - PM_dict['rx_sigpwr_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SIG_POWER_PM) - PM_dict['rx_sigpwr_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SIG_POWER_PM) - PM_dict['rx_sigpwr_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SIG_POWER_PM) - - PM_dict['rx_soproc_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_SOPROC_PM) - PM_dict['rx_soproc_min'] = self.xcvr_eeprom.read(consts.RX_MIN_SOPROC_PM) - PM_dict['rx_soproc_max'] = self.xcvr_eeprom.read(consts.RX_MAX_SOPROC_PM) - - PM_dict['rx_mer_avg'] = self.xcvr_eeprom.read(consts.RX_AVG_MER_PM) - PM_dict['rx_mer_min'] = self.xcvr_eeprom.read(consts.RX_MIN_MER_PM) - PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM) - - - return PM_dict - - def get_module_state(self): - result = self.xcvr_eeprom.read(consts.MODULE_STATE) >> 1 - DICT = self.xcvr_eeprom.mem_map.codes.MODULE_STATE - return DICT.get(result, "Unknown") - - def get_module_firmware_fault_state_changed(self): - result = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) - datapath_firmware_fault = bool((result >> 2) & 0x1) - module_firmware_fault = bool((result >> 1) & 0x1) - module_state_changed = bool(result & 0x1) - return datapath_firmware_fault, module_firmware_fault, module_state_changed - - def get_datapath_state(self): - result = self.xcvr_eeprom.read(consts.DATAPATH_STATE) - dp_lane7 = (result >> 0) & 0xf - dp_lane8 = (result >> 4) & 0xf - dp_lane5 = (result >> 8) & 0xf - dp_lane6 = (result >> 12) & 0xf - dp_lane3 = (result >> 16) & 0xf - dp_lane4 = (result >> 20) & 0xf - dp_lane1 = (result >> 24) & 0xf - dp_lane2 = (result >> 28) & 0xf - dp_state_raw = [dp_lane1, dp_lane2, dp_lane3, dp_lane4, dp_lane5, dp_lane6, dp_lane7, dp_lane8] - DICT = self.xcvr_eeprom.mem_map.codes.DATAPATH_STATE - dp_state = [DICT.get(dp_lane, "Unknown") for dp_lane in dp_state_raw] - return dp_state - - def get_tx_output_status(self): - result = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) - tx_output_status = [] - for bitpos in range(BYTELENGTH): - tx_output_status.append(bool((result >> bitpos) & 0x1)) - return tx_output_status - - def get_rx_output_status(self): - result = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) - rx_output_status = [] - for bitpos in range(BYTELENGTH): - rx_output_status.append(bool((result >> bitpos) & 0x1)) - return rx_output_status - - def get_tx_fault(self): - result = self.xcvr_eeprom.read(consts.TX_FAULT_FLAG) - tx_fault = [] - for bitpos in range(BYTELENGTH): - tx_fault.append(bool((result >> bitpos) & 0x1)) - return tx_fault - - def get_tx_los(self): - result = self.xcvr_eeprom.read(consts.TX_LOS_FLAG) - tx_los = [] - for bitpos in range(BYTELENGTH): - tx_los.append(bool((result >> bitpos) & 0x1)) - return tx_los - - def get_tx_cdr_lol(self): - result = self.xcvr_eeprom.read(consts.TX_CDR_LOL) - tx_lol = [] - for bitpos in range(BYTELENGTH): - tx_lol.append(bool((result >> bitpos) & 0x1)) - return tx_lol - - def get_rx_los(self): - result = self.xcvr_eeprom.read(consts.RX_LOS_FLAG) - rx_los = [] - for bitpos in range(BYTELENGTH): - rx_los.append(bool((result >> bitpos) & 0x1)) - return rx_los - - def get_rx_cdr_lol(self): - result = self.xcvr_eeprom.read(consts.RX_CDR_LOL) - rx_lol = [] - for bitpos in range(BYTELENGTH): - rx_lol.append(bool((result >> bitpos) & 0x1)) - return rx_lol - - def get_config_lane_status(self): - result = self.xcvr_eeprom.read(consts.CONFIG_LANE_STATUS) - config_status_lane7 = (result >> 0) & 0xf - config_status_lane8 = (result >> 4) & 0xf - config_status_lane5 = (result >> 8) & 0xf - config_status_lane6 = (result >> 12) & 0xf - config_status_lane3 = (result >> 16) & 0xf - config_status_lane4 = (result >> 20) & 0xf - config_status_lane1 = (result >> 24) & 0xf - config_status_lane2 = (result >> 28) & 0xf - config_status_raw = [config_status_lane1, config_status_lane2, config_status_lane3, config_status_lane4, - config_status_lane5, config_status_lane6, config_status_lane7, config_status_lane8] - DICT = self.xcvr_eeprom.mem_map.codes.CONFIG_STATUS - config_status = [DICT.get(config_lane, "Unknown") for config_lane in config_status_raw] - return config_status - - def get_dpinit_pending(self): - result = self.xcvr_eeprom.read(consts.DPINIT_PENDING) - dpinit_pending = [] - for bitpos in range(BYTELENGTH): - dpinit_pending.append(bool((result >> bitpos) & 0x1)) - return dpinit_pending - - def get_tuning_in_progress(self): - return bool(self.xcvr_eeprom.read(consts.TUNING_IN_PROGRESS)) - - def get_wavelength_unlocked(self): - return bool(self.xcvr_eeprom.read(consts.WAVELENGTH_UNLOCKED)) - - def get_laser_tuning_summary(self): - result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) - laser_tuning_summary = [] - if (result >> 5) & 0x1: - laser_tuning_summary.append("TargetOutputPowerOOR") - if (result >> 4) & 0x1: - laser_tuning_summary.append("FineTuningOutOfRange") - if (result >> 3) & 0x1: - laser_tuning_summary.append("TuningNotAccepted") - if (result >> 2) & 0x1: - laser_tuning_summary.append("InvalidChannel") - if (result >> 1) & 0x1: - laser_tuning_summary.append("WavelengthUnlocked") - if (result >> 0) & 0x1: - laser_tuning_summary.append("TuningComplete") - return laser_tuning_summary - - def set_low_power(self, AssertLowPower): - low_power_control = AssertLowPower << 6 - self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control) - - def set_laser_freq(self, freq): - freq_grid = 0x70 - self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) - channel_number = int(round((freq - 193.1)/0.025)) - assert channel_number % 3 == 0 - self.set_low_power(True) - time.sleep(5) - self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) - time.sleep(1) - self.set_low_power(False) - time.sleep(1) - - def set_TX_power(self, TX_power): - self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, TX_power) - time.sleep(1) - - def get_loopback_capability(self): - allowed_loopback_result = self.xcvr_eeprom.read(consts.LOOPBACK_CAPABILITY) - loopback_capability = dict() - loopback_capability['simultaneous_host_media_loopback_supported'] = bool((allowed_loopback_result >> 6) & 0x1) - loopback_capability['per_lane_media_loopback_supported'] = bool((allowed_loopback_result >> 5) & 0x1) - loopback_capability['per_lane_host_loopback_supported'] = bool((allowed_loopback_result >> 4) & 0x1) - loopback_capability['host_side_input_loopback_supported'] = bool((allowed_loopback_result >> 3) & 0x1) - loopback_capability['host_side_output_loopback_supported'] = bool((allowed_loopback_result >> 2) & 0x1) - loopback_capability['media_side_input_loopback_supported'] = bool((allowed_loopback_result >> 1) & 0x1) - loopback_capability['media_side_output_loopback_supported'] = bool((allowed_loopback_result >> 0) & 0x1) - return loopback_capability - - def set_loopback_mode(self, loopback_mode): - ''' - Loopback mode has to be one of the five: - 1. "none" (default) - 2. "host-side-input" - 3. "host-side-output" - 4. "media-side-input" - 5. "media-side-output" - The function will look at 13h:128 to check advertized loopback capabilities. - ''' - loopback_capability = self.get_loopback_capability() - if loopback_mode == 'none': - self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0) - self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0) - self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0) - self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0) - elif loopback_mode == 'host-side-input': - assert loopback_capability['host_side_input_loopback_supported'] - self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0xff) - elif loopback_mode == 'host-side-output': - assert loopback_capability['host_side_output_loopback_supported'] - self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0xff) - elif loopback_mode == 'media-side-input': - assert loopback_capability['media_side_input_loopback_supported'] - self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0x1) - elif loopback_mode == 'media-side-output': - assert loopback_capability['media_side_output_loopback_supported'] - self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0x1) - - # TODO: other XcvrApi methods diff --git a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py index 216348c53..b069b3e73 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py @@ -260,55 +260,4 @@ class Sff8024(XcvrCodes): '04': '10GBASE-T (Clause 55)', } - MEDIA_INTERFACE_TECH = { - 0: '850 nm VCSEL', - 1: '1310 nm VCSEL', - 2: '1550 nm VCSEL', - 3: '1310 nm FP', - 4: '1310 nm DFB', - 5: '1550 nm DFB', - 6: '1310 nm EML', - 7: '1550 nm EML', - 8: 'Others', - 9: '1490 nm DFB', - 10: 'Copper cable unequalized', - 11: 'Copper cable passive equalized', - 12: 'Copper cable, near and far end limiting active equalizers', - 13: 'Copper cable, far end limiting active equalizers', - 14: 'Copper cable, near end limiting active equalizers', - 15: 'Copper cable, linear active equalizers', - 16: 'C-band tunable laser', - 17: 'L-band tunable laser', - } - - MODULE_STATE = { - 1: 'ModuleLowPwr', - 2: 'ModulePwrUp', - 3: 'ModuleReady', - 4: 'ModulePwrDn', - 5: 'ModuleFault', - } - - DATAPATH_STATE = { - 1: 'DataPathDeactivated', - 2: 'DataPathInit', - 3: 'DataPathDeinit', - 4: 'DataPathActivated', - 5: 'DataPathTxTurnOn', - 6: 'DataPathTxTurnOff', - 7: 'DataPathInitialized', - } - - CONFIG_STATUS = { - 0: 'ConfigUndefined', - 1: 'ConfigSuccess', - 2: 'ConfigRejected', - 3: 'ConfigRejectedInvalidAppSel', - 4: 'ConfigRejectedInvalidDataPath', - 5: 'ConfigRejectedInvalidSI', - 6: 'ConfigRejectedLaneInUse', - 7: 'ConfigRejectedPartialDataPath', - 12: 'ConfigInProgress', - } - # TODO: Add other codes diff --git a/sonic_platform_base/sonic_xcvr/fields/consts.py b/sonic_platform_base/sonic_xcvr/fields/consts.py index 49131fbf5..aa2521ac2 100644 --- a/sonic_platform_base/sonic_xcvr/fields/consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/consts.py @@ -39,37 +39,94 @@ TRANS_DOM_FIELD = "TransceiverDom" CASE_TEMP = "ModuleTemp" VOLTAGE = "Supply3V3" -RX_POW1 = "Rx1Power" -RX_POW2 = "Rx2Power" -RX_POW3 = "Rx3Power" -RX_POW4 = "Rx4Power" -TX_BIAS1 = "Tx1Bias" -TX_BIAS2 = "Tx2Bias" -TX_BIAS3 = "Tx3Bias" -TX_BIAS4 = "Tx4Bias" +TX_POW = "TxPower" +RX_POW = "RxPower" +TX_BIAS = "TxBias" GRID_SPACING = "Tx1SelectedGridSpacing" LASER_CONFIG_CHANNEL = "Tx1ChannelNumber" LASER_CURRENT_FREQ = "Tx1CurrentLaserFrequency" TX_CONFIG_POWER = "Tx1TargetOutputPower" -MEDIA_OUTPUT_LOOPBACK = "MediaSideOutputLoopbackEnable" -MEDIA_INPUT_LOOPBACK = "MediaSideInputLoopbackEnable" -HOST_OUTPUT_LOOPBACK = "HostSideOutputLoopbackEnable" -HOST_INPUT_LOOPBACK = "HostSideLoopbackEnable" AUX_MON_TYPE = "AuxMonitorType" AUX1_MON = "Aux1MonValue" AUX2_MON = "Aux2MonValue" AUX3_MON = "Aux3MonValue" +CUSTOM_MON = "CustomMonValue" + +# Loopback +TRANS_LOOPBACK_FIELD = "TransceiverLoopback" +LOOPBACK_CAPABILITY = "LoopbackCapability" +MEDIA_OUTPUT_LOOPBACK = "MediaSideOutputLoopbackEnable" +MEDIA_INPUT_LOOPBACK = "MediaSideInputLoopbackEnable" +HOST_OUTPUT_LOOPBACK = "HostSideOutputLoopbackEnable" +HOST_INPUT_LOOPBACK = "HostSideLoopbackEnable" + +# Threshold +TRANS_THRESHOLD_FIELD = "TransceiverThreshold" +CASE_TEMP_HIGH_ALARM = "TempeartureHighAlarmThreshold" +CASE_TEMP_LOW_ALARM = "TempeartureLowAlarmThreshold" +CASE_TEMP_HIGH_WARN = "TempeartureHighWarningThreshold" +CASE_TEMP_LOW_WARN = "TempeartureLowWarningThreshold" +VOLTAGE_HIGH_ALARM = "Supply3V3HighAlarmThreshold" +VOLTAGE_LOW_ALARM = "Supply3V3LowAlarmThreshold" +VOLTAGE_HIGH_WARN = "Supply3V3HighWarningThreshold" +VOLTAGE_LOW_WARN = "Supply3V3LowWarningThreshold" +AUX1_HIGH_ALARM = "Aux1MonitorHighAlarmThreshold" +AUX1_LOW_ALARM = "Aux1MonitorLowAlarmThreshold" +AUX1_HIGH_WARN = "Aux1MonitorHighWarningThreshold" +AUX1_LOW_WARN = "Aux1MonitorLowWarningThreshold" +AUX2_HIGH_ALARM = "Aux2MonitorHighAlarmThreshold" +AUX2_LOW_ALARM = "Aux2MonitorLowAlarmThreshold" +AUX2_HIGH_WARN = "Aux2MonitorHighWarningThreshold" +AUX2_LOW_WARN = "Aux2MonitorLowWarningThreshold" +AUX3_HIGH_ALARM = "Aux3MonitorHighAlarmThreshold" +AUX3_LOW_ALARM = "Aux3MonitorLowAlarmThreshold" +AUX3_HIGH_WARN = "Aux3MonitorHighWarningThreshold" +AUX3_LOW_WARN = "Aux3MonitorLowWarningThreshold" +TX_POWER_HIGH_ALARM = "TxOpticalPowerHighAlarmThreshold" +TX_POWER_LOW_ALARM = "TxOpticalPowerLowAlarmThreshold" +TX_POWER_HIGH_WARN = "TxOpticalPowerHighWarningThreshold" +TX_POWER_LOW_WARN = "TxOpticalPowerLowWarningThreshold" +TX_BIAS_CURR_HIGH_ALARM = "TxBiasCurrentHighAlarmThreshold" +TX_BIAS_CURR_LOW_ALARM = "TxBiasCurrentLowAlarmThreshold" +TX_BIAS_CURR_HIGH_WARN = "TxBiasCurrentHighWarningThreshold" +TX_BIAS_CURR_LOW_WARN = "TxBiasCurrentLowWarningThreshold" +RX_POWER_HIGH_ALARM = "RxOpticalPowerHighAlarmThreshold" +RX_POWER_LOW_ALARM = "RxOpticalPowerLowAlarmThreshold" +RX_POWER_HIGH_WARN = "RxOpticalPowerHighWarningThreshold" +RX_POWER_LOW_WARN = "RxOpticalPowerLowWarningThreshold" +SUPPORT_GRID = "GridSupported" +LOW_CHANNEL = "LowChannel75GHz" +HIGH_CHANNEL = "HighChannel75GHz" +MIN_PROG_OUTPUT_POWER = "MinProgOutputPower" +MAX_PROG_OUTPUT_POWER = "MaxProgOutputPower" # Status -TRANS_STATUS_FIELD = "TransceiverStatus" +TRANS_MODULE_STATUS_FIELD = "TransceiverModuleStatus" +TRANS_LANE_STATUS_FIELD = "TransceiverLaneStatus" MODULE_STATE = "ModuleState" MODULE_FIRMWARE_FAULT_INFO = "FirmwareFault" +MODULE_FLAG_BYTE1 = "ModuleFlagByte1" +MODULE_FLAG_BYTE2 = "ModuleFlagByte2" +MODULE_FLAG_BYTE3 = "ModuleFlagByte3" DATAPATH_STATE= "DataPathStateHostLane" TX_OUTPUT_STATUS = "TxOutputStatus" RX_OUTPUT_STATUS = "RxOutputStatus" TX_FAULT_FLAG = "TxFault" TX_LOS_FLAG = "TxLOS" TX_CDR_LOL = "TxCDRLOL" +TX_POWER_HIGH_ALARM_FLAG = "TxPowerHighAlarmFlag" +TX_POWER_LOW_ALARM_FLAG = "TxPowerLowAlarmFlag" +TX_POWER_HIGH_WARN_FLAG = "TxPowerHighWarnFlag" +TX_POWER_LOW_WARN_FLAG = "TxPowerLowWarnFlag" +TX_BIAS_HIGH_ALARM_FLAG = "TxBiasHighAlarmFlag" +TX_BIAS_LOW_ALARM_FLAG = "TxBiasLowAlarmFlag" +TX_BIAS_HIGH_WARN_FLAG = "TxBiasHighWarnFlag" +TX_BIAS_LOW_WARN_FLAG = "TxBiasLowWarnFlag" +RX_POWER_HIGH_ALARM_FLAG = "RxPowerHighAlarmFlag" +RX_POWER_LOW_ALARM_FLAG = "RxPowerLowAlarmFlag" +RX_POWER_HIGH_WARN_FLAG = "RxPowerHighWarnFlag" +RX_POWER_LOW_WARN_FLAG = "RxPowerLowWarnFlag" + RX_LOS_FLAG = "RxLOS" RX_CDR_LOL = "RxCDRLOL" CONFIG_LANE_STATUS = "ConfigStatusLane" @@ -81,7 +138,7 @@ # CONFIG TRANS_CONFIG_FIELD = "TransceriverConfig" MODULE_LEVEL_CONTROL = "ModuleControl" -LOOPBACK_CAPABILITY = "LoopbackCapability" + # C-CMIS @@ -90,7 +147,7 @@ ## Media Lane Link Performance Monitoring # PM TRANS_PM_FIELD = "TransceiverPm" -FREEZE_REQUEST = "FreezeRequest" +VDM_CONTROL = "VdmControl" MEDIA_LANE_FEC_PM = "Media Lane FEC Performance Monitoring" MEDIA_LANE_LINK_PM = "Media Lane Link Performance Monitoring" RX_BITS_PM = "rxBitsPm" 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 e56404cb0..fd937f010 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -25,21 +25,21 @@ def __init__(self, codes): super(CmisMemMap, self).__init__(codes) self.ADMIN_INFO = RegGroupField(consts.ADMIN_INFO_FIELD, - CodeRegField(consts.ID_FIELD, get_addr(0x0, 128), self.codes.XCVR_IDENTIFIERS), + CodeRegField(consts.ID_FIELD, get_addr(0x0, 128), self.codes['sff8024'].XCVR_IDENTIFIERS), StringRegField(consts.VENDOR_NAME_FIELD, get_addr(0x0, 129), size=16), HexRegField(consts.VENDOR_OUI_FIELD, get_addr(0x0, 145), size=3), StringRegField(consts.VENDOR_PART_NO_FIELD, get_addr(0x0, 148), size=16), StringRegField(consts.VENDOR_REV, get_addr(0x0, 164), size=2), StringRegField(consts.VENDOR_SERIAL_NO, get_addr(0x0, 166), size=16), StringRegField(consts.VENDOR_DATE,get_addr(0x0,182), size = 8), - CodeRegField(consts.CONNECTOR_TYPE, get_addr(0x0, 203), self.codes.CONNECTOR_TYPE), - CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, get_addr(0x0, 86), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_TYPE, get_addr(0x0, 85), self.codes.MODULE_MEDIA_TYPE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, get_addr(0x0, 87), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_SM, get_addr(0x0, 87), self.codes.SM_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, get_addr(0x0, 87), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, get_addr(0x0, 87), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, get_addr(0x0, 87), self.codes.BASE_T_MEDIA_INTERFACE), + CodeRegField(consts.CONNECTOR_TYPE, get_addr(0x0, 203), self.codes['sff8024'].CONNECTOR_TYPE), + CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, get_addr(0x0, 86), self.codes['sff8024'].HOST_ELECTRICAL_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_TYPE, get_addr(0x0, 85), self.codes['sff8024'].MODULE_MEDIA_TYPE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, get_addr(0x0, 87), self.codes['sff8024'].NM_850_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_SM, get_addr(0x0, 87), self.codes['sff8024'].SM_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, get_addr(0x0, 87), self.codes['sff8024'].PASSIVE_COPPER_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, get_addr(0x0, 87), self.codes['sff8024'].ACTIVE_CABLE_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, get_addr(0x0, 87), self.codes['sff8024'].BASE_T_MEDIA_INTERFACE), NumberRegField(consts.LANE_COUNT, get_addr(0x0, 88), format="B", size=1), NumberRegField(consts.HOST_LANE_ASSIGNMENT_OPTION, get_addr(0x0, 89), format="B", size=1), NumberRegField(consts.MEDIA_LANE_ASSIGNMENT_OPTION, get_addr(0x1, 176), format="B", size=1), @@ -51,7 +51,7 @@ def __init__(self, codes): NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_6, get_addr(0x11, 211), format="B", size=1), NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_7, get_addr(0x11, 212), format="B", size=1), NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_8, get_addr(0x11, 213), format="B", size=1), - CodeRegField(consts.MEDIA_INTERFACE_TECH, get_addr(0x0, 212), self.codes.MEDIA_INTERFACE_TECH), + CodeRegField(consts.MEDIA_INTERFACE_TECH, get_addr(0x0, 212), self.codes['cmis_code'].MEDIA_INTERFACE_TECH), NumberRegField(consts.HW_MAJOR_REV, get_addr(0x1, 130), size=1), NumberRegField(consts.HW_MINOR_REV, get_addr(0x1, 131), size=1), NumberRegField(consts.CMIS_REVISION, get_addr(0x0, 1), format="B", size=1), @@ -65,40 +65,97 @@ def __init__(self, codes): self.TRANS_DOM = RegGroupField(consts.TRANS_DOM_FIELD, NumberRegField(consts.CASE_TEMP, get_addr(0x0, 14), format=">h", size=2, scale=256.0), NumberRegField(consts.VOLTAGE, get_addr(0x0, 16), format=">H", size=2, scale=10000.0), - NumberRegField(consts.RX_POW1, get_addr(0x11, 186), format=">H", size=2, scale=10000.0), - NumberRegField(consts.RX_POW2, get_addr(0x11, 188), format=">H", size=2, scale=10000.0), - NumberRegField(consts.RX_POW3, get_addr(0x11, 190), format=">H", size=2, scale=10000.0), - NumberRegField(consts.RX_POW4, get_addr(0x11, 192), format=">H", size=2, scale=10000.0), - NumberRegField(consts.TX_BIAS1, get_addr(0x11, 170), format=">H", size=2, scale=500.0), - NumberRegField(consts.TX_BIAS2, get_addr(0x11, 172), format=">H", size=2, scale=500.0), - NumberRegField(consts.TX_BIAS3, get_addr(0x11, 174), format=">H", size=2, scale=500.0), - NumberRegField(consts.TX_BIAS4, get_addr(0x11, 176), format=">H", size=2, scale=500.0), + NumberRegField(consts.TX_POW, get_addr(0x11, 154), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POW, get_addr(0x11, 186), format=">H", size=2, scale=10000.0), + NumberRegField(consts.TX_BIAS, get_addr(0x11, 170), format=">H", size=2, scale=500.0), NumberRegField(consts.GRID_SPACING, get_addr(0x12, 128), size=1, ro=False), NumberRegField(consts.LASER_CONFIG_CHANNEL, get_addr(0x12, 136), format=">h", size=2, ro=False), NumberRegField(consts.LASER_CURRENT_FREQ, get_addr(0x12, 168), format=">L", size=4), NumberRegField(consts.TX_CONFIG_POWER, get_addr(0x12, 200), format=">h", size=2, scale=100.0, ro=False), - NumberRegField(consts.LOOPBACK_CAPABILITY, get_addr(0x13, 128), size=1), - RegBitField(consts.MEDIA_OUTPUT_LOOPBACK, offset=get_addr(0x13, 180), bitpos=0, ro=False), - RegBitField(consts.MEDIA_INPUT_LOOPBACK, offset=get_addr(0x13, 181), bitpos=0, ro=False), - NumberRegField(consts.HOST_OUTPUT_LOOPBACK, get_addr(0x13, 182), size=1, ro=False), - NumberRegField(consts.HOST_INPUT_LOOPBACK, get_addr(0x13, 183), size=1, ro=False), NumberRegField(consts.AUX_MON_TYPE, get_addr(0x1, 145), size=1), NumberRegField(consts.AUX1_MON, get_addr(0x0, 18), format=">h", size=2), NumberRegField(consts.AUX2_MON, get_addr(0x0, 20), format=">h", size=2), NumberRegField(consts.AUX3_MON, get_addr(0x0, 22), format=">h", size=2), + NumberRegField(consts.CUSTOM_MON, get_addr(0x0, 24), format=">H", size=2), ) - self.TRANS_STATUS = RegGroupField(consts.TRANS_STATUS_FIELD, + self.TRANS_LOOPBACK = RegGroupField(consts.TRANS_LOOPBACK_FIELD, + NumberRegField(consts.LOOPBACK_CAPABILITY, get_addr(0x13, 128), size=1), + RegBitField(consts.MEDIA_OUTPUT_LOOPBACK, offset=get_addr(0x13, 180), bitpos=0, ro=False), + RegBitField(consts.MEDIA_INPUT_LOOPBACK, offset=get_addr(0x13, 181), bitpos=0, ro=False), + NumberRegField(consts.HOST_OUTPUT_LOOPBACK, get_addr(0x13, 182), size=1, ro=False), + NumberRegField(consts.HOST_INPUT_LOOPBACK, get_addr(0x13, 183), size=1, ro=False), + ) + + self.TRANS_THRESHOLD = RegGroupField(consts.TRANS_THRESHOLD_FIELD, + NumberRegField(consts.CASE_TEMP_HIGH_ALARM, get_addr(0x2, 128), format=">h", size=2, scale=256.0), + NumberRegField(consts.CASE_TEMP_LOW_ALARM, get_addr(0x2, 130), format=">h", size=2, scale=256.0), + NumberRegField(consts.CASE_TEMP_HIGH_WARN, get_addr(0x2, 132), format=">h", size=2, scale=256.0), + NumberRegField(consts.CASE_TEMP_LOW_WARN, get_addr(0x2, 134), format=">h", size=2, scale=256.0), + NumberRegField(consts.VOLTAGE_HIGH_ALARM, get_addr(0x2, 136), format=">h", size=2, scale=10000.0), + NumberRegField(consts.VOLTAGE_LOW_ALARM, get_addr(0x2, 138), format=">h", size=2, scale=10000.0), + NumberRegField(consts.VOLTAGE_HIGH_WARN, get_addr(0x2, 140), format=">h", size=2, scale=10000.0), + NumberRegField(consts.VOLTAGE_LOW_WARN, get_addr(0x2, 142), format=">h", size=2, scale=10000.0), + NumberRegField(consts.AUX1_HIGH_ALARM, get_addr(0x2, 144), format=">h", size=2), + NumberRegField(consts.AUX1_LOW_ALARM, get_addr(0x2, 146), format=">h", size=2), + NumberRegField(consts.AUX1_HIGH_WARN, get_addr(0x2, 148), format=">h", size=2), + NumberRegField(consts.AUX1_LOW_WARN, get_addr(0x2, 150), format=">h", size=2), + NumberRegField(consts.AUX2_HIGH_ALARM, get_addr(0x2, 152), format=">h", size=2), + NumberRegField(consts.AUX2_LOW_ALARM, get_addr(0x2, 154), format=">h", size=2), + NumberRegField(consts.AUX2_HIGH_WARN, get_addr(0x2, 156), format=">h", size=2), + NumberRegField(consts.AUX2_LOW_WARN, get_addr(0x2, 158), format=">h", size=2), + NumberRegField(consts.AUX3_HIGH_ALARM, get_addr(0x2, 160), format=">h", size=2), + NumberRegField(consts.AUX3_LOW_ALARM, get_addr(0x2, 162), format=">h", size=2), + NumberRegField(consts.AUX3_HIGH_WARN, get_addr(0x2, 164), format=">h", size=2), + NumberRegField(consts.AUX3_LOW_WARN, get_addr(0x2, 166), format=">h", size=2), + NumberRegField(consts.TX_POWER_HIGH_ALARM, get_addr(0x2, 176), format=">H", size=2, scale=10000.0), + NumberRegField(consts.TX_POWER_LOW_ALARM, get_addr(0x2, 178), format=">H", size=2, scale=10000.0), + NumberRegField(consts.TX_POWER_HIGH_WARN, get_addr(0x2, 180), format=">H", size=2, scale=10000.0), + NumberRegField(consts.TX_POWER_LOW_WARN, get_addr(0x2, 182), format=">H", size=2, scale=10000.0), + NumberRegField(consts.TX_BIAS_CURR_HIGH_ALARM, get_addr(0x2, 184), format=">H", size=2, scale=500.0), + NumberRegField(consts.TX_BIAS_CURR_LOW_ALARM, get_addr(0x2, 186), format=">H", size=2, scale=500.0), + NumberRegField(consts.TX_BIAS_CURR_HIGH_WARN, get_addr(0x2, 188), format=">H", size=2, scale=500.0), + NumberRegField(consts.TX_BIAS_CURR_LOW_WARN, get_addr(0x2, 190), format=">H", size=2, scale=500.0), + NumberRegField(consts.RX_POWER_HIGH_ALARM, get_addr(0x2, 192), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POWER_LOW_ALARM, get_addr(0x2, 194), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POWER_HIGH_WARN, get_addr(0x2, 196), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POWER_LOW_WARN, get_addr(0x2, 198), format=">H", size=2, scale=10000.0), + NumberRegField(consts.SUPPORT_GRID, get_addr(0x4, 128)), + NumberRegField(consts.LOW_CHANNEL, get_addr(0x4, 158), format=">h", size=2), + NumberRegField(consts.HIGH_CHANNEL, get_addr(0x4, 160), format=">h", size=2), + NumberRegField(consts.MIN_PROG_OUTPUT_POWER, get_addr(0x4, 198), format=">h", size=2, scale = 100.0), + NumberRegField(consts.MAX_PROG_OUTPUT_POWER, get_addr(0x4, 200), format=">h", size=2, scale = 100.0), + ) + + self.TRANS_MODULE_STATUS = RegGroupField(consts.TRANS_MODULE_STATUS_FIELD, NumberRegField(consts.MODULE_STATE, get_addr(0x0, 3), size=1), NumberRegField(consts.MODULE_FIRMWARE_FAULT_INFO, get_addr(0x0, 8), size=1), + NumberRegField(consts.MODULE_FLAG_BYTE1, get_addr(0x0, 9), size=1), + NumberRegField(consts.MODULE_FLAG_BYTE2, get_addr(0x0, 10), size=1), + NumberRegField(consts.MODULE_FLAG_BYTE3, get_addr(0x0, 11), size=1), + ) + + self.TRANS_LANE_STATUS = RegGroupField(consts.TRANS_LANE_STATUS_FIELD, NumberRegField(consts.DATAPATH_STATE, get_addr(0x11, 128), format = '>I', size=4), NumberRegField(consts.RX_OUTPUT_STATUS, get_addr(0x11, 132), size=1), NumberRegField(consts.TX_OUTPUT_STATUS, get_addr(0x11, 133), size=1), NumberRegField(consts.TX_FAULT_FLAG, get_addr(0x11, 135), size=1), NumberRegField(consts.TX_LOS_FLAG, get_addr(0x11, 136), size=1), NumberRegField(consts.TX_CDR_LOL, get_addr(0x11, 137), size=1), + NumberRegField(consts.TX_POWER_HIGH_ALARM_FLAG, get_addr(0x11, 139), size=1), + NumberRegField(consts.TX_POWER_LOW_ALARM_FLAG, get_addr(0x11, 140), size=1), + NumberRegField(consts.TX_POWER_HIGH_WARN_FLAG, get_addr(0x11, 141), size=1), + NumberRegField(consts.TX_POWER_LOW_WARN_FLAG, get_addr(0x11, 142), size=1), + NumberRegField(consts.TX_BIAS_HIGH_ALARM_FLAG, get_addr(0x11, 143), size=1), + NumberRegField(consts.TX_BIAS_LOW_ALARM_FLAG, get_addr(0x11, 144), size=1), + NumberRegField(consts.TX_BIAS_HIGH_WARN_FLAG, get_addr(0x11, 145), size=1), + NumberRegField(consts.TX_BIAS_LOW_WARN_FLAG, get_addr(0x11, 146), size=1), NumberRegField(consts.RX_LOS_FLAG, get_addr(0x11, 147), size=1), NumberRegField(consts.RX_CDR_LOL, get_addr(0x11, 148), size=1), + NumberRegField(consts.RX_POWER_HIGH_ALARM_FLAG, get_addr(0x11, 149), size=1), + NumberRegField(consts.RX_POWER_LOW_ALARM_FLAG, get_addr(0x11, 150), size=1), + NumberRegField(consts.RX_POWER_HIGH_WARN_FLAG, get_addr(0x11, 151), size=1), + NumberRegField(consts.RX_POWER_LOW_WARN_FLAG, get_addr(0x11, 152), size=1), NumberRegField(consts.CONFIG_LANE_STATUS, get_addr(0x11, 202), format=">I", size=4), NumberRegField(consts.DPINIT_PENDING, get_addr(0x11, 235), size=1), RegBitField(consts.TUNING_IN_PROGRESS, offset=get_addr(0x12, 222), bitpos=1), @@ -107,7 +164,7 @@ def __init__(self, codes): ) self.TRANS_PM = RegGroupField(consts.TRANS_PM_FIELD, - NumberRegField(consts.FREEZE_REQUEST, get_addr(0x2f, 144), size=1, ro=False), + NumberRegField(consts.VDM_CONTROL, get_addr(0x2f, 144), size=1, ro=False), ) self.MEDIA_LANE_FEC_PM = RegGroupField(consts.MEDIA_LANE_FEC_PM, @@ -124,6 +181,7 @@ def __init__(self, codes): # TODO: add other PMs... ) + # MEDIA_LANE_LINK_PM block corresponds to all the coherent PMs in C-CMIS spec reported in Page 35h. self.MEDIA_LANE_LINK_PM = RegGroupField(consts.MEDIA_LANE_LINK_PM, NumberRegField(consts.RX_AVG_CD_PM, get_addr(0x35, 128), format=">i", size=4), NumberRegField(consts.RX_MIN_CD_PM, get_addr(0x35, 132), format=">i", size=4), diff --git a/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py b/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py index ce9c33350..fc83895bf 100644 --- a/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py +++ b/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py @@ -8,7 +8,8 @@ from .xcvr_eeprom import XcvrEeprom # TODO: remove the following imports from .codes.public.sff8024 import Sff8024 -from .api.public.cmis import CmisApi +from .codes.public.cmis_code import CmisCode +from .api.public.c_cmis import CCmisApi from .mem_maps.public.cmis import CmisMemMap class XcvrApiFactory(object): @@ -22,7 +23,7 @@ def _get_id(self): def create_xcvr_api(self): # TODO: load correct classes from id_mapping file - codes = Sff8024 + codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} mem_map = CmisMemMap(codes) xcvr_eeprom = XcvrEeprom(self.reader, self.writer, mem_map) - return CmisApi(xcvr_eeprom) + return CCmisApi(xcvr_eeprom) From 43432e7493b1d3231aa0d57bb53b6592bf0308d1 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Fri, 1 Oct 2021 16:39:58 -0700 Subject: [PATCH 05/16] add CDB and VDM features --- .../sonic_xcvr/api/public/c_cmis.py | 239 +++++++++++++++++- .../sonic_xcvr/codes/public/cmis_code.py | 48 ++++ .../sonic_xcvr/fields/consts.py | 13 +- .../sonic_xcvr/fields/xcvr_field.py | 20 +- .../sonic_xcvr/mem_maps/public/cmis.py | 12 + sonic_platform_base/sonic_xcvr/xcvr_eeprom.py | 42 +++ 6 files changed, 363 insertions(+), 11 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index 017bc0b96..23510d603 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -5,7 +5,11 @@ """ from ...fields import consts from ..xcvr_api import XcvrApi +from .cmisCDB import CmisCdbApi +from .cmisVDM import CmisVdmApi import time +import datetime + BYTELENGTH = 8 class CCmisApi(XcvrApi): NUM_CHANNELS = 8 @@ -428,6 +432,18 @@ def get_custom_field(self, signed = False, scale = 1.0): return result + def get_VDM_api(self): + self.vdm = CmisVdmApi(self.xcvr_eeprom) + + def get_VDM(self): + try: + self.vdm + except: + self.get_VDM_api() + + VDM = self.vdm.get_VDM_allpage() + return VDM + def get_PM(self): ''' This function returns the PMs reported in Page 34h and 35h in OIF C-CMIS document @@ -865,6 +881,35 @@ def get_laser_tuning_summary(self): laser_tuning_summary.append("TuningComplete") return laser_tuning_summary + def get_supported_freq_config(self): + ''' + This function returns the supported freq grid + allowed channel number bound in 75 GHz grid + allowed frequency bound in 75 GHz grid + ''' + grid_supported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) + low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) + hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) + low_freq_supported = 193.1 + low_ch_num * 0.025 + high_freq_supported = 193.1 + hi_ch_num * 0.025 + return grid_supported, low_ch_num, hi_ch_num, low_freq_supported, high_freq_supported + + def get_supported_power_config(self): + ''' + This function returns the supported TX power range + ''' + min_prog_tx_output_power = self.xcvr_eeprom.read(consts.MIN_PROG_OUTPUT_POWER) + max_prog_tx_output_power = self.xcvr_eeprom.read(consts.MAX_PROG_OUTPUT_POWER) + return min_prog_tx_output_power, max_prog_tx_output_power + + def reset_module(self, reset = False): + ''' + This function resets the module + ''' + if reset: + reset_control = reset << 3 + self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, reset_control) + def set_low_power(self, AssertLowPower): ''' This function sets the module to low power state. @@ -879,15 +924,13 @@ def set_laser_freq(self, freq): This function sets the laser frequency. Unit in THz ZR application will not support fine tuning of the laser ''' - GridSupported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) - GridSupported_75GHz = (GridSupported >> 7) & 0x1 - assert GridSupported_75GHz + grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() + grid_supported_75GHz = (grid_supported >> 7) & 0x1 + assert grid_supported_75GHz freq_grid = 0x70 self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) channel_number = int(round((freq - 193.1)/0.025)) assert channel_number % 3 == 0 - low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) - hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) if channel_number > hi_ch_num or channel_number < low_ch_num: raise ValueError('Provisioned frequency out of range. Max Freq: 196.1; Min Freq: 191.3 THz.') self.set_low_power(True) @@ -901,8 +944,7 @@ def set_TX_power(self, TX_power): ''' This function sets the TX output power. Unit in dBm ''' - min_prog_tx_output_power = self.xcvr_eeprom.read(consts.MIN_PROG_OUTPUT_POWER) - max_prog_tx_output_power = self.xcvr_eeprom.read(consts.MAX_PROG_OUTPUT_POWER) + min_prog_tx_output_power, max_prog_tx_output_power = self.get_supported_power_config() if TX_power > max_prog_tx_output_power or TX_power < min_prog_tx_output_power: raise ValueError('Provisioned TX power out of range. Max: %.1f; Min: %.1f dBm.' %(max_prog_tx_output_power, min_prog_tx_output_power)) @@ -952,4 +994,185 @@ def set_loopback_mode(self, loopback_mode): self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0x1) elif loopback_mode == 'media-side-output': assert loopback_capability['media_side_output_loopback_supported'] - self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0x1) \ No newline at end of file + self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0x1) + + + def get_CDB_api(self): + self.cdb = CmisCdbApi(self.xcvr_eeprom) + + def get_module_FW_upgrade_feature(self, verbose = False): + try: + self.cdb + except: + self.get_CDB_api() + # get fw upgrade features (CMD 0041h) + starttime = time.time() + autopaging_flag = bool((self.xcvr_eeprom.read(consts.CDB_SUPPORT) >> 4) & 0x1) + writelength = (self.xcvr_eeprom.read(consts.CDB_SEQ_WRITE_LENGTH_EXT) + 1) * 8 + print('Auto page support: %s' %autopaging_flag) + print('Max write length: %d' %writelength) + rpllen, rpl_chkcode, rpl = self.cdb.cmd0041h() + if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: + startLPLsize = rpl[2] + print('Start payload size %d' % startLPLsize) + maxblocksize = (rpl[4] + 1) * 8 + print('Max block size %d' % maxblocksize) + lplEplSupport = {0x00 : 'No write to LPL/EPL supported', + 0x01 : 'Write to LPL supported', + 0x10 : 'Write to EPL supported', + 0x11 : 'Write to LPL/EPL supported'} + print('{}'.format(lplEplSupport[rpl[5]])) + if rpl[5] == 1: + lplonly_flag = True + else: + lplonly_flag = False + print('Abort CMD102h supported %s' %bool(rpl[1] & 0x01)) + if verbose: + print('Copy CMD108h supported %s' %bool((rpl[1] >> 1) & 0x01)) + print('Skipping erased blocks supported %s' %bool((rpl[1] >> 2) & 0x01)) + print('Full image readback supported %s' %bool((rpl[1] >> 7) & 0x01)) + print('Default erase byte {:#x}'.format(rpl[3])) + print('Read to LPL/EPL {:#x}'.format(rpl[6])) + + else: + raise ValueError, 'Reply payload check code error' + elapsedtime = time.time()-starttime + print('Get module FW upgrade features time: %.2f s' %elapsedtime) + return startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength + + def get_module_FW_info(self): + try: + self.cdb + except: + self.get_CDB_api() + # get fw info (CMD 0100h) + starttime = time.time() + print('\nGet module FW info') + rpllen, rpl_chkcode, rpl = self.cdb.cmd0100h() + if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: + # Regiter 9Fh:136 + fwStatus = rpl[0] + # Registers 9Fh:138,139; 140,141 + print('Image A Version: %d.%d; BuildNum: %d' %(rpl[2], rpl[3], ((rpl[4]<< 8) | rpl[5]))) + # Registers 9Fh:174,175; 176.177 + print('Image B Version: %d.%d; BuildNum: %d' %(rpl[38], rpl[39], ((rpl[40]<< 8) | rpl[41]))) + + ImageARunning = (fwStatus & 0x01) # bit 0 - image A is running + ImageACommitted = ((fwStatus >> 1) & 0x01) # bit 1 - image A is committed + ImageBRunning = ((fwStatus >> 4) & 0x01) # bit 4 - image B is running + ImageBCommitted = ((fwStatus >> 5) & 0x01) # bit 5 - image B is committed + + if ImageARunning == 1: + RunningImage = 'A' + elif ImageBRunning == 1: + RunningImage = 'B' + if ImageACommitted == 1: + CommittedImage = 'A' + elif ImageBCommitted == 1: + CommittedImage = 'B' + print('Running Image: %s; Committed Image: %s' %(RunningImage, CommittedImage)) + else: + raise ValueError, 'Reply payload check code error' + elapsedtime = time.time()-starttime + print('Get module FW info time: %.2f s' %elapsedtime) + + def module_FW_run(self): + try: + self.cdb + except: + self.get_CDB_api() + # run module FW (CMD 0109h) + starttime = time.time() + _, FW_run_status, _ = self.cdb.cmd0109h() + if FW_run_status == 1: + print('Module FW run: Success') + else: + self.cdb.cmd0102h() + print('Module FW run: Fail') + elapsedtime = time.time()-starttime + print('Module FW run time: %.2f s\n' %elapsedtime) + + def module_FW_commit(self): + try: + self.cdb + except: + self.get_CDB_api() + # commit module FW (CMD 010Ah) + starttime = time.time() + _, FW_run_status, _ = self.cdb.cmd010Ah() + if FW_commit_status == 1: + print('Module FW commit: Success') + else: + self.cdb.cmd0102h() + print('Module FW commit: Fail') + elapsedtime = time.time()-starttime + print('Module FW commit time: %.2f s\n' %elapsedtime) + + def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath): + try: + self.cdb + except: + self.get_CDB_api() + # start fw download (CMD 0101h) + starttime = time.time() + f = open(imagepath, 'rb') + f.seek(0, 2) + imagesize = f.tell() + f.seek(0, 0) + startdata = f.read(startLPLsize) + print('\nStart FW downloading') + print("startLPLsize is %d" %startLPLsize) + FW_start_status = self.cdb.cmd0101h(startLPLsize, bytearray(startdata), imagesize) + if FW_start_status == 1: + print('Start module FW download: Success') + else: + print('Start module FW download: Fail') + self.cdb.cmd0102h() + raise ValueError, 'FW_start_status %d' %FW_start_status + elapsedtime = time.time()-starttime + print('Start module FW download time: %.2f s' %elapsedtime) + + # start periodically writing (CMD 0103h or 0104h) + assert maxblocksize == 2048 or lplonly_flag + if lplonly_flag: + BLOCK_SIZE = 116 + else: + BLOCK_SIZE = maxblocksize + address = 0 + remaining = imagesize - startLPLsize + print("\nTotal size: {} start bytes: {} remaining: {}".format(imagesize, startLPLsize, remaining)) + while remaining > 0: + if remaining < BLOCK_SIZE: + count = remaining + else: + count = BLOCK_SIZE + data = f.read(count) + progress = (imagesize - remaining) * 100.0 / imagesize + if lplonly_flag: + self.cdb.cmd0103h(address, data) + else: + self.cdb.cmd0104h(address, data, autopaging_flag, writelength) + elapsedtime = time.time()-starttime + print('Address: {:#08x}; Count: {}; Progress: {:.2f}%; Time: {:.2f}s'.format(address, count, progress, elapsedtime)) + address += count + remaining -= count + elapsedtime = time.time()-starttime + print('Total module FW download time: %.2f s' %elapsedtime) + + # complete FW download (CMD 0107h) + FW_complete_status = self.cdb.cmd0107h() + if FW_complete_status == 1: + print('Module FW download complete: Success') + else: + print('Module FW download complete: Fail') + elapsedtime = time.time()-elapsedtime-starttime + print('Complete module FW download time: %.2f s\n' %elapsedtime) + + def module_firmware_upgrade(self, imagepath): + self.get_module_FW_info() + startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength = self.get_module_FW_upgrade_feature() + self.module_FW_download(startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath) + self.module_FW_run() + time.sleep(60) + self.module_FW_commit() + self.get_module_FW_info() \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py b/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py index 1cf8d5220..302dae3f6 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py @@ -57,4 +57,52 @@ class CmisCode(XcvrCodes): 12: 'ConfigInProgress', } + VDM_TYPE = { + # VDM_ID: [VDM_NAME, DATA_TYPE, SCALE] + 1: ['Laser Age [%]', 'U16', 1], + 2: ['TEC Current [%]', 'S16', 100.0/32767], + 3: ['Laser Frequency Error [MHz]', 'S16', 10], + 4: ['Laser Temperature [C]', 'S16', 1.0/256], + 5: ['eSNR Media Input [dB]', 'U16', 1.0/256], + 6: ['eSNR Host Input [dB]', 'U16', 1.0/256], + 7: ['PAM4 Level Transition Parameter Media Input [dB]', 'U16', 1.0/256], + 8: ['PAM4 Level Transition Parameter Host Input [dB]', 'U16', 1.0/256], + 9: ['Pre-FEC BER Minimum Media Input', 'F16', 1], + 10: ['Pre-FEC BER Minimum Host Input', 'F16', 1], + 11: ['Pre-FEC BER Maximum Media Input', 'F16', 1], + 12: ['Pre-FEC BER Maximum Host Input', 'F16', 1], + 13: ['Pre-FEC BER Average Media Input', 'F16', 1], + 14: ['Pre-FEC BER Average Host Input', 'F16', 1], + 15: ['Pre-FEC BER Current Value Media Input', 'F16', 1], + 16: ['Pre-FEC BER Current Value Host Input', 'F16', 1], + 17: ['Errored Frames Minimum Media Input', 'F16', 1], + 18: ['Errored Frames Minimum Host Input', 'F16', 1], + 19: ['Errored Frames Maximum Media Input', 'F16', 1], + 20: ['Errored Frames Minimum Host Input', 'F16', 1], + 21: ['Errored Frames Average Media Input', 'F16', 1], + 22: ['Errored Frames Average Host Input', 'F16', 1], + 23: ['Errored Frames Current Value Media Input', 'F16', 1], + 24: ['Errored Frames Current Value Host Input', 'F16', 1], + 128: ['Modulator Bias X/I [%]', 'U16', 100.0/65535], + 129: ['Modulator Bias X/Q [%]', 'U16', 100.0/65535], + 130: ['Modulator Bias Y/I [%]', 'U16', 100.0/65535], + 131: ['Modulator Bias Y/Q [%]', 'U16', 100.0/65535], + 132: ['Modulator Bias X_Phase [%]', 'U16', 100.0/65535], + 133: ['Modulator Bias Y_Phase [%]', 'U16', 100.0/65535], + 134: ['CD high granularity, short link [ps/nm]', 'S16', 1], + 135: ['CD low granularity, long link [ps/nm]', 'S16', 20], + 136: ['DGD [ps]', 'U16', 0.01], + 137: ['SOPMD [ps^2]', 'U16', 0.01], + 138: ['PDL [dB]', 'U16', 0.1], + 139: ['OSNR [dB]', 'U16', 0.1], + 140: ['eSNR [dB]', 'U16', 0.1], + 141: ['CFO [MHz]', 'S16', 1], + 142: ['EVM_modem [%]', 'U16', 100.0/65535], + 143: ['Tx Power [dBm]', 'S16', 0.01], + 144: ['Rx Total Power [dBm]', 'S16', 0.01], + 145: ['Rx Signal Power [dBm]', 'S16', 0.01], + 146: ['SOP ROC [krad/s]', 'U16', 1], + 147: ['MER [dB]', 'U16', 0.1] + } + # TODO: Add other codes \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/fields/consts.py b/sonic_platform_base/sonic_xcvr/fields/consts.py index aa2521ac2..d7c90e06d 100644 --- a/sonic_platform_base/sonic_xcvr/fields/consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/consts.py @@ -108,6 +108,7 @@ MODULE_FLAG_BYTE1 = "ModuleFlagByte1" MODULE_FLAG_BYTE2 = "ModuleFlagByte2" MODULE_FLAG_BYTE3 = "ModuleFlagByte3" +CDB1_STATUS = "Cdb1Status" DATAPATH_STATE= "DataPathStateHostLane" TX_OUTPUT_STATUS = "TxOutputStatus" RX_OUTPUT_STATUS = "RxOutputStatus" @@ -147,6 +148,7 @@ ## Media Lane Link Performance Monitoring # PM TRANS_PM_FIELD = "TransceiverPm" +VDM_SUPPORTED_PAGE = "VdmSupportedPage" VDM_CONTROL = "VdmControl" MEDIA_LANE_FEC_PM = "Media Lane FEC Performance Monitoring" MEDIA_LANE_LINK_PM = "Media Lane Link Performance Monitoring" @@ -204,7 +206,14 @@ RX_MIN_MER_PM = "rxMinMerPm" RX_MAX_MER_PM = "rxMaxMerPm" - - +# CDB +TRANS_CDB_FIELD = "TransceiverCdb" +CDB_SUPPORT = "CdbSupport" +CDB_SEQ_WRITE_LENGTH_EXT = "CdbReadWriteLengthExtension" +CDB_RPL_LENGTH = "CdbReplyLength" +CDB_RPL_CHKCODE = "CdbReplyCheckCode" +CDB_LPL = "CdbLocalPayload" +CDB_CMD = "CdbCommand" +CDB_WRITE_MSG = "CdbWriteMessage" diff --git a/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py b/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py index 6391f756b..d36b70c3f 100644 --- a/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py +++ b/sonic_platform_base/sonic_xcvr/fields/xcvr_field.py @@ -146,7 +146,7 @@ def decode(self, raw_data): decoded >>= self.start_bitpos if self.scale is not None: return decoded / self.scale - return decoded + return decoded def encode(self, val, raw_state=None): assert not self.ro @@ -154,6 +154,24 @@ def encode(self, val, raw_state=None): return bytearray(struct.pack(self.format, int(val * self.scale))) return bytearray(struct.pack(self.format, int(val))) +class ListRegField(RegField): + """ + Interprets byte(s) as a number + """ + def __init__(self, name, offset, *fields, **kwargs): + super(ListRegField, self).__init__( name, offset, *fields, **kwargs) + self.format = kwargs.get("format", "B") + + def decode(self, raw_data): + decoded = struct.unpack(self.format, raw_data) + return decoded + + def encode(self, val, raw_state=None): + assert not self.ro + if type(val) == bytearray: + return val + return bytearray(struct.pack(self.format, int(val))) + class StringRegField(RegField): """ Interprets byte(s) as a string 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 fd937f010..d0b42c704 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -9,6 +9,7 @@ CodeRegField, HexRegField, NumberRegField, + ListRegField, RegGroupField, StringRegField, RegBitField, @@ -133,6 +134,7 @@ def __init__(self, codes): NumberRegField(consts.MODULE_FLAG_BYTE1, get_addr(0x0, 9), size=1), NumberRegField(consts.MODULE_FLAG_BYTE2, get_addr(0x0, 10), size=1), NumberRegField(consts.MODULE_FLAG_BYTE3, get_addr(0x0, 11), size=1), + NumberRegField(consts.CDB1_STATUS, get_addr(0x0, 37), size=1), ) self.TRANS_LANE_STATUS = RegGroupField(consts.TRANS_LANE_STATUS_FIELD, @@ -164,6 +166,7 @@ def __init__(self, codes): ) self.TRANS_PM = RegGroupField(consts.TRANS_PM_FIELD, + NumberRegField(consts.VDM_SUPPORTED_PAGE, get_addr(0x2f, 128), size=1, ro=False), NumberRegField(consts.VDM_CONTROL, get_addr(0x2f, 144), size=1, ro=False), ) @@ -232,4 +235,13 @@ def __init__(self, codes): NumberRegField(consts.MODULE_LEVEL_CONTROL, get_addr(0x0, 26), size=1, ro=False), ) + self.TRANS_CDB = RegGroupField(consts.TRANS_CDB_FIELD, + NumberRegField(consts.CDB_SUPPORT, get_addr(0x01, 163), size=1), + NumberRegField(consts.CDB_SEQ_WRITE_LENGTH_EXT, get_addr(0x01, 164), size=1), + NumberRegField(consts.CDB_RPL_LENGTH, get_addr(0x9f, 134), size=1, ro=False), + NumberRegField(consts.CDB_RPL_CHKCODE, get_addr(0x9f, 135), size=1, ro=False), + ListRegField(consts.CDB_LPL, get_addr(0x9f, 136), format='120B', size=120, ro=False), + ListRegField(consts.CDB_CMD, get_addr(0x9f, 128), format='2B', size=2, ro=False), + ListRegField(consts.CDB_WRITE_MSG, get_addr(0x9f, 130), format='126B', size=126, ro=False), + ) # TODO: add remaining fields diff --git a/sonic_platform_base/sonic_xcvr/xcvr_eeprom.py b/sonic_platform_base/sonic_xcvr/xcvr_eeprom.py index 4902be56a..93f0c9faa 100644 --- a/sonic_platform_base/sonic_xcvr/xcvr_eeprom.py +++ b/sonic_platform_base/sonic_xcvr/xcvr_eeprom.py @@ -3,6 +3,7 @@ Common API used by all XcvrApis to read and write to various fields that can be found in a xcvr EEPROM """ +import struct class XcvrEeprom(object): def __init__(self, reader, writer, mem_map): @@ -24,6 +25,30 @@ def read(self, field_name): raw_data = self.reader(field.get_offset(), field.get_size()) return field.decode(raw_data) if raw_data is not None else None + def read_flexible(self, offset, size, return_raw = False): + """ + Read values from a field in EEPROM in a more flexible way + + Args: + offset: an integer indicating the offset of the starting position of the + EEPROM byte(s) to read from + + size: an integer indicating how many bytes to read from + Returns: + The value(s) of the field, if the read is successful and None otherwise + """ + raw_data = self.reader(offset, size) + if return_raw: + return raw_data + if raw_data is None: + return None + else: + if size == 1: + data = struct.unpack("%dB" %size, raw_data)[0] + else: + data = struct.unpack("%dB" %size, raw_data) + return data + def write(self, field_name, value): """ Write a value to a field in EEPROM @@ -43,3 +68,20 @@ def write(self, field_name, value): else: encoded_data = field.encode(value) return self.writer(field.get_offset(), field.get_size(), encoded_data) + + def write_flexible(self, offset, size, bytearray_data): + """ + Write values to a field in EEPROM in a more flexible way + + Args: + offset: an integer indicating the offset of the starting position of the + EEPROM byte(s) to write to + + size: an integer indicating how many bytes to write to + + bytearray_data: a bytearray as write bugger to be written into EEPROM + + Returns: + Boolean, True if the write is successful and False otherwise + """ + return self.writer(offset, size, bytearray_data) From 4939daa269e92c25dd66631956743051aef50a09 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Fri, 1 Oct 2021 16:45:43 -0700 Subject: [PATCH 06/16] add CDB and CDM features, add two files --- .../sonic_xcvr/api/public/cmisCDB.py | 364 ++++++++++++++++++ .../sonic_xcvr/api/public/cmisVDM.py | 113 ++++++ 2 files changed, 477 insertions(+) create mode 100644 sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py create mode 100644 sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py new file mode 100644 index 000000000..a520b14d2 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py @@ -0,0 +1,364 @@ +from ...fields import consts +from ..xcvr_api import XcvrApi +import struct +import time + +LPLPAGE = 0x9f +CDB_RPL_OFFSET = 136 +CDB_WRITE_MSG_START = 130 +PAGE_LENGTH = 128 +INIT_OFFSET = 128 +CMDLEN = 2 +MAX_TRY = 3 + +class CmisCdbApi(XcvrApi): + def __init__(self, xcvr_eeprom): + super(CmisCdbApi, self).__init__(xcvr_eeprom) + + def cdb1_chkflags(self): + ''' + This function detects if there is datapath or module firmware fault. + If there is no firmware fault, it checks if CDB command completes. + It retruns True if the CDB command is incomplete and returns False if complete + + Bit 7: L-Cdb2CommandComplete Latched Flag to indicate completion of the CDB command + for CDB block 2. Support is advertised in field 01h:163.7-6 + + Bit 6: L-Cdb1CommandComplete Latched Flag to indicate completion of the CDB command + for CDB block 1. Support is advertised in field 01h:163.7-6 + + Bit 5-3: - Reserved + + Bit 2: L-DataPathFirmwareFault Latched Flag to indicate that subordinated firmware in an + auxiliary device for processing transmitted or received + signals (e.g. a DSP) has failed. + + Bit 1: L-ModuleFirmwareFault Latched Flag to indicate that self-supervision of the main + module firmware has detected a failure in the main module + firmware itself. There are several possible causes of the + error such as program memory becoming corrupted and + incomplete firmware loading. + + Bit 0: L-ModuleStateChanged Latched Flag to indicate a Module State Change + ''' + status = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) + datapath_firmware_fault = bool((status >> 2) & 0x1) + module_firmware_fault = bool((status >> 1) & 0x1) + cdb1_command_complete = bool((status >> 6) & 0x1) + assert not datapath_firmware_fault + assert not module_firmware_fault + if cdb1_command_complete: + return False + else: + return True + + def cdb_chkcode(self, cmd): + ''' + This function calculates and returns the checksum of a CDB command + ''' + checksum = 0 + for byte in cmd: + checksum += byte + return 0xff - (checksum & 0xff) + + def cdb1_chkstatus(self): + ''' + This function checks the CDB status. + The format of returned values is busy flag, failed flag and cause + + CDB command status + Bit 7: CdbIsBusy + Bit 6: CdbHasFailed + Bit 5-0: CdBCommandResult + Coarse Status CdbIsBusy CdbHasFailed + IN PROGRESS 1 X (dont care) + SUCCESS 0 0 + FAILED 0 1 + + IN PROGRESS + 00h=Reserved + 01h=Command is captured but not processed + 02h=Command checking is in progress + 03h=Previous CMD was ABORTED by CMD Abort + 04h-1Fh=Reserved + 20h-2Fh=Reserved + 30h-3Fh=Custom + + SUCCESS + 00h=Reserved + 01h=Command completed successfully + 02h=Reserved + 03h=Previous CMD was ABORTED by CMD Abort + 04h-1Fh=Reserved + 20h-2Fh=Reserved + 30h-3Fh=Custom + + FAILED + 00h=Reserved + 01h=CMDCode unknown + 02h=Parameter range error or parameter not supported + 03h=Previous CMD was not ABORTED by CMD Abort + 04h=Command checking time out + 05h=CdbCheckCode Error + 06h=Password related error (command specific meaning) + 07h=Command not compatible with operating status + 08h-0Fh=Reserved for STS command checking error + 10h-1Fh=Reserved + 20h-2Fh=For individual STS command or task error + 30h-3Fh=Custom + ''' + status = self.xcvr_eeprom.read(consts.CDB1_STATUS) + is_busy = bool((status >> 7) & 0x1) + while is_busy: + time.sleep(1) + is_busy = bool((status >> 7) & 0x1) + return status + + def write_cdb(self, cmd): + ''' + This function writes a CDB command to page 0x9f + ''' + self.xcvr_eeprom.write_flexible(LPLPAGE*PAGE_LENGTH+CDB_WRITE_MSG_START, len(cmd)-CMDLEN, cmd[CMDLEN:]) + self.xcvr_eeprom.write_flexible(LPLPAGE*PAGE_LENGTH+INIT_OFFSET, CMDLEN, cmd[:CMDLEN]) + + def read_cdb(self): + ''' + This function reads the reply of a CDB command from page 0x9f + ''' + rpllen = self.xcvr_eeprom.read(consts.CDB_RPL_LENGTH) + rpl_chkcode = self.xcvr_eeprom.read(consts.CDB_RPL_CHKCODE) + rpl = self.xcvr_eeprom.read_flexible(LPLPAGE*PAGE_LENGTH+CDB_RPL_OFFSET, rpllen) + return rpllen, rpl_chkcode, rpl + + # Query status + def cmd0000h(self): + cmd = bytearray(b'\x00\x00\x00\x00\x02\x00\x00\x00\x00\x10') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return self.read_cdb() + + # Enter password + def cmd0001h(self): + cmd = bytearray(b'\x00\x01\x00\x00\x04\x00\x00\x00\x00\x00\x10\x11') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return self.read_cdb() + + def cmd0040h(self): + cmd = bytearray(b'\x00\x40\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return self.read_cdb() + + # Firmware Update Features Supported + def cmd0041h(self): + cmd = bytearray(b'\x00\x41\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return self.read_cdb() + + # Get FW info + def cmd0100h(self): + cmd = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return self.read_cdb() + + # Start FW download + def cmd0101h(self, startLPLsize, header, imagesize): + print("Image size is {}".format(imagesize)) + cmd = bytearray(b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + cmd[132-INIT_OFFSET] = startLPLsize + 8 + cmd[136-INIT_OFFSET] = (imagesize >> 24) & 0xff + cmd[137-INIT_OFFSET] = (imagesize >> 16) & 0xff + cmd[138-INIT_OFFSET] = (imagesize >> 8) & 0xff + cmd[139-INIT_OFFSET] = (imagesize >> 0) & 0xff + cmd += header + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return status + + # Abort FW download + def cmd0102h(self): + cmd = bytearray(b'\x01\x02\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return status + + # Download FW with LPL + def cmd0103h(self, addr, data): + # lpl_len includes 136-139, four bytes, data is 116-byte long. + lpl_len = len(data) + 4 + cmd = bytearray(b'\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') + cmd[132-INIT_OFFSET] = lpl_len & 0xff + cmd[136-INIT_OFFSET] = (addr >> 24) & 0xff + cmd[137-INIT_OFFSET] = (addr >> 16) & 0xff + cmd[138-INIT_OFFSET] = (addr >> 8) & 0xff + cmd[139-INIT_OFFSET] = (addr >> 0) & 0xff + # pad data to 116 bytes just in case, make sure to fill all 0x9f page + paddedPayload = data.ljust(116, b'\x00') + cmd += paddedPayload + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return status + + # Download FW with EPL + def cmd0104h(self, addr, data, autopaging_flag, writelength): + epl_len = 2048 + subtime = time.time() + if not autopaging_flag: + pages = epl_len // PAGE_LENGTH + if (epl_len % PAGE_LENGTH) != 0: + pages += 1 + # write to page 0xA0 - 0xAF (max of 16 pages) + for pageoffset in range(pages): + next_page = 0xa0 + pageoffset + if PAGE_LENGTH*(pageoffset + 1) <= epl_len: + datachunk = data[PAGE_LENGTH*pageoffset : PAGE_LENGTH*(pageoffset + 1)] + self.xcvr_eeprom.write_flexible(next_page*PAGE_LENGTH+INIT_OFFSET, PAGE_LENGTH, datachunk) + else: + datachunk = data[INIT_OFFSET*pageoffset : ] + self.xcvr_eeprom.write_flexible(next_page*PAGE_LENGTH+INIT_OFFSET, len(datachunk), datachunk) + else: + sections = epl_len // writelength + if (epl_len % writelength) != 0: + sections += 1 + # write to page 0xA0 - 0xAF (max of 16 pages), with length of writelength per piece + for offset in range(0, epl_len, writelength): + if offset + writelength <= epl_len: + datachunk = data[offset : offset + writelength] + self.xcvr_eeprom.write_flexible(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, writelength, datachunk) + else: + datachunk = data[offset : ] + self.xcvr_eeprom.write_flexible(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, len(datachunk), datachunk) + subtimeint = time.time()-subtime + print('2048B write time: %.2fs' %subtimeint) + cmd = bytearray(b'\x01\x04\x08\x00\x04\x00\x00\x00') + addr_byte = struct.pack('>L',addr) + cmd += addr_byte + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return status + # FW download complete + def cmd0107h(self): + cmd = bytearray(b'\x01\x07\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return status + + # Run FW image + # mode: + # 00h = Traffic affecting Reset to Inactive Image. + # 01h = Attempt Hitless Reset to Inactive Image + # 02h = Traffic affecting Reset to Running Image. + # 03h = Attempt Hitless Reset to Running Image + def cmd0109h(self, mode=0x01): + cmd = bytearray(b'\x01\x09\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00') + cmd[137-INIT_OFFSET] = mode + cmd[138-INIT_OFFSET] = 2 # Delay to Reset 512 ms + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return status + + # Commit FW image + def cmd010Ah(self): + cmd = bytearray(b'\x01\x0A\x00\x00\x00\x00\x00\x00') + cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) + for attemp in range(MAX_TRY): + self.write_cdb(cmd) + time.sleep(2) + status = self.cdb1_chkstatus() + if (status != 0x1): + print('CDB1 status: Fail. CDB1 status %d' %status) + continue + else: + break + return status diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py new file mode 100644 index 000000000..e02ab97b8 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py @@ -0,0 +1,113 @@ +from ...fields import consts +from ..xcvr_api import XcvrApi +import struct +import time + +PAGE_SIZE = 128 +PAGE_OFFSET = 128 +THRSH_SPACING = 8 +VDM_SIZE = 2 + +class CmisVdmApi(XcvrApi): + def __init__(self, xcvr_eeprom): + super(CmisVdmApi, self).__init__(xcvr_eeprom) + + def get_F16(self, value): + scale_exponent = (value >> 11) & 0x1f + mantissa = value & 0x7ff + result = mantissa*10**(scale_exponent-24) + return result + + def get_VDM_page(self, page): + if page not in [0x20, 0x21, 0x22, 0x23]: + raise ValueError('Page not in VDM Descriptor range!') + VDM_descriptor = self.xcvr_eeprom.read_flexible(page * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) + # Odd Adress VDM observable type ID, real-time monitored value in Page + 4 + VDM_typeID = VDM_descriptor[1::2] + # Even Address + # Bit 7-4: Threshold set ID in Page + 8, in group of 8 bytes, 16 sets/page + # Bit 3-0: n. Monitored lane n+1 + VDM_lane = [(elem & 0xf) for elem in VDM_descriptor[0::2]] + VDM_thresholdID = [(elem>>4) for elem in VDM_descriptor[0::2]] + VDM_valuePage = page + 4 + VDM_thrshPage = page + 8 + VDM_Page_data = {} + for index, typeID in enumerate(VDM_typeID): + if typeID not in self.xcvr_eeprom.mem_map.codes['cmis_code'].VDM_TYPE: + continue + else: + vdm_info_dict = self.xcvr_eeprom.mem_map.codes['cmis_code'].VDM_TYPE[typeID] + thrshID = VDM_thresholdID[index] + vdm_type = vdm_info_dict[0] + vdm_format = vdm_info_dict[1] + scale = vdm_info_dict[2] + + vdm_value_offset = VDM_valuePage * PAGE_SIZE + PAGE_OFFSET + VDM_SIZE * index + vdm_high_alarm_offset = VDM_thrshPage * PAGE_SIZE + PAGE_OFFSET + THRSH_SPACING * thrshID + vdm_low_alarm_offset = vdm_high_alarm_offset + 2 + vdm_high_warn_offset = vdm_high_alarm_offset + 4 + vdm_low_warn_offset = vdm_high_alarm_offset + 6 + + thrshID = VDM_thresholdID[index] + vdm_value_raw = self.xcvr_eeprom.read_flexible(vdm_value_offset, VDM_SIZE, True) + vdm_thrsh_high_alarm_raw = self.xcvr_eeprom.read_flexible(vdm_high_alarm_offset, VDM_SIZE, True) + vdm_thrsh_low_alarm_raw = self.xcvr_eeprom.read_flexible(vdm_low_alarm_offset, VDM_SIZE, True) + vdm_thrsh_high_warn_raw = self.xcvr_eeprom.read_flexible(vdm_high_warn_offset, VDM_SIZE, True) + vdm_thrsh_low_warn_raw = self.xcvr_eeprom.read_flexible(vdm_low_warn_offset, VDM_SIZE, True) + if vdm_format == 'S16': + vdm_value = struct.unpack('>h',vdm_value_raw)[0] * scale + vdm_thrsh_high_alarm = struct.unpack('>h', vdm_thrsh_high_alarm_raw)[0] * scale + vdm_thrsh_low_alarm = struct.unpack('>h', vdm_thrsh_low_alarm_raw)[0] * scale + vdm_thrsh_high_warn = struct.unpack('>h', vdm_thrsh_high_warn_raw)[0] * scale + vdm_thrsh_low_warn = struct.unpack('>h', vdm_thrsh_low_warn_raw)[0] * scale + elif vdm_format == 'U16': + vdm_value = struct.unpack('>H',vdm_value_raw)[0] * scale + vdm_thrsh_high_alarm = struct.unpack('>H', vdm_thrsh_high_alarm_raw)[0] * scale + vdm_thrsh_low_alarm = struct.unpack('>H', vdm_thrsh_low_alarm_raw)[0] * scale + vdm_thrsh_high_warn = struct.unpack('>H', vdm_thrsh_high_warn_raw)[0] * scale + vdm_thrsh_low_warn = struct.unpack('>H', vdm_thrsh_low_warn_raw)[0] * scale + elif vdm_format == 'F16': + vdm_value_int = struct.unpack('>H',vdm_value_raw)[0] + vdm_value = self.get_F16(vdm_value_int) + vdm_thrsh_high_alarm_int = struct.unpack('>H', vdm_thrsh_high_alarm_raw)[0] + vdm_thrsh_low_alarm_int = struct.unpack('>H', vdm_thrsh_low_alarm_raw)[0] + vdm_thrsh_high_warn_int = struct.unpack('>H', vdm_thrsh_high_warn_raw)[0] + vdm_thrsh_low_warn_int = struct.unpack('>H', vdm_thrsh_low_warn_raw)[0] + vdm_thrsh_high_alarm = self.get_F16(vdm_thrsh_high_alarm_int) + vdm_thrsh_low_alarm = self.get_F16(vdm_thrsh_low_alarm_int) + vdm_thrsh_high_warn = self.get_F16(vdm_thrsh_high_warn_int) + vdm_thrsh_low_warn = self.get_F16(vdm_thrsh_low_warn_int) + else: + continue + + if vdm_type not in VDM_Page_data: + VDM_Page_data[vdm_type] = { + VDM_lane[index]+1: [vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn] + } + + else: + VDM_Page_data[vdm_info_dict[0]][VDM_lane[index]+1] = [ + vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn + ] + return VDM_Page_data + + def get_VDM_allpage(self): + vdm_page_supported_raw = self.xcvr_eeprom.read(consts.VDM_SUPPORTED_PAGE) & 0x3 + VDM_START_PAGE = 0x20 + VDM = dict() + self.xcvr_eeprom.write(consts.VDM_CONTROL, 128) + time.sleep(5) + self.xcvr_eeprom.write(consts.VDM_CONTROL, 0) + time.sleep(1) + for page in range(VDM_START_PAGE, VDM_START_PAGE + vdm_page_supported_raw + 1): + VDM_current_page = self.get_VDM_page(page) + VDM.update(VDM_current_page) + return VDM \ No newline at end of file From 75e192b3bb0dc8b7dc96d4369f0d1413884f79dd Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Thu, 7 Oct 2021 11:42:41 -0700 Subject: [PATCH 07/16] add unit test for functions in CCmisApi --- pytest.ini | 2 +- .../sonic_xcvr/api/public/c_cmis.py | 31 +- tests/sonic_xcvr/test_ccmis.py | 971 ++++++++++++++++++ 3 files changed, 988 insertions(+), 16 deletions(-) create mode 100644 tests/sonic_xcvr/test_ccmis.py diff --git a/pytest.ini b/pytest.ini index f540f4138..142a21e74 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,2 @@ [pytest] -addopts = --cov=sonic_platform_base --cov-report html --cov-report term --cov-report xml --junitxml=test-results.xml -v +addopts = --cov=sonic_platform_base tests/sonic_xcvr/test_ccmis.py --cov-report html --cov-report term --cov-report xml --junitxml=test-results.xml -v diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index 23510d603..dfcb1875b 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -299,21 +299,21 @@ def get_freq_grid(self): def get_laser_config_freq(self): ''' - This function returns the configured laser frequency. Unit in MHz + This function returns the configured laser frequency. Unit in GHz ''' freq_grid = self.get_freq_grid() channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) if freq_grid == 75: - config_freq = 193100000 + channel * freq_grid/3*1000 + config_freq = 193100 + channel * freq_grid/3 else: - config_freq = 193100000 + channel * freq_grid + config_freq = 193100 + channel * freq_grid return config_freq def get_current_laser_freq(self): ''' - This function returns the monitored laser frequency. Unit in MHz + This function returns the monitored laser frequency. Unit in GHz ''' - return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ) + return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ)/1000 def get_TX_config_power(self): ''' @@ -883,15 +883,16 @@ def get_laser_tuning_summary(self): def get_supported_freq_config(self): ''' - This function returns the supported freq grid + This function returns the supported freq grid, low and high supported channel in 75GHz grid, + and low and high frequency supported in GHz. allowed channel number bound in 75 GHz grid - allowed frequency bound in 75 GHz grid + allowed frequency bound in 75 GHz grid ''' grid_supported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) - low_freq_supported = 193.1 + low_ch_num * 0.025 - high_freq_supported = 193.1 + hi_ch_num * 0.025 + low_freq_supported = 193100 + low_ch_num * 25 + high_freq_supported = 193100 + hi_ch_num * 25 return grid_supported, low_ch_num, hi_ch_num, low_freq_supported, high_freq_supported def get_supported_power_config(self): @@ -921,7 +922,7 @@ def set_low_power(self, AssertLowPower): def set_laser_freq(self, freq): ''' - This function sets the laser frequency. Unit in THz + This function sets the laser frequency. Unit in GHz ZR application will not support fine tuning of the laser ''' grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() @@ -929,10 +930,10 @@ def set_laser_freq(self, freq): assert grid_supported_75GHz freq_grid = 0x70 self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) - channel_number = int(round((freq - 193.1)/0.025)) + channel_number = int(round((freq - 193100)/25)) assert channel_number % 3 == 0 if channel_number > hi_ch_num or channel_number < low_ch_num: - raise ValueError('Provisioned frequency out of range. Max Freq: 196.1; Min Freq: 191.3 THz.') + raise ValueError('Provisioned frequency out of range. Max Freq: 196100; Min Freq: 191300 GHz.') self.set_low_power(True) time.sleep(5) self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) @@ -1035,7 +1036,7 @@ def get_module_FW_upgrade_feature(self, verbose = False): print('Read to LPL/EPL {:#x}'.format(rpl[6])) else: - raise ValueError, 'Reply payload check code error' + raise ValueError('Reply payload check code error') elapsedtime = time.time()-starttime print('Get module FW upgrade features time: %.2f s' %elapsedtime) return startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength @@ -1072,7 +1073,7 @@ def get_module_FW_info(self): CommittedImage = 'B' print('Running Image: %s; Committed Image: %s' %(RunningImage, CommittedImage)) else: - raise ValueError, 'Reply payload check code error' + raise ValueError('Reply payload check code error') elapsedtime = time.time()-starttime print('Get module FW info time: %.2f s' %elapsedtime) @@ -1128,7 +1129,7 @@ def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin else: print('Start module FW download: Fail') self.cdb.cmd0102h() - raise ValueError, 'FW_start_status %d' %FW_start_status + raise ValueError('FW_start_status %d' %FW_start_status) elapsedtime = time.time()-starttime print('Start module FW download time: %.2f s' %elapsedtime) diff --git a/tests/sonic_xcvr/test_ccmis.py b/tests/sonic_xcvr/test_ccmis.py new file mode 100644 index 000000000..40f3ea2bd --- /dev/null +++ b/tests/sonic_xcvr/test_ccmis.py @@ -0,0 +1,971 @@ +from mock import MagicMock +import pytest +from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi +from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap +from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom +from sonic_platform_base.sonic_xcvr.codes.public.sff8024 import Sff8024 +from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode + +class TestCCmis(object): + + def mock_ccmis_api(self): + codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + mem_map = CmisMemMap(codes) + reader = MagicMock(return_value=None) + writer = MagicMock() + xcvr_eeprom = XcvrEeprom(reader, writer, mem_map) + api = CCmisApi(xcvr_eeprom) + return api + + @pytest.mark.parametrize("mock_response, expected", [ + ("1234567890", "1234567890"), + ("ABCD", "ABCD") + ]) + def test_get_model(self, mock_response, expected): + """ + Verify all api access valid fields + """ + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_model() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("0.0", "0.0"), + ("1.2", "1.2") + ]) + def test_get_vendor_rev(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_rev() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("100000000", "100000000") + ]) + def test_get_vendor_serial(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_serial() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("1a-1a-1a", "1a-1a-1a") + ]) + def test_get_vendor_name(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_name() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("ABCDE", "ABCDE") + ]) + def test_get_vendor_OUI(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_OUI() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("21010100", "21010100") + ]) + def test_get_vendor_date(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_date() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("LC", "LC") + ]) + def test_get_connector_type(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_connector_type() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("Single Mode Fiber (SMF)", "Single Mode Fiber (SMF)") + ]) + def test_get_module_media_type(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_module_media_type() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("400GAUI-8 C2M (Annex 120E)", "400GAUI-8 C2M (Annex 120E)") + ]) + def test_get_host_electrical_interface(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_electrical_interface() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + ("Single Mode Fiber (SMF)", "400ZR", "400ZR") + ]) + def test_get_module_media_interface(self, mock_response1, mock_response2, expected): + api = self.mock_ccmis_api() + api.get_module_media_type = MagicMock() + api.get_module_media_type.return_value = mock_response1 + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response2 + result = api.get_module_media_interface() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x81, 8) + ]) + def test_get_host_lane_count(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_lane_count() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x81, 1) + ]) + def test_get_media_lane_count(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_lane_count() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_get_host_lane_assignment_option(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_lane_assignment_option() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_get_media_lane_assignment_option(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_lane_assignment_option() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10], + {'hostlane1': 1, 'hostlane2': 1, 'hostlane3': 1, 'hostlane4': 1, + 'hostlane5': 1, 'hostlane6': 1, 'hostlane7': 1, 'hostlane8': 1}) + ]) + def test_get_active_apsel_hostlane(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_active_apsel_hostlane() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ('C-band tunable laser', 'C-band tunable laser') + ]) + def test_get_media_interface_technology(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_interface_technology() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0, 1], '0.1') + ]) + def test_get_module_hardware_revision(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_hardware_revision() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x50, '5.0') + ]) + def test_get_cmis_rev(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_cmis_rev() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0, 1], '0.1') + ]) + def test_get_module_active_firmware(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_active_firmware() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0, 1], '0.1') + ]) + def test_get_module_inactive_firmware(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_inactive_firmware() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([45, 80, -10, 75, 0], + {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0}) + ]) + def test_get_module_temperature(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_temperature() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([3.3, 3.5, 3.1, 3.45, 3.15], + {'monitor value': 3.3, 'high alarm': 3.5, 'low alarm': 3.1, 'high warn': 3.45, 'low warn': 3.15}) + ]) + def test_get_module_voltage(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_voltage() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([-10, -2, -15, -4, -14], + {'monitor value lane1': -10, 'high alarm': -2, 'low alarm': -15, 'high warn': -4, 'low warn': -14}) + ]) + def test_get_txpower(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_txpower() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([-10, -2, -15, -4, -14], + {'monitor value lane1': -10, 'high alarm': -2, 'low alarm': -15, 'high warn': -4, 'low warn': -14}) + ]) + def test_get_rxpower(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_rxpower() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([50, 70, 0, 68, 0], + {'monitor value lane1': 50, 'high alarm': 70, 'low alarm': 0, 'high warn': 68, 'low warn': 0}) + ]) + def test_get_txbias(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_txbias() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x70, 75) + ]) + def test_get_freq_grid(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_freq_grid() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + (75, 12, 193400), + (75, -30, 192350), + ]) + def test_get_laser_config_freq(self, mock_response1, mock_response2, expected): + api = self.mock_ccmis_api() + api.get_freq_grid = MagicMock() + api.get_freq_grid.return_value = mock_response1 + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response2 + result = api.get_laser_config_freq() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (193100000, 193100) + ]) + def test_get_current_laser_freq(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_current_laser_freq() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (-10, -10) + ]) + def test_get_TX_config_power(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_TX_config_power() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False), + (1, True), + ]) + def test_get_media_output_loopback(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_output_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False), + (1, True), + ]) + def test_get_media_input_loopback(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_input_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, [False,False,False,False,False,False,False,False]), + ]) + def test_get_host_output_loopback(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_output_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, [False,False,False,False,False,False,False,False]), + ]) + def test_get_host_input_loopback(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_input_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0xc2, (0,1,0)), + ]) + def test_get_aux_mon_type(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_aux_mon_type() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + ([0,1,0], + [11520, 20480, -2560, 19200, 0], + {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0} + ) + ]) + def test_get_laser_temperature(self, mock_response1, mock_response2, expected): + api = self.mock_ccmis_api() + api.get_aux_mon_type = MagicMock() + api.get_aux_mon_type.return_value = mock_response1 + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response2 + result = api.get_laser_temperature() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + ([0,1,0], + [32767, 65534, 0, 49150.5, 0], + {'monitor value': 1, 'high alarm': 2, 'low alarm': 0, 'high warn': 1.5, 'low warn': 0} + ) + ]) + def test_get_laser_TEC_current(self, mock_response1, mock_response2, expected): + api = self.mock_ccmis_api() + api.get_aux_mon_type = MagicMock() + api.get_aux_mon_type.return_value = mock_response1 + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response2 + result = api.get_laser_TEC_current() + assert result == expected + + @pytest.mark.parametrize("input_param, mock_response, expected", [ + ([False, 1.0], 100, 100.0) + ]) + def test_get_custom_field(self, input_param, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_custom_field(*input_param) + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([100000000, 1000000, 100000, 800, 1200, # preFEC_BER + 10000, 100, 0, 0, 0, # uncorr_frame + 1400, 1300, 1500, # CD + 7.0, 5.5, 9.2, # DGD + 40, 20, 60, # SOPMD + 1.0, 0.8, 1.2, # PDL + 28, 26, 30, # OSNR + 17, 15, 18, # ESNR + 200, 150, 250, # CFO + 15, 13, 18, # EVM + -10, -9.5, -10.5, # TX power + -8, -7, -9, # RX total power + -8, -7, -9, # RX channel power + 5, 3, 8, # SOPROc + 0, 0, 0, # MER + ], + {'preFEC_BER_cur': 0.001, 'preFEC_BER_min': 0.0008, 'preFEC_BER_max': 0.0012, + 'preFEC_uncorr_frame_ratio_cur': 0, 'preFEC_uncorr_frame_ratio_min': 0, 'preFEC_uncorr_frame_ratio_max': 0, + 'rx_cd_avg': 1400, 'rx_cd_min': 1300, 'rx_cd_max': 1500, + 'rx_dgd_avg': 7.0, 'rx_dgd_min': 5.5, 'rx_dgd_max': 9.2, + 'rx_sopmd_avg': 40, 'rx_sopmd_min': 20, 'rx_sopmd_max': 60, + 'rx_pdl_avg': 1.0, 'rx_pdl_min': 0.8, 'rx_pdl_max': 1.2, + 'rx_osnr_avg': 28, 'rx_osnr_min': 26, 'rx_osnr_max': 30, + 'rx_esnr_avg': 17, 'rx_esnr_min': 15, 'rx_esnr_max': 18, + 'rx_cfo_avg': 200, 'rx_cfo_min': 150, 'rx_cfo_max': 250, + 'rx_evm_avg': 15, 'rx_evm_min': 13, 'rx_evm_max': 18, + 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, + 'rx_power_avg': -8, 'rx_power_min': -7, 'rx_power_max': -9, + 'rx_sigpwr_avg': -8, 'rx_sigpwr_min': -7, 'rx_sigpwr_max': -9, + 'rx_soproc_avg': 5, 'rx_soproc_min': 3, 'rx_soproc_max': 8, + 'rx_mer_avg': 0, 'rx_mer_min': 0, 'rx_mer_max': 0 + } + ) + ]) + def test_get_PM(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_PM() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (6, "ModuleReady") + ]) + def test_get_module_state(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_module_state() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (65, (False, False, True)) + ]) + def test_get_module_firmware_fault_state_changed(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_module_firmware_fault_state_changed() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0, 0, 0], + { + 'voltage_flags': { + 'voltage_high_alarm_flag': False, + 'voltage_low_alarm_flag': False, + 'voltage_high_warn_flag': False, + 'voltage_low_warn_flag': False + }, + 'case_temp_flags': { + 'case_temp_high_alarm_flag': False, + 'case_temp_low_alarm_flag': False, + 'case_temp_high_warn_flag': False, + 'case_temp_low_warn_flag': False + }, + 'aux1_flags': { + 'aux1_high_alarm_flag': False, + 'aux1_low_alarm_flag': False, + 'aux1_high_warn_flag': False, + 'aux1_low_warn_flag': False + }, + 'aux2_flags': { + 'aux2_high_alarm_flag': False, + 'aux2_low_alarm_flag': False, + 'aux2_high_warn_flag': False, + 'aux2_low_warn_flag': False + }, + 'aux3_flags': { + 'aux3_high_alarm_flag': False, + 'aux3_low_alarm_flag': False, + 'aux3_high_warn_flag': False, + 'aux3_low_warn_flag': False + }, + 'custom_mon_flags': { + 'custom_mon_high_alarm_flag': False, + 'custom_mon_low_alarm_flag': False, + 'custom_mon_high_warn_flag': False, + 'custom_mon_low_warn_flag': False + } + }) + ]) + def test_get_module_level_flag(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_level_flag() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1145324612, + { + 'dp_lane1': 'DataPathActivated', + 'dp_lane2': 'DataPathActivated', + 'dp_lane3': 'DataPathActivated', + 'dp_lane4': 'DataPathActivated', + 'dp_lane5': 'DataPathActivated', + 'dp_lane6': 'DataPathActivated', + 'dp_lane7': 'DataPathActivated', + 'dp_lane8': 'DataPathActivated', + }) + ]) + def test_get_datapath_state(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_datapath_state() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0xff, + { + 'TX_lane1': True, + 'TX_lane2': True, + 'TX_lane3': True, + 'TX_lane4': True, + 'TX_lane5': True, + 'TX_lane6': True, + 'TX_lane7': True, + 'TX_lane8': True, + }) + ]) + def test_get_tx_output_status(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tx_output_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0xff, + { + 'RX_lane1': True, + 'RX_lane2': True, + 'RX_lane3': True, + 'RX_lane4': True, + 'RX_lane5': True, + 'RX_lane6': True, + 'RX_lane7': True, + 'RX_lane8': True, + }) + ]) + def test_get_rx_output_status(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_rx_output_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }) + ]) + def test_get_tx_fault(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tx_fault() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }) + ]) + def test_get_tx_los(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tx_los() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }) + ]) + def test_get_tx_cdr_lol(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tx_cdr_lol() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0x00, 0x00, 0x00, 0x00], + { + 'tx_power_high_alarm':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_power_low_alarm':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_power_high_warn':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_power_low_warn':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + } + }) + ]) + def test_get_tx_power_flag(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_tx_power_flag() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0x00, 0x00, 0x00, 0x00], + { + 'tx_bias_high_alarm':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_bias_low_alarm':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_bias_high_warn':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_bias_low_warn':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + } + }) + ]) + def test_get_tx_bias_flag(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_tx_bias_flag() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0x00, 0x00, 0x00, 0x00], + { + 'rx_power_high_alarm':{ + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }, + 'rx_power_low_alarm':{ + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }, + 'rx_power_high_warn':{ + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }, + 'rx_power_low_warn':{ + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + } + }) + ]) + def test_get_rx_power_flag(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_rx_power_flag() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }) + ]) + def test_get_rx_los(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_rx_los() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }) + ]) + def test_get_rx_cdr_lol(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_rx_cdr_lol() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (286331153, + { + 'config_DP_status_hostlane1': 'ConfigSuccess', + 'config_DP_status_hostlane2': 'ConfigSuccess', + 'config_DP_status_hostlane3': 'ConfigSuccess', + 'config_DP_status_hostlane4': 'ConfigSuccess', + 'config_DP_status_hostlane5': 'ConfigSuccess', + 'config_DP_status_hostlane6': 'ConfigSuccess', + 'config_DP_status_hostlane7': 'ConfigSuccess', + 'config_DP_status_hostlane8': 'ConfigSuccess', + }) + ]) + def test_get_config_datapath_hostlane_status(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_config_datapath_hostlane_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, + { + 'hostlane1': False, + 'hostlane2': False, + 'hostlane3': False, + 'hostlane4': False, + 'hostlane5': False, + 'hostlane6': False, + 'hostlane7': False, + 'hostlane8': False, + }) + ]) + def test_get_dpinit_pending(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_dpinit_pending() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False) + ]) + def test_get_tuning_in_progress(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tuning_in_progress() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False) + ]) + def test_get_wavelength_unlocked(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_wavelength_unlocked() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, ['TuningComplete']) + ]) + def test_get_laser_tuning_summary(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_laser_tuning_summary() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([190, -72, 120], (190, -72, 120, 191300, 196100)) + ]) + def test_get_supported_freq_config(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_supported_freq_config() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([-20, 0], (-20,0)) + ]) + def test_get_supported_power_config(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_supported_power_config() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (127, + { + 'simultaneous_host_media_loopback_supported': True, + 'per_lane_media_loopback_supported': True, + 'per_lane_host_loopback_supported': True, + 'host_side_input_loopback_supported': True, + 'host_side_output_loopback_supported': True, + 'media_side_input_loopback_supported': True, + 'media_side_output_loopback_supported': True + }) + ]) + def test_get_loopback_capability(self, mock_response, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_loopback_capability() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + ([0x77, 0xff], [18, 35, (0, 7, 112, 255, 255, 16, 0, 0, 19, 136, 0, 100, 3, 232, 19, 136, 58, 152)], + (112, 2048, False, True, 2048) + ) + ]) + def test_get_module_FW_upgrade_feature(self, mock_response1, mock_response2, expected): + api = self.mock_ccmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response1 + api.cdb = MagicMock() + api.cdb.cmd0041h = MagicMock() + api.cdb.cmd0041h.return_value = mock_response2 + api.cdb.cdb_chkcode = MagicMock() + api.cdb.cdb_chkcode.return_value = mock_response2[1] + result = api.get_module_FW_upgrade_feature() + assert result == expected + + # TODO: call other methods in the api From d1876829e67f164c4999c7bcd39129c27c640441 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Thu, 7 Oct 2021 22:19:49 -0700 Subject: [PATCH 08/16] 1. Add VDM flags; 2. Under api>public, transfer cmis related functions from c_cmis.py to cmis.py --- pytest.ini | 2 +- .../sonic_xcvr/api/public/c_cmis.py | 1069 +--------------- .../sonic_xcvr/api/public/cmis.py | 1085 +++++++++++++++++ .../sonic_xcvr/api/public/cmisVDM.py | 41 +- .../sonic_xcvr/xcvr_api_factory.py | 4 +- tests/sonic_xcvr/test_ccmis.py | 961 +-------------- tests/sonic_xcvr/test_cmis.py | 969 ++++++++++++++- 7 files changed, 2079 insertions(+), 2052 deletions(-) diff --git a/pytest.ini b/pytest.ini index 142a21e74..a88c650f8 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,2 @@ [pytest] -addopts = --cov=sonic_platform_base tests/sonic_xcvr/test_ccmis.py --cov-report html --cov-report term --cov-report xml --junitxml=test-results.xml -v +addopts = --cov=sonic_platform_base tests/sonic_xcvr/test_cmis.py --cov-report html --cov-report term --cov-report xml --junitxml=test-results.xml -v diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index dfcb1875b..d13bc538c 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -8,8 +8,6 @@ from .cmisCDB import CmisCdbApi from .cmisVDM import CmisVdmApi import time -import datetime - BYTELENGTH = 8 class CCmisApi(XcvrApi): NUM_CHANNELS = 8 @@ -17,434 +15,7 @@ class CCmisApi(XcvrApi): def __init__(self, xcvr_eeprom): super(CCmisApi, self).__init__(xcvr_eeprom) - # Transceiver Information - def get_model(self): - ''' - This function returns the part number of the module - ''' - return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD) - - def get_vendor_rev(self): - ''' - This function returns the revision level for part number provided by vendor - ''' - return self.xcvr_eeprom.read(consts.VENDOR_REV) - - def get_vendor_serial(self): - ''' - This function returns the serial number of the module - ''' - return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO) - - def get_vendor_name(self): - ''' - This function returns the vendor name of the module - ''' - return self.xcvr_eeprom.read(consts.VENDOR_NAME_FIELD) - - def get_module_type(self): - ''' - This function returns the SFF8024Identifier (module type / form-factor). Table 4-1 in SFF-8024 Rev4.6 - ''' - return self.xcvr_eeprom.read(consts.ID_FIELD) - - def get_vendor_OUI(self): - ''' - This function returns the vendor IEEE company ID - ''' - return self.xcvr_eeprom.read(consts.VENDOR_OUI_FIELD) - - def get_vendor_date(self): - ''' - This function returns the module manufacture date. It returns YYMMDDXX. XX is the lot code. - ''' - return self.xcvr_eeprom.read(consts.VENDOR_DATE) - - def get_connector_type(self): - ''' - This function returns module connector. Table 4-3 in SFF-8024 Rev4.6 - ''' - return self.xcvr_eeprom.read(consts.CONNECTOR_TYPE) - - def get_module_media_type(self): - ''' - This function returns module media type: MMF, SMF, Passive Copper Cable, Active Cable Assembly or Base-T. - ''' - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_TYPE) - - def get_host_electrical_interface(self): - ''' - This function returns module host electrical interface. Table 4-5 in SFF-8024 Rev4.6 - ''' - return self.xcvr_eeprom.read(consts.HOST_ELECTRICAL_INTERFACE) - - def get_module_media_interface(self): - ''' - This function returns module media electrical interface. Table 4-6 ~ 4-10 in SFF-8024 Rev4.6 - ''' - media_type = self.get_module_media_type() - if media_type == 'Multimode Fiber (MMF)': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM) - elif media_type == 'Single Mode Fiber (SMF)': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_SM) - elif media_type == 'Passive Copper Cable': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER) - elif media_type == 'Active Cable Assembly': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE) - elif media_type == 'BASE-T': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_BASE_T) - else: - return 'Unknown media interface' - - def get_host_lane_count(self): - ''' - This function returns number of host lanes - ''' - lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) - return (lane_count >> 4) & 0xf - - def get_media_lane_count(self): - ''' - This function returns number of media lanes - ''' - lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) - return (lane_count) & 0xf - - def get_host_lane_assignment_option(self): - ''' - This function returns the host lane that the application begins on - ''' - return self.xcvr_eeprom.read(consts.HOST_LANE_ASSIGNMENT_OPTION) - - def get_media_lane_assignment_option(self): - ''' - This function returns the media lane that the application is allowed to begin on - ''' - return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION) - - def get_active_apsel_hostlane(self): - ''' - This function returns the application select code that each host lane has - ''' - apsel_dict = dict() - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_1) - apsel_dict['hostlane1'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_2) - apsel_dict['hostlane2'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_3) - apsel_dict['hostlane3'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_4) - apsel_dict['hostlane4'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_5) - apsel_dict['hostlane5'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_6) - apsel_dict['hostlane6'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_7) - apsel_dict['hostlane7'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_8) - apsel_dict['hostlane8'] = (result >> 4) & 0xf - return apsel_dict - - def get_media_interface_technology(self): - ''' - This function returns the media lane technology - ''' - return self.xcvr_eeprom.read(consts.MEDIA_INTERFACE_TECH) - - def get_module_hardware_revision(self): - ''' - This function returns the module hardware revision - ''' - hw_major_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) - hw_minor_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) - hw_rev = [str(num) for num in [hw_major_rev, hw_minor_rev]] - return '.'.join(hw_rev) - - def get_cmis_rev(self): - ''' - This function returns the CMIS version the module complies to - ''' - cmis = self.xcvr_eeprom.read(consts.CMIS_REVISION) - cmis_major = (cmis >> 4) & 0xf - cmis_minor = (cmis) & 0xf - cmis_rev = [str(num) for num in [cmis_major, cmis_minor]] - return '.'.join(cmis_rev) - - def get_module_active_firmware(self): - ''' - This function returns the active firmware version - ''' - active_fw_major = self.xcvr_eeprom.read(consts.ACTIVE_FW_MAJOR_REV) - active_fw_minor = self.xcvr_eeprom.read(consts.ACTIVE_FW_MINOR_REV) - active_fw = [str(num) for num in [active_fw_major, active_fw_minor]] - return '.'.join(active_fw) - - def get_module_inactive_firmware(self): - ''' - This function returns the inactive firmware version - ''' - inactive_fw_major = self.xcvr_eeprom.read(consts.INACTIVE_FW_MAJOR_REV) - inactive_fw_minor = self.xcvr_eeprom.read(consts.INACTIVE_FW_MINOR_REV) - inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]] - return '.'.join(inactive_fw) - - # Transceiver DOM - def get_module_temperature(self): - ''' - This function returns the module case temperature and its thresholds. Unit in deg C - ''' - case_temp_dict = dict() - case_temp = self.xcvr_eeprom.read(consts.CASE_TEMP) - case_temp_high_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_ALARM) - case_temp_low_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_ALARM) - case_temp_high_warn = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_WARN) - case_temp_low_warn = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_WARN) - case_temp_dict = {'monitor value': case_temp, - 'high alarm': case_temp_high_alarm, - 'low alarm': case_temp_low_alarm, - 'high warn': case_temp_high_warn, - 'low warn': case_temp_low_warn} - return case_temp_dict - - def get_module_voltage(self): - ''' - This function returns the monitored value of the 3.3-V supply voltage and its thresholds. - Unit in V - ''' - voltage_dict = dict() - voltage = self.xcvr_eeprom.read(consts.VOLTAGE) - voltage_high_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_ALARM) - voltage_low_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_ALARM) - voltage_high_warn = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_WARN) - voltage_low_warn = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_WARN) - voltage_dict = {'monitor value': voltage, - 'high alarm': voltage_high_alarm, - 'low alarm': voltage_low_alarm, - 'high warn': voltage_high_warn, - 'low warn': voltage_low_warn} - return voltage_dict - - def get_txpower(self): - ''' - This function returns the TX output power. Unit in mW - ''' - tx_power_dict = dict() - tx_power = self.xcvr_eeprom.read(consts.TX_POW) - tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM) - tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM) - tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN) - tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN) - tx_power_dict = {'monitor value lane1': tx_power, - 'high alarm': tx_power_high_alarm, - 'low alarm': tx_power_low_alarm, - 'high warn': tx_power_high_warn, - 'low warn': tx_power_low_warn} - return tx_power_dict - - def get_rxpower(self): - ''' - This function returns the RX input power. Unit in mW - ''' - rx_power_dict = dict() - rx_power = self.xcvr_eeprom.read(consts.RX_POW) - rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM) - rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM) - rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN) - rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN) - rx_power_dict = {'monitor value lane1': rx_power, - 'high alarm': rx_power_high_alarm, - 'low alarm': rx_power_low_alarm, - 'high warn': rx_power_high_warn, - 'low warn': rx_power_low_warn} - return rx_power_dict - - def get_txbias(self): - ''' - This function returns the TX laser bias current. Unit in mA - ''' - tx_bias_current_dict = dict() - tx_bias_current = self.xcvr_eeprom.read(consts.TX_BIAS) - tx_bias_current_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_ALARM) - tx_bias_current_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_ALARM) - tx_bias_current_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_WARN) - tx_bias_current_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_WARN) - tx_bias_current_dict = {'monitor value lane1': tx_bias_current, - 'high alarm': tx_bias_current_high_alarm, - 'low alarm': tx_bias_current_low_alarm, - 'high warn': tx_bias_current_high_warn, - 'low warn': tx_bias_current_low_warn} - return tx_bias_current_dict - - def get_freq_grid(self): - ''' - This function returns the configured frequency grid. Unit in GHz - ''' - freq_grid = self.xcvr_eeprom.read(consts.GRID_SPACING) >> 4 - if freq_grid == 7: - return 75 - elif freq_grid == 6: - return 33 - elif freq_grid == 5: - return 100 - elif freq_grid == 4: - return 50 - elif freq_grid == 3: - return 25 - elif freq_grid == 2: - return 12.5 - elif freq_grid == 1: - return 6.25 - elif freq_grid == 0: - return 3.125 - - def get_laser_config_freq(self): - ''' - This function returns the configured laser frequency. Unit in GHz - ''' - freq_grid = self.get_freq_grid() - channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) - if freq_grid == 75: - config_freq = 193100 + channel * freq_grid/3 - else: - config_freq = 193100 + channel * freq_grid - return config_freq - - def get_current_laser_freq(self): - ''' - This function returns the monitored laser frequency. Unit in GHz - ''' - return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ)/1000 - - def get_TX_config_power(self): - ''' - This function returns the configured TX output power. Unit in dBm - ''' - return self.xcvr_eeprom.read(consts.TX_CONFIG_POWER) - - def get_media_output_loopback(self): - ''' - This function returns the media output loopback status - ''' - result = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) - return result == 1 - - def get_media_input_loopback(self): - ''' - This function returns the media input loopback status - ''' - result = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) - return result == 1 - - def get_host_output_loopback(self): - ''' - This function returns the host output loopback status - ''' - result = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) - loopback_status = [] - for bitpos in range(BYTELENGTH): - loopback_status.append(bool((result >> bitpos) & 0x1)) - return loopback_status - - def get_host_input_loopback(self): - ''' - This function returns the host input loopback status - ''' - result = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) - loopback_status = [] - for bitpos in range(BYTELENGTH): - loopback_status.append(bool((result >> bitpos) & 0x1)) - return loopback_status - - def get_aux_mon_type(self): - ''' - This function returns the aux monitor types - ''' - result = self.xcvr_eeprom.read(consts.AUX_MON_TYPE) - aux1_mon_type = result & 0x1 - aux2_mon_type = (result >> 1) & 0x1 - aux3_mon_type = (result >> 2) & 0x1 - return aux1_mon_type, aux2_mon_type, aux3_mon_type - - def get_laser_temperature(self): - ''' - This function returns the laser temperature monitor value - ''' - aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() - LASER_TEMP_SCALE = 256.0 - laser_temp_dict = dict() - if aux2_mon_type == 0: - laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE - laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEMP_SCALE - laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEMP_SCALE - laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEMP_SCALE - laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEMP_SCALE - elif aux2_mon_type == 1 and aux3_mon_type == 0: - laser_temp = self.xcvr_eeprom.read(consts.AUX3_MON)/LASER_TEMP_SCALE - laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX3_HIGH_ALARM)/LASER_TEMP_SCALE - laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX3_LOW_ALARM)/LASER_TEMP_SCALE - laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX3_HIGH_WARN)/LASER_TEMP_SCALE - laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX3_LOW_WARN)/LASER_TEMP_SCALE - else: - return None - laser_temp_dict = {'monitor value': laser_temp, - 'high alarm': laser_temp_high_alarm, - 'low alarm': laser_temp_low_alarm, - 'high warn': laser_temp_high_warn, - 'low warn': laser_temp_low_warn} - return laser_temp_dict - - def get_laser_TEC_current(self): - ''' - This function returns the laser TEC current monitor value - ''' - aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() - LASER_TEC_CURRENT_SCALE = 32767.0 - laser_tec_current_dict = dict() - if aux1_mon_type == 1: - laser_tec_current = self.xcvr_eeprom.read(consts.AUX1_MON)/LASER_TEC_CURRENT_SCALE - laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX1_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE - laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX1_LOW_ALARM)/LASER_TEC_CURRENT_SCALE - laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX1_HIGH_WARN)/LASER_TEC_CURRENT_SCALE - laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX1_LOW_WARN)/LASER_TEC_CURRENT_SCALE - elif aux1_mon_type == 0 and aux2_mon_type == 1: - laser_tec_current = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEC_CURRENT_SCALE - laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE - laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEC_CURRENT_SCALE - laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEC_CURRENT_SCALE - laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEC_CURRENT_SCALE - else: - return None - laser_tec_current_dict = {'monitor value': laser_tec_current, - 'high alarm': laser_tec_current_high_alarm, - 'low alarm': laser_tec_current_low_alarm, - 'high warn': laser_tec_current_high_warn, - 'low warn': laser_tec_current_low_warn} - return laser_tec_current_dict - - def get_custom_field(self, signed = False, scale = 1.0): - ''' - This function returns the custom monitor field - ''' - result = self.xcvr_eeprom.read(consts.CUSTOM_MON) - if signed: - result -= 2**15 - result /= scale - return result - - - def get_VDM_api(self): - self.vdm = CmisVdmApi(self.xcvr_eeprom) - - def get_VDM(self): - try: - self.vdm - except: - self.get_VDM_api() - - VDM = self.vdm.get_VDM_allpage() - return VDM - - def get_PM(self): + def get_PM_all(self): ''' This function returns the PMs reported in Page 34h and 35h in OIF C-CMIS document CD: unit in ps/nm @@ -539,641 +110,3 @@ def get_PM(self): PM_dict['rx_mer_min'] = self.xcvr_eeprom.read(consts.RX_MIN_MER_PM) PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM) return PM_dict - - - # Transceiver status - def get_module_state(self): - ''' - This function returns the module state - ''' - result = self.xcvr_eeprom.read(consts.MODULE_STATE) >> 1 - DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].MODULE_STATE - return DICT.get(result, "Unknown") - - def get_module_firmware_fault_state_changed(self): - ''' - This function returns datapath firmware fault state, module firmware fault state - and whether module state changed - ''' - result = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) - datapath_firmware_fault = bool((result >> 2) & 0x1) - module_firmware_fault = bool((result >> 1) & 0x1) - module_state_changed = bool(result & 0x1) - return datapath_firmware_fault, module_firmware_fault, module_state_changed - - def get_module_level_flag(self): - ''' - This function returns teh module level flags, including - - 3.3 V voltage supply flags - - Case temperature flags - - Aux 1 flags - - Aux 2 flags - - Aux 3 flags - - Custom field flags - ''' - module_flag_byte1 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE1) - module_flag_byte2 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE2) - module_flag_byte3 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE3) - - voltage_high_alarm_flag = bool((module_flag_byte1 >> 4) & 0x1) - voltage_low_alarm_flag = bool((module_flag_byte1 >> 5) & 0x1) - voltage_high_warn_flag = bool((module_flag_byte1 >> 6) & 0x1) - voltage_low_warn_flag = bool((module_flag_byte1 >> 7) & 0x1) - voltage_flags = {'voltage_high_alarm_flag': voltage_high_alarm_flag, - 'voltage_low_alarm_flag': voltage_low_alarm_flag, - 'voltage_high_warn_flag': voltage_high_warn_flag, - 'voltage_low_warn_flag': voltage_low_warn_flag} - - case_temp_high_alarm_flag = bool((module_flag_byte1 >> 0) & 0x1) - case_temp_low_alarm_flag = bool((module_flag_byte1 >> 1) & 0x1) - case_temp_high_warn_flag = bool((module_flag_byte1 >> 2) & 0x1) - case_temp_low_warn_flag = bool((module_flag_byte1 >> 3) & 0x1) - case_temp_flags = {'case_temp_high_alarm_flag': case_temp_high_alarm_flag, - 'case_temp_low_alarm_flag': case_temp_low_alarm_flag, - 'case_temp_high_warn_flag': case_temp_high_warn_flag, - 'case_temp_low_warn_flag': case_temp_low_warn_flag} - - aux2_high_alarm_flag = bool((module_flag_byte2 >> 4) & 0x1) - aux2_low_alarm_flag = bool((module_flag_byte2 >> 5) & 0x1) - aux2_high_warn_flag = bool((module_flag_byte2 >> 6) & 0x1) - aux2_low_warn_flag = bool((module_flag_byte2 >> 7) & 0x1) - aux2_flags = {'aux2_high_alarm_flag': aux2_high_alarm_flag, - 'aux2_low_alarm_flag': aux2_low_alarm_flag, - 'aux2_high_warn_flag': aux2_high_warn_flag, - 'aux2_low_warn_flag': aux2_low_warn_flag} - - aux1_high_alarm_flag = bool((module_flag_byte2 >> 0) & 0x1) - aux1_low_alarm_flag = bool((module_flag_byte2 >> 1) & 0x1) - aux1_high_warn_flag = bool((module_flag_byte2 >> 2) & 0x1) - aux1_low_warn_flag = bool((module_flag_byte2 >> 3) & 0x1) - aux1_flags = {'aux1_high_alarm_flag': aux1_high_alarm_flag, - 'aux1_low_alarm_flag': aux1_low_alarm_flag, - 'aux1_high_warn_flag': aux1_high_warn_flag, - 'aux1_low_warn_flag': aux1_low_warn_flag} - - custom_mon_high_alarm_flag = bool((module_flag_byte3 >> 4) & 0x1) - custom_mon_low_alarm_flag = bool((module_flag_byte3 >> 5) & 0x1) - custom_mon_high_warn_flag = bool((module_flag_byte3 >> 6) & 0x1) - custom_mon_low_warn_flag = bool((module_flag_byte3 >> 7) & 0x1) - custom_mon_flags = {'custom_mon_high_alarm_flag': custom_mon_high_alarm_flag, - 'custom_mon_low_alarm_flag': custom_mon_low_alarm_flag, - 'custom_mon_high_warn_flag': custom_mon_high_warn_flag, - 'custom_mon_low_warn_flag': custom_mon_low_warn_flag} - - aux3_high_alarm_flag = bool((module_flag_byte3 >> 0) & 0x1) - aux3_low_alarm_flag = bool((module_flag_byte3 >> 1) & 0x1) - aux3_high_warn_flag = bool((module_flag_byte3 >> 2) & 0x1) - aux3_low_warn_flag = bool((module_flag_byte3 >> 3) & 0x1) - aux3_flags = {'aux3_high_alarm_flag': aux3_high_alarm_flag, - 'aux3_low_alarm_flag': aux3_low_alarm_flag, - 'aux3_high_warn_flag': aux3_high_warn_flag, - 'aux3_low_warn_flag': aux3_low_warn_flag} - - module_flag = {'voltage_flags': voltage_flags, - 'case_temp_flags': case_temp_flags, - 'aux1_flags': aux1_flags, - 'aux2_flags': aux2_flags, - 'aux3_flags': aux3_flags, - 'custom_mon_flags': custom_mon_flags} - return module_flag - - def get_datapath_state(self): - ''' - This function returns the eight datapath states - ''' - result = self.xcvr_eeprom.read(consts.DATAPATH_STATE) - dp_lane7 = (result >> 0) & 0xf - dp_lane8 = (result >> 4) & 0xf - dp_lane5 = (result >> 8) & 0xf - dp_lane6 = (result >> 12) & 0xf - dp_lane3 = (result >> 16) & 0xf - dp_lane4 = (result >> 20) & 0xf - dp_lane1 = (result >> 24) & 0xf - dp_lane2 = (result >> 28) & 0xf - DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].DATAPATH_STATE - dp_state_dict = {'dp_lane1': DICT.get(dp_lane1, "Unknown"), - 'dp_lane2': DICT.get(dp_lane2, "Unknown"), - 'dp_lane3': DICT.get(dp_lane3, "Unknown"), - 'dp_lane4': DICT.get(dp_lane4, "Unknown"), - 'dp_lane5': DICT.get(dp_lane5, "Unknown"), - 'dp_lane6': DICT.get(dp_lane6, "Unknown"), - 'dp_lane7': DICT.get(dp_lane7, "Unknown"), - 'dp_lane8': DICT.get(dp_lane8, "Unknown") - } - return dp_state_dict - - def get_tx_output_status(self): - ''' - This function returns whether TX output signals are valid - ''' - result = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) - tx_output_status_dict = dict() - for bitpos in range(BYTELENGTH): - tx_output_status_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return tx_output_status_dict - - def get_rx_output_status(self): - ''' - This function returns whether RX output signals are valid - ''' - result = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) - rx_output_status_dict = dict() - for bitpos in range(BYTELENGTH): - rx_output_status_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return rx_output_status_dict - - def get_tx_fault(self): - ''' - This function returns TX failure flag - ''' - result = self.xcvr_eeprom.read(consts.TX_FAULT_FLAG) - tx_fault_dict = dict() - for bitpos in range(BYTELENGTH): - tx_fault_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return tx_fault_dict - - def get_tx_los(self): - ''' - This function returns TX LOS flag - ''' - result = self.xcvr_eeprom.read(consts.TX_LOS_FLAG) - tx_los_dict = dict() - for bitpos in range(BYTELENGTH): - tx_los_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return tx_los_dict - - def get_tx_cdr_lol(self): - ''' - This function returns TX CDR LOL flag - ''' - result = self.xcvr_eeprom.read(consts.TX_CDR_LOL) - tx_lol_dict = dict() - for bitpos in range(BYTELENGTH): - tx_lol_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return tx_lol_dict - - def get_tx_power_flag(self): - ''' - This function returns TX power out of range flag - ''' - tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM_FLAG) - tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM_FLAG) - tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN_FLAG) - tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN_FLAG) - tx_power_high_alarm_dict = dict() - tx_power_low_alarm_dict = dict() - tx_power_high_warn_dict = dict() - tx_power_low_warn_dict = dict() - for bitpos in range(BYTELENGTH): - tx_power_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_alarm >> bitpos) & 0x1) - tx_power_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_alarm >> bitpos) & 0x1) - tx_power_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_warn >> bitpos) & 0x1) - tx_power_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_warn >> bitpos) & 0x1) - - tx_power_flag_dict = {'tx_power_high_alarm': tx_power_high_alarm_dict, - 'tx_power_low_alarm': tx_power_low_alarm_dict, - 'tx_power_high_warn': tx_power_high_warn_dict, - 'tx_power_low_warn': tx_power_low_warn_dict,} - return tx_power_flag_dict - - def get_tx_bias_flag(self): - ''' - This function returns TX bias out of range flag - ''' - tx_bias_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_ALARM_FLAG) - tx_bias_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_ALARM_FLAG) - tx_bias_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_WARN_FLAG) - tx_bias_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_WARN_FLAG) - tx_bias_high_alarm_dict = dict() - tx_bias_low_alarm_dict = dict() - tx_bias_high_warn_dict = dict() - tx_bias_low_warn_dict = dict() - for bitpos in range(BYTELENGTH): - tx_bias_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_alarm >> bitpos) & 0x1) - tx_bias_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_alarm >> bitpos) & 0x1) - tx_bias_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_warn >> bitpos) & 0x1) - tx_bias_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_warn >> bitpos) & 0x1) - - tx_bias_flag_dict = {'tx_bias_high_alarm': tx_bias_high_alarm_dict, - 'tx_bias_low_alarm': tx_bias_low_alarm_dict, - 'tx_bias_high_warn': tx_bias_high_warn_dict, - 'tx_bias_low_warn': tx_bias_low_warn_dict,} - return tx_bias_flag_dict - - def get_rx_power_flag(self): - ''' - This function returns RX power out of range flag - ''' - rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM_FLAG) - rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM_FLAG) - rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN_FLAG) - rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN_FLAG) - rx_power_high_alarm_dict = dict() - rx_power_low_alarm_dict = dict() - rx_power_high_warn_dict = dict() - rx_power_low_warn_dict = dict() - for bitpos in range(BYTELENGTH): - rx_power_high_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_alarm >> bitpos) & 0x1) - rx_power_low_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_alarm >> bitpos) & 0x1) - rx_power_high_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_warn >> bitpos) & 0x1) - rx_power_low_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_warn >> bitpos) & 0x1) - - rx_power_flag_dict = {'rx_power_high_alarm': rx_power_high_alarm_dict, - 'rx_power_low_alarm': rx_power_low_alarm_dict, - 'rx_power_high_warn': rx_power_high_warn_dict, - 'rx_power_low_warn': rx_power_low_warn_dict,} - return rx_power_flag_dict - - def get_rx_los(self): - ''' - This function returns RX LOS flag - ''' - result = self.xcvr_eeprom.read(consts.RX_LOS_FLAG) - rx_los_dict = dict() - for bitpos in range(BYTELENGTH): - rx_los_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return rx_los_dict - - def get_rx_cdr_lol(self): - ''' - This function returns RX CDR LOL flag - ''' - result = self.xcvr_eeprom.read(consts.RX_CDR_LOL) - rx_lol_dict = dict() - for bitpos in range(BYTELENGTH): - rx_lol_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return rx_lol_dict - - def get_config_datapath_hostlane_status(self): - ''' - This function returns configuration command execution - / result status for the datapath of each host lane - ''' - result = self.xcvr_eeprom.read(consts.CONFIG_LANE_STATUS) - config_status_lane7 = (result >> 0) & 0xf - config_status_lane8 = (result >> 4) & 0xf - config_status_lane5 = (result >> 8) & 0xf - config_status_lane6 = (result >> 12) & 0xf - config_status_lane3 = (result >> 16) & 0xf - config_status_lane4 = (result >> 20) & 0xf - config_status_lane1 = (result >> 24) & 0xf - config_status_lane2 = (result >> 28) & 0xf - config_status_raw = [config_status_lane1, config_status_lane2, config_status_lane3, config_status_lane4, - config_status_lane5, config_status_lane6, config_status_lane7, config_status_lane8] - DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].CONFIG_STATUS - config_status_dict = {'config_DP_status_hostlane1': DICT.get(config_status_lane1, "Unknown"), - 'config_DP_status_hostlane2': DICT.get(config_status_lane2, "Unknown"), - 'config_DP_status_hostlane3': DICT.get(config_status_lane3, "Unknown"), - 'config_DP_status_hostlane4': DICT.get(config_status_lane4, "Unknown"), - 'config_DP_status_hostlane5': DICT.get(config_status_lane5, "Unknown"), - 'config_DP_status_hostlane6': DICT.get(config_status_lane6, "Unknown"), - 'config_DP_status_hostlane7': DICT.get(config_status_lane7, "Unknown"), - 'config_DP_status_hostlane8': DICT.get(config_status_lane8, "Unknown") - } - return config_status_dict - - def get_dpinit_pending(self): - ''' - This function returns datapath init pending status. - 0 means datapath init not pending. - 1 means datapath init pending. DPInit not yet executed after successful ApplyDPInit. - Hence the active control set content may deviate from the actual hardware config - ''' - result = self.xcvr_eeprom.read(consts.DPINIT_PENDING) - dpinit_pending_dict = dict() - for bitpos in range(BYTELENGTH): - dpinit_pending_dict['hostlane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return dpinit_pending_dict - - def get_tuning_in_progress(self): - ''' - This function returns tunning in progress status. - 0 means tuning not in progress - 1 means tuning in progress - ''' - return bool(self.xcvr_eeprom.read(consts.TUNING_IN_PROGRESS)) - - def get_wavelength_unlocked(self): - ''' - This function returns wavelength unlocked status. - 0 means wavelength locked - 1 means wavelength unlocked - ''' - return bool(self.xcvr_eeprom.read(consts.WAVELENGTH_UNLOCKED)) - - def get_laser_tuning_summary(self): - ''' - This function returns laser tuning status summary - ''' - result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) - laser_tuning_summary = [] - if (result >> 5) & 0x1: - laser_tuning_summary.append("TargetOutputPowerOOR") - if (result >> 4) & 0x1: - laser_tuning_summary.append("FineTuningOutOfRange") - if (result >> 3) & 0x1: - laser_tuning_summary.append("TuningNotAccepted") - if (result >> 2) & 0x1: - laser_tuning_summary.append("InvalidChannel") - if (result >> 1) & 0x1: - laser_tuning_summary.append("WavelengthUnlocked") - if (result >> 0) & 0x1: - laser_tuning_summary.append("TuningComplete") - return laser_tuning_summary - - def get_supported_freq_config(self): - ''' - This function returns the supported freq grid, low and high supported channel in 75GHz grid, - and low and high frequency supported in GHz. - allowed channel number bound in 75 GHz grid - allowed frequency bound in 75 GHz grid - ''' - grid_supported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) - low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) - hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) - low_freq_supported = 193100 + low_ch_num * 25 - high_freq_supported = 193100 + hi_ch_num * 25 - return grid_supported, low_ch_num, hi_ch_num, low_freq_supported, high_freq_supported - - def get_supported_power_config(self): - ''' - This function returns the supported TX power range - ''' - min_prog_tx_output_power = self.xcvr_eeprom.read(consts.MIN_PROG_OUTPUT_POWER) - max_prog_tx_output_power = self.xcvr_eeprom.read(consts.MAX_PROG_OUTPUT_POWER) - return min_prog_tx_output_power, max_prog_tx_output_power - - def reset_module(self, reset = False): - ''' - This function resets the module - ''' - if reset: - reset_control = reset << 3 - self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, reset_control) - - def set_low_power(self, AssertLowPower): - ''' - This function sets the module to low power state. - AssertLowPower being 0 means "set to high power" - AssertLowPower being 1 means "set to low power" - ''' - low_power_control = AssertLowPower << 6 - self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control) - - def set_laser_freq(self, freq): - ''' - This function sets the laser frequency. Unit in GHz - ZR application will not support fine tuning of the laser - ''' - grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() - grid_supported_75GHz = (grid_supported >> 7) & 0x1 - assert grid_supported_75GHz - freq_grid = 0x70 - self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) - channel_number = int(round((freq - 193100)/25)) - assert channel_number % 3 == 0 - if channel_number > hi_ch_num or channel_number < low_ch_num: - raise ValueError('Provisioned frequency out of range. Max Freq: 196100; Min Freq: 191300 GHz.') - self.set_low_power(True) - time.sleep(5) - self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) - time.sleep(1) - self.set_low_power(False) - time.sleep(1) - - def set_TX_power(self, TX_power): - ''' - This function sets the TX output power. Unit in dBm - ''' - min_prog_tx_output_power, max_prog_tx_output_power = self.get_supported_power_config() - if TX_power > max_prog_tx_output_power or TX_power < min_prog_tx_output_power: - raise ValueError('Provisioned TX power out of range. Max: %.1f; Min: %.1f dBm.' - %(max_prog_tx_output_power, min_prog_tx_output_power)) - self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, TX_power) - time.sleep(1) - - def get_loopback_capability(self): - ''' - This function returns the module loopback capability as advertised - ''' - allowed_loopback_result = self.xcvr_eeprom.read(consts.LOOPBACK_CAPABILITY) - loopback_capability = dict() - loopback_capability['simultaneous_host_media_loopback_supported'] = bool((allowed_loopback_result >> 6) & 0x1) - loopback_capability['per_lane_media_loopback_supported'] = bool((allowed_loopback_result >> 5) & 0x1) - loopback_capability['per_lane_host_loopback_supported'] = bool((allowed_loopback_result >> 4) & 0x1) - loopback_capability['host_side_input_loopback_supported'] = bool((allowed_loopback_result >> 3) & 0x1) - loopback_capability['host_side_output_loopback_supported'] = bool((allowed_loopback_result >> 2) & 0x1) - loopback_capability['media_side_input_loopback_supported'] = bool((allowed_loopback_result >> 1) & 0x1) - loopback_capability['media_side_output_loopback_supported'] = bool((allowed_loopback_result >> 0) & 0x1) - return loopback_capability - - def set_loopback_mode(self, loopback_mode): - ''' - This function sets the module loopback mode. - Loopback mode has to be one of the five: - 1. "none" (default) - 2. "host-side-input" - 3. "host-side-output" - 4. "media-side-input" - 5. "media-side-output" - The function will look at 13h:128 to check advertized loopback capabilities. - ''' - loopback_capability = self.get_loopback_capability() - if loopback_mode == 'none': - self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0) - self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0) - self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0) - self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0) - elif loopback_mode == 'host-side-input': - assert loopback_capability['host_side_input_loopback_supported'] - self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0xff) - elif loopback_mode == 'host-side-output': - assert loopback_capability['host_side_output_loopback_supported'] - self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0xff) - elif loopback_mode == 'media-side-input': - assert loopback_capability['media_side_input_loopback_supported'] - self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0x1) - elif loopback_mode == 'media-side-output': - assert loopback_capability['media_side_output_loopback_supported'] - self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0x1) - - - def get_CDB_api(self): - self.cdb = CmisCdbApi(self.xcvr_eeprom) - - def get_module_FW_upgrade_feature(self, verbose = False): - try: - self.cdb - except: - self.get_CDB_api() - # get fw upgrade features (CMD 0041h) - starttime = time.time() - autopaging_flag = bool((self.xcvr_eeprom.read(consts.CDB_SUPPORT) >> 4) & 0x1) - writelength = (self.xcvr_eeprom.read(consts.CDB_SEQ_WRITE_LENGTH_EXT) + 1) * 8 - print('Auto page support: %s' %autopaging_flag) - print('Max write length: %d' %writelength) - rpllen, rpl_chkcode, rpl = self.cdb.cmd0041h() - if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: - startLPLsize = rpl[2] - print('Start payload size %d' % startLPLsize) - maxblocksize = (rpl[4] + 1) * 8 - print('Max block size %d' % maxblocksize) - lplEplSupport = {0x00 : 'No write to LPL/EPL supported', - 0x01 : 'Write to LPL supported', - 0x10 : 'Write to EPL supported', - 0x11 : 'Write to LPL/EPL supported'} - print('{}'.format(lplEplSupport[rpl[5]])) - if rpl[5] == 1: - lplonly_flag = True - else: - lplonly_flag = False - print('Abort CMD102h supported %s' %bool(rpl[1] & 0x01)) - if verbose: - print('Copy CMD108h supported %s' %bool((rpl[1] >> 1) & 0x01)) - print('Skipping erased blocks supported %s' %bool((rpl[1] >> 2) & 0x01)) - print('Full image readback supported %s' %bool((rpl[1] >> 7) & 0x01)) - print('Default erase byte {:#x}'.format(rpl[3])) - print('Read to LPL/EPL {:#x}'.format(rpl[6])) - - else: - raise ValueError('Reply payload check code error') - elapsedtime = time.time()-starttime - print('Get module FW upgrade features time: %.2f s' %elapsedtime) - return startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength - - def get_module_FW_info(self): - try: - self.cdb - except: - self.get_CDB_api() - # get fw info (CMD 0100h) - starttime = time.time() - print('\nGet module FW info') - rpllen, rpl_chkcode, rpl = self.cdb.cmd0100h() - if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: - # Regiter 9Fh:136 - fwStatus = rpl[0] - # Registers 9Fh:138,139; 140,141 - print('Image A Version: %d.%d; BuildNum: %d' %(rpl[2], rpl[3], ((rpl[4]<< 8) | rpl[5]))) - # Registers 9Fh:174,175; 176.177 - print('Image B Version: %d.%d; BuildNum: %d' %(rpl[38], rpl[39], ((rpl[40]<< 8) | rpl[41]))) - - ImageARunning = (fwStatus & 0x01) # bit 0 - image A is running - ImageACommitted = ((fwStatus >> 1) & 0x01) # bit 1 - image A is committed - ImageBRunning = ((fwStatus >> 4) & 0x01) # bit 4 - image B is running - ImageBCommitted = ((fwStatus >> 5) & 0x01) # bit 5 - image B is committed - - if ImageARunning == 1: - RunningImage = 'A' - elif ImageBRunning == 1: - RunningImage = 'B' - if ImageACommitted == 1: - CommittedImage = 'A' - elif ImageBCommitted == 1: - CommittedImage = 'B' - print('Running Image: %s; Committed Image: %s' %(RunningImage, CommittedImage)) - else: - raise ValueError('Reply payload check code error') - elapsedtime = time.time()-starttime - print('Get module FW info time: %.2f s' %elapsedtime) - - def module_FW_run(self): - try: - self.cdb - except: - self.get_CDB_api() - # run module FW (CMD 0109h) - starttime = time.time() - _, FW_run_status, _ = self.cdb.cmd0109h() - if FW_run_status == 1: - print('Module FW run: Success') - else: - self.cdb.cmd0102h() - print('Module FW run: Fail') - elapsedtime = time.time()-starttime - print('Module FW run time: %.2f s\n' %elapsedtime) - - def module_FW_commit(self): - try: - self.cdb - except: - self.get_CDB_api() - # commit module FW (CMD 010Ah) - starttime = time.time() - _, FW_run_status, _ = self.cdb.cmd010Ah() - if FW_commit_status == 1: - print('Module FW commit: Success') - else: - self.cdb.cmd0102h() - print('Module FW commit: Fail') - elapsedtime = time.time()-starttime - print('Module FW commit time: %.2f s\n' %elapsedtime) - - def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath): - try: - self.cdb - except: - self.get_CDB_api() - # start fw download (CMD 0101h) - starttime = time.time() - f = open(imagepath, 'rb') - f.seek(0, 2) - imagesize = f.tell() - f.seek(0, 0) - startdata = f.read(startLPLsize) - print('\nStart FW downloading') - print("startLPLsize is %d" %startLPLsize) - FW_start_status = self.cdb.cmd0101h(startLPLsize, bytearray(startdata), imagesize) - if FW_start_status == 1: - print('Start module FW download: Success') - else: - print('Start module FW download: Fail') - self.cdb.cmd0102h() - raise ValueError('FW_start_status %d' %FW_start_status) - elapsedtime = time.time()-starttime - print('Start module FW download time: %.2f s' %elapsedtime) - - # start periodically writing (CMD 0103h or 0104h) - assert maxblocksize == 2048 or lplonly_flag - if lplonly_flag: - BLOCK_SIZE = 116 - else: - BLOCK_SIZE = maxblocksize - address = 0 - remaining = imagesize - startLPLsize - print("\nTotal size: {} start bytes: {} remaining: {}".format(imagesize, startLPLsize, remaining)) - while remaining > 0: - if remaining < BLOCK_SIZE: - count = remaining - else: - count = BLOCK_SIZE - data = f.read(count) - progress = (imagesize - remaining) * 100.0 / imagesize - if lplonly_flag: - self.cdb.cmd0103h(address, data) - else: - self.cdb.cmd0104h(address, data, autopaging_flag, writelength) - elapsedtime = time.time()-starttime - print('Address: {:#08x}; Count: {}; Progress: {:.2f}%; Time: {:.2f}s'.format(address, count, progress, elapsedtime)) - address += count - remaining -= count - elapsedtime = time.time()-starttime - print('Total module FW download time: %.2f s' %elapsedtime) - - # complete FW download (CMD 0107h) - FW_complete_status = self.cdb.cmd0107h() - if FW_complete_status == 1: - print('Module FW download complete: Success') - else: - print('Module FW download complete: Fail') - elapsedtime = time.time()-elapsedtime-starttime - print('Complete module FW download time: %.2f s\n' %elapsedtime) - - def module_firmware_upgrade(self, imagepath): - self.get_module_FW_info() - startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength = self.get_module_FW_upgrade_feature() - self.module_FW_download(startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath) - self.module_FW_run() - time.sleep(60) - self.module_FW_commit() - self.get_module_FW_info() \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index 2d1bd8246..f160d4362 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -6,6 +6,9 @@ from ...fields import consts from ..xcvr_api import XcvrApi +from .cmisCDB import CmisCdbApi +from .cmisVDM import CmisVdmApi +from .c_cmis import CCmisApi import time BYTELENGTH = 8 class CmisApi(XcvrApi): @@ -14,6 +17,1088 @@ class CmisApi(XcvrApi): def __init__(self, xcvr_eeprom): super(CmisApi, self).__init__(xcvr_eeprom) + # Transceiver Information + def get_model(self): + ''' + This function returns the part number of the module + ''' + return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD) + + def get_vendor_rev(self): + ''' + This function returns the revision level for part number provided by vendor + ''' + return self.xcvr_eeprom.read(consts.VENDOR_REV) + + def get_vendor_serial(self): + ''' + This function returns the serial number of the module + ''' + return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO) + + def get_vendor_name(self): + ''' + This function returns the vendor name of the module + ''' + return self.xcvr_eeprom.read(consts.VENDOR_NAME_FIELD) + + def get_module_type(self): + ''' + This function returns the SFF8024Identifier (module type / form-factor). Table 4-1 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.ID_FIELD) + + def get_vendor_OUI(self): + ''' + This function returns the vendor IEEE company ID + ''' + return self.xcvr_eeprom.read(consts.VENDOR_OUI_FIELD) + + def get_vendor_date(self): + ''' + This function returns the module manufacture date. It returns YYMMDDXX. XX is the lot code. + ''' + return self.xcvr_eeprom.read(consts.VENDOR_DATE) + + def get_connector_type(self): + ''' + This function returns module connector. Table 4-3 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.CONNECTOR_TYPE) + + def get_module_media_type(self): + ''' + This function returns module media type: MMF, SMF, Passive Copper Cable, Active Cable Assembly or Base-T. + ''' + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_TYPE) + + def get_host_electrical_interface(self): + ''' + This function returns module host electrical interface. Table 4-5 in SFF-8024 Rev4.6 + ''' + return self.xcvr_eeprom.read(consts.HOST_ELECTRICAL_INTERFACE) + + def get_module_media_interface(self): + ''' + This function returns module media electrical interface. Table 4-6 ~ 4-10 in SFF-8024 Rev4.6 + ''' + media_type = self.get_module_media_type() + if media_type == 'Multimode Fiber (MMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM) + elif media_type == 'Single Mode Fiber (SMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_SM) + elif media_type == 'Passive Copper Cable': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER) + elif media_type == 'Active Cable Assembly': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE) + elif media_type == 'BASE-T': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_BASE_T) + else: + return 'Unknown media interface' + + def get_host_lane_count(self): + ''' + This function returns number of host lanes + ''' + lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) + return (lane_count >> 4) & 0xf + + def get_media_lane_count(self): + ''' + This function returns number of media lanes + ''' + lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) + return (lane_count) & 0xf + + def get_host_lane_assignment_option(self): + ''' + This function returns the host lane that the application begins on + ''' + return self.xcvr_eeprom.read(consts.HOST_LANE_ASSIGNMENT_OPTION) + + def get_media_lane_assignment_option(self): + ''' + This function returns the media lane that the application is allowed to begin on + ''' + return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION) + + def get_active_apsel_hostlane(self): + ''' + This function returns the application select code that each host lane has + ''' + apsel_dict = dict() + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_1) + apsel_dict['hostlane1'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_2) + apsel_dict['hostlane2'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_3) + apsel_dict['hostlane3'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_4) + apsel_dict['hostlane4'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_5) + apsel_dict['hostlane5'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_6) + apsel_dict['hostlane6'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_7) + apsel_dict['hostlane7'] = (result >> 4) & 0xf + result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_8) + apsel_dict['hostlane8'] = (result >> 4) & 0xf + return apsel_dict + + def get_media_interface_technology(self): + ''' + This function returns the media lane technology + ''' + return self.xcvr_eeprom.read(consts.MEDIA_INTERFACE_TECH) + + def get_module_hardware_revision(self): + ''' + This function returns the module hardware revision + ''' + hw_major_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) + hw_minor_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) + hw_rev = [str(num) for num in [hw_major_rev, hw_minor_rev]] + return '.'.join(hw_rev) + + def get_cmis_rev(self): + ''' + This function returns the CMIS version the module complies to + ''' + cmis = self.xcvr_eeprom.read(consts.CMIS_REVISION) + cmis_major = (cmis >> 4) & 0xf + cmis_minor = (cmis) & 0xf + cmis_rev = [str(num) for num in [cmis_major, cmis_minor]] + return '.'.join(cmis_rev) + + def get_module_active_firmware(self): + ''' + This function returns the active firmware version + ''' + active_fw_major = self.xcvr_eeprom.read(consts.ACTIVE_FW_MAJOR_REV) + active_fw_minor = self.xcvr_eeprom.read(consts.ACTIVE_FW_MINOR_REV) + active_fw = [str(num) for num in [active_fw_major, active_fw_minor]] + return '.'.join(active_fw) + + def get_module_inactive_firmware(self): + ''' + This function returns the inactive firmware version + ''' + inactive_fw_major = self.xcvr_eeprom.read(consts.INACTIVE_FW_MAJOR_REV) + inactive_fw_minor = self.xcvr_eeprom.read(consts.INACTIVE_FW_MINOR_REV) + inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]] + return '.'.join(inactive_fw) + + # Transceiver DOM + def get_module_temperature(self): + ''' + This function returns the module case temperature and its thresholds. Unit in deg C + ''' + case_temp_dict = dict() + case_temp = self.xcvr_eeprom.read(consts.CASE_TEMP) + case_temp_high_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_ALARM) + case_temp_low_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_ALARM) + case_temp_high_warn = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_WARN) + case_temp_low_warn = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_WARN) + case_temp_dict = {'monitor value': case_temp, + 'high alarm': case_temp_high_alarm, + 'low alarm': case_temp_low_alarm, + 'high warn': case_temp_high_warn, + 'low warn': case_temp_low_warn} + return case_temp_dict + + def get_module_voltage(self): + ''' + This function returns the monitored value of the 3.3-V supply voltage and its thresholds. + Unit in V + ''' + voltage_dict = dict() + voltage = self.xcvr_eeprom.read(consts.VOLTAGE) + voltage_high_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_ALARM) + voltage_low_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_ALARM) + voltage_high_warn = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_WARN) + voltage_low_warn = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_WARN) + voltage_dict = {'monitor value': voltage, + 'high alarm': voltage_high_alarm, + 'low alarm': voltage_low_alarm, + 'high warn': voltage_high_warn, + 'low warn': voltage_low_warn} + return voltage_dict + + def get_txpower(self): + ''' + This function returns the TX output power. Unit in mW + ''' + tx_power_dict = dict() + tx_power = self.xcvr_eeprom.read(consts.TX_POW) + tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM) + tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM) + tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN) + tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN) + tx_power_dict = {'monitor value lane1': tx_power, + 'high alarm': tx_power_high_alarm, + 'low alarm': tx_power_low_alarm, + 'high warn': tx_power_high_warn, + 'low warn': tx_power_low_warn} + return tx_power_dict + + def get_rxpower(self): + ''' + This function returns the RX input power. Unit in mW + ''' + rx_power_dict = dict() + rx_power = self.xcvr_eeprom.read(consts.RX_POW) + rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM) + rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM) + rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN) + rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN) + rx_power_dict = {'monitor value lane1': rx_power, + 'high alarm': rx_power_high_alarm, + 'low alarm': rx_power_low_alarm, + 'high warn': rx_power_high_warn, + 'low warn': rx_power_low_warn} + return rx_power_dict + + def get_txbias(self): + ''' + This function returns the TX laser bias current. Unit in mA + ''' + tx_bias_current_dict = dict() + tx_bias_current = self.xcvr_eeprom.read(consts.TX_BIAS) + tx_bias_current_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_ALARM) + tx_bias_current_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_ALARM) + tx_bias_current_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_WARN) + tx_bias_current_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_WARN) + tx_bias_current_dict = {'monitor value lane1': tx_bias_current, + 'high alarm': tx_bias_current_high_alarm, + 'low alarm': tx_bias_current_low_alarm, + 'high warn': tx_bias_current_high_warn, + 'low warn': tx_bias_current_low_warn} + return tx_bias_current_dict + + def get_freq_grid(self): + ''' + This function returns the configured frequency grid. Unit in GHz + ''' + freq_grid = self.xcvr_eeprom.read(consts.GRID_SPACING) >> 4 + if freq_grid == 7: + return 75 + elif freq_grid == 6: + return 33 + elif freq_grid == 5: + return 100 + elif freq_grid == 4: + return 50 + elif freq_grid == 3: + return 25 + elif freq_grid == 2: + return 12.5 + elif freq_grid == 1: + return 6.25 + elif freq_grid == 0: + return 3.125 + + def get_laser_config_freq(self): + ''' + This function returns the configured laser frequency. Unit in GHz + ''' + freq_grid = self.get_freq_grid() + channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) + if freq_grid == 75: + config_freq = 193100 + channel * freq_grid/3 + else: + config_freq = 193100 + channel * freq_grid + return config_freq + + def get_current_laser_freq(self): + ''' + This function returns the monitored laser frequency. Unit in GHz + ''' + return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ)/1000 + + def get_TX_config_power(self): + ''' + This function returns the configured TX output power. Unit in dBm + ''' + return self.xcvr_eeprom.read(consts.TX_CONFIG_POWER) + + def get_media_output_loopback(self): + ''' + This function returns the media output loopback status + ''' + result = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) + return result == 1 + + def get_media_input_loopback(self): + ''' + This function returns the media input loopback status + ''' + result = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) + return result == 1 + + def get_host_output_loopback(self): + ''' + This function returns the host output loopback status + ''' + result = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) + loopback_status = [] + for bitpos in range(BYTELENGTH): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status + + def get_host_input_loopback(self): + ''' + This function returns the host input loopback status + ''' + result = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) + loopback_status = [] + for bitpos in range(BYTELENGTH): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status + + def get_aux_mon_type(self): + ''' + This function returns the aux monitor types + ''' + result = self.xcvr_eeprom.read(consts.AUX_MON_TYPE) + aux1_mon_type = result & 0x1 + aux2_mon_type = (result >> 1) & 0x1 + aux3_mon_type = (result >> 2) & 0x1 + return aux1_mon_type, aux2_mon_type, aux3_mon_type + + def get_laser_temperature(self): + ''' + This function returns the laser temperature monitor value + ''' + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + LASER_TEMP_SCALE = 256.0 + laser_temp_dict = dict() + if aux2_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE + laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEMP_SCALE + laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEMP_SCALE + laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEMP_SCALE + laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEMP_SCALE + elif aux2_mon_type == 1 and aux3_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX3_MON)/LASER_TEMP_SCALE + laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX3_HIGH_ALARM)/LASER_TEMP_SCALE + laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX3_LOW_ALARM)/LASER_TEMP_SCALE + laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX3_HIGH_WARN)/LASER_TEMP_SCALE + laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX3_LOW_WARN)/LASER_TEMP_SCALE + else: + return None + laser_temp_dict = {'monitor value': laser_temp, + 'high alarm': laser_temp_high_alarm, + 'low alarm': laser_temp_low_alarm, + 'high warn': laser_temp_high_warn, + 'low warn': laser_temp_low_warn} + return laser_temp_dict + + def get_laser_TEC_current(self): + ''' + This function returns the laser TEC current monitor value + ''' + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + LASER_TEC_CURRENT_SCALE = 32767.0 + laser_tec_current_dict = dict() + if aux1_mon_type == 1: + laser_tec_current = self.xcvr_eeprom.read(consts.AUX1_MON)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX1_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX1_LOW_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX1_HIGH_WARN)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX1_LOW_WARN)/LASER_TEC_CURRENT_SCALE + elif aux1_mon_type == 0 and aux2_mon_type == 1: + laser_tec_current = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEC_CURRENT_SCALE + else: + return None + laser_tec_current_dict = {'monitor value': laser_tec_current, + 'high alarm': laser_tec_current_high_alarm, + 'low alarm': laser_tec_current_low_alarm, + 'high warn': laser_tec_current_high_warn, + 'low warn': laser_tec_current_low_warn} + return laser_tec_current_dict + + def get_custom_field(self, signed = False, scale = 1.0): + ''' + This function returns the custom monitor field + ''' + result = self.xcvr_eeprom.read(consts.CUSTOM_MON) + if signed: + result -= 2**15 + result /= scale + return result + + + def get_VDM_api(self): + self.vdm = CmisVdmApi(self.xcvr_eeprom) + + def get_VDM(self): + ''' + This function returns all the VDM items, including real time monitor value, threholds and flags + ''' + try: + self.vdm + except: + self.get_VDM_api() + VDM = self.vdm.get_VDM_allpage() + return VDM + + def get_ccmis_api(self): + self.ccmis = CCmisApi(self.xcvr_eeprom) + + def get_PM(self): + + ''' + This function returns all the PMs. For more detailed info check get_PM_all in CCmisApi + ''' + try: + self.ccmis + except: + self.get_ccmis_api() + PM_dict = self.ccmis.get_PM_all() + return PM_dict + + + # Transceiver status + def get_module_state(self): + ''' + This function returns the module state + ''' + result = self.xcvr_eeprom.read(consts.MODULE_STATE) >> 1 + DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].MODULE_STATE + return DICT.get(result, "Unknown") + + def get_module_firmware_fault_state_changed(self): + ''' + This function returns datapath firmware fault state, module firmware fault state + and whether module state changed + ''' + result = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) + datapath_firmware_fault = bool((result >> 2) & 0x1) + module_firmware_fault = bool((result >> 1) & 0x1) + module_state_changed = bool(result & 0x1) + return datapath_firmware_fault, module_firmware_fault, module_state_changed + + def get_module_level_flag(self): + ''' + This function returns teh module level flags, including + - 3.3 V voltage supply flags + - Case temperature flags + - Aux 1 flags + - Aux 2 flags + - Aux 3 flags + - Custom field flags + ''' + module_flag_byte1 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE1) + module_flag_byte2 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE2) + module_flag_byte3 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE3) + + voltage_high_alarm_flag = bool((module_flag_byte1 >> 4) & 0x1) + voltage_low_alarm_flag = bool((module_flag_byte1 >> 5) & 0x1) + voltage_high_warn_flag = bool((module_flag_byte1 >> 6) & 0x1) + voltage_low_warn_flag = bool((module_flag_byte1 >> 7) & 0x1) + voltage_flags = {'voltage_high_alarm_flag': voltage_high_alarm_flag, + 'voltage_low_alarm_flag': voltage_low_alarm_flag, + 'voltage_high_warn_flag': voltage_high_warn_flag, + 'voltage_low_warn_flag': voltage_low_warn_flag} + + case_temp_high_alarm_flag = bool((module_flag_byte1 >> 0) & 0x1) + case_temp_low_alarm_flag = bool((module_flag_byte1 >> 1) & 0x1) + case_temp_high_warn_flag = bool((module_flag_byte1 >> 2) & 0x1) + case_temp_low_warn_flag = bool((module_flag_byte1 >> 3) & 0x1) + case_temp_flags = {'case_temp_high_alarm_flag': case_temp_high_alarm_flag, + 'case_temp_low_alarm_flag': case_temp_low_alarm_flag, + 'case_temp_high_warn_flag': case_temp_high_warn_flag, + 'case_temp_low_warn_flag': case_temp_low_warn_flag} + + aux2_high_alarm_flag = bool((module_flag_byte2 >> 4) & 0x1) + aux2_low_alarm_flag = bool((module_flag_byte2 >> 5) & 0x1) + aux2_high_warn_flag = bool((module_flag_byte2 >> 6) & 0x1) + aux2_low_warn_flag = bool((module_flag_byte2 >> 7) & 0x1) + aux2_flags = {'aux2_high_alarm_flag': aux2_high_alarm_flag, + 'aux2_low_alarm_flag': aux2_low_alarm_flag, + 'aux2_high_warn_flag': aux2_high_warn_flag, + 'aux2_low_warn_flag': aux2_low_warn_flag} + + aux1_high_alarm_flag = bool((module_flag_byte2 >> 0) & 0x1) + aux1_low_alarm_flag = bool((module_flag_byte2 >> 1) & 0x1) + aux1_high_warn_flag = bool((module_flag_byte2 >> 2) & 0x1) + aux1_low_warn_flag = bool((module_flag_byte2 >> 3) & 0x1) + aux1_flags = {'aux1_high_alarm_flag': aux1_high_alarm_flag, + 'aux1_low_alarm_flag': aux1_low_alarm_flag, + 'aux1_high_warn_flag': aux1_high_warn_flag, + 'aux1_low_warn_flag': aux1_low_warn_flag} + + custom_mon_high_alarm_flag = bool((module_flag_byte3 >> 4) & 0x1) + custom_mon_low_alarm_flag = bool((module_flag_byte3 >> 5) & 0x1) + custom_mon_high_warn_flag = bool((module_flag_byte3 >> 6) & 0x1) + custom_mon_low_warn_flag = bool((module_flag_byte3 >> 7) & 0x1) + custom_mon_flags = {'custom_mon_high_alarm_flag': custom_mon_high_alarm_flag, + 'custom_mon_low_alarm_flag': custom_mon_low_alarm_flag, + 'custom_mon_high_warn_flag': custom_mon_high_warn_flag, + 'custom_mon_low_warn_flag': custom_mon_low_warn_flag} + + aux3_high_alarm_flag = bool((module_flag_byte3 >> 0) & 0x1) + aux3_low_alarm_flag = bool((module_flag_byte3 >> 1) & 0x1) + aux3_high_warn_flag = bool((module_flag_byte3 >> 2) & 0x1) + aux3_low_warn_flag = bool((module_flag_byte3 >> 3) & 0x1) + aux3_flags = {'aux3_high_alarm_flag': aux3_high_alarm_flag, + 'aux3_low_alarm_flag': aux3_low_alarm_flag, + 'aux3_high_warn_flag': aux3_high_warn_flag, + 'aux3_low_warn_flag': aux3_low_warn_flag} + + module_flag = {'voltage_flags': voltage_flags, + 'case_temp_flags': case_temp_flags, + 'aux1_flags': aux1_flags, + 'aux2_flags': aux2_flags, + 'aux3_flags': aux3_flags, + 'custom_mon_flags': custom_mon_flags} + return module_flag + + def get_datapath_state(self): + ''' + This function returns the eight datapath states + ''' + result = self.xcvr_eeprom.read(consts.DATAPATH_STATE) + dp_lane7 = (result >> 0) & 0xf + dp_lane8 = (result >> 4) & 0xf + dp_lane5 = (result >> 8) & 0xf + dp_lane6 = (result >> 12) & 0xf + dp_lane3 = (result >> 16) & 0xf + dp_lane4 = (result >> 20) & 0xf + dp_lane1 = (result >> 24) & 0xf + dp_lane2 = (result >> 28) & 0xf + DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].DATAPATH_STATE + dp_state_dict = {'dp_lane1': DICT.get(dp_lane1, "Unknown"), + 'dp_lane2': DICT.get(dp_lane2, "Unknown"), + 'dp_lane3': DICT.get(dp_lane3, "Unknown"), + 'dp_lane4': DICT.get(dp_lane4, "Unknown"), + 'dp_lane5': DICT.get(dp_lane5, "Unknown"), + 'dp_lane6': DICT.get(dp_lane6, "Unknown"), + 'dp_lane7': DICT.get(dp_lane7, "Unknown"), + 'dp_lane8': DICT.get(dp_lane8, "Unknown") + } + return dp_state_dict + + def get_tx_output_status(self): + ''' + This function returns whether TX output signals are valid + ''' + result = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) + tx_output_status_dict = dict() + for bitpos in range(BYTELENGTH): + tx_output_status_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_output_status_dict + + def get_rx_output_status(self): + ''' + This function returns whether RX output signals are valid + ''' + result = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) + rx_output_status_dict = dict() + for bitpos in range(BYTELENGTH): + rx_output_status_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return rx_output_status_dict + + def get_tx_fault(self): + ''' + This function returns TX failure flag + ''' + result = self.xcvr_eeprom.read(consts.TX_FAULT_FLAG) + tx_fault_dict = dict() + for bitpos in range(BYTELENGTH): + tx_fault_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_fault_dict + + def get_tx_los(self): + ''' + This function returns TX LOS flag + ''' + result = self.xcvr_eeprom.read(consts.TX_LOS_FLAG) + tx_los_dict = dict() + for bitpos in range(BYTELENGTH): + tx_los_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_los_dict + + def get_tx_cdr_lol(self): + ''' + This function returns TX CDR LOL flag + ''' + result = self.xcvr_eeprom.read(consts.TX_CDR_LOL) + tx_lol_dict = dict() + for bitpos in range(BYTELENGTH): + tx_lol_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_lol_dict + + def get_tx_power_flag(self): + ''' + This function returns TX power out of range flag + ''' + tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM_FLAG) + tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM_FLAG) + tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN_FLAG) + tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN_FLAG) + tx_power_high_alarm_dict = dict() + tx_power_low_alarm_dict = dict() + tx_power_high_warn_dict = dict() + tx_power_low_warn_dict = dict() + for bitpos in range(BYTELENGTH): + tx_power_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_alarm >> bitpos) & 0x1) + tx_power_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_alarm >> bitpos) & 0x1) + tx_power_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_warn >> bitpos) & 0x1) + tx_power_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_warn >> bitpos) & 0x1) + + tx_power_flag_dict = {'tx_power_high_alarm': tx_power_high_alarm_dict, + 'tx_power_low_alarm': tx_power_low_alarm_dict, + 'tx_power_high_warn': tx_power_high_warn_dict, + 'tx_power_low_warn': tx_power_low_warn_dict,} + return tx_power_flag_dict + + def get_tx_bias_flag(self): + ''' + This function returns TX bias out of range flag + ''' + tx_bias_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_ALARM_FLAG) + tx_bias_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_ALARM_FLAG) + tx_bias_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_WARN_FLAG) + tx_bias_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_WARN_FLAG) + tx_bias_high_alarm_dict = dict() + tx_bias_low_alarm_dict = dict() + tx_bias_high_warn_dict = dict() + tx_bias_low_warn_dict = dict() + for bitpos in range(BYTELENGTH): + tx_bias_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_alarm >> bitpos) & 0x1) + tx_bias_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_alarm >> bitpos) & 0x1) + tx_bias_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_warn >> bitpos) & 0x1) + tx_bias_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_warn >> bitpos) & 0x1) + + tx_bias_flag_dict = {'tx_bias_high_alarm': tx_bias_high_alarm_dict, + 'tx_bias_low_alarm': tx_bias_low_alarm_dict, + 'tx_bias_high_warn': tx_bias_high_warn_dict, + 'tx_bias_low_warn': tx_bias_low_warn_dict,} + return tx_bias_flag_dict + + def get_rx_power_flag(self): + ''' + This function returns RX power out of range flag + ''' + rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM_FLAG) + rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM_FLAG) + rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN_FLAG) + rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN_FLAG) + rx_power_high_alarm_dict = dict() + rx_power_low_alarm_dict = dict() + rx_power_high_warn_dict = dict() + rx_power_low_warn_dict = dict() + for bitpos in range(BYTELENGTH): + rx_power_high_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_alarm >> bitpos) & 0x1) + rx_power_low_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_alarm >> bitpos) & 0x1) + rx_power_high_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_warn >> bitpos) & 0x1) + rx_power_low_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_warn >> bitpos) & 0x1) + + rx_power_flag_dict = {'rx_power_high_alarm': rx_power_high_alarm_dict, + 'rx_power_low_alarm': rx_power_low_alarm_dict, + 'rx_power_high_warn': rx_power_high_warn_dict, + 'rx_power_low_warn': rx_power_low_warn_dict,} + return rx_power_flag_dict + + def get_rx_los(self): + ''' + This function returns RX LOS flag + ''' + result = self.xcvr_eeprom.read(consts.RX_LOS_FLAG) + rx_los_dict = dict() + for bitpos in range(BYTELENGTH): + rx_los_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return rx_los_dict + + def get_rx_cdr_lol(self): + ''' + This function returns RX CDR LOL flag + ''' + result = self.xcvr_eeprom.read(consts.RX_CDR_LOL) + rx_lol_dict = dict() + for bitpos in range(BYTELENGTH): + rx_lol_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return rx_lol_dict + + def get_config_datapath_hostlane_status(self): + ''' + This function returns configuration command execution + / result status for the datapath of each host lane + ''' + result = self.xcvr_eeprom.read(consts.CONFIG_LANE_STATUS) + config_status_lane7 = (result >> 0) & 0xf + config_status_lane8 = (result >> 4) & 0xf + config_status_lane5 = (result >> 8) & 0xf + config_status_lane6 = (result >> 12) & 0xf + config_status_lane3 = (result >> 16) & 0xf + config_status_lane4 = (result >> 20) & 0xf + config_status_lane1 = (result >> 24) & 0xf + config_status_lane2 = (result >> 28) & 0xf + config_status_raw = [config_status_lane1, config_status_lane2, config_status_lane3, config_status_lane4, + config_status_lane5, config_status_lane6, config_status_lane7, config_status_lane8] + DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].CONFIG_STATUS + config_status_dict = {'config_DP_status_hostlane1': DICT.get(config_status_lane1, "Unknown"), + 'config_DP_status_hostlane2': DICT.get(config_status_lane2, "Unknown"), + 'config_DP_status_hostlane3': DICT.get(config_status_lane3, "Unknown"), + 'config_DP_status_hostlane4': DICT.get(config_status_lane4, "Unknown"), + 'config_DP_status_hostlane5': DICT.get(config_status_lane5, "Unknown"), + 'config_DP_status_hostlane6': DICT.get(config_status_lane6, "Unknown"), + 'config_DP_status_hostlane7': DICT.get(config_status_lane7, "Unknown"), + 'config_DP_status_hostlane8': DICT.get(config_status_lane8, "Unknown") + } + return config_status_dict + + def get_dpinit_pending(self): + ''' + This function returns datapath init pending status. + 0 means datapath init not pending. + 1 means datapath init pending. DPInit not yet executed after successful ApplyDPInit. + Hence the active control set content may deviate from the actual hardware config + ''' + result = self.xcvr_eeprom.read(consts.DPINIT_PENDING) + dpinit_pending_dict = dict() + for bitpos in range(BYTELENGTH): + dpinit_pending_dict['hostlane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return dpinit_pending_dict + + def get_tuning_in_progress(self): + ''' + This function returns tunning in progress status. + 0 means tuning not in progress + 1 means tuning in progress + ''' + return bool(self.xcvr_eeprom.read(consts.TUNING_IN_PROGRESS)) + + def get_wavelength_unlocked(self): + ''' + This function returns wavelength unlocked status. + 0 means wavelength locked + 1 means wavelength unlocked + ''' + return bool(self.xcvr_eeprom.read(consts.WAVELENGTH_UNLOCKED)) + + def get_laser_tuning_summary(self): + ''' + This function returns laser tuning status summary + ''' + result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) + laser_tuning_summary = [] + if (result >> 5) & 0x1: + laser_tuning_summary.append("TargetOutputPowerOOR") + if (result >> 4) & 0x1: + laser_tuning_summary.append("FineTuningOutOfRange") + if (result >> 3) & 0x1: + laser_tuning_summary.append("TuningNotAccepted") + if (result >> 2) & 0x1: + laser_tuning_summary.append("InvalidChannel") + if (result >> 1) & 0x1: + laser_tuning_summary.append("WavelengthUnlocked") + if (result >> 0) & 0x1: + laser_tuning_summary.append("TuningComplete") + return laser_tuning_summary + + def get_supported_freq_config(self): + ''' + This function returns the supported freq grid, low and high supported channel in 75GHz grid, + and low and high frequency supported in GHz. + allowed channel number bound in 75 GHz grid + allowed frequency bound in 75 GHz grid + ''' + grid_supported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) + low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) + hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) + low_freq_supported = 193100 + low_ch_num * 25 + high_freq_supported = 193100 + hi_ch_num * 25 + return grid_supported, low_ch_num, hi_ch_num, low_freq_supported, high_freq_supported + + def get_supported_power_config(self): + ''' + This function returns the supported TX power range + ''' + min_prog_tx_output_power = self.xcvr_eeprom.read(consts.MIN_PROG_OUTPUT_POWER) + max_prog_tx_output_power = self.xcvr_eeprom.read(consts.MAX_PROG_OUTPUT_POWER) + return min_prog_tx_output_power, max_prog_tx_output_power + + def reset_module(self, reset = False): + ''' + This function resets the module + ''' + if reset: + reset_control = reset << 3 + self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, reset_control) + + def set_low_power(self, AssertLowPower): + ''' + This function sets the module to low power state. + AssertLowPower being 0 means "set to high power" + AssertLowPower being 1 means "set to low power" + ''' + low_power_control = AssertLowPower << 6 + self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control) + + def set_laser_freq(self, freq): + ''' + This function sets the laser frequency. Unit in GHz + ZR application will not support fine tuning of the laser + Microsoft will only supports 75 GHz frequency grid + ''' + grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() + grid_supported_75GHz = (grid_supported >> 7) & 0x1 + assert grid_supported_75GHz + freq_grid = 0x70 + self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) + channel_number = int(round((freq - 193100)/25)) + assert channel_number % 3 == 0 + if channel_number > hi_ch_num or channel_number < low_ch_num: + raise ValueError('Provisioned frequency out of range. Max Freq: 196100; Min Freq: 191300 GHz.') + self.set_low_power(True) + time.sleep(5) + self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) + time.sleep(1) + self.set_low_power(False) + time.sleep(1) + + def set_TX_power(self, TX_power): + ''' + This function sets the TX output power. Unit in dBm + ''' + min_prog_tx_output_power, max_prog_tx_output_power = self.get_supported_power_config() + if TX_power > max_prog_tx_output_power or TX_power < min_prog_tx_output_power: + raise ValueError('Provisioned TX power out of range. Max: %.1f; Min: %.1f dBm.' + %(max_prog_tx_output_power, min_prog_tx_output_power)) + self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, TX_power) + time.sleep(1) + + def get_loopback_capability(self): + ''' + This function returns the module loopback capability as advertised + ''' + allowed_loopback_result = self.xcvr_eeprom.read(consts.LOOPBACK_CAPABILITY) + loopback_capability = dict() + loopback_capability['simultaneous_host_media_loopback_supported'] = bool((allowed_loopback_result >> 6) & 0x1) + loopback_capability['per_lane_media_loopback_supported'] = bool((allowed_loopback_result >> 5) & 0x1) + loopback_capability['per_lane_host_loopback_supported'] = bool((allowed_loopback_result >> 4) & 0x1) + loopback_capability['host_side_input_loopback_supported'] = bool((allowed_loopback_result >> 3) & 0x1) + loopback_capability['host_side_output_loopback_supported'] = bool((allowed_loopback_result >> 2) & 0x1) + loopback_capability['media_side_input_loopback_supported'] = bool((allowed_loopback_result >> 1) & 0x1) + loopback_capability['media_side_output_loopback_supported'] = bool((allowed_loopback_result >> 0) & 0x1) + return loopback_capability + + def set_loopback_mode(self, loopback_mode): + ''' + This function sets the module loopback mode. + Loopback mode has to be one of the five: + 1. "none" (default) + 2. "host-side-input" + 3. "host-side-output" + 4. "media-side-input" + 5. "media-side-output" + The function will look at 13h:128 to check advertized loopback capabilities. + ''' + loopback_capability = self.get_loopback_capability() + if loopback_mode == 'none': + self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0) + self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0) + elif loopback_mode == 'host-side-input': + assert loopback_capability['host_side_input_loopback_supported'] + self.xcvr_eeprom.write(consts.HOST_INPUT_LOOPBACK, 0xff) + elif loopback_mode == 'host-side-output': + assert loopback_capability['host_side_output_loopback_supported'] + self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0xff) + elif loopback_mode == 'media-side-input': + assert loopback_capability['media_side_input_loopback_supported'] + self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0x1) + elif loopback_mode == 'media-side-output': + assert loopback_capability['media_side_output_loopback_supported'] + self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0x1) + + + def get_CDB_api(self): + self.cdb = CmisCdbApi(self.xcvr_eeprom) + + def get_module_FW_upgrade_feature(self, verbose = False): + try: + self.cdb + except: + self.get_CDB_api() + # get fw upgrade features (CMD 0041h) + starttime = time.time() + autopaging_flag = bool((self.xcvr_eeprom.read(consts.CDB_SUPPORT) >> 4) & 0x1) + writelength = (self.xcvr_eeprom.read(consts.CDB_SEQ_WRITE_LENGTH_EXT) + 1) * 8 + print('Auto page support: %s' %autopaging_flag) + print('Max write length: %d' %writelength) + rpllen, rpl_chkcode, rpl = self.cdb.cmd0041h() + if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: + startLPLsize = rpl[2] + print('Start payload size %d' % startLPLsize) + maxblocksize = (rpl[4] + 1) * 8 + print('Max block size %d' % maxblocksize) + lplEplSupport = {0x00 : 'No write to LPL/EPL supported', + 0x01 : 'Write to LPL supported', + 0x10 : 'Write to EPL supported', + 0x11 : 'Write to LPL/EPL supported'} + print('{}'.format(lplEplSupport[rpl[5]])) + if rpl[5] == 1: + lplonly_flag = True + else: + lplonly_flag = False + print('Abort CMD102h supported %s' %bool(rpl[1] & 0x01)) + if verbose: + print('Copy CMD108h supported %s' %bool((rpl[1] >> 1) & 0x01)) + print('Skipping erased blocks supported %s' %bool((rpl[1] >> 2) & 0x01)) + print('Full image readback supported %s' %bool((rpl[1] >> 7) & 0x01)) + print('Default erase byte {:#x}'.format(rpl[3])) + print('Read to LPL/EPL {:#x}'.format(rpl[6])) + + else: + raise ValueError('Reply payload check code error') + elapsedtime = time.time()-starttime + print('Get module FW upgrade features time: %.2f s' %elapsedtime) + return startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength + + def get_module_FW_info(self): + try: + self.cdb + except: + self.get_CDB_api() + # get fw info (CMD 0100h) + starttime = time.time() + print('\nGet module FW info') + rpllen, rpl_chkcode, rpl = self.cdb.cmd0100h() + if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: + # Regiter 9Fh:136 + fwStatus = rpl[0] + # Registers 9Fh:138,139; 140,141 + print('Image A Version: %d.%d; BuildNum: %d' %(rpl[2], rpl[3], ((rpl[4]<< 8) | rpl[5]))) + # Registers 9Fh:174,175; 176.177 + print('Image B Version: %d.%d; BuildNum: %d' %(rpl[38], rpl[39], ((rpl[40]<< 8) | rpl[41]))) + + ImageARunning = (fwStatus & 0x01) # bit 0 - image A is running + ImageACommitted = ((fwStatus >> 1) & 0x01) # bit 1 - image A is committed + ImageBRunning = ((fwStatus >> 4) & 0x01) # bit 4 - image B is running + ImageBCommitted = ((fwStatus >> 5) & 0x01) # bit 5 - image B is committed + + if ImageARunning == 1: + RunningImage = 'A' + elif ImageBRunning == 1: + RunningImage = 'B' + if ImageACommitted == 1: + CommittedImage = 'A' + elif ImageBCommitted == 1: + CommittedImage = 'B' + print('Running Image: %s; Committed Image: %s' %(RunningImage, CommittedImage)) + else: + raise ValueError('Reply payload check code error') + elapsedtime = time.time()-starttime + print('Get module FW info time: %.2f s' %elapsedtime) + + def module_FW_run(self): + try: + self.cdb + except: + self.get_CDB_api() + # run module FW (CMD 0109h) + starttime = time.time() + _, FW_run_status, _ = self.cdb.cmd0109h() + if FW_run_status == 1: + print('Module FW run: Success') + else: + self.cdb.cmd0102h() + print('Module FW run: Fail') + elapsedtime = time.time()-starttime + print('Module FW run time: %.2f s\n' %elapsedtime) + + def module_FW_commit(self): + try: + self.cdb + except: + self.get_CDB_api() + # commit module FW (CMD 010Ah) + starttime = time.time() + _, FW_run_status, _ = self.cdb.cmd010Ah() + if FW_commit_status == 1: + print('Module FW commit: Success') + else: + self.cdb.cmd0102h() + print('Module FW commit: Fail') + elapsedtime = time.time()-starttime + print('Module FW commit time: %.2f s\n' %elapsedtime) + + def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath): + try: + self.cdb + except: + self.get_CDB_api() + # start fw download (CMD 0101h) + starttime = time.time() + f = open(imagepath, 'rb') + f.seek(0, 2) + imagesize = f.tell() + f.seek(0, 0) + startdata = f.read(startLPLsize) + print('\nStart FW downloading') + print("startLPLsize is %d" %startLPLsize) + FW_start_status = self.cdb.cmd0101h(startLPLsize, bytearray(startdata), imagesize) + if FW_start_status == 1: + print('Start module FW download: Success') + else: + print('Start module FW download: Fail') + self.cdb.cmd0102h() + raise ValueError('FW_start_status %d' %FW_start_status) + elapsedtime = time.time()-starttime + print('Start module FW download time: %.2f s' %elapsedtime) + + # start periodically writing (CMD 0103h or 0104h) + assert maxblocksize == 2048 or lplonly_flag + if lplonly_flag: + BLOCK_SIZE = 116 + else: + BLOCK_SIZE = maxblocksize + address = 0 + remaining = imagesize - startLPLsize + print("\nTotal size: {} start bytes: {} remaining: {}".format(imagesize, startLPLsize, remaining)) + while remaining > 0: + if remaining < BLOCK_SIZE: + count = remaining + else: + count = BLOCK_SIZE + data = f.read(count) + progress = (imagesize - remaining) * 100.0 / imagesize + if lplonly_flag: + self.cdb.cmd0103h(address, data) + else: + self.cdb.cmd0104h(address, data, autopaging_flag, writelength) + elapsedtime = time.time()-starttime + print('Address: {:#08x}; Count: {}; Progress: {:.2f}%; Time: {:.2f}s'.format(address, count, progress, elapsedtime)) + address += count + remaining -= count + elapsedtime = time.time()-starttime + print('Total module FW download time: %.2f s' %elapsedtime) + + # complete FW download (CMD 0107h) + FW_complete_status = self.cdb.cmd0107h() + if FW_complete_status == 1: + print('Module FW download complete: Success') + else: + print('Module FW download complete: Fail') + elapsedtime = time.time()-elapsedtime-starttime + print('Complete module FW download time: %.2f s\n' %elapsedtime) + + def module_firmware_upgrade(self, imagepath): + self.get_module_FW_info() + startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength = self.get_module_FW_upgrade_feature() + self.module_FW_download(startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath) + self.module_FW_run() + time.sleep(60) + self.module_FW_commit() + self.get_module_FW_info() # TODO: other XcvrApi methods diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py index e02ab97b8..c6a9bcbae 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py @@ -7,6 +7,7 @@ PAGE_OFFSET = 128 THRSH_SPACING = 8 VDM_SIZE = 2 +VDM_FLAG_PAGE = 0x2c class CmisVdmApi(XcvrApi): def __init__(self, xcvr_eeprom): @@ -18,10 +19,11 @@ def get_F16(self, value): result = mantissa*10**(scale_exponent-24) return result - def get_VDM_page(self, page): + def get_VDM_page(self, page, VDM_flag_page): if page not in [0x20, 0x21, 0x22, 0x23]: raise ValueError('Page not in VDM Descriptor range!') VDM_descriptor = self.xcvr_eeprom.read_flexible(page * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) + # Odd Adress VDM observable type ID, real-time monitored value in Page + 4 VDM_typeID = VDM_descriptor[1::2] # Even Address @@ -32,11 +34,12 @@ def get_VDM_page(self, page): VDM_valuePage = page + 4 VDM_thrshPage = page + 8 VDM_Page_data = {} + VDM_TYPE_DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].VDM_TYPE for index, typeID in enumerate(VDM_typeID): - if typeID not in self.xcvr_eeprom.mem_map.codes['cmis_code'].VDM_TYPE: + if typeID not in VDM_TYPE_DICT: continue else: - vdm_info_dict = self.xcvr_eeprom.mem_map.codes['cmis_code'].VDM_TYPE[typeID] + vdm_info_dict = VDM_TYPE_DICT[typeID] thrshID = VDM_thresholdID[index] vdm_type = vdm_info_dict[0] vdm_format = vdm_info_dict[1] @@ -80,13 +83,25 @@ def get_VDM_page(self, page): else: continue + vdm_flag_offset = 32 * (page - 0x20) + index//2 + bit_offset = 4*(index%2) + vdm_high_alarm_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset)) & 0x1) + vdm_low_alarm_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset+1)) & 0x1) + vdm_high_warn_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset+2)) & 0x1) + vdm_low_warn_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset+3)) & 0x1) + if vdm_type not in VDM_Page_data: VDM_Page_data[vdm_type] = { - VDM_lane[index]+1: [vdm_value, - vdm_thrsh_high_alarm, - vdm_thrsh_low_alarm, - vdm_thrsh_high_warn, - vdm_thrsh_low_warn] + VDM_lane[index]+1: [ + vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn, + vdm_high_alarm_flag, + vdm_low_alarm_flag, + vdm_high_warn_flag, + vdm_low_warn_flag] } else: @@ -95,8 +110,11 @@ def get_VDM_page(self, page): vdm_thrsh_high_alarm, vdm_thrsh_low_alarm, vdm_thrsh_high_warn, - vdm_thrsh_low_warn - ] + vdm_thrsh_low_warn, + vdm_high_alarm_flag, + vdm_low_alarm_flag, + vdm_high_warn_flag, + vdm_low_warn_flag] return VDM_Page_data def get_VDM_allpage(self): @@ -107,7 +125,8 @@ def get_VDM_allpage(self): time.sleep(5) self.xcvr_eeprom.write(consts.VDM_CONTROL, 0) time.sleep(1) + VDM_flag_page = self.xcvr_eeprom.read_flexible(VDM_FLAG_PAGE * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) for page in range(VDM_START_PAGE, VDM_START_PAGE + vdm_page_supported_raw + 1): - VDM_current_page = self.get_VDM_page(page) + VDM_current_page = self.get_VDM_page(page, VDM_flag_page) VDM.update(VDM_current_page) return VDM \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py b/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py index fc83895bf..85abf64d6 100644 --- a/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py +++ b/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py @@ -9,7 +9,7 @@ # TODO: remove the following imports from .codes.public.sff8024 import Sff8024 from .codes.public.cmis_code import CmisCode -from .api.public.c_cmis import CCmisApi +from .api.public.cmis import CmisApi from .mem_maps.public.cmis import CmisMemMap class XcvrApiFactory(object): @@ -26,4 +26,4 @@ def create_xcvr_api(self): codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} mem_map = CmisMemMap(codes) xcvr_eeprom = XcvrEeprom(self.reader, self.writer, mem_map) - return CCmisApi(xcvr_eeprom) + return CmisApi(xcvr_eeprom) diff --git a/tests/sonic_xcvr/test_ccmis.py b/tests/sonic_xcvr/test_ccmis.py index 40f3ea2bd..c4d40fa22 100644 --- a/tests/sonic_xcvr/test_ccmis.py +++ b/tests/sonic_xcvr/test_ccmis.py @@ -7,965 +7,6 @@ from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode class TestCCmis(object): - - def mock_ccmis_api(self): - codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} - mem_map = CmisMemMap(codes) - reader = MagicMock(return_value=None) - writer = MagicMock() - xcvr_eeprom = XcvrEeprom(reader, writer, mem_map) - api = CCmisApi(xcvr_eeprom) - return api - - @pytest.mark.parametrize("mock_response, expected", [ - ("1234567890", "1234567890"), - ("ABCD", "ABCD") - ]) - def test_get_model(self, mock_response, expected): - """ - Verify all api access valid fields - """ - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_model() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ("0.0", "0.0"), - ("1.2", "1.2") - ]) - def test_get_vendor_rev(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_vendor_rev() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ("100000000", "100000000") - ]) - def test_get_vendor_serial(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_vendor_serial() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ("1a-1a-1a", "1a-1a-1a") - ]) - def test_get_vendor_name(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_vendor_name() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ("ABCDE", "ABCDE") - ]) - def test_get_vendor_OUI(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_vendor_OUI() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ("21010100", "21010100") - ]) - def test_get_vendor_date(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_vendor_date() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ("LC", "LC") - ]) - def test_get_connector_type(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_connector_type() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ("Single Mode Fiber (SMF)", "Single Mode Fiber (SMF)") - ]) - def test_get_module_media_type(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_module_media_type() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ("400GAUI-8 C2M (Annex 120E)", "400GAUI-8 C2M (Annex 120E)") - ]) - def test_get_host_electrical_interface(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_host_electrical_interface() - assert result == expected - - @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - ("Single Mode Fiber (SMF)", "400ZR", "400ZR") - ]) - def test_get_module_media_interface(self, mock_response1, mock_response2, expected): - api = self.mock_ccmis_api() - api.get_module_media_type = MagicMock() - api.get_module_media_type.return_value = mock_response1 - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response2 - result = api.get_module_media_interface() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x81, 8) - ]) - def test_get_host_lane_count(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_host_lane_count() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x81, 1) - ]) - def test_get_media_lane_count(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_media_lane_count() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (1, 1) - ]) - def test_get_host_lane_assignment_option(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_host_lane_assignment_option() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (1, 1) - ]) - def test_get_media_lane_assignment_option(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_media_lane_assignment_option() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10], - {'hostlane1': 1, 'hostlane2': 1, 'hostlane3': 1, 'hostlane4': 1, - 'hostlane5': 1, 'hostlane6': 1, 'hostlane7': 1, 'hostlane8': 1}) - ]) - def test_get_active_apsel_hostlane(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_active_apsel_hostlane() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ('C-band tunable laser', 'C-band tunable laser') - ]) - def test_get_media_interface_technology(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_media_interface_technology() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([0, 1], '0.1') - ]) - def test_get_module_hardware_revision(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_module_hardware_revision() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x50, '5.0') - ]) - def test_get_cmis_rev(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_cmis_rev() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([0, 1], '0.1') - ]) - def test_get_module_active_firmware(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_module_active_firmware() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([0, 1], '0.1') - ]) - def test_get_module_inactive_firmware(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_module_inactive_firmware() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([45, 80, -10, 75, 0], - {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0}) - ]) - def test_get_module_temperature(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_module_temperature() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([3.3, 3.5, 3.1, 3.45, 3.15], - {'monitor value': 3.3, 'high alarm': 3.5, 'low alarm': 3.1, 'high warn': 3.45, 'low warn': 3.15}) - ]) - def test_get_module_voltage(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_module_voltage() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([-10, -2, -15, -4, -14], - {'monitor value lane1': -10, 'high alarm': -2, 'low alarm': -15, 'high warn': -4, 'low warn': -14}) - ]) - def test_get_txpower(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_txpower() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([-10, -2, -15, -4, -14], - {'monitor value lane1': -10, 'high alarm': -2, 'low alarm': -15, 'high warn': -4, 'low warn': -14}) - ]) - def test_get_rxpower(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_rxpower() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([50, 70, 0, 68, 0], - {'monitor value lane1': 50, 'high alarm': 70, 'low alarm': 0, 'high warn': 68, 'low warn': 0}) - ]) - def test_get_txbias(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_txbias() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x70, 75) - ]) - def test_get_freq_grid(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_freq_grid() - assert result == expected - - @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - (75, 12, 193400), - (75, -30, 192350), - ]) - def test_get_laser_config_freq(self, mock_response1, mock_response2, expected): - api = self.mock_ccmis_api() - api.get_freq_grid = MagicMock() - api.get_freq_grid.return_value = mock_response1 - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response2 - result = api.get_laser_config_freq() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (193100000, 193100) - ]) - def test_get_current_laser_freq(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_current_laser_freq() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (-10, -10) - ]) - def test_get_TX_config_power(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_TX_config_power() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0, False), - (1, True), - ]) - def test_get_media_output_loopback(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_media_output_loopback() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0, False), - (1, True), - ]) - def test_get_media_input_loopback(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_media_input_loopback() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0, [False,False,False,False,False,False,False,False]), - ]) - def test_get_host_output_loopback(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_host_output_loopback() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0, [False,False,False,False,False,False,False,False]), - ]) - def test_get_host_input_loopback(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_host_input_loopback() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0xc2, (0,1,0)), - ]) - def test_get_aux_mon_type(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_aux_mon_type() - assert result == expected - - @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - ([0,1,0], - [11520, 20480, -2560, 19200, 0], - {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0} - ) - ]) - def test_get_laser_temperature(self, mock_response1, mock_response2, expected): - api = self.mock_ccmis_api() - api.get_aux_mon_type = MagicMock() - api.get_aux_mon_type.return_value = mock_response1 - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response2 - result = api.get_laser_temperature() - assert result == expected - - @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - ([0,1,0], - [32767, 65534, 0, 49150.5, 0], - {'monitor value': 1, 'high alarm': 2, 'low alarm': 0, 'high warn': 1.5, 'low warn': 0} - ) - ]) - def test_get_laser_TEC_current(self, mock_response1, mock_response2, expected): - api = self.mock_ccmis_api() - api.get_aux_mon_type = MagicMock() - api.get_aux_mon_type.return_value = mock_response1 - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response2 - result = api.get_laser_TEC_current() - assert result == expected - - @pytest.mark.parametrize("input_param, mock_response, expected", [ - ([False, 1.0], 100, 100.0) - ]) - def test_get_custom_field(self, input_param, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_custom_field(*input_param) - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([100000000, 1000000, 100000, 800, 1200, # preFEC_BER - 10000, 100, 0, 0, 0, # uncorr_frame - 1400, 1300, 1500, # CD - 7.0, 5.5, 9.2, # DGD - 40, 20, 60, # SOPMD - 1.0, 0.8, 1.2, # PDL - 28, 26, 30, # OSNR - 17, 15, 18, # ESNR - 200, 150, 250, # CFO - 15, 13, 18, # EVM - -10, -9.5, -10.5, # TX power - -8, -7, -9, # RX total power - -8, -7, -9, # RX channel power - 5, 3, 8, # SOPROc - 0, 0, 0, # MER - ], - {'preFEC_BER_cur': 0.001, 'preFEC_BER_min': 0.0008, 'preFEC_BER_max': 0.0012, - 'preFEC_uncorr_frame_ratio_cur': 0, 'preFEC_uncorr_frame_ratio_min': 0, 'preFEC_uncorr_frame_ratio_max': 0, - 'rx_cd_avg': 1400, 'rx_cd_min': 1300, 'rx_cd_max': 1500, - 'rx_dgd_avg': 7.0, 'rx_dgd_min': 5.5, 'rx_dgd_max': 9.2, - 'rx_sopmd_avg': 40, 'rx_sopmd_min': 20, 'rx_sopmd_max': 60, - 'rx_pdl_avg': 1.0, 'rx_pdl_min': 0.8, 'rx_pdl_max': 1.2, - 'rx_osnr_avg': 28, 'rx_osnr_min': 26, 'rx_osnr_max': 30, - 'rx_esnr_avg': 17, 'rx_esnr_min': 15, 'rx_esnr_max': 18, - 'rx_cfo_avg': 200, 'rx_cfo_min': 150, 'rx_cfo_max': 250, - 'rx_evm_avg': 15, 'rx_evm_min': 13, 'rx_evm_max': 18, - 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, - 'rx_power_avg': -8, 'rx_power_min': -7, 'rx_power_max': -9, - 'rx_sigpwr_avg': -8, 'rx_sigpwr_min': -7, 'rx_sigpwr_max': -9, - 'rx_soproc_avg': 5, 'rx_soproc_min': 3, 'rx_soproc_max': 8, - 'rx_mer_avg': 0, 'rx_mer_min': 0, 'rx_mer_max': 0 - } - ) - ]) - def test_get_PM(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_PM() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (6, "ModuleReady") - ]) - def test_get_module_state(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_module_state() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (65, (False, False, True)) - ]) - def test_get_module_firmware_fault_state_changed(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_module_firmware_fault_state_changed() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([0, 0, 0], - { - 'voltage_flags': { - 'voltage_high_alarm_flag': False, - 'voltage_low_alarm_flag': False, - 'voltage_high_warn_flag': False, - 'voltage_low_warn_flag': False - }, - 'case_temp_flags': { - 'case_temp_high_alarm_flag': False, - 'case_temp_low_alarm_flag': False, - 'case_temp_high_warn_flag': False, - 'case_temp_low_warn_flag': False - }, - 'aux1_flags': { - 'aux1_high_alarm_flag': False, - 'aux1_low_alarm_flag': False, - 'aux1_high_warn_flag': False, - 'aux1_low_warn_flag': False - }, - 'aux2_flags': { - 'aux2_high_alarm_flag': False, - 'aux2_low_alarm_flag': False, - 'aux2_high_warn_flag': False, - 'aux2_low_warn_flag': False - }, - 'aux3_flags': { - 'aux3_high_alarm_flag': False, - 'aux3_low_alarm_flag': False, - 'aux3_high_warn_flag': False, - 'aux3_low_warn_flag': False - }, - 'custom_mon_flags': { - 'custom_mon_high_alarm_flag': False, - 'custom_mon_low_alarm_flag': False, - 'custom_mon_high_warn_flag': False, - 'custom_mon_low_warn_flag': False - } - }) - ]) - def test_get_module_level_flag(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_module_level_flag() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (1145324612, - { - 'dp_lane1': 'DataPathActivated', - 'dp_lane2': 'DataPathActivated', - 'dp_lane3': 'DataPathActivated', - 'dp_lane4': 'DataPathActivated', - 'dp_lane5': 'DataPathActivated', - 'dp_lane6': 'DataPathActivated', - 'dp_lane7': 'DataPathActivated', - 'dp_lane8': 'DataPathActivated', - }) - ]) - def test_get_datapath_state(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_datapath_state() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0xff, - { - 'TX_lane1': True, - 'TX_lane2': True, - 'TX_lane3': True, - 'TX_lane4': True, - 'TX_lane5': True, - 'TX_lane6': True, - 'TX_lane7': True, - 'TX_lane8': True, - }) - ]) - def test_get_tx_output_status(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_tx_output_status() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0xff, - { - 'RX_lane1': True, - 'RX_lane2': True, - 'RX_lane3': True, - 'RX_lane4': True, - 'RX_lane5': True, - 'RX_lane6': True, - 'RX_lane7': True, - 'RX_lane8': True, - }) - ]) - def test_get_rx_output_status(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_rx_output_status() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x00, - { - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }) - ]) - def test_get_tx_fault(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_tx_fault() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x00, - { - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }) - ]) - def test_get_tx_los(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_tx_los() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x00, - { - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }) - ]) - def test_get_tx_cdr_lol(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_tx_cdr_lol() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([0x00, 0x00, 0x00, 0x00], - { - 'tx_power_high_alarm':{ - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }, - 'tx_power_low_alarm':{ - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }, - 'tx_power_high_warn':{ - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }, - 'tx_power_low_warn':{ - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - } - }) - ]) - def test_get_tx_power_flag(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_tx_power_flag() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([0x00, 0x00, 0x00, 0x00], - { - 'tx_bias_high_alarm':{ - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }, - 'tx_bias_low_alarm':{ - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }, - 'tx_bias_high_warn':{ - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - }, - 'tx_bias_low_warn':{ - 'TX_lane1': False, - 'TX_lane2': False, - 'TX_lane3': False, - 'TX_lane4': False, - 'TX_lane5': False, - 'TX_lane6': False, - 'TX_lane7': False, - 'TX_lane8': False, - } - }) - ]) - def test_get_tx_bias_flag(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_tx_bias_flag() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([0x00, 0x00, 0x00, 0x00], - { - 'rx_power_high_alarm':{ - 'RX_lane1': False, - 'RX_lane2': False, - 'RX_lane3': False, - 'RX_lane4': False, - 'RX_lane5': False, - 'RX_lane6': False, - 'RX_lane7': False, - 'RX_lane8': False, - }, - 'rx_power_low_alarm':{ - 'RX_lane1': False, - 'RX_lane2': False, - 'RX_lane3': False, - 'RX_lane4': False, - 'RX_lane5': False, - 'RX_lane6': False, - 'RX_lane7': False, - 'RX_lane8': False, - }, - 'rx_power_high_warn':{ - 'RX_lane1': False, - 'RX_lane2': False, - 'RX_lane3': False, - 'RX_lane4': False, - 'RX_lane5': False, - 'RX_lane6': False, - 'RX_lane7': False, - 'RX_lane8': False, - }, - 'rx_power_low_warn':{ - 'RX_lane1': False, - 'RX_lane2': False, - 'RX_lane3': False, - 'RX_lane4': False, - 'RX_lane5': False, - 'RX_lane6': False, - 'RX_lane7': False, - 'RX_lane8': False, - } - }) - ]) - def test_get_rx_power_flag(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_rx_power_flag() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x00, - { - 'RX_lane1': False, - 'RX_lane2': False, - 'RX_lane3': False, - 'RX_lane4': False, - 'RX_lane5': False, - 'RX_lane6': False, - 'RX_lane7': False, - 'RX_lane8': False, - }) - ]) - def test_get_rx_los(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_rx_los() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0x00, - { - 'RX_lane1': False, - 'RX_lane2': False, - 'RX_lane3': False, - 'RX_lane4': False, - 'RX_lane5': False, - 'RX_lane6': False, - 'RX_lane7': False, - 'RX_lane8': False, - }) - ]) - def test_get_rx_cdr_lol(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_rx_cdr_lol() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (286331153, - { - 'config_DP_status_hostlane1': 'ConfigSuccess', - 'config_DP_status_hostlane2': 'ConfigSuccess', - 'config_DP_status_hostlane3': 'ConfigSuccess', - 'config_DP_status_hostlane4': 'ConfigSuccess', - 'config_DP_status_hostlane5': 'ConfigSuccess', - 'config_DP_status_hostlane6': 'ConfigSuccess', - 'config_DP_status_hostlane7': 'ConfigSuccess', - 'config_DP_status_hostlane8': 'ConfigSuccess', - }) - ]) - def test_get_config_datapath_hostlane_status(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_config_datapath_hostlane_status() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0, - { - 'hostlane1': False, - 'hostlane2': False, - 'hostlane3': False, - 'hostlane4': False, - 'hostlane5': False, - 'hostlane6': False, - 'hostlane7': False, - 'hostlane8': False, - }) - ]) - def test_get_dpinit_pending(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_dpinit_pending() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0, False) - ]) - def test_get_tuning_in_progress(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_tuning_in_progress() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0, False) - ]) - def test_get_wavelength_unlocked(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_wavelength_unlocked() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (1, ['TuningComplete']) - ]) - def test_get_laser_tuning_summary(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_laser_tuning_summary() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([190, -72, 120], (190, -72, 120, 191300, 196100)) - ]) - def test_get_supported_freq_config(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_supported_freq_config() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([-20, 0], (-20,0)) - ]) - def test_get_supported_power_config(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_supported_power_config() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (127, - { - 'simultaneous_host_media_loopback_supported': True, - 'per_lane_media_loopback_supported': True, - 'per_lane_host_loopback_supported': True, - 'host_side_input_loopback_supported': True, - 'host_side_output_loopback_supported': True, - 'media_side_input_loopback_supported': True, - 'media_side_output_loopback_supported': True - }) - ]) - def test_get_loopback_capability(self, mock_response, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_loopback_capability() - assert result == expected - - @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - ([0x77, 0xff], [18, 35, (0, 7, 112, 255, 255, 16, 0, 0, 19, 136, 0, 100, 3, 232, 19, 136, 58, 152)], - (112, 2048, False, True, 2048) - ) - ]) - def test_get_module_FW_upgrade_feature(self, mock_response1, mock_response2, expected): - api = self.mock_ccmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response1 - api.cdb = MagicMock() - api.cdb.cmd0041h = MagicMock() - api.cdb.cmd0041h.return_value = mock_response2 - api.cdb.cdb_chkcode = MagicMock() - api.cdb.cdb_chkcode.return_value = mock_response2[1] - result = api.get_module_FW_upgrade_feature() - assert result == expected + pass # TODO: call other methods in the api diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 60e34efef..08904f1c7 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -1,21 +1,970 @@ from mock import MagicMock - +import pytest from sonic_platform_base.sonic_xcvr.api.public.cmis import CmisApi from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom from sonic_platform_base.sonic_xcvr.codes.public.sff8024 import Sff8024 +from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode class TestCmis(object): - codes = Sff8024 - mem_map = CmisMemMap(codes) - reader = MagicMock(return_value=None) - writer = MagicMock() - eeprom = XcvrEeprom(reader, writer, mem_map) - api = CmisApi(eeprom) - - def test_api(self): + + def mock_cmis_api(self): + codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + mem_map = CmisMemMap(codes) + reader = MagicMock(return_value=None) + writer = MagicMock() + xcvr_eeprom = XcvrEeprom(reader, writer, mem_map) + api = CmisApi(xcvr_eeprom) + return api + + @pytest.mark.parametrize("mock_response, expected", [ + ("1234567890", "1234567890"), + ("ABCD", "ABCD") + ]) + def test_get_model(self, mock_response, expected): """ Verify all api access valid fields """ - self.api.get_model() + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_model() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("0.0", "0.0"), + ("1.2", "1.2") + ]) + def test_get_vendor_rev(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_rev() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("100000000", "100000000") + ]) + def test_get_vendor_serial(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_serial() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("1a-1a-1a", "1a-1a-1a") + ]) + def test_get_vendor_name(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_name() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("ABCDE", "ABCDE") + ]) + def test_get_vendor_OUI(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_OUI() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("21010100", "21010100") + ]) + def test_get_vendor_date(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_vendor_date() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("LC", "LC") + ]) + def test_get_connector_type(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_connector_type() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("Single Mode Fiber (SMF)", "Single Mode Fiber (SMF)") + ]) + def test_get_module_media_type(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_module_media_type() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ("400GAUI-8 C2M (Annex 120E)", "400GAUI-8 C2M (Annex 120E)") + ]) + def test_get_host_electrical_interface(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_electrical_interface() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + ("Single Mode Fiber (SMF)", "400ZR", "400ZR") + ]) + def test_get_module_media_interface(self, mock_response1, mock_response2, expected): + api = self.mock_cmis_api() + api.get_module_media_type = MagicMock() + api.get_module_media_type.return_value = mock_response1 + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response2 + result = api.get_module_media_interface() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x81, 8) + ]) + def test_get_host_lane_count(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_lane_count() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x81, 1) + ]) + def test_get_media_lane_count(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_lane_count() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_get_host_lane_assignment_option(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_lane_assignment_option() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_get_media_lane_assignment_option(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_lane_assignment_option() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10], + {'hostlane1': 1, 'hostlane2': 1, 'hostlane3': 1, 'hostlane4': 1, + 'hostlane5': 1, 'hostlane6': 1, 'hostlane7': 1, 'hostlane8': 1}) + ]) + def test_get_active_apsel_hostlane(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_active_apsel_hostlane() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ('C-band tunable laser', 'C-band tunable laser') + ]) + def test_get_media_interface_technology(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_interface_technology() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0, 1], '0.1') + ]) + def test_get_module_hardware_revision(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_hardware_revision() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x50, '5.0') + ]) + def test_get_cmis_rev(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_cmis_rev() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0, 1], '0.1') + ]) + def test_get_module_active_firmware(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_active_firmware() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0, 1], '0.1') + ]) + def test_get_module_inactive_firmware(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_inactive_firmware() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([45, 80, -10, 75, 0], + {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0}) + ]) + def test_get_module_temperature(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_temperature() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([3.3, 3.5, 3.1, 3.45, 3.15], + {'monitor value': 3.3, 'high alarm': 3.5, 'low alarm': 3.1, 'high warn': 3.45, 'low warn': 3.15}) + ]) + def test_get_module_voltage(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_voltage() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([-10, -2, -15, -4, -14], + {'monitor value lane1': -10, 'high alarm': -2, 'low alarm': -15, 'high warn': -4, 'low warn': -14}) + ]) + def test_get_txpower(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_txpower() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([-10, -2, -15, -4, -14], + {'monitor value lane1': -10, 'high alarm': -2, 'low alarm': -15, 'high warn': -4, 'low warn': -14}) + ]) + def test_get_rxpower(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_rxpower() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([50, 70, 0, 68, 0], + {'monitor value lane1': 50, 'high alarm': 70, 'low alarm': 0, 'high warn': 68, 'low warn': 0}) + ]) + def test_get_txbias(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_txbias() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x70, 75) + ]) + def test_get_freq_grid(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_freq_grid() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + (75, 12, 193400), + (75, -30, 192350), + ]) + def test_get_laser_config_freq(self, mock_response1, mock_response2, expected): + api = self.mock_cmis_api() + api.get_freq_grid = MagicMock() + api.get_freq_grid.return_value = mock_response1 + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response2 + result = api.get_laser_config_freq() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (193100000, 193100) + ]) + def test_get_current_laser_freq(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_current_laser_freq() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (-10, -10) + ]) + def test_get_TX_config_power(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_TX_config_power() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False), + (1, True), + ]) + def test_get_media_output_loopback(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_output_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False), + (1, True), + ]) + def test_get_media_input_loopback(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_media_input_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, [False,False,False,False,False,False,False,False]), + ]) + def test_get_host_output_loopback(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_output_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, [False,False,False,False,False,False,False,False]), + ]) + def test_get_host_input_loopback(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_host_input_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0xc2, (0,1,0)), + ]) + def test_get_aux_mon_type(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_aux_mon_type() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + ([0,1,0], + [11520, 20480, -2560, 19200, 0], + {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0} + ) + ]) + def test_get_laser_temperature(self, mock_response1, mock_response2, expected): + api = self.mock_cmis_api() + api.get_aux_mon_type = MagicMock() + api.get_aux_mon_type.return_value = mock_response1 + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response2 + result = api.get_laser_temperature() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + ([0,1,0], + [32767, 65534, 0, 49150.5, 0], + {'monitor value': 1, 'high alarm': 2, 'low alarm': 0, 'high warn': 1.5, 'low warn': 0} + ) + ]) + def test_get_laser_TEC_current(self, mock_response1, mock_response2, expected): + api = self.mock_cmis_api() + api.get_aux_mon_type = MagicMock() + api.get_aux_mon_type.return_value = mock_response1 + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response2 + result = api.get_laser_TEC_current() + assert result == expected + + @pytest.mark.parametrize("input_param, mock_response, expected", [ + ([False, 1.0], 100, 100.0) + ]) + def test_get_custom_field(self, input_param, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_custom_field(*input_param) + assert result == expected + + # @pytest.mark.parametrize("mock_response, expected", [ + # ([100000000, 1000000, 100000, 800, 1200, # preFEC_BER + # 10000, 100, 0, 0, 0, # uncorr_frame + # 1400, 1300, 1500, # CD + # 7.0, 5.5, 9.2, # DGD + # 40, 20, 60, # SOPMD + # 1.0, 0.8, 1.2, # PDL + # 28, 26, 30, # OSNR + # 17, 15, 18, # ESNR + # 200, 150, 250, # CFO + # 15, 13, 18, # EVM + # -10, -9.5, -10.5, # TX power + # -8, -7, -9, # RX total power + # -8, -7, -9, # RX channel power + # 5, 3, 8, # SOPROc + # 0, 0, 0, # MER + # ], + # {'preFEC_BER_cur': 0.001, 'preFEC_BER_min': 0.0008, 'preFEC_BER_max': 0.0012, + # 'preFEC_uncorr_frame_ratio_cur': 0, 'preFEC_uncorr_frame_ratio_min': 0, 'preFEC_uncorr_frame_ratio_max': 0, + # 'rx_cd_avg': 1400, 'rx_cd_min': 1300, 'rx_cd_max': 1500, + # 'rx_dgd_avg': 7.0, 'rx_dgd_min': 5.5, 'rx_dgd_max': 9.2, + # 'rx_sopmd_avg': 40, 'rx_sopmd_min': 20, 'rx_sopmd_max': 60, + # 'rx_pdl_avg': 1.0, 'rx_pdl_min': 0.8, 'rx_pdl_max': 1.2, + # 'rx_osnr_avg': 28, 'rx_osnr_min': 26, 'rx_osnr_max': 30, + # 'rx_esnr_avg': 17, 'rx_esnr_min': 15, 'rx_esnr_max': 18, + # 'rx_cfo_avg': 200, 'rx_cfo_min': 150, 'rx_cfo_max': 250, + # 'rx_evm_avg': 15, 'rx_evm_min': 13, 'rx_evm_max': 18, + # 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, + # 'rx_power_avg': -8, 'rx_power_min': -7, 'rx_power_max': -9, + # 'rx_sigpwr_avg': -8, 'rx_sigpwr_min': -7, 'rx_sigpwr_max': -9, + # 'rx_soproc_avg': 5, 'rx_soproc_min': 3, 'rx_soproc_max': 8, + # 'rx_mer_avg': 0, 'rx_mer_min': 0, 'rx_mer_max': 0 + # } + # ) + # ]) + # def test_get_PM(self, mock_response, expected): + # api = self.mock_cmis_api() + # api.xcvr_eeprom.read = MagicMock() + # api.xcvr_eeprom.read.side_effect = mock_response + # result = api.get_PM() + # assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (6, "ModuleReady") + ]) + def test_get_module_state(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_module_state() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (65, (False, False, True)) + ]) + def test_get_module_firmware_fault_state_changed(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_module_firmware_fault_state_changed() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0, 0, 0], + { + 'voltage_flags': { + 'voltage_high_alarm_flag': False, + 'voltage_low_alarm_flag': False, + 'voltage_high_warn_flag': False, + 'voltage_low_warn_flag': False + }, + 'case_temp_flags': { + 'case_temp_high_alarm_flag': False, + 'case_temp_low_alarm_flag': False, + 'case_temp_high_warn_flag': False, + 'case_temp_low_warn_flag': False + }, + 'aux1_flags': { + 'aux1_high_alarm_flag': False, + 'aux1_low_alarm_flag': False, + 'aux1_high_warn_flag': False, + 'aux1_low_warn_flag': False + }, + 'aux2_flags': { + 'aux2_high_alarm_flag': False, + 'aux2_low_alarm_flag': False, + 'aux2_high_warn_flag': False, + 'aux2_low_warn_flag': False + }, + 'aux3_flags': { + 'aux3_high_alarm_flag': False, + 'aux3_low_alarm_flag': False, + 'aux3_high_warn_flag': False, + 'aux3_low_warn_flag': False + }, + 'custom_mon_flags': { + 'custom_mon_high_alarm_flag': False, + 'custom_mon_low_alarm_flag': False, + 'custom_mon_high_warn_flag': False, + 'custom_mon_low_warn_flag': False + } + }) + ]) + def test_get_module_level_flag(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_module_level_flag() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1145324612, + { + 'dp_lane1': 'DataPathActivated', + 'dp_lane2': 'DataPathActivated', + 'dp_lane3': 'DataPathActivated', + 'dp_lane4': 'DataPathActivated', + 'dp_lane5': 'DataPathActivated', + 'dp_lane6': 'DataPathActivated', + 'dp_lane7': 'DataPathActivated', + 'dp_lane8': 'DataPathActivated', + }) + ]) + def test_get_datapath_state(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_datapath_state() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0xff, + { + 'TX_lane1': True, + 'TX_lane2': True, + 'TX_lane3': True, + 'TX_lane4': True, + 'TX_lane5': True, + 'TX_lane6': True, + 'TX_lane7': True, + 'TX_lane8': True, + }) + ]) + def test_get_tx_output_status(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tx_output_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0xff, + { + 'RX_lane1': True, + 'RX_lane2': True, + 'RX_lane3': True, + 'RX_lane4': True, + 'RX_lane5': True, + 'RX_lane6': True, + 'RX_lane7': True, + 'RX_lane8': True, + }) + ]) + def test_get_rx_output_status(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_rx_output_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }) + ]) + def test_get_tx_fault(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tx_fault() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }) + ]) + def test_get_tx_los(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tx_los() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }) + ]) + def test_get_tx_cdr_lol(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tx_cdr_lol() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0x00, 0x00, 0x00, 0x00], + { + 'tx_power_high_alarm':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_power_low_alarm':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_power_high_warn':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_power_low_warn':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + } + }) + ]) + def test_get_tx_power_flag(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_tx_power_flag() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0x00, 0x00, 0x00, 0x00], + { + 'tx_bias_high_alarm':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_bias_low_alarm':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_bias_high_warn':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + }, + 'tx_bias_low_warn':{ + 'TX_lane1': False, + 'TX_lane2': False, + 'TX_lane3': False, + 'TX_lane4': False, + 'TX_lane5': False, + 'TX_lane6': False, + 'TX_lane7': False, + 'TX_lane8': False, + } + }) + ]) + def test_get_tx_bias_flag(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_tx_bias_flag() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([0x00, 0x00, 0x00, 0x00], + { + 'rx_power_high_alarm':{ + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }, + 'rx_power_low_alarm':{ + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }, + 'rx_power_high_warn':{ + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }, + 'rx_power_low_warn':{ + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + } + }) + ]) + def test_get_rx_power_flag(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_rx_power_flag() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }) + ]) + def test_get_rx_los(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_rx_los() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0x00, + { + 'RX_lane1': False, + 'RX_lane2': False, + 'RX_lane3': False, + 'RX_lane4': False, + 'RX_lane5': False, + 'RX_lane6': False, + 'RX_lane7': False, + 'RX_lane8': False, + }) + ]) + def test_get_rx_cdr_lol(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_rx_cdr_lol() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (286331153, + { + 'config_DP_status_hostlane1': 'ConfigSuccess', + 'config_DP_status_hostlane2': 'ConfigSuccess', + 'config_DP_status_hostlane3': 'ConfigSuccess', + 'config_DP_status_hostlane4': 'ConfigSuccess', + 'config_DP_status_hostlane5': 'ConfigSuccess', + 'config_DP_status_hostlane6': 'ConfigSuccess', + 'config_DP_status_hostlane7': 'ConfigSuccess', + 'config_DP_status_hostlane8': 'ConfigSuccess', + }) + ]) + def test_get_config_datapath_hostlane_status(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_config_datapath_hostlane_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, + { + 'hostlane1': False, + 'hostlane2': False, + 'hostlane3': False, + 'hostlane4': False, + 'hostlane5': False, + 'hostlane6': False, + 'hostlane7': False, + 'hostlane8': False, + }) + ]) + def test_get_dpinit_pending(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_dpinit_pending() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False) + ]) + def test_get_tuning_in_progress(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_tuning_in_progress() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False) + ]) + def test_get_wavelength_unlocked(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_wavelength_unlocked() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, ['TuningComplete']) + ]) + def test_get_laser_tuning_summary(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_laser_tuning_summary() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([190, -72, 120], (190, -72, 120, 191300, 196100)) + ]) + def test_get_supported_freq_config(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_supported_freq_config() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([-20, 0], (-20,0)) + ]) + def test_get_supported_power_config(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response + result = api.get_supported_power_config() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (127, + { + 'simultaneous_host_media_loopback_supported': True, + 'per_lane_media_loopback_supported': True, + 'per_lane_host_loopback_supported': True, + 'host_side_input_loopback_supported': True, + 'host_side_output_loopback_supported': True, + 'media_side_input_loopback_supported': True, + 'media_side_output_loopback_supported': True + }) + ]) + def test_get_loopback_capability(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_loopback_capability() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + ([0x77, 0xff], [18, 35, (0, 7, 112, 255, 255, 16, 0, 0, 19, 136, 0, 100, 3, 232, 19, 136, 58, 152)], + (112, 2048, False, True, 2048) + ) + ]) + def test_get_module_FW_upgrade_feature(self, mock_response1, mock_response2, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.side_effect = mock_response1 + api.cdb = MagicMock() + api.cdb.cmd0041h = MagicMock() + api.cdb.cmd0041h.return_value = mock_response2 + api.cdb.cdb_chkcode = MagicMock() + api.cdb.cdb_chkcode.return_value = mock_response2[1] + result = api.get_module_FW_upgrade_feature() + assert result == expected # TODO: call other methods in the api From 044f060a1194511686369c503fcae2c5b9b987ca Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Wed, 13 Oct 2021 09:21:50 -0700 Subject: [PATCH 09/16] include functions interfacing with xcvrd in CmisApi --- .../sonic_xcvr/api/public/c_cmis.py | 4 +- .../sonic_xcvr/api/public/cmis.py | 924 +++++++++++++++++- .../sonic_xcvr/codes/public/cmis_code.py | 9 +- .../sonic_xcvr/fields/consts.py | 1 + .../sonic_xcvr/mem_maps/public/cmis.py | 1 + 5 files changed, 923 insertions(+), 16 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index d13bc538c..7132a8eb8 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -43,7 +43,7 @@ def get_PM_all(self): rx_max_corr_bits_subint_pm = self.xcvr_eeprom.read(consts.RX_MAX_CORR_BITS_SUB_INTERVAL_PM) if (rx_bits_subint_pm != 0) and (rx_bits_pm != 0): - PM_dict['preFEC_BER_cur'] = rx_corr_bits_pm*1.0/rx_bits_pm + PM_dict['preFEC_BER_avg'] = rx_corr_bits_pm*1.0/rx_bits_pm PM_dict['preFEC_BER_min'] = rx_min_corr_bits_subint_pm*1.0/rx_bits_subint_pm PM_dict['preFEC_BER_max'] = rx_max_corr_bits_subint_pm*1.0/rx_bits_subint_pm @@ -54,7 +54,7 @@ def get_PM_all(self): rx_max_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MIN_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) if (rx_frames_subint_pm != 0) and (rx_frames_pm != 0): - PM_dict['preFEC_uncorr_frame_ratio_cur'] = rx_frames_uncorr_err_pm*1.0/rx_frames_subint_pm + PM_dict['preFEC_uncorr_frame_ratio_avg'] = rx_frames_uncorr_err_pm*1.0/rx_frames_subint_pm PM_dict['preFEC_uncorr_frame_ratio_min'] = rx_min_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm PM_dict['preFEC_uncorr_frame_ratio_max'] = rx_max_frames_uncorr_err_subint_pm*1.0/rx_frames_subint_pm diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index f160d4362..d848313c3 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -471,6 +471,12 @@ def get_module_state(self): DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].MODULE_STATE return DICT.get(result, "Unknown") + def get_module_fault_cause(self): + ''' + This function returns the module fault cause + ''' + return self.xcvr_eeprom.read(consts.MODULE_FAULT_CAUSE) + def get_module_firmware_fault_state_changed(self): ''' This function returns datapath firmware fault state, module firmware fault state @@ -585,7 +591,7 @@ def get_datapath_state(self): def get_tx_output_status(self): ''' - This function returns whether TX output signals are valid + This function returns whether TX output signals are valid on TX media lane ''' result = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) tx_output_status_dict = dict() @@ -595,7 +601,7 @@ def get_tx_output_status(self): def get_rx_output_status(self): ''' - This function returns whether RX output signals are valid + This function returns whether RX output signals are valid on RX host lane ''' result = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) rx_output_status_dict = dict() @@ -605,7 +611,7 @@ def get_rx_output_status(self): def get_tx_fault(self): ''' - This function returns TX failure flag + This function returns TX failure flag on TX media lane ''' result = self.xcvr_eeprom.read(consts.TX_FAULT_FLAG) tx_fault_dict = dict() @@ -615,7 +621,7 @@ def get_tx_fault(self): def get_tx_los(self): ''' - This function returns TX LOS flag + This function returns TX LOS flag on TX host lane ''' result = self.xcvr_eeprom.read(consts.TX_LOS_FLAG) tx_los_dict = dict() @@ -625,7 +631,7 @@ def get_tx_los(self): def get_tx_cdr_lol(self): ''' - This function returns TX CDR LOL flag + This function returns TX CDR LOL flag on TX host lane ''' result = self.xcvr_eeprom.read(consts.TX_CDR_LOL) tx_lol_dict = dict() @@ -635,7 +641,7 @@ def get_tx_cdr_lol(self): def get_tx_power_flag(self): ''' - This function returns TX power out of range flag + This function returns TX power out of range flag on TX media lane ''' tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM_FLAG) tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM_FLAG) @@ -659,7 +665,7 @@ def get_tx_power_flag(self): def get_tx_bias_flag(self): ''' - This function returns TX bias out of range flag + This function returns TX bias out of range flag on TX media lane ''' tx_bias_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_ALARM_FLAG) tx_bias_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_ALARM_FLAG) @@ -683,7 +689,7 @@ def get_tx_bias_flag(self): def get_rx_power_flag(self): ''' - This function returns RX power out of range flag + This function returns RX power out of range flag on RX media lane ''' rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM_FLAG) rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM_FLAG) @@ -707,7 +713,7 @@ def get_rx_power_flag(self): def get_rx_los(self): ''' - This function returns RX LOS flag + This function returns RX LOS flag on RX media lane ''' result = self.xcvr_eeprom.read(consts.RX_LOS_FLAG) rx_los_dict = dict() @@ -717,7 +723,7 @@ def get_rx_los(self): def get_rx_cdr_lol(self): ''' - This function returns RX CDR LOL flag + This function returns RX CDR LOL flag on RX media lane ''' result = self.xcvr_eeprom.read(consts.RX_CDR_LOL) rx_lol_dict = dict() @@ -768,7 +774,7 @@ def get_dpinit_pending(self): def get_tuning_in_progress(self): ''' - This function returns tunning in progress status. + This function returns tunning in progress status on media lane 0 means tuning not in progress 1 means tuning in progress ''' @@ -776,7 +782,7 @@ def get_tuning_in_progress(self): def get_wavelength_unlocked(self): ''' - This function returns wavelength unlocked status. + This function returns wavelength unlocked status on media lane 0 means wavelength locked 1 means wavelength unlocked ''' @@ -784,7 +790,7 @@ def get_wavelength_unlocked(self): def get_laser_tuning_summary(self): ''' - This function returns laser tuning status summary + This function returns laser tuning status summary on media lane ''' result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) laser_tuning_summary = [] @@ -1099,6 +1105,898 @@ def module_firmware_upgrade(self, imagepath): time.sleep(60) self.module_FW_commit() self.get_module_FW_info() + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_INFO|ifname ; information for module on port + ; field = value + module_media_type = 1*255VCHAR ; module media interface ID + host_electrical_interface = 1*255VCHAR ; host electrical interface ID + media_interface_code = 1*255VCHAR ; media interface code + host_lane_count = INTEGER ; host lane count + media_lane_count = INTEGER ; media lane count + host_lane_assignment_option = INTEGER ; permissible first host lane number for application + media_lane_assignment_option = INTEGER ; permissible first media lane number for application + active_apsel_hostlane1 = INTEGER ; active application selected code assigned to host lane 1 + active_apsel_hostlane2 = INTEGER ; active application selected code assigned to host lane 2 + active_apsel_hostlane3 = INTEGER ; active application selected code assigned to host lane 3 + active_apsel_hostlane4 = INTEGER ; active application selected code assigned to host lane 4 + active_apsel_hostlane5 = INTEGER ; active application selected code assigned to host lane 5 + active_apsel_hostlane6 = INTEGER ; active application selected code assigned to host lane 6 + active_apsel_hostlane7 = INTEGER ; active application selected code assigned to host lane 7 + active_apsel_hostlane8 = INTEGER ; active application selected code assigned to host lane 8 + media_interface_technology = 1*255VCHAR ; media interface technology + hardwarerev = 1*255VCHAR ; module hardware revision + serialnum = 1*255VCHAR ; module serial number + manufacturename = 1*255VCHAR ; module venndor name + modelname = 1*255VCHAR ; module model name + vendor_rev = 1*255VCHAR ; module vendor revision + vendor_oui = 1*255VCHAR ; vendor organizationally unique identifier + vendor_date = 1*255VCHAR ; module manufacture date + connector_type = 1*255VCHAR ; connector type + specification_compliance = 1*255VCHAR ; electronic or optical interfaces that supported + active_firmware = 1*255VCHAR ; active firmware + inactive_firmware = 1*255VCHAR ; inactive firmware + supported_max_tx_power = FLOAT ; support maximum tx power + supported_min_tx_power = FLOAT ; support minimum tx power + supported_max_laser_freq = FLOAT ; support maximum laser frequency + supported_min_laser_freq = FLOAT ; support minimum laser frequency + ================================================================================ + """ + trans_info = dict() + trans_info['module_media_type'] = self.get_module_media_type() + trans_info['host_electrical_interface'] = self.get_host_electrical_interface() + trans_info['media_interface_code'] = self.get_module_media_interface() + trans_info['host_lane_count'] = self.get_host_lane_count() + trans_info['media_lane_count'] = self.get_media_lane_count() + trans_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option() + trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() + trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() + apsel_dict = self.get_active_apsel_hostlane() + trans_info['active_apsel_hostlane1'] = apsel_dict['hostlane1'] + trans_info['active_apsel_hostlane2'] = apsel_dict['hostlane2'] + trans_info['active_apsel_hostlane3'] = apsel_dict['hostlane3'] + trans_info['active_apsel_hostlane4'] = apsel_dict['hostlane4'] + trans_info['active_apsel_hostlane5'] = apsel_dict['hostlane5'] + trans_info['active_apsel_hostlane6'] = apsel_dict['hostlane6'] + trans_info['active_apsel_hostlane7'] = apsel_dict['hostlane7'] + trans_info['active_apsel_hostlane8'] = apsel_dict['hostlane8'] + trans_info['media_interface_technology'] = self.get_media_interface_technology() + trans_info['hardwarerev'] = self.get_module_hardware_revision() + trans_info['serialnum'] = self.get_vendor_serial() + trans_info['manufacturename'] = self.get_vendor_name() + trans_info['vendor_rev'] = self.get_vendor_rev() + trans_info['vendor_oui'] = self.get_vendor_OUI() + trans_info['vendor_date'] = self.get_vendor_date() + trans_info['connector_type'] = self.get_connector_type() + trans_info['specification_compliance'] = self.get_cmis_rev() + trans_info['active_firmware'] = self.get_module_active_firmware() + trans_info['inactive_firmware'] = self.get_module_inactive_firmware() + min_power, max_power = self.get_supported_power_config() + trans_info['supported_max_tx_power'] = max_power + trans_info['supported_max_tx_power'] = min_power + _, _, _, low_freq_supported, high_freq_supported = self.get_supported_freq_config() + trans_info['supported_max_laser_freq'] = high_freq_supported + trans_info['supported_min_laser_freq'] = low_freq_supported + return trans_info + + def get_transceiver_bulk_status(self): + """ + Retrieves bulk status info for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_DOM_SENSOR|ifname ; information module DOM sensors on port + ; field = value + temperature = FLOAT ; temperature value in Celsius + voltage = FLOAT ; voltage value + txpower = FLOAT ; tx power in mW + rxpower = FLOAT ; rx power in mW + txbias = FLOAT ; tx bias in mA + laser_temperature = FLOAT ; laser temperature value in Celsius + prefec_ber = FLOAT ; prefec ber + postfec_ber = FLOAT ; postfec ber + cd_shortlink = FLOAT ; chromatic dispersion, high granularity, short link in ps/nm + cd_longlink = FLOAT ; chromatic dispersion, low granularity, long link in ps/nm + dgd = FLOAT ; differential group delay in ps + sopmd = FLOAT ; second order polarization mode dispersion in ps^2 + pdl = FLOAT ; polarization dependent loss in db + osnr = FLOAT ; optical signal to noise ratio in db + esnr = FLOAT ; electrical signal to noise ratio in db + cfo = FLOAT ; carrier frequency offset in MHz + soproc = FLOAT ; state of polarization rate of change in krad/s + laser_config_freq = FLOAT ; laser configured frequency in MHz + laser_curr_freq = FLOAT ; laser current frequency in MHz + tx_config_power = FLOAT ; configured tx output power in dbm + tx_curr_power = FLOAT ; tx current output power in dbm + rx_tot_power = FLOAT ; rx total power in dbm + rx_sig_power = FLOAT ; rx signal power in dbm + bias_xi = FLOAT ; modulator bias xi + bias_xq = FLOAT ; modulator bias xq + bias_xp = FLOAT ; modulator bias xp + bias_yi = FLOAT ; modulator bias yi + bias_yq = FLOAT ; modulator bias yq + bias_yp = FLOAT ; modulator bias yp + ======================================================================== + """ + trans_dom = dict() + case_temp_dict = self.get_module_temperature() + trans_dom['temperature'] = case_temp_dict['monitor value'] + voltage_dict = self.get_module_voltage() + trans_dom['voltage'] = voltage_dict['monitor value'] + tx_power_dict = self.get_txpower() + trans_dom['txpower'] = tx_power_dict['monitor value lane1'] + rx_power_dict = self.get_rxpower() + trans_dom['rxpower'] = rx_power_dict['monitor value lane1'] + tx_bias_current_dict = self.get_txbias() + trans_dom['txbias'] = tx_bias_current_dict['monitor value lane1'] + laser_temp_dict = self.get_laser_temperature() + trans_dom['laser_temperature'] = laser_temp_dict['monitor value'] + vdm_dict = self.get_VDM() + trans_dom['prefec_ber'] = vdm_dict['Pre-FEC BER Average Media Input'][1][0] + trans_dom['postfec_ber'] = vdm_dict['Errored Frames Average Media Input'][1][0] + trans_dom['bias_xi'] = vdm_dict['Modulator Bias X/I [%]'][1][0] + trans_dom['bias_xq'] = vdm_dict['Modulator Bias X/Q [%]'][1][0] + trans_dom['bias_xp'] = vdm_dict['Modulator Bias X_Phase [%]'][1][0] + trans_dom['bias_yi'] = vdm_dict['Modulator Bias Y/I [%]'][1][0] + trans_dom['bias_yq'] = vdm_dict['Modulator Bias Y/Q [%]'][1][0] + trans_dom['bias_yp'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][0] + trans_dom['cd_shortlink'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][0] + trans_dom['cd_longlink'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][0] + trans_dom['dgd'] = vdm_dict['DGD [ps]'][1][0] + trans_dom['sopmd'] = vdm_dict['SOPMD [ps^2]'][1][0] + trans_dom['pdl'] = vdm_dict['PDL [dB]'][1][0] + trans_dom['osnr'] = vdm_dict['OSNR [dB]'][1][0] + trans_dom['esnr'] = vdm_dict['eSNR [dB]'][1][0] + trans_dom['cfo'] = vdm_dict['CFO [MHz]'][1][0] + trans_dom['tx_curr_power'] = vdm_dict['Tx Power [dBm]'][1][0] + trans_dom['rx_tot_power'] = vdm_dict['Rx Total Power [dBm]'][1][0] + trans_dom['rx_sig_power'] = vdm_dict['Rx Signal Power [dBm]'][1][0] + trans_dom['laser_config_freq'] = self.get_laser_config_freq() + trans_dom['laser_curr_freq'] = self.get_current_laser_freq() + trans_dom['tx_config_power'] = self.get_TX_config_power() + return trans_dom + + def get_transceiver_threshold_info(self): + """ + Retrieves threshold info for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_STATUS|ifname ; DOM threshold information for module on port + ; field = value + temphighalarm = FLOAT ; temperature high alarm threshold in Celsius + temphighwarning = FLOAT ; temperature high warning threshold in Celsius + templowalarm = FLOAT ; temperature low alarm threshold in Celsius + templowwarning = FLOAT ; temperature low warning threshold in Celsius + vcchighalarm = FLOAT ; vcc high alarm threshold in V + vcchighwarning = FLOAT ; vcc high warning threshold in V + vcclowalarm = FLOAT ; vcc low alarm threshold in V + vcclowwarning = FLOAT ; vcc low warning threshold in V + txpowerhighalarm = FLOAT ; tx power high alarm threshold in mW + txpowerlowalarm = FLOAT ; tx power low alarm threshold in mW + txpowerhighwarning = FLOAT ; tx power high warning threshold in mW + txpowerlowwarning = FLOAT ; tx power low alarm threshold in mW + rxpowerhighalarm = FLOAT ; rx power high alarm threshold in mW + rxpowerlowalarm = FLOAT ; rx power low alarm threshold in mW + rxpowerhighwarning = FLOAT ; rx power high warning threshold in mW + rxpowerlowwarning = FLOAT ; rx power low warning threshold in mW + txbiashighalarm = FLOAT ; tx bias high alarm threshold in mA + txbiaslowalarm = FLOAT ; tx bias low alarm threshold in mA + txbiashighwarning = FLOAT ; tx bias high warning threshold in mA + txbiaslowwarning = FLOAT ; tx bias low warning threshold in mA + lasertemphighalarm = FLOAT ; laser temperature high alarm threshold in Celsius + lasertemplowalarm = FLOAT ; laser temperature low alarm threshold in Celsius + lasertemphighwarning = FLOAT ; laser temperature high warning threshold in Celsius + lasertemplowwarning = FLOAT ; laser temperature low warning threshold in Celsius + prefecberhighalarm = FLOAT ; prefec ber high alarm threshold + prefecberlowalarm = FLOAT ; prefec ber low alarm threshold + prefecberhighwarning = FLOAT ; prefec ber high warning threshold + prefecberlowwarning = FLOAT ; prefec ber low warning threshold + postfecberhighalarm = FLOAT ; postfec ber high alarm threshold + postfecberlowalarm = FLOAT ; postfec ber low alarm threshold + postfecberhighwarning = FLOAT ; postfec ber high warning threshold + postfecberlowwarning = FLOAT ; postfec ber low warning threshold + biasxihighalarm = FLOAT ; bias xi high alarm threshold in percent + biasxilowalarm = FLOAT ; bias xi low alarm threshold in percent + biasxihighwarning = FLOAT ; bias xi high warning threshold in percent + biasxilowwarning = FLOAT ; bias xi low warning threshold in percent + biasxqhighalarm = FLOAT ; bias xq high alarm threshold in percent + biasxqlowalarm = FLOAT ; bias xq low alarm threshold in percent + biasxqhighwarning = FLOAT ; bias xq high warning threshold in percent + biasxqlowwarning = FLOAT ; bias xq low warning threshold in percent + biasxphighalarm = FLOAT ; bias xp high alarm threshold in percent + biasxplowalarm = FLOAT ; bias xp low alarm threshold in percent + biasxphighwarning = FLOAT ; bias xp high warning threshold in percent + biasxplowwarning = FLOAT ; bias xp low warning threshold in percent + biasyihighalarm = FLOAT ; bias yi high alarm threshold in percent + biasyilowalarm = FLOAT ; bias yi low alarm threshold in percent + biasyihighwarning = FLOAT ; bias yi high warning threshold in percent + biasyilowwarning = FLOAT ; bias yi low warning threshold in percent + biasyqhighalarm = FLOAT ; bias yq high alarm threshold in percent + biasyqlowalarm = FLOAT ; bias yq low alarm threshold in percent + biasyqhighwarning = FLOAT ; bias yq high warning threshold in percent + biasyqlowwarning = FLOAT ; bias yq low warning threshold in percent + biasyphighalarm = FLOAT ; bias yp high alarm threshold in percent + biasyplowalarm = FLOAT ; bias yp low alarm threshold in percent + biasyphighwarning = FLOAT ; bias yp high warning threshold in percent + biasyplowwarning = FLOAT ; bias yp low warning threshold in percent + cdshorthighalarm = FLOAT ; cd short high alarm threshold in ps/nm + cdshortlowalarm = FLOAT ; cd short low alarm threshold in ps/nm + cdshorthighwarning = FLOAT ; cd short high warning threshold in ps/nm + cdshortlowwarning = FLOAT ; cd short low warning threshold in ps/nm + cdlonghighalarm = FLOAT ; cd long high alarm threshold in ps/nm + cdlonglowalarm = FLOAT ; cd long low alarm threshold in ps/nm + cdlonghighwarning = FLOAT ; cd long high warning threshold in ps/nm + cdlonglowwarning = FLOAT ; cd long low warning threshold in ps/nm + dgdhighalarm = FLOAT ; dgd high alarm threshold in ps + dgdlowalarm = FLOAT ; dgd low alarm threshold in ps + dgdhighwarning = FLOAT ; dgd high warning threshold in ps + dgdlowwarning = FLOAT ; dgd low warning threshold in ps + sopmdhighalarm = FLOAT ; sopmd high alarm threshold in ps^2 + sopmdlowalarm = FLOAT ; sopmd low alarm threshold in ps^2 + sopmdhighwarning = FLOAT ; sopmd high warning threshold in ps^2 + sopmdlowwarning = FLOAT ; sopmd low warning threshold in ps^2 + pdlhighalarm = FLOAT ; pdl high alarm threshold in db + pdllowalarm = FLOAT ; pdl low alarm threshold in db + pdlhighwarning = FLOAT ; pdl high warning threshold in db + pdllowwarning = FLOAT ; pdl low warning threshold in db + osnrhighalarm = FLOAT ; osnr high alarm threshold in db + osnrlowalarm = FLOAT ; osnr low alarm threshold in db + osnrhighwarning = FLOAT ; osnr high warning threshold in db + osnrlowwarning = FLOAT ; osnr low warning threshold in db + esnrhighalarm = FLOAT ; esnr high alarm threshold in db + esnrlowalarm = FLOAT ; esnr low alarm threshold in db + esnrhighwarning = FLOAT ; esnr high warning threshold in db + esnrlowwarning = FLOAT ; esnr low warning threshold in db + cfohighalarm = FLOAT ; cfo high alarm threshold in MHz + cfolowalarm = FLOAT ; cfo low alarm threshold in MHz + cfohighwarning = FLOAT ; cfo high warning threshold in MHz + cfolowwarning = FLOAT ; cfo low warning threshold in MHz + txcurrpowerhighalarm = FLOAT ; txcurrpower high alarm threshold in dbm + txcurrpowerlowalarm = FLOAT ; txcurrpower low alarm threshold in dbm + txcurrpowerhighwarning = FLOAT ; txcurrpower high warning threshold in dbm + txcurrpowerlowwarning = FLOAT ; txcurrpower low warning threshold in dbm + rxtotpowerhighalarm = FLOAT ; rxtotpower high alarm threshold in dbm + rxtotpowerlowalarm = FLOAT ; rxtotpower low alarm threshold in dbm + rxtotpowerhighwarning = FLOAT ; rxtotpower high warning threshold in dbm + rxtotpowerlowwarning = FLOAT ; rxtotpower low warning threshold in dbm + rxsigpowerhighalarm = FLOAT ; rxsigpower high alarm threshold in dbm + rxsigpowerlowalarm = FLOAT ; rxsigpower low alarm threshold in dbm + rxsigpowerhighwarning = FLOAT ; rxsigpower high warning threshold in dbm + rxsigpowerlowwarning = FLOAT ; rxsigpower low warning threshold in dbm + ======================================================================== + """ + trans_dom_th = dict() + case_temp_dict = self.get_module_temperature() + trans_dom_th['temphighalarm'] = case_temp_dict['high alarm'] + trans_dom_th['templowalarm'] = case_temp_dict['low alarm'] + trans_dom_th['temphighwarning'] = case_temp_dict['high warn'] + trans_dom_th['templowwarning'] = case_temp_dict['low warn'] + voltage_dict = self.get_module_voltage() + trans_dom_th['vcchighalarm'] = voltage_dict['high alarm'] + trans_dom_th['vcclowalarm'] = voltage_dict['low alarm'] + trans_dom_th['vcchighwarning'] = voltage_dict['high warn'] + trans_dom_th['vcclowwarning'] = voltage_dict['low warn'] + tx_power_dict = self.get_txpower() + trans_dom_th['txpowerhighalarm'] = tx_power_dict['high alarm'] + trans_dom_th['txpowerlowalarm'] = tx_power_dict['low alarm'] + trans_dom_th['txpowerhighwarning'] = tx_power_dict['high warn'] + trans_dom_th['txpowerlowwarning'] = tx_power_dict['low warn'] + rx_power_dict = self.get_rxpower() + trans_dom_th['rxpowerhighalarm'] = rx_power_dict['high alarm'] + trans_dom_th['rxpowerlowalarm'] = rx_power_dict['low alarm'] + trans_dom_th['rxpowerhighwarning'] = rx_power_dict['high warn'] + trans_dom_th['rxpowerlowwarning'] = rx_power_dict['low warn'] + tx_bias_current_dict = self.get_txbias() + trans_dom_th['txbiashighalarm'] = tx_bias_dict['high alarm'] + trans_dom_th['txbiaslowalarm'] = tx_bias_dict['low alarm'] + trans_dom_th['txbiashighwarning'] = tx_bias_dict['high warn'] + trans_dom_th['txbiaslowwarning'] = tx_bias_dict['low warn'] + laser_temp_dict = self.get_laser_temperature() + trans_dom_th['lasertemphighalarm'] = laser_temp_dict['high alarm'] + trans_dom_th['lasertemplowalarm'] = laser_temp_dict['low alarm'] + trans_dom_th['lasertemphighwarning'] = laser_temp_dict['high warn'] + trans_dom_th['lasertemplowwarning'] = laser_temp_dict['low warn'] + vdm_dict = self.get_VDM() + trans_dom_th['prefecberhighalarm'] = vdm_dict['Pre-FEC BER Average Media Input'][1][1] + trans_dom_th['prefecberlowalarm'] = vdm_dict['Pre-FEC BER Average Media Input'][1][2] + trans_dom_th['prefecberhighwarning'] = vdm_dict['Pre-FEC BER Average Media Input'][1][3] + trans_dom_th['prefecberlowwarning'] = vdm_dict['Pre-FEC BER Average Media Input'][1][4] + trans_dom_th['postfecberhighalarm'] = vdm_dict['Errored Frames Average Media Input'][1][1] + trans_dom_th['postfecberlowalarm'] = vdm_dict['Errored Frames Average Media Input'][1][2] + trans_dom_th['postfecberhighwarning'] = vdm_dict['Errored Frames Average Media Input'][1][3] + trans_dom_th['postfecberlowwarning'] = vdm_dict['Errored Frames Average Media Input'][1][4] + trans_dom_th['biasxihighalarm'] = vdm_dict['Modulator Bias X/I [%]'][1][1] + trans_dom_th['biasxilowalarm'] = vdm_dict['Modulator Bias X/I [%]'][1][2] + trans_dom_th['biasxihighwarning'] = vdm_dict['Modulator Bias X/I [%]'][1][3] + trans_dom_th['biasxilowwarning'] = vdm_dict['Modulator Bias X/I [%]'][1][4] + trans_dom_th['biasxqhighalarm'] = vdm_dict['Modulator Bias X/Q [%]'][1][1] + trans_dom_th['biasxqlowalarm'] = vdm_dict['Modulator Bias X/Q [%]'][1][2] + trans_dom_th['biasxqhighwarning'] = vdm_dict['Modulator Bias X/Q [%]'][1][3] + trans_dom_th['biasxqlowwarning'] = vdm_dict['Modulator Bias X/Q [%]'][1][4] + trans_dom_th['biasxphighalarm'] = vdm_dict['Modulator Bias X_Phase [%]'][1][1] + trans_dom_th['biasxplowalarm'] = vdm_dict['Modulator Bias X_Phase [%]'][1][2] + trans_dom_th['biasxphighwarning'] = vdm_dict['Modulator Bias X_Phase [%]'][1][3] + trans_dom_th['biasxplowwarning'] = vdm_dict['Modulator Bias X_Phase [%]'][1][4] + trans_dom_th['biasyihighalarm'] = vdm_dict['Modulator Bias Y/I [%]'][1][1] + trans_dom_th['biasyilowalarm'] = vdm_dict['Modulator Bias Y/I [%]'][1][2] + trans_dom_th['biasyihighwarning'] = vdm_dict['Modulator Bias Y/I [%]'][1][3] + trans_dom_th['biasyilowwarning'] = vdm_dict['Modulator Bias Y/I [%]'][1][4] + trans_dom_th['biasyqhighalarm'] = vdm_dict['Modulator Bias Y/Q [%]'][1][1] + trans_dom_th['biasyqlowalarm'] = vdm_dict['Modulator Bias Y/Q [%]'][1][2] + trans_dom_th['biasyqhighwarning'] = vdm_dict['Modulator Bias Y/Q [%]'][1][3] + trans_dom_th['biasyqlowwarning'] = vdm_dict['Modulator Bias Y/Q [%]'][1][4] + trans_dom_th['biasyphighalarm'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][1] + trans_dom_th['biasyplowalarm'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][2] + trans_dom_th['biasyphighwarning'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][3] + trans_dom_th['biasyplowwarning'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][4] + trans_dom_th['cdshorthighalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][1] + trans_dom_th['cdshortlowalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][2] + trans_dom_th['cdshorthighwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][3] + trans_dom_th['cdshortlowwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][4] + trans_dom_th['cdlonghighalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][1] + trans_dom_th['cdlonglowalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][2] + trans_dom_th['cdlonghighwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][3] + trans_dom_th['cdlonglowwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][4] + trans_dom_th['dgdhighalarm'] = vdm_dict['DGD [ps]'][1][1] + trans_dom_th['dgdlowalarm'] = vdm_dict['DGD [ps]'][1][2] + trans_dom_th['dgdhighwarning'] = vdm_dict['DGD [ps]'][1][3] + trans_dom_th['dgdlowwarning'] = vdm_dict['DGD [ps]'][1][4] + trans_dom_th['sopmdhighalarm'] = vdm_dict['SOPMD [ps^2]'][1][1] + trans_dom_th['sopmdlowalarm'] = vdm_dict['SOPMD [ps^2]'][1][2] + trans_dom_th['sopmdhighwarning'] = vdm_dict['SOPMD [ps^2]'][1][3] + trans_dom_th['sopmdlowwarning'] = vdm_dict['SOPMD [ps^2]'][1][4] + trans_dom_th['pdlhighalarm'] = vdm_dict['PDL [dB]'][1][1] + trans_dom_th['pdllowalarm'] = vdm_dict['PDL [dB]'][1][2] + trans_dom_th['pdlhighwarning'] = vdm_dict['PDL [dB]'][1][3] + trans_dom_th['pdllowwarning'] = vdm_dict['PDL [dB]'][1][4] + trans_dom_th['osnrhighalarm'] = vdm_dict['OSNR [dB]'][1][1] + trans_dom_th['osnrlowalarm'] = vdm_dict['OSNR [dB]'][1][2] + trans_dom_th['osnrhighwarning'] = vdm_dict['OSNR [dB]'][1][3] + trans_dom_th['osnrlowwarning'] = vdm_dict['OSNR [dB]'][1][4] + trans_dom_th['esnrhighalarm'] = vdm_dict['eSNR [dB]'][1][1] + trans_dom_th['esnrlowalarm'] = vdm_dict['eSNR [dB]'][1][2] + trans_dom_th['esnrhighwarning'] = vdm_dict['eSNR [dB]'][1][3] + trans_dom_th['esnrlowwarning'] = vdm_dict['eSNR [dB]'][1][4] + trans_dom_th['cfohighalarm'] = vdm_dict['CFO [MHz]'][1][1] + trans_dom_th['cfolowalarm'] = vdm_dict['CFO [MHz]'][1][2] + trans_dom_th['cfohighwarning'] = vdm_dict['CFO [MHz]'][1][3] + trans_dom_th['cfolowwarning'] = vdm_dict['CFO [MHz]'][1][4] + trans_dom_th['txcurrpowerhighalarm'] = vdm_dict['Tx Power [dBm]'][1][1] + trans_dom_th['txcurrpowerlowalarm'] = vdm_dict['Tx Power [dBm]'][1][2] + trans_dom_th['txcurrpowerhighwarning'] = vdm_dict['Tx Power [dBm]'][1][3] + trans_dom_th['txcurrpowerlowwarning'] = vdm_dict['Tx Power [dBm]'][1][4] + trans_dom_th['rxtotpowerhighalarm'] = vdm_dict['Rx Total Power [dBm]'][1][1] + trans_dom_th['rxtotpowerlowalarm'] = vdm_dict['Rx Total Power [dBm]'][1][2] + trans_dom_th['rxtotpowerhighwarning'] = vdm_dict['Rx Total Power [dBm]'][1][3] + trans_dom_th['rxtotpowerlowwarning'] = vdm_dict['Rx Total Power [dBm]'][1][4] + trans_dom_th['rxsigpowerhighalarm'] = vdm_dict['Rx Signal Power [dBm]'][1][1] + trans_dom_th['rxsigpowerlowalarm'] = vdm_dict['Rx Signal Power [dBm]'][1][2] + trans_dom_th['rxsigpowerhighwarning'] = vdm_dict['Rx Signal Power [dBm]'][1][3] + trans_dom_th['rxsigpowerlowwarning'] = vdm_dict['Rx Signal Power [dBm]'][1][4] + return trans_dom_th + + def get_transceiver_status(self): + """ + Retrieves transceiver status of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_STATUS|ifname ; Error information for module on port + ; field = value + status = 1*255VCHAR ; code of the module status (plug in, plug out) + error = 1*255VCHAR ; module error (N/A or a string consisting of error descriptions joined by "|", like "error1 | error2" ) + module_state = 1*255VCHAR ; current module state (ModuleLowPwr, ModulePwrUp, ModuleReady, ModulePwrDn, Fault) + module_fault_cause = 1*255VCHAR ; reason of entering the module fault state + datapath_firmware_fault = BOOLEAN ; datapath (DSP) firmware fault + module_firmware_fault = BOOLEAN ; module firmware fault + module_state_changed = BOOLEAN ; module state changed + datapath_hostlane1 = 1*255VCHAR ; data path state indicator on host lane 1 + datapath_hostlane2 = 1*255VCHAR ; data path state indicator on host lane 2 + datapath_hostlane3 = 1*255VCHAR ; data path state indicator on host lane 3 + datapath_hostlane4 = 1*255VCHAR ; data path state indicator on host lane 4 + datapath_hostlane5 = 1*255VCHAR ; data path state indicator on host lane 5 + datapath_hostlane6 = 1*255VCHAR ; data path state indicator on host lane 6 + datapath_hostlane7 = 1*255VCHAR ; data path state indicator on host lane 7 + datapath_hostlane8 = 1*255VCHAR ; data path state indicator on host lane 8 + txoutput_status = BOOLEAN ; tx output status on media lane + rxoutput_status_hostlane1 = BOOLEAN ; rx output status on host lane 1 + rxoutput_status_hostlane2 = BOOLEAN ; rx output status on host lane 2 + rxoutput_status_hostlane3 = BOOLEAN ; rx output status on host lane 3 + rxoutput_status_hostlane4 = BOOLEAN ; rx output status on host lane 4 + rxoutput_status_hostlane5 = BOOLEAN ; rx output status on host lane 5 + rxoutput_status_hostlane6 = BOOLEAN ; rx output status on host lane 6 + rxoutput_status_hostlane7 = BOOLEAN ; rx output status on host lane 7 + rxoutput_status_hostlane8 = BOOLEAN ; rx output status on host lane 8 + txfault = BOOLEAN ; tx fault flag on media lane + txlos_hostlane1 = BOOLEAN ; tx loss of signal flag on host lane 1 + txlos_hostlane2 = BOOLEAN ; tx loss of signal flag on host lane 2 + txlos_hostlane3 = BOOLEAN ; tx loss of signal flag on host lane 3 + txlos_hostlane4 = BOOLEAN ; tx loss of signal flag on host lane 4 + txlos_hostlane5 = BOOLEAN ; tx loss of signal flag on host lane 5 + txlos_hostlane6 = BOOLEAN ; tx loss of signal flag on host lane 6 + txlos_hostlane7 = BOOLEAN ; tx loss of signal flag on host lane 7 + txlos_hostlane8 = BOOLEAN ; tx loss of signal flag on host lane 8 + txcdrlol_hostlane1 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 1 + txcdrlol_hostlane2 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 2 + txcdrlol_hostlane3 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 3 + txcdrlol_hostlane4 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 4 + txcdrlol_hostlane5 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 5 + txcdrlol_hostlane6 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 6 + txcdrlol_hostlane7 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 7 + txcdrlol_hostlane8 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 8 + rxlos = BOOLEAN ; rx loss of signal flag on media lane + rxcdrlol = BOOLEAN ; rx clock and data recovery loss of lock on media lane + config_state_hostlane1 = 1*255VCHAR ; configuration status for the data path of host line 1 + config_state_hostlane2 = 1*255VCHAR ; configuration status for the data path of host line 2 + config_state_hostlane3 = 1*255VCHAR ; configuration status for the data path of host line 3 + config_state_hostlane4 = 1*255VCHAR ; configuration status for the data path of host line 4 + config_state_hostlane5 = 1*255VCHAR ; configuration status for the data path of host line 5 + config_state_hostlane6 = 1*255VCHAR ; configuration status for the data path of host line 6 + config_state_hostlane7 = 1*255VCHAR ; configuration status for the data path of host line 7 + config_state_hostlane8 = 1*255VCHAR ; configuration status for the data path of host line 8 + dpinit_pending_hostlane1 = BOOLEAN ; data path configuration updated on host lane 1 + dpinit_pending_hostlane2 = BOOLEAN ; data path configuration updated on host lane 2 + dpinit_pending_hostlane3 = BOOLEAN ; data path configuration updated on host lane 3 + dpinit_pending_hostlane4 = BOOLEAN ; data path configuration updated on host lane 4 + dpinit_pending_hostlane5 = BOOLEAN ; data path configuration updated on host lane 5 + dpinit_pending_hostlane6 = BOOLEAN ; data path configuration updated on host lane 6 + dpinit_pending_hostlane7 = BOOLEAN ; data path configuration updated on host lane 7 + dpinit_pending_hostlane8 = BOOLEAN ; data path configuration updated on host lane 8 + tuning_in_progress = BOOLEAN ; tuning in progress status + wavelength_unlock_status = BOOLEAN ; laser unlocked status + target_output_power_oor = BOOLEAN ; target output power out of range flag + fine_tuning_oor = BOOLEAN ; fine tuning out of range flag + tuning_not_accepted = BOOLEAN ; tuning not accepted flag + invalid_channel_num = BOOLEAN ; invalid channel number flag + tuning_complete = BOOLEAN ; tuning complete flag + temphighalarm_flag = BOOLEAN ; temperature high alarm flag + temphighwarning_flag = BOOLEAN ; temperature high warning flag + templowalarm_flag = BOOLEAN ; temperature low alarm flag + templowwarning_flag = BOOLEAN ; temperature low warning flag + vcchighalarm_flag = BOOLEAN ; vcc high alarm flag + vcchighwarning_flag = BOOLEAN ; vcc high warning flag + vcclowalarm_flag = BOOLEAN ; vcc low alarm flag + vcclowwarning_flag = BOOLEAN ; vcc low warning flag + txpowerhighalarm_flag = BOOLEAN ; tx power high alarm flag + txpowerlowalarm_flag = BOOLEAN ; tx power low alarm flag + txpowerhighwarning_flag = BOOLEAN ; tx power high warning flag + txpowerlowwarning_flag = BOOLEAN ; tx power low alarm flag + rxpowerhighalarm_flag = BOOLEAN ; rx power high alarm flag + rxpowerlowalarm_flag = BOOLEAN ; rx power low alarm flag + rxpowerhighwarning_flag = BOOLEAN ; rx power high warning flag + rxpowerlowwarning_flag = BOOLEAN ; rx power low warning flag + txbiashighalarm_flag = BOOLEAN ; tx bias high alarm flag + txbiaslowalarm_flag = BOOLEAN ; tx bias low alarm flag + txbiashighwarning_flag = BOOLEAN ; tx bias high warning flag + txbiaslowwarning_flag = BOOLEAN ; tx bias low warning flag + lasertemphighalarm_flag = BOOLEAN ; laser temperature high alarm flag + lasertemplowalarm_flag = BOOLEAN ; laser temperature low alarm flag + lasertemphighwarning_flag = BOOLEAN ; laser temperature high warning flag + lasertemplowwarning_flag = BOOLEAN ; laser temperature low warning flag + prefecberhighalarm_flag = BOOLEAN ; prefec ber high alarm flag + prefecberlowalarm_flag = BOOLEAN ; prefec ber low alarm flag + prefecberhighwarning_flag = BOOLEAN ; prefec ber high warning flag + prefecberlowwarning_flag = BOOLEAN ; prefec ber low warning flag + postfecberhighalarm_flag = BOOLEAN ; postfec ber high alarm flag + postfecberlowalarm_flag = BOOLEAN ; postfec ber low alarm flag + postfecberhighwarning_flag = BOOLEAN ; postfec ber high warning flag + postfecberlowwarning_flag = BOOLEAN ; postfec ber low warning flag + biasxihighalarm_flag = BOOLEAN ; bias xi high alarm flag + biasxilowalarm_flag = BOOLEAN ; bias xi low alarm flag + biasxihighwarning_flag = BOOLEAN ; bias xi high warning flag + biasxilowwarning_flag = BOOLEAN ; bias xi low warning flag + biasxqhighalarm_flag = BOOLEAN ; bias xq high alarm flag + biasxqlowalarm_flag = BOOLEAN ; bias xq low alarm flag + biasxqhighwarning_flag = BOOLEAN ; bias xq high warning flag + biasxqlowwarning_flag = BOOLEAN ; bias xq low warning flag + biasxphighalarm_flag = BOOLEAN ; bias xp high alarm flag + biasxplowalarm_flag = BOOLEAN ; bias xp low alarm flag + biasxphighwarning_flag = BOOLEAN ; bias xp high warning flag + biasxplowwarning_flag = BOOLEAN ; bias xp low warning flag + biasyihighalarm_flag = BOOLEAN ; bias yi high alarm flag + biasyilowalarm_flag = BOOLEAN ; bias yi low alarm flag + biasyihighwarning_flag = BOOLEAN ; bias yi high warning flag + biasyilowwarning_flag = BOOLEAN ; bias yi low warning flag + biasyqhighalarm_flag = BOOLEAN ; bias yq high alarm flag + biasyqlowalarm_flag = BOOLEAN ; bias yq low alarm flag + biasyqhighwarning_flag = BOOLEAN ; bias yq high warning flag + biasyqlowwarning_flag = BOOLEAN ; bias yq low warning flag + biasyphighalarm_flag = BOOLEAN ; bias yp high alarm flag + biasyplowalarm_flag = BOOLEAN ; bias yp low alarm flag + biasyphighwarning_flag = BOOLEAN ; bias yp high warning flag + biasyplowwarning_flag = BOOLEAN ; bias yp low warning flag + cdshorthighalarm_flag = BOOLEAN ; cd short high alarm flag + cdshortlowalarm_flag = BOOLEAN ; cd short low alarm flag + cdshorthighwarning_flag = BOOLEAN ; cd short high warning flag + cdshortlowwarning_flag = BOOLEAN ; cd short low warning flag + cdlonghighalarm_flag = BOOLEAN ; cd long high alarm flag + cdlonglowalarm_flag = BOOLEAN ; cd long low alarm flag + cdlonghighwarning_flag = BOOLEAN ; cd long high warning flag + cdlonglowwarning_flag = BOOLEAN ; cd long low warning flag + dgdhighalarm_flag = BOOLEAN ; dgd high alarm flag + dgdlowalarm_flag = BOOLEAN ; dgd low alarm flag + dgdhighwarning_flag = BOOLEAN ; dgd high warning flag + dgdlowwarning_flag = BOOLEAN ; dgd low warning flag + sopmdhighalarm_flag = BOOLEAN ; sopmd high alarm flag + sopmdlowalarm_flag = BOOLEAN ; sopmd low alarm flag + sopmdhighwarning_flag = BOOLEAN ; sopmd high warning flag + sopmdlowwarning_flag = BOOLEAN ; sopmd low warning flag + pdlhighalarm_flag = BOOLEAN ; pdl high alarm flag + pdllowalarm_flag = BOOLEAN ; pdl low alarm flag + pdlhighwarning_flag = BOOLEAN ; pdl high warning flag + pdllowwarning_flag = BOOLEAN ; pdl low warning flag + osnrhighalarm_flag = BOOLEAN ; osnr high alarm flag + osnrlowalarm_flag = BOOLEAN ; osnr low alarm flag + osnrhighwarning_flag = BOOLEAN ; osnr high warning flag + osnrlowwarning_flag = BOOLEAN ; osnr low warning flag + esnrhighalarm_flag = BOOLEAN ; esnr high alarm flag + esnrlowalarm_flag = BOOLEAN ; esnr low alarm flag + esnrhighwarning_flag = BOOLEAN ; esnr high warning flag + esnrlowwarning_flag = BOOLEAN ; esnr low warning flag + cfohighalarm_flag = BOOLEAN ; cfo high alarm flag + cfolowalarm_flag = BOOLEAN ; cfo low alarm flag + cfohighwarning_flag = BOOLEAN ; cfo high warning flag + cfolowwarning_flag = BOOLEAN ; cfo low warning flag + txcurrpowerhighalarm_flag = BOOLEAN ; txcurrpower high alarm flag + txcurrpowerlowalarm_flag = BOOLEAN ; txcurrpower low alarm flag + txcurrpowerhighwarning_flag = BOOLEAN ; txcurrpower high warning flag + txcurrpowerlowwarning_flag = BOOLEAN ; txcurrpower low warning flag + rxtotpowerhighalarm_flag = BOOLEAN ; rxtotpower high alarm flag + rxtotpowerlowalarm_flag = BOOLEAN ; rxtotpower low alarm flag + rxtotpowerhighwarning_flag = BOOLEAN ; rxtotpower high warning flag + rxtotpowerlowwarning_flag = BOOLEAN ; rxtotpower low warning flag + rxsigpowerhighalarm_flag = BOOLEAN ; rxsigpower high alarm flag + rxsigpowerlowalarm_flag = BOOLEAN ; rxsigpower low alarm flag + rxsigpowerhighwarning_flag = BOOLEAN ; rxsigpower high warning flag + rxsigpowerlowwarning_flag = BOOLEAN ; rxsigpower low warning flag + ================================================================================ + """ + trans_status = dict() + trans_status['module_state'] = self.get_module_state() + trans_status['module_fault_cause'] = self.get_module_fault_cause() + dp_fw_fault, module_fw_fault, module_state_changed = self.get_module_firmware_fault_state_changed() + trans_status['datapath_firmware_fault'] = dp_fw_fault + trans_status['module_firmware_fault'] = module_fw_fault + trans_status['module_state_changed'] = module_state_changed + trans_status['datapath_firmware_fault'] = dp_fw_fault + dp_state_dict = self.get_datapath_state() + trans_status['datapath_hostlane1'] = dp_state_dict['dp_lane1'] + trans_status['datapath_hostlane2'] = dp_state_dict['dp_lane2'] + trans_status['datapath_hostlane3'] = dp_state_dict['dp_lane3'] + trans_status['datapath_hostlane4'] = dp_state_dict['dp_lane4'] + trans_status['datapath_hostlane5'] = dp_state_dict['dp_lane5'] + trans_status['datapath_hostlane6'] = dp_state_dict['dp_lane6'] + trans_status['datapath_hostlane7'] = dp_state_dict['dp_lane7'] + trans_status['datapath_hostlane8'] = dp_state_dict['dp_lane8'] + tx_output_status_dict = self.get_tx_output_status() + trans_status['txoutput_status'] = tx_output_status_dict['TX_lane1'] + rx_output_status_dict = self.get_rx_output_status() + trans_status['rxoutput_status_hostlane1'] = tx_output_status_dict['RX_lane1'] + trans_status['rxoutput_status_hostlane2'] = tx_output_status_dict['RX_lane2'] + trans_status['rxoutput_status_hostlane3'] = tx_output_status_dict['RX_lane3'] + trans_status['rxoutput_status_hostlane4'] = tx_output_status_dict['RX_lane4'] + trans_status['rxoutput_status_hostlane5'] = tx_output_status_dict['RX_lane5'] + trans_status['rxoutput_status_hostlane6'] = tx_output_status_dict['RX_lane6'] + trans_status['rxoutput_status_hostlane7'] = tx_output_status_dict['RX_lane7'] + trans_status['rxoutput_status_hostlane8'] = tx_output_status_dict['RX_lane8'] + tx_fault_dict = self.get_tx_fault() + trans_status['txfault'] = tx_output_status_dict['TX_lane1'] + tx_los_dict = self.get_tx_los() + trans_status['txlos_hostlane1'] = tx_los_dict['TX_lane1'] + trans_status['txlos_hostlane2'] = tx_los_dict['TX_lane2'] + trans_status['txlos_hostlane3'] = tx_los_dict['TX_lane3'] + trans_status['txlos_hostlane4'] = tx_los_dict['TX_lane4'] + trans_status['txlos_hostlane5'] = tx_los_dict['TX_lane5'] + trans_status['txlos_hostlane6'] = tx_los_dict['TX_lane6'] + trans_status['txlos_hostlane7'] = tx_los_dict['TX_lane7'] + trans_status['txlos_hostlane8'] = tx_los_dict['TX_lane8'] + tx_lol_dict = self.get_tx_cdr_lol() + trans_status['txcdrlol_hostlane1'] = tx_lol_dict['TX_lane1'] + trans_status['txcdrlol_hostlane2'] = tx_lol_dict['TX_lane2'] + trans_status['txcdrlol_hostlane3'] = tx_lol_dict['TX_lane3'] + trans_status['txcdrlol_hostlane4'] = tx_lol_dict['TX_lane4'] + trans_status['txcdrlol_hostlane5'] = tx_lol_dict['TX_lane5'] + trans_status['txcdrlol_hostlane6'] = tx_lol_dict['TX_lane6'] + trans_status['txcdrlol_hostlane7'] = tx_lol_dict['TX_lane7'] + trans_status['txcdrlol_hostlane8'] = tx_lol_dict['TX_lane8'] + rx_los_dict = self.get_rx_los() + trans_status['rxlos'] = rx_los_dict['RX_lane1'] + rx_lol_dict = self.get_rx_los() + trans_status['rxcdrlol'] = rx_lol_dict['RX_lane1'] + config_status_dict = self.get_config_datapath_hostlane_status() + trans_status['config_state_hostlane1'] = config_status_dict['config_DP_status_hostlane1'] + trans_status['config_state_hostlane2'] = config_status_dict['config_DP_status_hostlane2'] + trans_status['config_state_hostlane3'] = config_status_dict['config_DP_status_hostlane3'] + trans_status['config_state_hostlane4'] = config_status_dict['config_DP_status_hostlane4'] + trans_status['config_state_hostlane5'] = config_status_dict['config_DP_status_hostlane5'] + trans_status['config_state_hostlane6'] = config_status_dict['config_DP_status_hostlane6'] + trans_status['config_state_hostlane7'] = config_status_dict['config_DP_status_hostlane7'] + trans_status['config_state_hostlane8'] = config_status_dict['config_DP_status_hostlane8'] + dpinit_pending_dict = self.get_dpinit_pending() + trans_status['dpinit_pending_hostlane1'] = dpinit_pending_dict['hostlane1'] + trans_status['dpinit_pending_hostlane2'] = dpinit_pending_dict['hostlane2'] + trans_status['dpinit_pending_hostlane3'] = dpinit_pending_dict['hostlane3'] + trans_status['dpinit_pending_hostlane4'] = dpinit_pending_dict['hostlane4'] + trans_status['dpinit_pending_hostlane5'] = dpinit_pending_dict['hostlane5'] + trans_status['dpinit_pending_hostlane6'] = dpinit_pending_dict['hostlane6'] + trans_status['dpinit_pending_hostlane7'] = dpinit_pending_dict['hostlane7'] + trans_status['dpinit_pending_hostlane8'] = dpinit_pending_dict['hostlane8'] + trans_status['tuning_in_progress'] = self.get_tuning_in_progress() + trans_status['wavelength_unlock_status'] = self.get_wavelength_unlocked() + laser_tuning_summary = self.get_laser_tuning_summary() + trans_status['target_output_power_oor'] = 'TargetOutputPowerOOR' in laser_tuning_summary + trans_status['fine_tuning_oor'] = 'FineTuningOutOfRange' in laser_tuning_summary + trans_status['tuning_not_accepted'] = 'TuningNotAccepted' in laser_tuning_summary + trans_status['invalid_channel_num'] = 'InvalidChannel' in laser_tuning_summary + trans_status['tuning_complete'] = 'TuningComplete' in laser_tuning_summary + module_flag = self.get_module_level_flag() + trans_status['temphighalarm_flag'] = module_flag['case_temp_flags']['case_temp_high_alarm_flag'] + trans_status['templowalarm_flag'] = module_flag['case_temp_flags']['case_temp_low_alarm_flag'] + trans_status['temphighwarning_flag'] = module_flag['case_temp_flags']['case_temp_high_warn_flag'] + trans_status['templowwarning_flag'] = module_flag['case_temp_flags']['case_temp_low_warn_flag'] + trans_status['vcchighalarm_flag'] = module_flag['voltage_flags']['voltage_high_alarm_flag'] + trans_status['vcclowalarm_flag'] = module_flag['voltage_flags']['voltage_low_alarm_flag'] + trans_status['vcchighwarning_flag'] = module_flag['voltage_flags']['voltage_high_warn_flag'] + trans_status['vcclowwarning_flag'] = module_flag['voltage_flags']['voltage_low_warn_flag'] + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + if aux2_mon_type == 0: + trans_status['lasertemphighalarm_flag'] = module_flag['aux2_flags']['aux2_high_alarm_flag'] + trans_status['lasertemplowalarm_flag'] = module_flag['aux2_flags']['aux2_low_alarm_flag'] + trans_status['lasertemphighwarning_flag'] = module_flag['aux2_flags']['aux2_high_warn_flag'] + trans_status['lasertemplowwarning_flag'] = module_flag['aux2_flags']['aux2_low_warn_flag'] + elif aux2_mon_type == 1 and aux3_mon_type == 0: + trans_status['lasertemphighalarm_flag'] = module_flag['aux3_flags']['aux3_high_alarm_flag'] + trans_status['lasertemplowalarm_flag'] = module_flag['aux3_flags']['aux3_low_alarm_flag'] + trans_status['lasertemphighwarning_flag'] = module_flag['aux3_flags']['aux3_high_warn_flag'] + trans_status['lasertemplowwarning_flag'] = module_flag['aux3_flags']['aux3_low_warn_flag'] + + tx_power_flag_dict = self.get_tx_power_flag() + trans_status['txpowerhighalarm_flag'] = tx_power_flag_dict['tx_power_high_alarm']['TX_lane1'] + trans_status['txpowerlowalarm_flag'] = tx_power_flag_dict['tx_power_low_alarm']['TX_lane1'] + trans_status['txpowerhighwarning_flag'] = tx_power_flag_dict['tx_power_high_warn']['TX_lane1'] + trans_status['txpowerlowwarning_flag'] = tx_power_flag_dict['tx_power_low_warn']['TX_lane1'] + rx_power_flag_dict = self.get_rx_power_flag() + trans_status['rxpowerhighalarm_flag'] = rx_power_flag_dict['tx_power_high_alarm']['RX_lane1'] + trans_status['rxpowerlowalarm_flag'] = rx_power_flag_dict['tx_power_low_alarm']['RX_lane1'] + trans_status['rxpowerhighwarning_flag'] = rx_power_flag_dict['tx_power_high_warn']['RX_lane1'] + trans_status['rxpowerlowwarning_flag'] = rx_power_flag_dict['tx_power_low_warn']['RX_lane1'] + tx_bias_flag_dict = self.get_tx_bias_flag() + trans_status['txbiashighalarm_flag'] = tx_bias_flag_dict['tx_bias_high_alarm']['TX_lane1'] + trans_status['txbiaslowalarm_flag'] = tx_bias_flag_dict['tx_bias_low_alarm']['TX_lane1'] + trans_status['txbiashighwarning_flag'] = tx_bias_flag_dict['tx_bias_high_warn']['TX_lane1'] + trans_status['txbiaslowwarning_flag'] = tx_bias_flag_dict['tx_bias_low_warn']['TX_lane1'] + vdm_dict = self.get_VDM() + trans_status['prefecberhighalarm_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][5] + trans_status['prefecberlowalarm_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][6] + trans_status['prefecberhighwarning_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][7] + trans_status['prefecberlowwarning_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][8] + trans_status['postfecberhighalarm_flag'] = vdm_dict['Errored Frames Average Media Input'][1][5] + trans_status['postfecberlowalarm_flag'] = vdm_dict['Errored Frames Average Media Input'][1][6] + trans_status['postfecberhighwarning_flag'] = vdm_dict['Errored Frames Average Media Input'][1][7] + trans_status['postfecberlowwarning_flag'] = vdm_dict['Errored Frames Average Media Input'][1][8] + trans_status['biasxihighalarm_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][5] + trans_status['biasxilowalarm_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][6] + trans_status['biasxihighwarning_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][7] + trans_status['biasxilowwarning_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][8] + trans_status['biasxqhighalarm_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][5] + trans_status['biasxqlowalarm_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][6] + trans_status['biasxqhighwarning_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][7] + trans_status['biasxqlowwarning_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][8] + trans_status['biasxphighalarm_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][5] + trans_status['biasxplowalarm_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][6] + trans_status['biasxphighwarning_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][7] + trans_status['biasxplowwarning_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][8] + trans_status['biasyihighalarm_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][5] + trans_status['biasyilowalarm_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][6] + trans_status['biasyihighwarning_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][7] + trans_status['biasyilowwarning_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][8] + trans_status['biasyqhighalarm_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][5] + trans_status['biasyqlowalarm_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][6] + trans_status['biasyqhighwarning_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][7] + trans_status['biasyqlowwarning_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][8] + trans_status['biasyphighalarm_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][5] + trans_status['biasyplowalarm_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][6] + trans_status['biasyphighwarning_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][7] + trans_status['biasyplowwarning_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][8] + trans_dom_th['cdshorthighalarm_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][5] + trans_dom_th['cdshortlowalarm_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][6] + trans_dom_th['cdshorthighwarning_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][7] + trans_dom_th['cdshortlowwarning_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][8] + trans_dom_th['cdlonghighalarm_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][5] + trans_dom_th['cdlonglowalarm_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][6] + trans_dom_th['cdlonghighwarning_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][7] + trans_dom_th['cdlonglowwarning_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][8] + trans_dom_th['dgdhighalarm_flag'] = vdm_dict['DGD [ps]'][1][5] + trans_dom_th['dgdlowalarm_flag'] = vdm_dict['DGD [ps]'][1][6] + trans_dom_th['dgdhighwarning_flag'] = vdm_dict['DGD [ps]'][1][7] + trans_dom_th['dgdlowwarning_flag'] = vdm_dict['DGD [ps]'][1][8] + trans_dom_th['sopmdhighalarm_flag'] = vdm_dict['SOPMD [ps^2]'][1][5] + trans_dom_th['sopmdlowalarm_flag'] = vdm_dict['SOPMD [ps^2]'][1][6] + trans_dom_th['sopmdhighwarning_flag'] = vdm_dict['SOPMD [ps^2]'][1][7] + trans_dom_th['sopmdlowwarning_flag'] = vdm_dict['SOPMD [ps^2]'][1][8] + trans_dom_th['pdlhighalarm_flag'] = vdm_dict['PDL [dB]'][1][5] + trans_dom_th['pdllowalarm_flag'] = vdm_dict['PDL [dB]'][1][6] + trans_dom_th['pdlhighwarning_flag'] = vdm_dict['PDL [dB]'][1][7] + trans_dom_th['pdllowwarning_flag'] = vdm_dict['PDL [dB]'][1][8] + trans_dom_th['osnrhighalarm_flag'] = vdm_dict['OSNR [dB]'][1][5] + trans_dom_th['osnrlowalarm_flag'] = vdm_dict['OSNR [dB]'][1][6] + trans_dom_th['osnrhighwarning_flag'] = vdm_dict['OSNR [dB]'][1][7] + trans_dom_th['osnrlowwarning_flag'] = vdm_dict['OSNR [dB]'][1][8] + trans_dom_th['esnrhighalarm_flag'] = vdm_dict['eSNR [dB]'][1][5] + trans_dom_th['esnrlowalarm_flag'] = vdm_dict['eSNR [dB]'][1][6] + trans_dom_th['esnrhighwarning_flag'] = vdm_dict['eSNR [dB]'][1][7] + trans_dom_th['esnrlowwarning_flag'] = vdm_dict['eSNR [dB]'][1][8] + trans_dom_th['cfohighalarm_flag'] = vdm_dict['CFO [MHz]'][1][5] + trans_dom_th['cfolowalarm_flag'] = vdm_dict['CFO [MHz]'][1][6] + trans_dom_th['cfohighwarning_flag'] = vdm_dict['CFO [MHz]'][1][7] + trans_dom_th['cfolowwarning_flag'] = vdm_dict['CFO [MHz]'][1][8] + trans_dom_th['txcurrpowerhighalarm_flag'] = vdm_dict['Tx Power [dBm]'][1][5] + trans_dom_th['txcurrpowerlowalarm_flag'] = vdm_dict['Tx Power [dBm]'][1][6] + trans_dom_th['txcurrpowerhighwarning_flag'] = vdm_dict['Tx Power [dBm]'][1][7] + trans_dom_th['txcurrpowerlowwarning_flag'] = vdm_dict['Tx Power [dBm]'][1][8] + trans_dom_th['rxtotpowerhighalarm_flag'] = vdm_dict['Rx Total Power [dBm]'][1][5] + trans_dom_th['rxtotpowerlowalarm_flag'] = vdm_dict['Rx Total Power [dBm]'][1][6] + trans_dom_th['rxtotpowerhighwarning_flag'] = vdm_dict['Rx Total Power [dBm]'][1][7] + trans_dom_th['rxtotpowerlowwarning_flag'] = vdm_dict['Rx Total Power [dBm]'][1][8] + trans_dom_th['rxsigpowerhighalarm_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][5] + trans_dom_th['rxsigpowerlowalarm_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][6] + trans_dom_th['rxsigpowerhighwarning_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][7] + trans_dom_th['rxsigpowerlowwarning_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][8] + return trans_status + + def get_transceiver_PM(self): + """ + Retrieves PM for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_PM|ifname ; information of PM on port + ; field = value + prefec_ber_avg = FLOAT ; prefec ber avg + prefec_ber_min = FLOAT ; prefec ber min + prefec_ber_max = FLOAT ; prefec ber max + uncorr_frames_avg = FLOAT ; uncorrected frames ratio avg + uncorr_frames_min = FLOAT ; uncorrected frames ratio min + uncorr_frames_max = FLOAT ; uncorrected frames ratio max + cd_avg = FLOAT ; chromatic dispersion avg + cd_min = FLOAT ; chromatic dispersion min + cd_max = FLOAT ; chromatic dispersion max + dgd_avg = FLOAT ; differential group delay avg + dgd_min = FLOAT ; differential group delay min + dgd_max = FLOAT ; differential group delay max + sopmd_avg = FLOAT ; second order polarization mode dispersion avg + sopmd_min = FLOAT ; second order polarization mode dispersion min + sopmd_max = FLOAT ; second order polarization mode dispersion max + pdl_avg = FLOAT ; polarization dependent loss avg + pdl_min = FLOAT ; polarization dependent loss min + pdl_max = FLOAT ; polarization dependent loss max + osnr_avg = FLOAT ; optical signal to noise ratio avg + osnr_min = FLOAT ; optical signal to noise ratio min + osnr_max = FLOAT ; optical signal to noise ratio max + esnr_avg = FLOAT ; electrical signal to noise ratio avg + esnr_min = FLOAT ; electrical signal to noise ratio min + esnr_max = FLOAT ; electrical signal to noise ratio max + cfo_avg = FLOAT ; carrier frequency offset avg + cfo_min = FLOAT ; carrier frequency offset min + cfo_max = FLOAT ; carrier frequency offset max + soproc_avg = FLOAT ; state of polarization rate of change avg + soproc_min = FLOAT ; state of polarization rate of change min + soproc_max = FLOAT ; state of polarization rate of change max + tx_power_avg = FLOAT ; tx output power avg + tx_power_min = FLOAT ; tx output power min + tx_power_max = FLOAT ; tx output power max + rx_tot_power_avg = FLOAT ; rx total power avg + rx_tot_power_min = FLOAT ; rx total power min + rx_tot_power_max = FLOAT ; rx total power max + rx_sig_power_avg = FLOAT ; rx signal power avg + rx_sig_power_min = FLOAT ; rx signal power min + rx_sig_power_max = FLOAT ; rx signal power max + ======================================================================== + """ + trans_pm = dict() + PM_dict = self.get_PM() + trans_pm['prefec_ber_avg'] = PM_dict['preFEC_BER_avg'] + trans_pm['prefec_ber_min'] = PM_dict['preFEC_BER_min'] + trans_pm['prefec_ber_max'] = PM_dict['preFEC_BER_max'] + trans_pm['uncorr_frames_avg'] = PM_dict['preFEC_uncorr_frame_ratio_avg'] + trans_pm['uncorr_frames_min'] = PM_dict['preFEC_uncorr_frame_ratio_min'] + trans_pm['uncorr_frames_max'] = PM_dict['preFEC_uncorr_frame_ratio_max'] + trans_pm['cd_avg'] = PM_dict['rx_cd_avg'] + trans_pm['cd_min'] = PM_dict['rx_cd_min'] + trans_pm['cd_max'] = PM_dict['rx_cd_max'] + trans_pm['dgd_avg'] = PM_dict['rx_dgd_avg'] + trans_pm['dgd_min'] = PM_dict['rx_dgd_min'] + trans_pm['dgd_max'] = PM_dict['rx_dgd_max'] + trans_pm['sopmd_avg'] = PM_dict['rx_sopmd_avg'] + trans_pm['sopmd_min'] = PM_dict['rx_sopmd_min'] + trans_pm['sopmd_max'] = PM_dict['rx_sopmd_max'] + trans_pm['pdl_avg'] = PM_dict['rx_pdl_avg'] + trans_pm['pdl_min'] = PM_dict['rx_pdl_min'] + trans_pm['pdl_max'] = PM_dict['rx_pdl_max'] + trans_pm['osnr_avg'] = PM_dict['rx_osnr_avg'] + trans_pm['osnr_min'] = PM_dict['rx_osnr_min'] + trans_pm['osnr_max'] = PM_dict['rx_osnr_max'] + trans_pm['esnr_avg'] = PM_dict['rx_esnr_avg'] + trans_pm['esnr_min'] = PM_dict['rx_esnr_min'] + trans_pm['esnr_max'] = PM_dict['rx_esnr_max'] + trans_pm['cfo_avg'] = PM_dict['rx_cfo_avg'] + trans_pm['cfo_min'] = PM_dict['rx_cfo_min'] + trans_pm['cfo_max'] = PM_dict['rx_cfo_max'] + trans_pm['soproc_avg'] = PM_dict['rx_soproc_avg'] + trans_pm['soproc_min'] = PM_dict['rx_soproc_min'] + trans_pm['soproc_max'] = PM_dict['rx_soproc_max'] + trans_pm['tx_power_avg'] = PM_dict['tx_power_avg'] + trans_pm['tx_power_min'] = PM_dict['tx_power_min'] + trans_pm['tx_power_max'] = PM_dict['tx_power_max'] + trans_pm['rx_tot_power_avg'] = PM_dict['rx_tot_power_avg'] + trans_pm['rx_tot_power_min'] = PM_dict['rx_tot_power_min'] + trans_pm['rx_tot_power_max'] = PM_dict['rx_tot_power_max'] + trans_pm['rx_sig_power_avg'] = PM_dict['rx_sig_power_avg'] + trans_pm['rx_sig_power_min'] = PM_dict['rx_sig_power_min'] + trans_pm['rx_sig_power_max'] = PM_dict['rx_sig_power_max'] + return trans_pm + + def get_transceiver_loopback(self): + """ + Retrieves loopback mode for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_PM|ifname ; information of loopback on port + ; field = value + media_output_loopback = BOOLEAN ; media side output loopback enable + media_input_loopback = BOOLEAN ; media side input loopback enable + host_output_loopback_lane1 = BOOLEAN ; host side output loopback enable lane1 + host_output_loopback_lane2 = BOOLEAN ; host side output loopback enable lane2 + host_output_loopback_lane3 = BOOLEAN ; host side output loopback enable lane3 + host_output_loopback_lane4 = BOOLEAN ; host side output loopback enable lane4 + host_output_loopback_lane5 = BOOLEAN ; host side output loopback enable lane5 + host_output_loopback_lane6 = BOOLEAN ; host side output loopback enable lane6 + host_output_loopback_lane7 = BOOLEAN ; host side output loopback enable lane7 + host_output_loopback_lane8 = BOOLEAN ; host side output loopback enable lane8 + host_input_loopback_lane1 = BOOLEAN ; host side input loopback enable lane1 + host_input_loopback_lane2 = BOOLEAN ; host side input loopback enable lane2 + host_input_loopback_lane3 = BOOLEAN ; host side input loopback enable lane3 + host_input_loopback_lane4 = BOOLEAN ; host side input loopback enable lane4 + host_input_loopback_lane5 = BOOLEAN ; host side input loopback enable lane5 + host_input_loopback_lane6 = BOOLEAN ; host side input loopback enable lane6 + host_input_loopback_lane7 = BOOLEAN ; host side input loopback enable lane7 + host_input_loopback_lane8 = BOOLEAN ; host side input loopback enable lane8 + ======================================================================== + """ + trans_loopback = dict() + trans_loopback['media_output_loopback'] = self.get_media_output_loopback() + trans_loopback['media_input_loopback'] = self.get_media_input_loopback() + host_output_loopback_status = self.get_host_output_loopback() + trans_loopback['host_output_loopback_lane1'] = host_output_loopback_status[0] + trans_loopback['host_output_loopback_lane2'] = host_output_loopback_status[1] + trans_loopback['host_output_loopback_lane3'] = host_output_loopback_status[2] + trans_loopback['host_output_loopback_lane4'] = host_output_loopback_status[3] + trans_loopback['host_output_loopback_lane5'] = host_output_loopback_status[4] + trans_loopback['host_output_loopback_lane6'] = host_output_loopback_status[5] + trans_loopback['host_output_loopback_lane7'] = host_output_loopback_status[6] + trans_loopback['host_output_loopback_lane8'] = host_output_loopback_status[7] + host_input_loopback_status = self.get_host_input_loopback() + trans_loopback['host_input_loopback_lane1'] = host_input_loopback_status[0] + trans_loopback['host_input_loopback_lane2'] = host_input_loopback_status[1] + trans_loopback['host_input_loopback_lane3'] = host_input_loopback_status[2] + trans_loopback['host_input_loopback_lane4'] = host_input_loopback_status[3] + trans_loopback['host_input_loopback_lane5'] = host_input_loopback_status[4] + trans_loopback['host_input_loopback_lane6'] = host_input_loopback_status[5] + trans_loopback['host_input_loopback_lane7'] = host_input_loopback_status[6] + trans_loopback['host_input_loopback_lane8'] = host_input_loopback_status[7] # TODO: other XcvrApi methods diff --git a/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py b/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py index 302dae3f6..2beaecbe7 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py @@ -35,6 +35,13 @@ class CmisCode(XcvrCodes): 5: 'ModuleFault', } + MODULE_FAULT_CAUSE = { + 0: 'No Fault detected', + 1: 'TEC runawawy', + 2: 'Data memory corrupted', + 3: 'Program memory corrupted', + } + DATAPATH_STATE = { 1: 'DataPathDeactivated', 2: 'DataPathInit', @@ -78,7 +85,7 @@ class CmisCode(XcvrCodes): 17: ['Errored Frames Minimum Media Input', 'F16', 1], 18: ['Errored Frames Minimum Host Input', 'F16', 1], 19: ['Errored Frames Maximum Media Input', 'F16', 1], - 20: ['Errored Frames Minimum Host Input', 'F16', 1], + 20: ['Errored Frames Maximum Host Input', 'F16', 1], 21: ['Errored Frames Average Media Input', 'F16', 1], 22: ['Errored Frames Average Host Input', 'F16', 1], 23: ['Errored Frames Current Value Media Input', 'F16', 1], diff --git a/sonic_platform_base/sonic_xcvr/fields/consts.py b/sonic_platform_base/sonic_xcvr/fields/consts.py index d7c90e06d..e96c81181 100644 --- a/sonic_platform_base/sonic_xcvr/fields/consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/consts.py @@ -109,6 +109,7 @@ MODULE_FLAG_BYTE2 = "ModuleFlagByte2" MODULE_FLAG_BYTE3 = "ModuleFlagByte3" CDB1_STATUS = "Cdb1Status" +MODULE_FAULT_CAUSE = "ModuleFaultCause" DATAPATH_STATE= "DataPathStateHostLane" TX_OUTPUT_STATUS = "TxOutputStatus" RX_OUTPUT_STATUS = "RxOutputStatus" 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 d0b42c704..3a2131a21 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -135,6 +135,7 @@ def __init__(self, codes): NumberRegField(consts.MODULE_FLAG_BYTE2, get_addr(0x0, 10), size=1), NumberRegField(consts.MODULE_FLAG_BYTE3, get_addr(0x0, 11), size=1), NumberRegField(consts.CDB1_STATUS, get_addr(0x0, 37), size=1), + CodeRegField(consts.MODULE_FAULT_CAUSE, get_addr(0x0, 41), self.codes['cmis_code'].MODULE_FAULT_CAUSE), ) self.TRANS_LANE_STATUS = RegGroupField(consts.TRANS_LANE_STATUS_FIELD, From a92e153e487022e776b29ccb1b9c1144e9b5d729 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Wed, 13 Oct 2021 13:30:09 -0700 Subject: [PATCH 10/16] 1. resolve LGTM warnings. 2. add descriptions in FW related functions. 3. add function module_firmware_switch to switch between A/B image --- .../sonic_xcvr/api/public/c_cmis.py | 2 - .../sonic_xcvr/api/public/cmis.py | 118 ++++++++++++++---- .../sonic_xcvr/api/public/cmisCDB.py | 2 +- .../sonic_xcvr/api/public/cmisVDM.py | 1 - .../sonic_xcvr/fields/consts.py | 12 -- .../sonic_xcvr/mem_maps/public/cmis.py | 8 +- tests/sonic_xcvr/test_ccmis.py | 14 +-- 7 files changed, 103 insertions(+), 54 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index 7132a8eb8..d84b8f772 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -5,8 +5,6 @@ """ from ...fields import consts from ..xcvr_api import XcvrApi -from .cmisCDB import CmisCdbApi -from .cmisVDM import CmisVdmApi import time BYTELENGTH = 8 class CCmisApi(XcvrApi): diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index f97a27570..bf87ad109 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -28,13 +28,13 @@ def get_vendor_rev(self): ''' This function returns the revision level for part number provided by vendor ''' - return self.xcvr_eeprom.read(consts.VENDOR_REV) + return self.xcvr_eeprom.read(consts.VENDOR_REV_FIELD) def get_vendor_serial(self): ''' This function returns the serial number of the module ''' - return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO) + return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO_FIELD) def get_vendor_name(self): ''' @@ -58,13 +58,13 @@ def get_vendor_date(self): ''' This function returns the module manufacture date. It returns YYMMDDXX. XX is the lot code. ''' - return self.xcvr_eeprom.read(consts.VENDOR_DATE) + return self.xcvr_eeprom.read(consts.VENDOR_DATE_FIELD) def get_connector_type(self): ''' This function returns module connector. Table 4-3 in SFF-8024 Rev4.6 ''' - return self.xcvr_eeprom.read(consts.CONNECTOR_TYPE) + return self.xcvr_eeprom.read(consts.CONNECTOR_FIELD) def get_module_media_type(self): ''' @@ -193,7 +193,6 @@ def get_module_temperature(self): ''' This function returns the module case temperature and its thresholds. Unit in deg C ''' - case_temp_dict = dict() case_temp = self.xcvr_eeprom.read(consts.CASE_TEMP) case_temp_high_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_ALARM) case_temp_low_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_ALARM) @@ -211,7 +210,6 @@ def get_module_voltage(self): This function returns the monitored value of the 3.3-V supply voltage and its thresholds. Unit in V ''' - voltage_dict = dict() voltage = self.xcvr_eeprom.read(consts.VOLTAGE) voltage_high_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_ALARM) voltage_low_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_ALARM) @@ -228,7 +226,6 @@ def get_txpower(self): ''' This function returns the TX output power. Unit in mW ''' - tx_power_dict = dict() tx_power = self.xcvr_eeprom.read(consts.TX_POW) tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM) tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM) @@ -245,7 +242,6 @@ def get_rxpower(self): ''' This function returns the RX input power. Unit in mW ''' - rx_power_dict = dict() rx_power = self.xcvr_eeprom.read(consts.RX_POW) rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM) rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM) @@ -262,7 +258,6 @@ def get_txbias(self): ''' This function returns the TX laser bias current. Unit in mA ''' - tx_bias_current_dict = dict() tx_bias_current = self.xcvr_eeprom.read(consts.TX_BIAS) tx_bias_current_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_ALARM) tx_bias_current_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_ALARM) @@ -371,7 +366,6 @@ def get_laser_temperature(self): ''' aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() LASER_TEMP_SCALE = 256.0 - laser_temp_dict = dict() if aux2_mon_type == 0: laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEMP_SCALE @@ -399,7 +393,6 @@ def get_laser_TEC_current(self): ''' aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() LASER_TEC_CURRENT_SCALE = 32767.0 - laser_tec_current_dict = dict() if aux1_mon_type == 1: laser_tec_current = self.xcvr_eeprom.read(consts.AUX1_MON)/LASER_TEC_CURRENT_SCALE laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX1_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE @@ -441,7 +434,7 @@ def get_VDM(self): ''' try: self.vdm - except: + except AttributeError: self.get_VDM_api() VDM = self.vdm.get_VDM_allpage() return VDM @@ -456,7 +449,7 @@ def get_PM(self): ''' try: self.ccmis - except: + except AttributeError: self.get_ccmis_api() PM_dict = self.ccmis.get_PM_all() return PM_dict @@ -745,8 +738,6 @@ def get_config_datapath_hostlane_status(self): config_status_lane4 = (result >> 20) & 0xf config_status_lane1 = (result >> 24) & 0xf config_status_lane2 = (result >> 28) & 0xf - config_status_raw = [config_status_lane1, config_status_lane2, config_status_lane3, config_status_lane4, - config_status_lane5, config_status_lane6, config_status_lane7, config_status_lane8] DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].CONFIG_STATUS config_status_dict = {'config_DP_status_hostlane1': DICT.get(config_status_lane1, "Unknown"), 'config_DP_status_hostlane2': DICT.get(config_status_lane2, "Unknown"), @@ -930,9 +921,15 @@ def get_CDB_api(self): self.cdb = CmisCdbApi(self.xcvr_eeprom) def get_module_FW_upgrade_feature(self, verbose = False): + """ + This function obtains CDB features supported by the module from CDB command 0041h, + such as start header size, maximum block size, whether extended payload messaging + (page 0xA0 - 0xAF) or only local payload is supported. These features are important because + the following upgrade with depend on these parameters. + """ try: self.cdb - except: + except AttributeError: self.get_CDB_api() # get fw upgrade features (CMD 0041h) starttime = time.time() @@ -970,9 +967,16 @@ def get_module_FW_upgrade_feature(self, verbose = False): return startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength def get_module_FW_info(self): + """ + This function returns firmware Image A and B version, running version, committed version + and whether both firmware images are valid. + Operational Status: 1 = running, 0 = not running + Administrative Status: 1=committed, 0=uncommitted + Validity Status: 1 = invalid, 0 = valid + """ try: self.cdb - except: + except AttributeError: self.get_CDB_api() # get fw info (CMD 0100h) starttime = time.time() @@ -982,14 +986,18 @@ def get_module_FW_info(self): # Regiter 9Fh:136 fwStatus = rpl[0] # Registers 9Fh:138,139; 140,141 - print('Image A Version: %d.%d; BuildNum: %d' %(rpl[2], rpl[3], ((rpl[4]<< 8) | rpl[5]))) + ImageA = '%d.%d.%d' %(rpl[2], rpl[3], ((rpl[4]<< 8) | rpl[5])) + print('Image A Version: %s' %ImageA) # Registers 9Fh:174,175; 176.177 - print('Image B Version: %d.%d; BuildNum: %d' %(rpl[38], rpl[39], ((rpl[40]<< 8) | rpl[41]))) + ImageB = '%d.%d.%d' %(rpl[38], rpl[39], ((rpl[40]<< 8) | rpl[41])) + print('Image B Version: %s' %ImageB) ImageARunning = (fwStatus & 0x01) # bit 0 - image A is running ImageACommitted = ((fwStatus >> 1) & 0x01) # bit 1 - image A is committed + ImageAValid = ((fwStatus >> 2) & 0x01) # bit 2 - image A is valid ImageBRunning = ((fwStatus >> 4) & 0x01) # bit 4 - image B is running ImageBCommitted = ((fwStatus >> 5) & 0x01) # bit 5 - image B is committed + ImageBValid = ((fwStatus >> 6) & 0x01) # bit 6 - image B is valid if ImageARunning == 1: RunningImage = 'A' @@ -1004,15 +1012,28 @@ def get_module_FW_info(self): raise ValueError('Reply payload check code error') elapsedtime = time.time()-starttime print('Get module FW info time: %.2f s' %elapsedtime) + return ImageA, ImageARunning, ImageACommitted, ImageAValid, ImageB, ImageBRunning, ImageBCommitted, ImageBValid - def module_FW_run(self): + def module_FW_run(self, mode = 0x01): + """ + This command is used to start and run a selected image. + This command transfers control from the currently + running firmware to a selected firmware that is started. It + can be used to switch between firmware versions, or to + perform a restart of the currently running firmware. + mode: + 00h = Traffic affecting Reset to Inactive Image. + 01h = Attempt Hitless Reset to Inactive Image + 02h = Traffic affecting Reset to Running Image. + 03h = Attempt Hitless Reset to Running Image + """ try: self.cdb - except: + except AttributeError: self.get_CDB_api() # run module FW (CMD 0109h) starttime = time.time() - _, FW_run_status, _ = self.cdb.cmd0109h() + FW_run_status = self.cdb.cmd0109h(mode) if FW_run_status == 1: print('Module FW run: Success') else: @@ -1022,13 +1043,17 @@ def module_FW_run(self): print('Module FW run time: %.2f s\n' %elapsedtime) def module_FW_commit(self): + """ + The host uses this command to commit the running image + so that the module will boot from it on future boots. + """ try: self.cdb - except: + except AttributeError: self.get_CDB_api() # commit module FW (CMD 010Ah) starttime = time.time() - _, FW_run_status, _ = self.cdb.cmd010Ah() + FW_commit_status= self.cdb.cmd010Ah() if FW_commit_status == 1: print('Module FW commit: Success') else: @@ -1038,9 +1063,24 @@ def module_FW_commit(self): print('Module FW commit time: %.2f s\n' %elapsedtime) def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath): + """ + This function performs the download of a firmware image to module eeprom + It starts CDB download by writing the header of start header size + from the designated firmware file to the local payload page 0x9F, with CDB command 0101h. + + Then it repeatedly reads from the given firmware file and write to the payload + space advertised from the first step. We use CDB command 0103h to write to the local payload; + we use CDB command 0104h to write to the extended paylaod. This step repeats until it reaches + end of the firmware file, or the CDB status failed. + + The last step is to complete the firmware upgrade with CDB command 0107h. + + Note that if the download process fails anywhere in the middle, we need to run CDB command 0102h + to abort the upgrade before we restart another upgrade process. + """ try: self.cdb - except: + except AttributeError: self.get_CDB_api() # start fw download (CMD 0101h) starttime = time.time() @@ -1098,14 +1138,38 @@ def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin print('Complete module FW download time: %.2f s\n' %elapsedtime) def module_firmware_upgrade(self, imagepath): + """ + This function performs firmware upgrade. + 1. show FW version in the beginning + 2. check module advertised FW download capability + 3. configure download + 4. show download progress + 5. configure run downloaded firmware + 6. configure commit downloaded firmware + 7. show FW version in the end + """ self.get_module_FW_info() startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength = self.get_module_FW_upgrade_feature() self.module_FW_download(startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath) - self.module_FW_run() + self.module_FW_run(mode = 0x01) time.sleep(60) self.module_FW_commit() self.get_module_FW_info() + def module_firmware_switch(self): + """ + This function switch the active/inactive module firmwarein the current module memory + """ + _, _, _, ImageAValid, _, _, _, ImageBValid = self.get_module_FW_info() + if ImageAValid == 0 and ImageBValid == 0: + self.module_FW_run(mode = 0x01) + time.sleep(60) + self.module_FW_commit() + self.get_module_FW_info() + else: + print('Not both images are valid.') + + def get_transceiver_info(self): """ Retrieves transceiver info of this SFP @@ -1690,7 +1754,7 @@ def get_transceiver_status(self): trans_status['rxoutput_status_hostlane7'] = rx_output_status_dict['RX_lane7'] trans_status['rxoutput_status_hostlane8'] = rx_output_status_dict['RX_lane8'] tx_fault_dict = self.get_tx_fault() - trans_status['txfault'] = tx_output_status_dict['TX_lane1'] + trans_status['txfault'] = tx_fault_dict['TX_lane1'] tx_los_dict = self.get_tx_los() trans_status['txlos_hostlane1'] = tx_los_dict['TX_lane1'] trans_status['txlos_hostlane2'] = tx_los_dict['TX_lane2'] diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py index a520b14d2..4540d0e19 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py @@ -332,7 +332,7 @@ def cmd0107h(self): # 01h = Attempt Hitless Reset to Inactive Image # 02h = Traffic affecting Reset to Running Image. # 03h = Attempt Hitless Reset to Running Image - def cmd0109h(self, mode=0x01): + def cmd0109h(self, mode = 0x01): cmd = bytearray(b'\x01\x09\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00') cmd[137-INIT_OFFSET] = mode cmd[138-INIT_OFFSET] = 2 # Delay to Reset 512 ms diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py index c6a9bcbae..05a2de767 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py @@ -51,7 +51,6 @@ def get_VDM_page(self, page, VDM_flag_page): vdm_high_warn_offset = vdm_high_alarm_offset + 4 vdm_low_warn_offset = vdm_high_alarm_offset + 6 - thrshID = VDM_thresholdID[index] vdm_value_raw = self.xcvr_eeprom.read_flexible(vdm_value_offset, VDM_SIZE, True) vdm_thrsh_high_alarm_raw = self.xcvr_eeprom.read_flexible(vdm_high_alarm_offset, VDM_SIZE, True) vdm_thrsh_low_alarm_raw = self.xcvr_eeprom.read_flexible(vdm_low_alarm_offset, VDM_SIZE, True) diff --git a/sonic_platform_base/sonic_xcvr/fields/consts.py b/sonic_platform_base/sonic_xcvr/fields/consts.py index f2a85e496..8db6c8304 100644 --- a/sonic_platform_base/sonic_xcvr/fields/consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/consts.py @@ -108,15 +108,6 @@ # CMIS ADMIN_INFO_FIELD = "AdminInfo" -ID_FIELD = "Identifier" -ID_ABBRV_FIELD = "Identifier Abbreviation" -VENDOR_NAME_FIELD = "VendorName" -VENDOR_OUI_FIELD = "VendorOUI" -VENDOR_PART_NO_FIELD = "VendorPN" -VENDOR_REV = "VendorRev" -VENDOR_SERIAL_NO = "VendorSN" -VENDOR_DATE = "DateCode" -CONNECTOR_TYPE = "ConnectorType" MODULE_MEDIA_TYPE = "ModuleMediaType" HOST_ELECTRICAL_INTERFACE = "HostElectricalInterfaceID" MODULE_MEDIA_INTERFACE_850NM = "ModuleMediaInterface850nm" @@ -303,9 +294,6 @@ RX_AVG_POWER_PM = "rxAvgPowerPm" RX_MIN_POWER_PM = "rxMinPowerPm" RX_MAX_POWER_PM = "rxMaxPowerPm" -RX_AVG_POWER_PM = "rxAvgPowerPm" -RX_MIN_POWER_PM = "rxMinPowerPm" -RX_MAX_POWER_PM = "rxMaxPowerPm" RX_AVG_SIG_POWER_PM = "rxAvgSigPowerPm" RX_MIN_SIG_POWER_PM = "rxMinSigPowerPm" RX_MAX_SIG_POWER_PM = "rxMaxSigPowerPm" 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 946791bd2..c65fc882d 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -30,10 +30,10 @@ def __init__(self, codes): StringRegField(consts.VENDOR_NAME_FIELD, get_addr(0x0, 129), size=16), HexRegField(consts.VENDOR_OUI_FIELD, get_addr(0x0, 145), size=3), StringRegField(consts.VENDOR_PART_NO_FIELD, get_addr(0x0, 148), size=16), - StringRegField(consts.VENDOR_REV, get_addr(0x0, 164), size=2), - StringRegField(consts.VENDOR_SERIAL_NO, get_addr(0x0, 166), size=16), - StringRegField(consts.VENDOR_DATE,get_addr(0x0,182), size = 8), - CodeRegField(consts.CONNECTOR_TYPE, get_addr(0x0, 203), self.codes['sff8024'].CONNECTORS), + StringRegField(consts.VENDOR_REV_FIELD, get_addr(0x0, 164), size=2), + StringRegField(consts.VENDOR_SERIAL_NO_FIELD, get_addr(0x0, 166), size=16), + StringRegField(consts.VENDOR_DATE_FIELD,get_addr(0x0,182), size = 8), + CodeRegField(consts.CONNECTOR_FIELD, get_addr(0x0, 203), self.codes['sff8024'].CONNECTORS), CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, get_addr(0x0, 86), self.codes['sff8024'].HOST_ELECTRICAL_INTERFACE), CodeRegField(consts.MODULE_MEDIA_TYPE, get_addr(0x0, 85), self.codes['sff8024'].MODULE_MEDIA_TYPE), CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, get_addr(0x0, 87), self.codes['sff8024'].NM_850_MEDIA_INTERFACE), diff --git a/tests/sonic_xcvr/test_ccmis.py b/tests/sonic_xcvr/test_ccmis.py index c4d40fa22..3d59f7927 100644 --- a/tests/sonic_xcvr/test_ccmis.py +++ b/tests/sonic_xcvr/test_ccmis.py @@ -1,10 +1,10 @@ -from mock import MagicMock -import pytest -from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi -from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap -from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom -from sonic_platform_base.sonic_xcvr.codes.public.sff8024 import Sff8024 -from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode +# from mock import MagicMock +# import pytest +# from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi +# from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap +# from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom +# from sonic_platform_base.sonic_xcvr.codes.public.sff8024 import Sff8024 +# from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode class TestCCmis(object): pass From ccc320aa85a0303d4986590691923b4f3cbd6ad9 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Wed, 13 Oct 2021 19:34:32 -0700 Subject: [PATCH 11/16] add unit test cases for sonic_xcvr/api/public/cmis.py --- .../sonic_xcvr/api/public/cmis.py | 14 +- .../sonic_xcvr/api/public/cmisCDB.py | 5 +- .../sonic_xcvr/mem_maps/public/cmis.py | 8 +- tests/sonic_xcvr/test_cmis.py | 682 +++++++++++++++++- 4 files changed, 697 insertions(+), 12 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index bf87ad109..2b3cbc178 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -1118,9 +1118,12 @@ def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin data = f.read(count) progress = (imagesize - remaining) * 100.0 / imagesize if lplonly_flag: - self.cdb.cmd0103h(address, data) + FW_download_status = self.cdb.cmd0103h(address, data) else: - self.cdb.cmd0104h(address, data, autopaging_flag, writelength) + FW_download_status = self.cdb.cmd0104h(address, data, autopaging_flag, writelength) + if FW_download_status != 1: + print('CDB download failed. CDB Status: %d' %FW_download_status) + exit(1) elapsedtime = time.time()-starttime print('Address: {:#08x}; Count: {}; Progress: {:.2f}%; Time: {:.2f}s'.format(address, count, progress, elapsedtime)) address += count @@ -1128,6 +1131,7 @@ def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin elapsedtime = time.time()-starttime print('Total module FW download time: %.2f s' %elapsedtime) + time.sleep(2) # complete FW download (CMD 0107h) FW_complete_status = self.cdb.cmd0107h() if FW_complete_status == 1: @@ -1220,7 +1224,6 @@ def get_transceiver_info(self): trans_info['media_lane_count'] = self.get_media_lane_count() trans_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option() trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() - trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() apsel_dict = self.get_active_apsel_hostlane() trans_info['active_apsel_hostlane1'] = apsel_dict['hostlane1'] trans_info['active_apsel_hostlane2'] = apsel_dict['hostlane2'] @@ -1243,7 +1246,7 @@ def get_transceiver_info(self): trans_info['inactive_firmware'] = self.get_module_inactive_firmware() min_power, max_power = self.get_supported_power_config() trans_info['supported_max_tx_power'] = max_power - trans_info['supported_max_tx_power'] = min_power + trans_info['supported_min_tx_power'] = min_power _, _, _, low_freq_supported, high_freq_supported = self.get_supported_freq_config() trans_info['supported_max_laser_freq'] = high_freq_supported trans_info['supported_min_laser_freq'] = low_freq_supported @@ -1732,7 +1735,6 @@ def get_transceiver_status(self): trans_status['datapath_firmware_fault'] = dp_fw_fault trans_status['module_firmware_fault'] = module_fw_fault trans_status['module_state_changed'] = module_state_changed - trans_status['datapath_firmware_fault'] = dp_fw_fault dp_state_dict = self.get_datapath_state() trans_status['datapath_hostlane1'] = dp_state_dict['dp_lane1'] trans_status['datapath_hostlane2'] = dp_state_dict['dp_lane2'] @@ -1775,7 +1777,7 @@ def get_transceiver_status(self): trans_status['txcdrlol_hostlane8'] = tx_lol_dict['TX_lane8'] rx_los_dict = self.get_rx_los() trans_status['rxlos'] = rx_los_dict['RX_lane1'] - rx_lol_dict = self.get_rx_los() + rx_lol_dict = self.get_rx_cdr_lol() trans_status['rxcdrlol'] = rx_lol_dict['RX_lane1'] config_status_dict = self.get_config_datapath_hostlane_status() trans_status['config_state_hostlane1'] = config_status_dict['config_DP_status_hostlane1'] diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py index 4540d0e19..503b212a6 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py @@ -10,6 +10,7 @@ INIT_OFFSET = 128 CMDLEN = 2 MAX_TRY = 3 +MAX_WAIT = 10 class CmisCdbApi(XcvrApi): def __init__(self, xcvr_eeprom): @@ -109,9 +110,11 @@ def cdb1_chkstatus(self): ''' status = self.xcvr_eeprom.read(consts.CDB1_STATUS) is_busy = bool((status >> 7) & 0x1) - while is_busy: + cnt = 0 + while is_busy and cnt < MAX_WAIT: time.sleep(1) is_busy = bool((status >> 7) & 0x1) + cnt += 1 return status def write_cdb(self, cmd): 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 c65fc882d..eb4439985 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -93,10 +93,10 @@ def __init__(self, codes): NumberRegField(consts.CASE_TEMP_LOW_ALARM, get_addr(0x2, 130), format=">h", size=2, scale=256.0), NumberRegField(consts.CASE_TEMP_HIGH_WARN, get_addr(0x2, 132), format=">h", size=2, scale=256.0), NumberRegField(consts.CASE_TEMP_LOW_WARN, get_addr(0x2, 134), format=">h", size=2, scale=256.0), - NumberRegField(consts.VOLTAGE_HIGH_ALARM, get_addr(0x2, 136), format=">h", size=2, scale=10000.0), - NumberRegField(consts.VOLTAGE_LOW_ALARM, get_addr(0x2, 138), format=">h", size=2, scale=10000.0), - NumberRegField(consts.VOLTAGE_HIGH_WARN, get_addr(0x2, 140), format=">h", size=2, scale=10000.0), - NumberRegField(consts.VOLTAGE_LOW_WARN, get_addr(0x2, 142), format=">h", size=2, scale=10000.0), + NumberRegField(consts.VOLTAGE_HIGH_ALARM, get_addr(0x2, 136), format=">H", size=2, scale=10000.0), + NumberRegField(consts.VOLTAGE_LOW_ALARM, get_addr(0x2, 138), format=">H", size=2, scale=10000.0), + NumberRegField(consts.VOLTAGE_HIGH_WARN, get_addr(0x2, 140), format=">H", size=2, scale=10000.0), + NumberRegField(consts.VOLTAGE_LOW_WARN, get_addr(0x2, 142), format=">H", size=2, scale=10000.0), NumberRegField(consts.AUX1_HIGH_ALARM, get_addr(0x2, 144), format=">h", size=2), NumberRegField(consts.AUX1_LOW_ALARM, get_addr(0x2, 146), format=">h", size=2), NumberRegField(consts.AUX1_HIGH_WARN, get_addr(0x2, 148), format=">h", size=2), diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 08904f1c7..3b012eac9 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -416,6 +416,34 @@ def test_get_custom_field(self, input_param, mock_response, expected): result = api.get_custom_field(*input_param) assert result == expected + @pytest.mark.parametrize("mock_response, expected",[ + ( + {'preFEC_BER_avg': 0.001}, + {'preFEC_BER_avg': 0.001} + ) + ]) + def test_get_PM(self, mock_response, expected): + api = self.mock_cmis_api() + api.ccmis = MagicMock() + api.ccmis.get_PM_all = MagicMock() + api.ccmis.get_PM_all.return_value = mock_response + result = api.get_PM() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + {'Pre-FEC BER Average Media Input': {1: [0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}}, + {'Pre-FEC BER Average Media Input': {1: [0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}} + ) + ]) + def test_get_VDM(self, mock_response, expected): + api = self.mock_cmis_api() + api.vdm = MagicMock() + api.vdm.get_VDM_allpage = MagicMock() + api.vdm.get_VDM_allpage.return_value = mock_response + result = api.get_VDM() + assert result == expected + # @pytest.mark.parametrize("mock_response, expected", [ # ([100000000, 1000000, 100000, 800, 1200, # preFEC_BER # 10000, 100, 0, 0, 0, # uncorr_frame @@ -962,9 +990,661 @@ def test_get_module_FW_upgrade_feature(self, mock_response1, mock_response2, exp api.xcvr_eeprom.read.side_effect = mock_response1 api.cdb = MagicMock() api.cdb.cmd0041h = MagicMock() - api.cdb.cmd0041h.return_value = mock_response2 + api.cdb.cmd0041h.return_value = mock_response2 api.cdb.cdb_chkcode = MagicMock() api.cdb.cdb_chkcode.return_value = mock_response2[1] result = api.get_module_FW_upgrade_feature() assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([110, 26, (3, 3, 1, 1, 0, 4, 1, 4, 3, 0, 0, 100, 3, 232, 19, 136, 58, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 4, 1, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)], + ('1.1.4', 1, 1, 0, '1.1.4', 0, 0, 0) + ) + ]) + def test_get_module_FW_info(self, mock_response, expected): + api = self.mock_cmis_api() + api.cdb = MagicMock() + api.cdb.cmd0100h = MagicMock() + api.cdb.cmd0100h.return_value = mock_response + api.cdb.cdb_chkcode = MagicMock() + api.cdb.cdb_chkcode.return_value = mock_response[1] + result = api.get_module_FW_info() + assert result == expected # TODO: call other methods in the api + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + 'Single Mode Fiber (SMF)', + '400GAUI-8 C2M (Annex 120E)', + '400ZR, DWDM, amplified', + 8, 1, 1, 1, + {'hostlane1': 1, 'hostlane2': 1, 'hostlane3': 1, 'hostlane4': 1, + 'hostlane5': 1, 'hostlane6': 1, 'hostlane7': 1, 'hostlane8': 1}, + '1550 nm DFB', + '0.0', + '00000000', + 'VENDOR_NAME', + '0.0', + 'xx-xx-xx', + '21010100', + 'LC', + '5.0', + '0.1', + '0.0', + (-20, 0), + (0xff, -72, 120, 191300, 196100) + ], + { + 'active_firmware': '0.1', + 'media_lane_count': 1, + 'supported_min_laser_freq': 191300, + 'inactive_firmware': '0.0', + 'vendor_rev': '0.0', + 'host_electrical_interface': '400GAUI-8 C2M (Annex 120E)', + 'vendor_oui': 'xx-xx-xx', + 'manufacturename': 'VENDOR_NAME', + 'media_interface_technology': '1550 nm DFB', + 'media_interface_code': '400ZR, DWDM, amplified', + 'serialnum': '00000000', + 'module_media_type': 'Single Mode Fiber (SMF)', + 'host_lane_count': 8, + 'active_apsel_hostlane1': 1, + 'active_apsel_hostlane3': 1, + 'active_apsel_hostlane2': 1, + 'active_apsel_hostlane5': 1, + 'active_apsel_hostlane4': 1, + 'active_apsel_hostlane7': 1, + 'active_apsel_hostlane6': 1, + 'supported_max_laser_freq': 196100, + 'active_apsel_hostlane8': 1, + 'hardwarerev': '0.0', + 'specification_compliance': '5.0', + 'media_lane_assignment_option': 1, + 'connector_type': 'LC', + 'host_lane_assignment_option': 1, + 'supported_max_tx_power': 0, + 'supported_min_tx_power': -20, + 'vendor_date': '21010100' + } + ) + ]) + def test_get_transceiver_info(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_module_media_type = MagicMock() + api.get_module_media_type.return_value = mock_response[0] + api.get_host_electrical_interface = MagicMock() + api.get_host_electrical_interface.return_value = mock_response[1] + api.get_module_media_interface = MagicMock() + api.get_module_media_interface.return_value = mock_response[2] + api.get_host_lane_count = MagicMock() + api.get_host_lane_count.return_value = mock_response[3] + api.get_media_lane_count = MagicMock() + api.get_media_lane_count.return_value = mock_response[4] + api.get_host_lane_assignment_option = MagicMock() + api.get_host_lane_assignment_option.return_value = mock_response[5] + api.get_media_lane_assignment_option = MagicMock() + api.get_media_lane_assignment_option.return_value = mock_response[6] + api.get_active_apsel_hostlane = MagicMock() + api.get_active_apsel_hostlane.return_value = mock_response[7] + api.get_media_interface_technology = MagicMock() + api.get_media_interface_technology.return_value = mock_response[8] + api.get_module_hardware_revision = MagicMock() + api.get_module_hardware_revision.return_value = mock_response[9] + api.get_vendor_serial = MagicMock() + api.get_vendor_serial.return_value = mock_response[10] + api.get_vendor_name = MagicMock() + api.get_vendor_name.return_value = mock_response[11] + api.get_vendor_rev = MagicMock() + api.get_vendor_rev.return_value = mock_response[12] + api.get_vendor_OUI = MagicMock() + api.get_vendor_OUI.return_value = mock_response[13] + api.get_vendor_date = MagicMock() + api.get_vendor_date.return_value = mock_response[14] + api.get_connector_type = MagicMock() + api.get_connector_type.return_value = mock_response[15] + api.get_cmis_rev = MagicMock() + api.get_cmis_rev.return_value = mock_response[16] + api.get_module_active_firmware = MagicMock() + api.get_module_active_firmware.return_value = mock_response[17] + api.get_module_inactive_firmware = MagicMock() + api.get_module_inactive_firmware.return_value = mock_response[18] + api.get_supported_power_config = MagicMock() + api.get_supported_power_config.return_value = mock_response[19] + api.get_supported_freq_config = MagicMock() + api.get_supported_freq_config.return_value = mock_response[20] + result = api.get_transceiver_info() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + {'monitor value': 50}, + {'monitor value': 3.3}, + {'monitor value lane1': 0.1}, + {'monitor value lane1': 0.09}, + {'monitor value lane1': 70}, + {'monitor value': 40}, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, + 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, + 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, + 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, + 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, + 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, + 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, + 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, + 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} + }, + 193100, 193100, -10 + ], + { + 'temperature': 50, + 'voltage': 3.3, + 'txpower': 0.1, + 'rxpower': 0.09, + 'txbias': 70, + 'laser_temperature': 40, + 'prefec_ber': 0.001, + 'postfec_ber': 0, + 'bias_xi': 50, + 'bias_xq': 50, + 'bias_xp': 50, + 'bias_yi': 50, + 'bias_yq': 50, + 'bias_yp': 50, + 'cd_shortlink': 1000, + 'cd_longlink': 1000, + 'dgd': 5, + 'sopmd': 5, + 'pdl': 0.5, + 'osnr': 30, + 'esnr': 16, + 'cfo': 100, + 'tx_curr_power': -10, + 'rx_tot_power': -10, + 'rx_sig_power': -10, + 'laser_config_freq': 193100, + 'laser_curr_freq': 193100, + 'tx_config_power': -10 + } + ) + ]) + def test_get_transceiver_bulk_status(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_module_temperature = MagicMock() + api.get_module_temperature.return_value = mock_response[0] + api.get_module_voltage = MagicMock() + api.get_module_voltage.return_value = mock_response[1] + api.get_txpower = MagicMock() + api.get_txpower.return_value = mock_response[2] + api.get_rxpower = MagicMock() + api.get_rxpower.return_value = mock_response[3] + api.get_txbias = MagicMock() + api.get_txbias.return_value = mock_response[4] + api.get_laser_temperature = MagicMock() + api.get_laser_temperature.return_value = mock_response[5] + api.get_VDM = MagicMock() + api.get_VDM.return_value = mock_response[6] + api.get_laser_config_freq = MagicMock() + api.get_laser_config_freq.return_value = mock_response[7] + api.get_current_laser_freq = MagicMock() + api.get_current_laser_freq.return_value = mock_response[8] + api.get_TX_config_power = MagicMock() + api.get_TX_config_power.return_value = mock_response[9] + result = api.get_transceiver_bulk_status() + assert result == expected + + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + {'high alarm': 80, 'low alarm': 0, 'high warn': 75, 'low warn': 10}, + {'high alarm': 3.5, 'low alarm': 3.1, 'high warn': 3.45, 'low warn': 3.15}, + {'high alarm': 1.0, 'low alarm': 0.01, 'high warn': 0.7, 'low warn': 0.02}, + {'high alarm': 2.0, 'low alarm': 0.01, 'high warn': 1.0, 'low warn': 0.02}, + {'high alarm': 90, 'low alarm': 10, 'high warn': 80, 'low warn': 20}, + {'high alarm': 80, 'low alarm': 10, 'high warn': 75, 'low warn': 20}, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, + 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, + 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, + 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, + 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, + 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, + 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, + 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, + 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} + } + ], + { + 'temphighalarm': 80, 'templowalarm': 0, 'temphighwarning': 75, 'templowwarning': 10, + 'vcchighalarm': 3.5, 'vcclowalarm': 3.1, 'vcchighwarning': 3.45, 'vcclowwarning': 3.15, + 'txpowerhighalarm': 1.0, 'txpowerlowalarm': 0.01, 'txpowerhighwarning': 0.7, 'txpowerlowwarning': 0.02, + 'rxpowerhighalarm': 2.0, 'rxpowerlowalarm': 0.01, 'rxpowerhighwarning': 1.0, 'rxpowerlowwarning': 0.02, + 'txbiashighalarm': 90, 'txbiaslowalarm': 10, 'txbiashighwarning': 80, 'txbiaslowwarning': 20, + 'lasertemphighalarm': 80, 'lasertemplowalarm': 10, 'lasertemphighwarning': 75, 'lasertemplowwarning': 20, + 'prefecberhighalarm': 0.0125, 'prefecberlowalarm': 0, 'prefecberhighwarning': 0.01, 'prefecberlowwarning': 0, + 'postfecberhighalarm': 1, 'postfecberlowalarm': 0, 'postfecberhighwarning': 1, 'postfecberlowwarning': 0, + 'biasxihighalarm': 90, 'biasxilowalarm': 10, 'biasxihighwarning': 85, 'biasxilowwarning': 15, + 'biasxqhighalarm': 90, 'biasxqlowalarm': 10, 'biasxqhighwarning': 85, 'biasxqlowwarning': 15, + 'biasxphighalarm': 90, 'biasxplowalarm': 10, 'biasxphighwarning': 85, 'biasxplowwarning': 15, + 'biasyihighalarm': 90, 'biasyilowalarm': 10, 'biasyihighwarning': 85, 'biasyilowwarning': 15, + 'biasyqhighalarm': 90, 'biasyqlowalarm': 10, 'biasyqhighwarning': 85, 'biasyqlowwarning': 15, + 'biasyphighalarm': 90, 'biasyplowalarm': 10, 'biasyphighwarning': 85, 'biasyplowwarning': 15, + 'cdshorthighalarm': 2000, 'cdshortlowalarm': 0, 'cdshorthighwarning': 1800, 'cdshortlowwarning': 0, + 'cdlonghighalarm': 2000, 'cdlonglowalarm': 0, 'cdlonghighwarning': 1800, 'cdlonglowwarning': 0, + 'dgdhighalarm': 30, 'dgdlowalarm': 0, 'dgdhighwarning': 25, 'dgdlowwarning': 0, + 'sopmdhighalarm': 100, 'sopmdlowalarm': 0, 'sopmdhighwarning': 80, 'sopmdlowwarning': 0, + 'pdlhighalarm': 3, 'pdllowalarm': 0, 'pdlhighwarning': 2.5, 'pdllowwarning': 0, + 'osnrhighalarm': 100, 'osnrlowalarm': 26, 'osnrhighwarning': 80, 'osnrlowwarning': 27, + 'esnrhighalarm': 100, 'esnrlowalarm': 13, 'esnrhighwarning': 80, 'esnrlowwarning': 14, + 'cfohighalarm': 5000, 'cfolowalarm': -5000, 'cfohighwarning': 4000, 'cfolowwarning': -4000, + 'txcurrpowerhighalarm': 0, 'txcurrpowerlowalarm': -18, 'txcurrpowerhighwarning': -2, 'txcurrpowerlowwarning': -16, + 'rxtotpowerhighalarm': 3, 'rxtotpowerlowalarm': -18, 'rxtotpowerhighwarning': 0, 'rxtotpowerlowwarning': -15, + 'rxsigpowerhighalarm': 3, 'rxsigpowerlowalarm': -18, 'rxsigpowerhighwarning': 0, 'rxsigpowerlowwarning': -15 + } + ) + ]) + def test_get_transceiver_threshold_info(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_module_temperature = MagicMock() + api.get_module_temperature.return_value = mock_response[0] + api.get_module_voltage = MagicMock() + api.get_module_voltage.return_value = mock_response[1] + api.get_txpower = MagicMock() + api.get_txpower.return_value = mock_response[2] + api.get_rxpower = MagicMock() + api.get_rxpower.return_value = mock_response[3] + api.get_txbias = MagicMock() + api.get_txbias.return_value = mock_response[4] + api.get_laser_temperature = MagicMock() + api.get_laser_temperature.return_value = mock_response[5] + api.get_VDM = MagicMock() + api.get_VDM.return_value = mock_response[6] + result = api.get_transceiver_threshold_info() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + 'ModuleReady', 'No Fault detected', (False, False, True), + { + 'dp_lane1': 'DataPathActivated', 'dp_lane2': 'DataPathActivated', + 'dp_lane3': 'DataPathActivated', 'dp_lane4': 'DataPathActivated', + 'dp_lane5': 'DataPathActivated', 'dp_lane6': 'DataPathActivated', + 'dp_lane7': 'DataPathActivated', 'dp_lane8': 'DataPathActivated' + }, + {'TX_lane1': True}, + { + 'RX_lane1': True, 'RX_lane2': True, 'RX_lane3': True, 'RX_lane4': True, + 'RX_lane5': True, 'RX_lane6': True, 'RX_lane7': True, 'RX_lane8': True + }, + {'TX_lane1': False}, + { + 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, + 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False + }, + { + 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, + 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False + }, + {'RX_lane1': False}, + {'RX_lane1': False}, + { + 'config_DP_status_hostlane1': 'ConfigSuccess', 'config_DP_status_hostlane2': 'ConfigSuccess', + 'config_DP_status_hostlane3': 'ConfigSuccess', 'config_DP_status_hostlane4': 'ConfigSuccess', + 'config_DP_status_hostlane5': 'ConfigSuccess', 'config_DP_status_hostlane6': 'ConfigSuccess', + 'config_DP_status_hostlane7': 'ConfigSuccess', 'config_DP_status_hostlane8': 'ConfigSuccess' + }, + { + 'hostlane1': False, 'hostlane2': False, + 'hostlane3': False, 'hostlane4': False, + 'hostlane5': False, 'hostlane6': False, + 'hostlane7': False, 'hostlane8': False + }, + False, False, ['TuningComplete'], + { + 'case_temp_flags': { + 'case_temp_high_alarm_flag': False, + 'case_temp_low_alarm_flag': False, + 'case_temp_high_warn_flag': False, + 'case_temp_low_warn_flag': False, + }, + 'voltage_flags': { + 'voltage_high_alarm_flag': False, + 'voltage_low_alarm_flag': False, + 'voltage_high_warn_flag': False, + 'voltage_low_warn_flag': False, + }, + 'aux1_flags': { + 'aux1_high_alarm_flag': False, + 'aux1_low_alarm_flag': False, + 'aux1_high_warn_flag': False, + 'aux1_low_warn_flag': False, + }, + 'aux2_flags': { + 'aux2_high_alarm_flag': False, + 'aux2_low_alarm_flag': False, + 'aux2_high_warn_flag': False, + 'aux2_low_warn_flag': False, + }, + 'aux3_flags': { + 'aux3_high_alarm_flag': False, + 'aux3_low_alarm_flag': False, + 'aux3_high_warn_flag': False, + 'aux3_low_warn_flag': False, + } + }, + (0, 0, 0), + { + 'tx_power_high_alarm': {'TX_lane1': False}, + 'tx_power_low_alarm': {'TX_lane1': False}, + 'tx_power_high_warn': {'TX_lane1': False}, + 'tx_power_low_warn': {'TX_lane1': False}, + }, + { + 'rx_power_high_alarm': {'RX_lane1': False}, + 'rx_power_low_alarm': {'RX_lane1': False}, + 'rx_power_high_warn': {'RX_lane1': False}, + 'rx_power_low_warn': {'RX_lane1': False}, + }, + { + 'tx_bias_high_alarm': {'TX_lane1': False}, + 'tx_bias_low_alarm': {'TX_lane1': False}, + 'tx_bias_high_warn': {'TX_lane1': False}, + 'tx_bias_low_warn': {'TX_lane1': False}, + }, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, + 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, + 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, + 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, + 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, + 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, + 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, + 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, + 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} + } + ], + { + 'module_state': 'ModuleReady', + 'module_fault_cause': 'No Fault detected', + 'datapath_firmware_fault': False, + 'module_firmware_fault': False, + 'module_state_changed': True, + 'datapath_hostlane1': 'DataPathActivated', + 'datapath_hostlane2': 'DataPathActivated', + 'datapath_hostlane3': 'DataPathActivated', + 'datapath_hostlane4': 'DataPathActivated', + 'datapath_hostlane5': 'DataPathActivated', + 'datapath_hostlane6': 'DataPathActivated', + 'datapath_hostlane7': 'DataPathActivated', + 'datapath_hostlane8': 'DataPathActivated', + 'txoutput_status': True, + 'rxoutput_status_hostlane1': True, + 'rxoutput_status_hostlane2': True, + 'rxoutput_status_hostlane3': True, + 'rxoutput_status_hostlane4': True, + 'rxoutput_status_hostlane5': True, + 'rxoutput_status_hostlane6': True, + 'rxoutput_status_hostlane7': True, + 'rxoutput_status_hostlane8': True, + 'txfault': False, + 'txlos_hostlane1': False, + 'txlos_hostlane2': False, + 'txlos_hostlane3': False, + 'txlos_hostlane4': False, + 'txlos_hostlane5': False, + 'txlos_hostlane6': False, + 'txlos_hostlane7': False, + 'txlos_hostlane8': False, + 'txcdrlol_hostlane1': False, + 'txcdrlol_hostlane2': False, + 'txcdrlol_hostlane3': False, + 'txcdrlol_hostlane4': False, + 'txcdrlol_hostlane5': False, + 'txcdrlol_hostlane6': False, + 'txcdrlol_hostlane7': False, + 'txcdrlol_hostlane8': False, + 'rxlos': False, + 'rxcdrlol': False, + 'config_state_hostlane1': 'ConfigSuccess', + 'config_state_hostlane2': 'ConfigSuccess', + 'config_state_hostlane3': 'ConfigSuccess', + 'config_state_hostlane4': 'ConfigSuccess', + 'config_state_hostlane5': 'ConfigSuccess', + 'config_state_hostlane6': 'ConfigSuccess', + 'config_state_hostlane7': 'ConfigSuccess', + 'config_state_hostlane8': 'ConfigSuccess', + 'dpinit_pending_hostlane1': False, + 'dpinit_pending_hostlane2': False, + 'dpinit_pending_hostlane3': False, + 'dpinit_pending_hostlane4': False, + 'dpinit_pending_hostlane5': False, + 'dpinit_pending_hostlane6': False, + 'dpinit_pending_hostlane7': False, + 'dpinit_pending_hostlane8': False, + 'tuning_in_progress': False, + 'wavelength_unlock_status': False, + 'target_output_power_oor': False, + 'fine_tuning_oor': False, + 'tuning_not_accepted': False, + 'invalid_channel_num': False, + 'tuning_complete': True, + 'temphighalarm_flag': False, 'templowalarm_flag': False, + 'temphighwarning_flag': False, 'templowwarning_flag': False, + 'vcchighalarm_flag': False, 'vcclowalarm_flag': False, + 'vcchighwarning_flag': False, 'vcclowwarning_flag': False, + 'lasertemphighalarm_flag': False, 'lasertemplowalarm_flag': False, + 'lasertemphighwarning_flag': False, 'lasertemplowwarning_flag': False, + 'txpowerhighalarm_flag': False, 'txpowerlowalarm_flag': False, + 'txpowerhighwarning_flag': False, 'txpowerlowwarning_flag': False, + 'rxpowerhighalarm_flag': False, 'rxpowerlowalarm_flag': False, + 'rxpowerhighwarning_flag': False, 'rxpowerlowwarning_flag': False, + 'txbiashighalarm_flag': False, 'txbiaslowalarm_flag': False, + 'txbiashighwarning_flag': False, 'txbiaslowwarning_flag': False, + 'prefecberhighalarm_flag': False, 'prefecberlowalarm_flag': False, + 'prefecberhighwarning_flag': False, 'prefecberlowwarning_flag': False, + 'postfecberhighalarm_flag': False, 'postfecberlowalarm_flag': False, + 'postfecberhighwarning_flag': False, 'postfecberlowwarning_flag': False, + 'biasxihighalarm_flag': False, 'biasxilowalarm_flag': False, + 'biasxihighwarning_flag': False, 'biasxilowwarning_flag': False, + 'biasxqhighalarm_flag': False, 'biasxqlowalarm_flag': False, + 'biasxqhighwarning_flag': False, 'biasxqlowwarning_flag': False, + 'biasxphighalarm_flag': False, 'biasxplowalarm_flag': False, + 'biasxphighwarning_flag': False, 'biasxplowwarning_flag': False, + 'biasyihighalarm_flag': False, 'biasyilowalarm_flag': False, + 'biasyihighwarning_flag': False, 'biasyilowwarning_flag': False, + 'biasyqhighalarm_flag': False, 'biasyqlowalarm_flag': False, + 'biasyqhighwarning_flag': False, 'biasyqlowwarning_flag': False, + 'biasyphighalarm_flag': False, 'biasyplowalarm_flag': False, + 'biasyphighwarning_flag': False, 'biasyplowwarning_flag': False, + 'cdshorthighalarm_flag': False, 'cdshortlowalarm_flag': False, + 'cdshorthighwarning_flag': False, 'cdshortlowwarning_flag': False, + 'cdlonghighalarm_flag': False, 'cdlonglowalarm_flag': False, + 'cdlonghighwarning_flag': False, 'cdlonglowwarning_flag': False, + 'dgdhighalarm_flag': False, 'dgdlowalarm_flag': False, + 'dgdhighwarning_flag': False, 'dgdlowwarning_flag': False, + 'sopmdhighalarm_flag': False, 'sopmdlowalarm_flag': False, + 'sopmdhighwarning_flag': False, 'sopmdlowwarning_flag': False, + 'pdlhighalarm_flag': False, 'pdllowalarm_flag': False, + 'pdlhighwarning_flag': False, 'pdllowwarning_flag': False, + 'osnrhighalarm_flag': False, 'osnrlowalarm_flag': False, + 'osnrhighwarning_flag': False, 'osnrlowwarning_flag': False, + 'esnrhighalarm_flag': False, 'esnrlowalarm_flag': False, + 'esnrhighwarning_flag': False, 'esnrlowwarning_flag': False, + 'cfohighalarm_flag': False, 'cfolowalarm_flag': False, + 'cfohighwarning_flag': False, 'cfolowwarning_flag': False, + 'txcurrpowerhighalarm_flag': False, 'txcurrpowerlowalarm_flag': False, + 'txcurrpowerhighwarning_flag': False, 'txcurrpowerlowwarning_flag': False, + 'rxtotpowerhighalarm_flag': False, 'rxtotpowerlowalarm_flag': False, + 'rxtotpowerhighwarning_flag': False, 'rxtotpowerlowwarning_flag': False, + 'rxsigpowerhighalarm_flag': False, 'rxsigpowerlowalarm_flag': False, + 'rxsigpowerhighwarning_flag': False, 'rxsigpowerlowwarning_flag': False, + + } + ) + ]) + def test_get_transceiver_status(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_module_state = MagicMock() + api.get_module_state.return_value = mock_response[0] + api.get_module_fault_cause = MagicMock() + api.get_module_fault_cause.return_value = mock_response[1] + api.get_module_firmware_fault_state_changed = MagicMock() + api.get_module_firmware_fault_state_changed.return_value = mock_response[2] + api.get_datapath_state = MagicMock() + api.get_datapath_state.return_value = mock_response[3] + api.get_tx_output_status = MagicMock() + api.get_tx_output_status.return_value = mock_response[4] + api.get_rx_output_status = MagicMock() + api.get_rx_output_status.return_value = mock_response[5] + api.get_tx_fault = MagicMock() + api.get_tx_fault.return_value = mock_response[6] + api.get_tx_los = MagicMock() + api.get_tx_los.return_value = mock_response[7] + api.get_tx_cdr_lol = MagicMock() + api.get_tx_cdr_lol.return_value = mock_response[8] + api.get_rx_los = MagicMock() + api.get_rx_los.return_value = mock_response[9] + api.get_rx_cdr_lol = MagicMock() + api.get_rx_cdr_lol.return_value = mock_response[10] + api.get_config_datapath_hostlane_status = MagicMock() + api.get_config_datapath_hostlane_status.return_value = mock_response[11] + api.get_dpinit_pending = MagicMock() + api.get_dpinit_pending.return_value = mock_response[12] + api.get_tuning_in_progress = MagicMock() + api.get_tuning_in_progress.return_value = mock_response[13] + api.get_wavelength_unlocked = MagicMock() + api.get_wavelength_unlocked.return_value = mock_response[14] + api.get_laser_tuning_summary = MagicMock() + api.get_laser_tuning_summary.return_value = mock_response[15] + api.get_module_level_flag = MagicMock() + api.get_module_level_flag.return_value = mock_response[16] + api.get_aux_mon_type = MagicMock() + api.get_aux_mon_type.return_value = mock_response[17] + api.get_tx_power_flag = MagicMock() + api.get_tx_power_flag.return_value = mock_response[18] + api.get_rx_power_flag = MagicMock() + api.get_rx_power_flag.return_value = mock_response[19] + api.get_tx_bias_flag = MagicMock() + api.get_tx_bias_flag.return_value = mock_response[20] + api.get_VDM = MagicMock() + api.get_VDM.return_value = mock_response[21] + result = api.get_transceiver_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ( + { + 'preFEC_BER_avg': 0.001, 'preFEC_BER_min': 0.0008, 'preFEC_BER_max': 0.0012, + 'preFEC_uncorr_frame_ratio_avg': 0, 'preFEC_uncorr_frame_ratio_min': 0, 'preFEC_uncorr_frame_ratio_max': 0, + 'rx_cd_avg': 1400, 'rx_cd_min': 1300, 'rx_cd_max': 1500, + 'rx_dgd_avg': 7.0, 'rx_dgd_min': 5.5, 'rx_dgd_max': 9.2, + 'rx_sopmd_avg': 40, 'rx_sopmd_min': 20, 'rx_sopmd_max': 60, + 'rx_pdl_avg': 1.0, 'rx_pdl_min': 0.8, 'rx_pdl_max': 1.2, + 'rx_osnr_avg': 28, 'rx_osnr_min': 26, 'rx_osnr_max': 30, + 'rx_esnr_avg': 17, 'rx_esnr_min': 15, 'rx_esnr_max': 18, + 'rx_cfo_avg': 200, 'rx_cfo_min': 150, 'rx_cfo_max': 250, + 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, + 'rx_power_avg': -8, 'rx_power_min': -7, 'rx_power_max': -9, + 'rx_sigpwr_avg': -8, 'rx_sigpwr_min': -7, 'rx_sigpwr_max': -9, + 'rx_soproc_avg': 5, 'rx_soproc_min': 3, 'rx_soproc_max': 8, + }, + { + 'prefec_ber_avg': 0.001, 'prefec_ber_min': 0.0008, 'prefec_ber_max': 0.0012, + 'uncorr_frames_avg': 0, 'uncorr_frames_min': 0, 'uncorr_frames_max': 0, + 'cd_avg': 1400, 'cd_min': 1300, 'cd_max': 1500, + 'dgd_avg': 7.0, 'dgd_min': 5.5, 'dgd_max': 9.2, + 'sopmd_avg': 40, 'sopmd_min': 20, 'sopmd_max': 60, + 'pdl_avg': 1.0, 'pdl_min': 0.8, 'pdl_max': 1.2, + 'osnr_avg': 28, 'osnr_min': 26, 'osnr_max': 30, + 'esnr_avg': 17, 'esnr_min': 15, 'esnr_max': 18, + 'cfo_avg': 200, 'cfo_min': 150, 'cfo_max': 250, + 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, + 'rx_tot_power_avg': -8, 'rx_tot_power_min': -7, 'rx_tot_power_max': -9, + 'rx_sig_power_avg': -8, 'rx_sig_power_min': -7, 'rx_sig_power_max': -9, + 'soproc_avg': 5, 'soproc_min': 3, 'soproc_max': 8, + } + ) + ]) + def test_get_transceiver_PM(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_PM = MagicMock() + api.get_PM.return_value = mock_response + result = api.get_transceiver_PM() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + False, + False, + [False, False, False, False, False, False, False, False], + [False, False, False, False, False, False, False, False] + ], + { + 'media_output_loopback': False, + 'media_input_loopback': False, + 'host_output_loopback_lane1': False, + 'host_output_loopback_lane2': False, + 'host_output_loopback_lane3': False, + 'host_output_loopback_lane4': False, + 'host_output_loopback_lane5': False, + 'host_output_loopback_lane6': False, + 'host_output_loopback_lane7': False, + 'host_output_loopback_lane8': False, + 'host_input_loopback_lane1': False, + 'host_input_loopback_lane2': False, + 'host_input_loopback_lane3': False, + 'host_input_loopback_lane4': False, + 'host_input_loopback_lane5': False, + 'host_input_loopback_lane6': False, + 'host_input_loopback_lane7': False, + 'host_input_loopback_lane8': False + } + ) + ]) + def test_get_transceiver_loopback(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_media_output_loopback = MagicMock() + api.get_media_output_loopback.return_value = mock_response[0] + api.get_media_input_loopback = MagicMock() + api.get_media_input_loopback.return_value = mock_response[1] + api.get_host_output_loopback = MagicMock() + api.get_host_output_loopback.return_value = mock_response[2] + api.get_host_input_loopback = MagicMock() + api.get_host_input_loopback.return_value = mock_response[3] + result = api.get_transceiver_loopback() + assert result == expected From f65fbfeb15acd0bf1778699c9db745abed5c828c Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Thu, 14 Oct 2021 10:37:25 -0700 Subject: [PATCH 12/16] add unit test cases for cmisCDB and cmisVDM --- pytest.ini | 2 +- .../sonic_xcvr/api/public/cmisCDB.py | 2 +- tests/sonic_xcvr/test_ccmis.py | 70 ++++++- tests/sonic_xcvr/test_cmis.py | 42 ----- tests/sonic_xcvr/test_cmisCDB.py | 176 ++++++++++++++++++ tests/sonic_xcvr/test_cmisVDM.py | 106 +++++++++++ 6 files changed, 346 insertions(+), 52 deletions(-) create mode 100644 tests/sonic_xcvr/test_cmisCDB.py create mode 100644 tests/sonic_xcvr/test_cmisVDM.py diff --git a/pytest.ini b/pytest.ini index a88c650f8..ba83deea8 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,2 +1,2 @@ [pytest] -addopts = --cov=sonic_platform_base tests/sonic_xcvr/test_cmis.py --cov-report html --cov-report term --cov-report xml --junitxml=test-results.xml -v +addopts = --cov=sonic_platform_base tests/sonic_xcvr/test_cmis.py sonic_platform_base tests/sonic_xcvr/test_ccmis.py sonic_platform_base tests/sonic_xcvr/test_cmisVDM.py sonic_platform_base tests/sonic_xcvr/test_cmisCDB.py --cov-report html --cov-report term --cov-report xml --junitxml=test-results.xml -v diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py index 503b212a6..872427cf2 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py @@ -161,7 +161,7 @@ def cmd0001h(self): continue else: break - return self.read_cdb() + return status def cmd0040h(self): cmd = bytearray(b'\x00\x40\x00\x00\x00\x00\x00\x00') diff --git a/tests/sonic_xcvr/test_ccmis.py b/tests/sonic_xcvr/test_ccmis.py index 3d59f7927..d99875792 100644 --- a/tests/sonic_xcvr/test_ccmis.py +++ b/tests/sonic_xcvr/test_ccmis.py @@ -1,12 +1,66 @@ -# from mock import MagicMock -# import pytest -# from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi -# from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap -# from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom -# from sonic_platform_base.sonic_xcvr.codes.public.sff8024 import Sff8024 -# from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode +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.c_cmis import CCmisApi +from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap +from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom +from sonic_platform_base.sonic_xcvr.codes.public.sff8024 import Sff8024 +from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode class TestCCmis(object): - pass + def mock_ccmis_api(self): + codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + mem_map = CmisMemMap(codes) + reader = MagicMock(return_value=None) + writer = MagicMock() + xcvr_eeprom = XcvrEeprom(reader, writer, mem_map) + api = CmisApi(xcvr_eeprom) + api.ccmis = CCmisApi(xcvr_eeprom) + return api.ccmis + + @pytest.mark.parametrize("mock_response, expected", [ + ( + [ + 1000000, 10000, 1000, 8, 12, # preFEC_BER + 10000, 100, 0, 0, 0, # uncorr_frame + 1400, 1300, 1500, # CD + 7.0, 5.5, 9.2, # DGD + 40, 20, 60, # SOPMD + 1.0, 0.8, 1.2, # PDL + 28, 26, 30, # OSNR + 17, 15, 18, # ESNR + 200, 150, 250, # CFO + 15, 13, 18, # EVM + -10, -9.5, -10.5, # TX power + -8, -7, -9, # RX total power + -8, -7, -9, # RX channel power + 5, 3, 8, # SOPROc + 0, 0, 0, # MER + ], + { + 'preFEC_BER_avg': 0.001, 'preFEC_BER_min': 0.0008, 'preFEC_BER_max': 0.0012, + 'preFEC_uncorr_frame_ratio_avg': 0, 'preFEC_uncorr_frame_ratio_min': 0, 'preFEC_uncorr_frame_ratio_max': 0, + 'rx_cd_avg': 1400, 'rx_cd_min': 1300, 'rx_cd_max': 1500, + 'rx_dgd_avg': 7.0, 'rx_dgd_min': 5.5, 'rx_dgd_max': 9.2, + 'rx_sopmd_avg': 40, 'rx_sopmd_min': 20, 'rx_sopmd_max': 60, + 'rx_pdl_avg': 1.0, 'rx_pdl_min': 0.8, 'rx_pdl_max': 1.2, + 'rx_osnr_avg': 28, 'rx_osnr_min': 26, 'rx_osnr_max': 30, + 'rx_esnr_avg': 17, 'rx_esnr_min': 15, 'rx_esnr_max': 18, + 'rx_cfo_avg': 200, 'rx_cfo_min': 150, 'rx_cfo_max': 250, + 'rx_evm_avg': 15, 'rx_evm_min': 13, 'rx_evm_max': 18, + 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, + 'rx_power_avg': -8, 'rx_power_min': -7, 'rx_power_max': -9, + 'rx_sigpwr_avg': -8, 'rx_sigpwr_min': -7, 'rx_sigpwr_max': -9, + 'rx_soproc_avg': 5, 'rx_soproc_min': 3, 'rx_soproc_max': 8, + 'rx_mer_avg': 0, 'rx_mer_min': 0, 'rx_mer_max': 0 + } + ) + ]) + def test_get_PM_all(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.xcvr_eeprom.read = MagicMock() + ccmis.xcvr_eeprom.read.side_effect = mock_response + result = ccmis.get_PM_all() + assert result == expected # TODO: call other methods in the api diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 3b012eac9..79d3a836a 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -444,48 +444,6 @@ def test_get_VDM(self, mock_response, expected): result = api.get_VDM() assert result == expected - # @pytest.mark.parametrize("mock_response, expected", [ - # ([100000000, 1000000, 100000, 800, 1200, # preFEC_BER - # 10000, 100, 0, 0, 0, # uncorr_frame - # 1400, 1300, 1500, # CD - # 7.0, 5.5, 9.2, # DGD - # 40, 20, 60, # SOPMD - # 1.0, 0.8, 1.2, # PDL - # 28, 26, 30, # OSNR - # 17, 15, 18, # ESNR - # 200, 150, 250, # CFO - # 15, 13, 18, # EVM - # -10, -9.5, -10.5, # TX power - # -8, -7, -9, # RX total power - # -8, -7, -9, # RX channel power - # 5, 3, 8, # SOPROc - # 0, 0, 0, # MER - # ], - # {'preFEC_BER_cur': 0.001, 'preFEC_BER_min': 0.0008, 'preFEC_BER_max': 0.0012, - # 'preFEC_uncorr_frame_ratio_cur': 0, 'preFEC_uncorr_frame_ratio_min': 0, 'preFEC_uncorr_frame_ratio_max': 0, - # 'rx_cd_avg': 1400, 'rx_cd_min': 1300, 'rx_cd_max': 1500, - # 'rx_dgd_avg': 7.0, 'rx_dgd_min': 5.5, 'rx_dgd_max': 9.2, - # 'rx_sopmd_avg': 40, 'rx_sopmd_min': 20, 'rx_sopmd_max': 60, - # 'rx_pdl_avg': 1.0, 'rx_pdl_min': 0.8, 'rx_pdl_max': 1.2, - # 'rx_osnr_avg': 28, 'rx_osnr_min': 26, 'rx_osnr_max': 30, - # 'rx_esnr_avg': 17, 'rx_esnr_min': 15, 'rx_esnr_max': 18, - # 'rx_cfo_avg': 200, 'rx_cfo_min': 150, 'rx_cfo_max': 250, - # 'rx_evm_avg': 15, 'rx_evm_min': 13, 'rx_evm_max': 18, - # 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, - # 'rx_power_avg': -8, 'rx_power_min': -7, 'rx_power_max': -9, - # 'rx_sigpwr_avg': -8, 'rx_sigpwr_min': -7, 'rx_sigpwr_max': -9, - # 'rx_soproc_avg': 5, 'rx_soproc_min': 3, 'rx_soproc_max': 8, - # 'rx_mer_avg': 0, 'rx_mer_min': 0, 'rx_mer_max': 0 - # } - # ) - # ]) - # def test_get_PM(self, mock_response, expected): - # api = self.mock_cmis_api() - # api.xcvr_eeprom.read = MagicMock() - # api.xcvr_eeprom.read.side_effect = mock_response - # result = api.get_PM() - # assert result == expected - @pytest.mark.parametrize("mock_response, expected", [ (6, "ModuleReady") ]) diff --git a/tests/sonic_xcvr/test_cmisCDB.py b/tests/sonic_xcvr/test_cmisCDB.py new file mode 100644 index 000000000..b27d67743 --- /dev/null +++ b/tests/sonic_xcvr/test_cmisCDB.py @@ -0,0 +1,176 @@ +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 +from sonic_platform_base.sonic_xcvr.codes.public.sff8024 import Sff8024 +from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode + +class TestCDB(object): + + def mock_cdb_api(self): + codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + mem_map = CmisMemMap(codes) + reader = MagicMock(return_value=None) + writer = MagicMock() + xcvr_eeprom = XcvrEeprom(reader, writer, mem_map) + api = CmisApi(xcvr_eeprom) + api.cdb = CmisCdbApi(xcvr_eeprom) + return api.cdb + + @pytest.mark.parametrize("mock_response, expected", [ + (64, False) + ]) + def test_cdb1_chkflags(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.xcvr_eeprom.read = MagicMock() + cdb.xcvr_eeprom.read.return_value = mock_response + result = cdb.cdb1_chkflags() + assert result == expected + + @pytest.mark.parametrize("input_param, expected", [ + (bytearray(b'\x00'), 255) + ]) + def test_cdb_chkcode(self, input_param, expected): + cdb = self.mock_cdb_api() + result = cdb.cdb_chkcode(input_param) + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_cdb1_chkstatus(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.xcvr_eeprom.read = MagicMock() + cdb.xcvr_eeprom.read.return_value = mock_response + result = cdb.cdb1_chkstatus() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ( + [18, 35, (0, 7, 112, 255, 255, 16, 0, 0, 19, 136, 0, 100, 3, 232, 19, 136, 58, 152)], + (18, 35, (0, 7, 112, 255, 255, 16, 0, 0, 19, 136, 0, 100, 3, 232, 19, 136, 58, 152)) + ) + ]) + def test_read_cdb(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.xcvr_eeprom.read = MagicMock() + cdb.xcvr_eeprom.read.side_effect = mock_response[0:2] + cdb.xcvr_eeprom.read_flexible = MagicMock() + cdb.xcvr_eeprom.read_flexible.return_value = mock_response[2] + result = cdb.read_cdb() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_cmd0001h(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0001h() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, (None, None, None)) + ]) + def test_cmd0040h(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0040h() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, (None, None, None)) + ]) + def test_cmd0041h(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0041h() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, (None, None, None)) + ]) + def test_cmd0100h(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0100h() + assert result == expected + + @pytest.mark.parametrize("input_param, mock_response, expected", [ + ([3, bytearray(b'\x00\x00\x00'), 1000000], 1, 1) + ]) + def test_cmd0101h(self, input_param, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0101h(*input_param) + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_cmd0102h(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0102h() + assert result == expected + + @pytest.mark.parametrize("input_param, mock_response, expected", [ + ([100, bytearray(116)], 1, 1) + ]) + def test_cmd0103h(self, input_param, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0103h(*input_param) + assert result == expected + + @pytest.mark.parametrize("input_param, mock_response, expected", [ + ([100, bytearray(2048), True, 2048], 1, 1) + ]) + def test_cmd0104h(self, input_param, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0104h(*input_param) + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_cmd0107h(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0107h() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_cmd0109h(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd0109h() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, 1) + ]) + def test_cmd010Ah(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.return_value = mock_response + result = cdb.cmd010Ah() + assert result == expected + + + \ No newline at end of file diff --git a/tests/sonic_xcvr/test_cmisVDM.py b/tests/sonic_xcvr/test_cmisVDM.py new file mode 100644 index 000000000..520e0f245 --- /dev/null +++ b/tests/sonic_xcvr/test_cmisVDM.py @@ -0,0 +1,106 @@ +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.cmisVDM import CmisVdmApi +from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap +from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom +from sonic_platform_base.sonic_xcvr.codes.public.sff8024 import Sff8024 +from sonic_platform_base.sonic_xcvr.codes.public.cmis_code import CmisCode + +class TestVDM(object): + + def mock_vdm_api(self): + codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + mem_map = CmisMemMap(codes) + reader = MagicMock(return_value=None) + writer = MagicMock() + xcvr_eeprom = XcvrEeprom(reader, writer, mem_map) + api = CmisApi(xcvr_eeprom) + api.vdm = CmisVdmApi(xcvr_eeprom) + return api.vdm + + @pytest.mark.parametrize("input_param, expected", [ + (0x9200, 0.000512) + ]) + def test_get_F16(self, input_param, expected): + vdm = self.mock_vdm_api() + result = vdm.get_F16(input_param) + assert result == expected + + @pytest.mark.parametrize("input_param, mock_response, expected", [ + ( + [0x20, [0]*128], # input_param + [ # mock_response + ( + 16, 9, 16, 11, 16, 13, 16, 15, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ), + + bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), + bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), + bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), + bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), + ], + { + 'Pre-FEC BER Minimum Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Maximum Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Average Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Current Value Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + + } + ) + ]) + def test_get_VDM_page(self, input_param, mock_response, expected): + vdm = self.mock_vdm_api() + vdm.xcvr_eeprom.read_flexible = MagicMock() + vdm.xcvr_eeprom.read_flexible.side_effect = mock_response + result = vdm.get_VDM_page(*input_param) + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ( + [ # mock_response + 0, # vdm_page_supported_raw + ( # VDM_flag_page + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ), + { # VDM_current_page + 'Pre-FEC BER Minimum Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Maximum Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Average Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Current Value Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + } + ], + { # VDM_current_page + 'Pre-FEC BER Minimum Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Maximum Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Average Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Pre-FEC BER Current Value Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + } + + ) + ]) + def test_get_VDM_allpage(self, mock_response, expected): + vdm = self.mock_vdm_api() + vdm.xcvr_eeprom.read = MagicMock() + vdm.xcvr_eeprom.read.return_value = mock_response[0] + vdm.xcvr_eeprom.read_flexible = MagicMock() + vdm.xcvr_eeprom.read_flexible.return_value = mock_response[1] + # input_param = [0x20, mock_response[1]] + vdm.get_VDM_page = MagicMock() + vdm.get_VDM_page.side_effect = mock_response[2:] + result = vdm.get_VDM_allpage() + assert result == expected \ No newline at end of file From 049e60253cc0848daccbc7d9e8ea77adba25c2b4 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Fri, 15 Oct 2021 00:08:03 -0700 Subject: [PATCH 13/16] add code coverage in unit test --- .../sonic_xcvr/api/public/cmis.py | 36 ++- .../sonic_xcvr/mem_maps/public/cmis.py | 4 +- tests/sonic_xcvr/test_cmis.py | 263 ++++++++++++++++-- tests/sonic_xcvr/test_cmisCDB.py | 74 +++-- tests/sonic_xcvr/test_cmisVDM.py | 17 +- 5 files changed, 329 insertions(+), 65 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index 2b3cbc178..124126cac 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -911,10 +911,10 @@ def set_loopback_mode(self, loopback_mode): self.xcvr_eeprom.write(consts.HOST_OUTPUT_LOOPBACK, 0xff) elif loopback_mode == 'media-side-input': assert loopback_capability['media_side_input_loopback_supported'] - self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0x1) + self.xcvr_eeprom.write(consts.MEDIA_INPUT_LOOPBACK, 0xff) elif loopback_mode == 'media-side-output': assert loopback_capability['media_side_output_loopback_supported'] - self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0x1) + self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0xff) def get_CDB_api(self): @@ -1315,9 +1315,15 @@ def get_transceiver_bulk_status(self): trans_dom['bias_yq'] = vdm_dict['Modulator Bias Y/Q [%]'][1][0] trans_dom['bias_yp'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][0] trans_dom['cd_shortlink'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][0] - trans_dom['cd_longlink'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][0] + try: + trans_dom['cd_longlink'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][0] + except KeyError: + pass trans_dom['dgd'] = vdm_dict['DGD [ps]'][1][0] - trans_dom['sopmd'] = vdm_dict['SOPMD [ps^2]'][1][0] + try: + trans_dom['sopmd'] = vdm_dict['SOPMD [ps^2]'][1][0] + except KeyError: + pass trans_dom['pdl'] = vdm_dict['PDL [dB]'][1][0] trans_dom['osnr'] = vdm_dict['OSNR [dB]'][1][0] trans_dom['esnr'] = vdm_dict['eSNR [dB]'][1][0] @@ -1509,18 +1515,24 @@ def get_transceiver_threshold_info(self): trans_dom_th['cdshortlowalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][2] trans_dom_th['cdshorthighwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][3] trans_dom_th['cdshortlowwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][4] - trans_dom_th['cdlonghighalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][1] - trans_dom_th['cdlonglowalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][2] - trans_dom_th['cdlonghighwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][3] - trans_dom_th['cdlonglowwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][4] + try: + trans_dom_th['cdlonghighalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][1] + trans_dom_th['cdlonglowalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][2] + trans_dom_th['cdlonghighwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][3] + trans_dom_th['cdlonglowwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][4] + except KeyError: + pass trans_dom_th['dgdhighalarm'] = vdm_dict['DGD [ps]'][1][1] trans_dom_th['dgdlowalarm'] = vdm_dict['DGD [ps]'][1][2] trans_dom_th['dgdhighwarning'] = vdm_dict['DGD [ps]'][1][3] trans_dom_th['dgdlowwarning'] = vdm_dict['DGD [ps]'][1][4] - trans_dom_th['sopmdhighalarm'] = vdm_dict['SOPMD [ps^2]'][1][1] - trans_dom_th['sopmdlowalarm'] = vdm_dict['SOPMD [ps^2]'][1][2] - trans_dom_th['sopmdhighwarning'] = vdm_dict['SOPMD [ps^2]'][1][3] - trans_dom_th['sopmdlowwarning'] = vdm_dict['SOPMD [ps^2]'][1][4] + try: + trans_dom_th['sopmdhighalarm'] = vdm_dict['SOPMD [ps^2]'][1][1] + trans_dom_th['sopmdlowalarm'] = vdm_dict['SOPMD [ps^2]'][1][2] + trans_dom_th['sopmdhighwarning'] = vdm_dict['SOPMD [ps^2]'][1][3] + trans_dom_th['sopmdlowwarning'] = vdm_dict['SOPMD [ps^2]'][1][4] + except KeyError: + pass trans_dom_th['pdlhighalarm'] = vdm_dict['PDL [dB]'][1][1] trans_dom_th['pdllowalarm'] = vdm_dict['PDL [dB]'][1][2] trans_dom_th['pdlhighwarning'] = vdm_dict['PDL [dB]'][1][3] 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 eb4439985..681c6cc86 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -82,8 +82,8 @@ def __init__(self, codes): self.TRANS_LOOPBACK = RegGroupField(consts.TRANS_LOOPBACK_FIELD, NumberRegField(consts.LOOPBACK_CAPABILITY, get_addr(0x13, 128), size=1), - RegBitField(consts.MEDIA_OUTPUT_LOOPBACK, offset=get_addr(0x13, 180), bitpos=0, ro=False), - RegBitField(consts.MEDIA_INPUT_LOOPBACK, offset=get_addr(0x13, 181), bitpos=0, ro=False), + NumberRegField(consts.MEDIA_OUTPUT_LOOPBACK, offset=get_addr(0x13, 180), size=1, ro=False), + NumberRegField(consts.MEDIA_INPUT_LOOPBACK, offset=get_addr(0x13, 181), size=1, ro=False), NumberRegField(consts.HOST_OUTPUT_LOOPBACK, get_addr(0x13, 182), size=1, ro=False), NumberRegField(consts.HOST_INPUT_LOOPBACK, get_addr(0x13, 183), size=1, ro=False), ) diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 79d3a836a..8758d8a39 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -62,6 +62,19 @@ def test_get_vendor_name(self, mock_response, expected): result = api.get_vendor_name() assert result == expected + @pytest.mark.parametrize("mock_response, expected", [ + ( + 'QSFP-DD Double Density 8X Pluggable Transceiver', + 'QSFP-DD Double Density 8X Pluggable Transceiver' + ) + ]) + def test_get_module_type(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_module_type() + assert result == expected + @pytest.mark.parametrize("mock_response, expected", [ ("ABCDE", "ABCDE") ]) @@ -113,7 +126,12 @@ def test_get_host_electrical_interface(self, mock_response, expected): assert result == expected @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - ("Single Mode Fiber (SMF)", "400ZR", "400ZR") + ("Single Mode Fiber (SMF)", "400ZR", "400ZR"), + ("Multimode Fiber (MMF)", "100GE BiDi", "100GE BiDi"), + ("Passive Copper Cable", "Copper cable", "Copper cable"), + ("Active Cable Assembly", "Active Loopback module", "Active Loopback module"), + ("BASE-T", "1000BASE-T (Clause 40)", "1000BASE-T (Clause 40)"), + ("ABCD", "ABCD", "Unknown media interface") ]) def test_get_module_media_interface(self, mock_response1, mock_response2, expected): api = self.mock_cmis_api() @@ -282,7 +300,14 @@ def test_get_txbias(self, mock_response, expected): assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (0x70, 75) + (0x70, 75), + (0x60, 33), + (0x50, 100), + (0x40, 50), + (0x30, 25), + (0x20, 12.5), + (0x10, 6.25), + (0x0, 3.125), ]) def test_get_freq_grid(self, mock_response, expected): api = self.mock_cmis_api() @@ -294,6 +319,7 @@ def test_get_freq_grid(self, mock_response, expected): @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ (75, 12, 193400), (75, -30, 192350), + (100, 10, 194100), ]) def test_get_laser_config_freq(self, mock_response1, mock_response2, expected): api = self.mock_cmis_api() @@ -377,10 +403,21 @@ def test_get_aux_mon_type(self, mock_response, expected): assert result == expected @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - ([0,1,0], - [11520, 20480, -2560, 19200, 0], - {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0} - ) + ( + [0,1,0], + [11520, 20480, -2560, 19200, 0], + {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0} + ), + ( + [0,0,0], + [11520, 20480, -2560, 19200, 0], + {'monitor value': 45, 'high alarm': 80, 'low alarm': -10, 'high warn': 75, 'low warn': 0} + ), + ( + [0,1,1], + [11520, 20480, -2560, 19200, 0], + None + ), ]) def test_get_laser_temperature(self, mock_response1, mock_response2, expected): api = self.mock_cmis_api() @@ -392,10 +429,21 @@ def test_get_laser_temperature(self, mock_response1, mock_response2, expected): assert result == expected @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - ([0,1,0], - [32767, 65534, 0, 49150.5, 0], - {'monitor value': 1, 'high alarm': 2, 'low alarm': 0, 'high warn': 1.5, 'low warn': 0} - ) + ( + [0,1,0], + [32767, 65534, 0, 49150.5, 0], + {'monitor value': 1, 'high alarm': 2, 'low alarm': 0, 'high warn': 1.5, 'low warn': 0} + ), + ( + [1,0,0], + [32767, 65534, 0, 49150.5, 0], + {'monitor value': 1, 'high alarm': 2, 'low alarm': 0, 'high warn': 1.5, 'low warn': 0} + ), + ( + [0,0,0], + [32767, 65534, 0, 49150.5, 0], + None + ), ]) def test_get_laser_TEC_current(self, mock_response1, mock_response2, expected): api = self.mock_cmis_api() @@ -407,7 +455,8 @@ def test_get_laser_TEC_current(self, mock_response1, mock_response2, expected): assert result == expected @pytest.mark.parametrize("input_param, mock_response, expected", [ - ([False, 1.0], 100, 100.0) + ([False, 1.0], 100, 100.0), + ([True, 1.0], 32668, -100.0), ]) def test_get_custom_field(self, input_param, mock_response, expected): api = self.mock_cmis_api() @@ -430,6 +479,12 @@ def test_get_PM(self, mock_response, expected): result = api.get_PM() assert result == expected + + def test_get_VDM_api(self): + api = self.mock_cmis_api() + api.vdm = api.get_VDM_api() + + @pytest.mark.parametrize("mock_response, expected",[ ( {'Pre-FEC BER Average Media Input': {1: [0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}}, @@ -444,6 +499,10 @@ def test_get_VDM(self, mock_response, expected): result = api.get_VDM() assert result == expected + def test_get_ccmis_api(self): + api = self.mock_cmis_api() + api.ccmis = api.get_ccmis_api() + @pytest.mark.parametrize("mock_response, expected", [ (6, "ModuleReady") ]) @@ -454,6 +513,16 @@ def test_get_module_state(self, mock_response, expected): result = api.get_module_state() assert result == expected + @pytest.mark.parametrize("mock_response, expected", [ + (1, (False, False, True)) + ]) + def test_get_module_firmware_fault_state_changed(self, mock_response, expected): + api = self.mock_cmis_api() + api.xcvr_eeprom.read = MagicMock() + api.xcvr_eeprom.read.return_value = mock_response + result = api.get_module_firmware_fault_state_changed() + assert result == expected + @pytest.mark.parametrize("mock_response, expected", [ (65, (False, False, True)) ]) @@ -889,7 +958,9 @@ def test_get_wavelength_unlocked(self, mock_response, expected): assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, ['TuningComplete']) + (1, ['TuningComplete']), + (62, ['TargetOutputPowerOOR', 'FineTuningOutOfRange', 'TuningNotAccepted', + 'InvalidChannel', 'WavelengthUnlocked']), ]) def test_get_laser_tuning_summary(self, mock_response, expected): api = self.mock_cmis_api() @@ -918,6 +989,40 @@ def test_get_supported_power_config(self, mock_response, expected): result = api.get_supported_power_config() assert result == expected + @pytest.mark.parametrize("input_param",[ + (True), (False) + ]) + def test_reset_module(self, input_param): + api = self.mock_cmis_api() + api.reset_module(input_param) + + @pytest.mark.parametrize("input_param",[ + (True), (False) + ]) + def test_set_low_power(self, input_param): + api = self.mock_cmis_api() + api.set_low_power(input_param) + + @pytest.mark.parametrize("input_param, mock_response",[ + (193100, (0xff, -72, 120, 191300, 196100)), + (195950, (0xff, -72, 120, 191300, 196100)), + ]) + def test_set_laser_freq(self, input_param, mock_response): + api = self.mock_cmis_api() + api.get_supported_freq_config = MagicMock() + api.get_supported_freq_config.return_value = mock_response + api.set_laser_freq(input_param) + + @pytest.mark.parametrize("input_param, mock_response",[ + (-10, (-14, -9)), + (-8, (-12, -8)), + ]) + def test_set_TX_power(self, input_param, mock_response): + api = self.mock_cmis_api() + api.get_supported_power_config = MagicMock() + api.get_supported_power_config.return_value = mock_response + api.set_TX_power(input_param) + @pytest.mark.parametrize("mock_response, expected", [ (127, { @@ -937,12 +1042,63 @@ def test_get_loopback_capability(self, mock_response, expected): result = api.get_loopback_capability() assert result == expected - @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - ([0x77, 0xff], [18, 35, (0, 7, 112, 255, 255, 16, 0, 0, 19, 136, 0, 100, 3, 232, 19, 136, 58, 152)], - (112, 2048, False, True, 2048) - ) + @pytest.mark.parametrize("input_param, mock_response",[ + ('none', { + 'host_side_input_loopback_supported': True, + 'host_side_output_loopback_supported': True, + 'media_side_input_loopback_supported': True, + 'media_side_output_loopback_supported': True + }), + ('host-side-input', { + 'host_side_input_loopback_supported': True, + 'host_side_output_loopback_supported': True, + 'media_side_input_loopback_supported': True, + 'media_side_output_loopback_supported': True + }), + ('host-side-output', { + 'host_side_input_loopback_supported': True, + 'host_side_output_loopback_supported': True, + 'media_side_input_loopback_supported': True, + 'media_side_output_loopback_supported': True + }), + ('media-side-input', { + 'host_side_input_loopback_supported': True, + 'host_side_output_loopback_supported': True, + 'media_side_input_loopback_supported': True, + 'media_side_output_loopback_supported': True + }), + ('media-side-output', { + 'host_side_input_loopback_supported': True, + 'host_side_output_loopback_supported': True, + 'media_side_input_loopback_supported': True, + 'media_side_output_loopback_supported': True + }), ]) - def test_get_module_FW_upgrade_feature(self, mock_response1, mock_response2, expected): + def test_set_loopback_mode(self, input_param, mock_response): + api = self.mock_cmis_api() + api.get_loopback_capability = MagicMock() + api.get_loopback_capability.return_value = mock_response + api.set_loopback_mode(input_param) + + def test_get_CDB_api(self): + api = self.mock_cmis_api() + api.cdb = api.get_CDB_api() + + @pytest.mark.parametrize("input_param, mock_response1, mock_response2, expected", [ + ( + False, + [0x77, 0xff], + [18, 35, (0, 7, 112, 255, 255, 16, 0, 0, 19, 136, 0, 100, 3, 232, 19, 136, 58, 152)], + (112, 2048, False, True, 2048) + ), + ( + True, + [0x77, 0xff], + [18, 35, (0, 7, 112, 255, 255, 1, 0, 0, 19, 136, 0, 100, 3, 232, 19, 136, 58, 152)], + (112, 2048, True, True, 2048) + ), + ]) + def test_get_module_FW_upgrade_feature(self, input_param, mock_response1, mock_response2, expected): api = self.mock_cmis_api() api.xcvr_eeprom.read = MagicMock() api.xcvr_eeprom.read.side_effect = mock_response1 @@ -951,13 +1107,18 @@ def test_get_module_FW_upgrade_feature(self, mock_response1, mock_response2, exp api.cdb.cmd0041h.return_value = mock_response2 api.cdb.cdb_chkcode = MagicMock() api.cdb.cdb_chkcode.return_value = mock_response2[1] - result = api.get_module_FW_upgrade_feature() + result = api.get_module_FW_upgrade_feature(input_param) assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - ([110, 26, (3, 3, 1, 1, 0, 4, 1, 4, 3, 0, 0, 100, 3, 232, 19, 136, 58, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 4, 1, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)], - ('1.1.4', 1, 1, 0, '1.1.4', 0, 0, 0) - ) + ( + [110, 26, (3, 3, 0, 0, 0, 1, 1, 4, 3, 0, 0, 100, 3, 232, 19, 136, 58, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)], + ('0.0.1', 1, 1, 0, '0.0.0', 0, 0, 0) + ), + ( + [110, 26, (48, 3, 0, 0, 0, 1, 1, 4, 3, 0, 0, 100, 3, 232, 19, 136, 58, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)], + ('0.0.1', 0, 0, 0, '0.0.0', 1, 1, 0) + ), ]) def test_get_module_FW_info(self, mock_response, expected): api = self.mock_cmis_api() @@ -968,7 +1129,65 @@ def test_get_module_FW_info(self, mock_response, expected): api.cdb.cdb_chkcode.return_value = mock_response[1] result = api.get_module_FW_info() assert result == expected - # TODO: call other methods in the api + + @pytest.mark.parametrize("input_param, mock_response", [ + (1, 1), + (1, 64) + ]) + def test_module_FW_run(self, input_param, mock_response): + api = self.mock_cmis_api() + api.cdb = MagicMock() + api.cdb.cmd0109h = MagicMock() + api.cdb.cmd0109h.return_value = mock_response + api.module_FW_run(input_param) + + @pytest.mark.parametrize("mock_response", [ + (1), (64) + ]) + def test_module_FW_commit(self, mock_response): + api = self.mock_cmis_api() + api.cdb = MagicMock() + api.cdb.cmd010Ah = MagicMock() + api.cdb.cmd010Ah.return_value = mock_response + api.module_FW_commit() + + # @pytest.mark.parametrize("input_param", [ + # (112, 2048, True, True, 2048, 'abc'), + # (112, 2048, False, True, 2048, 'abc') + # ]) + # def test_module_FW_download(self, input_param): + # api = self.mock_cmis_api() + # api.cdb = MagicMock() + # api.module_FW_download(*input_param) + + + @pytest.mark.parametrize("input_param, mock_response", [ + ( + 'abc', + (112, 2048, True, True, 2048) + ) + ]) + def test_module_firmware_upgrade(self, input_param, mock_response): + api = self.mock_cmis_api() + api.cdb = MagicMock() + api.cdb.get_module_FW_upgrade_feature = MagicMock() + api.cdb.get_module_FW_upgrade_feature.return_value = mock_response + api.cdb.module_firmware_upgrade(input_param) + + @pytest.mark.parametrize("mock_response", [ + ( + ('0.0.0', 1, 1, 0, '0.0.1', 0, 0, 0), + ('0.0.0', 1, 1, 0, '0.0.1', 0, 0, 1), + ) + ]) + def test_module_firmware_switch(self, mock_response): + api = self.mock_cmis_api() + api.cdb = MagicMock() + api.cdb.get_module_FW_info = MagicMock() + api.cdb.get_module_FW_info.return_value = mock_response + api.cdb.module_firmware_switch() + + @pytest.mark.parametrize("mock_response, expected",[ ( diff --git a/tests/sonic_xcvr/test_cmisCDB.py b/tests/sonic_xcvr/test_cmisCDB.py index b27d67743..497ae256c 100644 --- a/tests/sonic_xcvr/test_cmisCDB.py +++ b/tests/sonic_xcvr/test_cmisCDB.py @@ -20,7 +20,8 @@ def mock_cdb_api(self): return api.cdb @pytest.mark.parametrize("mock_response, expected", [ - (64, False) + (64, False), + (0, True) ]) def test_cdb1_chkflags(self, mock_response, expected): cdb = self.mock_cdb_api() @@ -38,12 +39,13 @@ def test_cdb_chkcode(self, input_param, expected): assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, 1) + ([1], 1), + ([128,128,128], 128) ]) def test_cdb1_chkstatus(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.xcvr_eeprom.read = MagicMock() - cdb.xcvr_eeprom.read.return_value = mock_response + cdb.xcvr_eeprom.read.side_effect = mock_response result = cdb.cdb1_chkstatus() assert result == expected @@ -63,112 +65,134 @@ def test_read_cdb(self, mock_response, expected): assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, 1) + ([1], (None, None, None)), + ([128, 128, 128], (None, None, None)), + ]) + def test_cmd0000h(self, mock_response, expected): + cdb = self.mock_cdb_api() + cdb.cdb1_chkstatus = MagicMock() + cdb.cdb1_chkstatus.side_effect = mock_response + result = cdb.cmd0000h() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([1], 1), + ([128, 128, 64], 64) ]) def test_cmd0001h(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0001h() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, (None, None, None)) + ([1], (None, None, None)), + ([64, 64, 64], (None, None, None)), ]) def test_cmd0040h(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0040h() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, (None, None, None)) + ([1], (None, None, None)), + ([64, 64, 64], (None, None, None)), ]) def test_cmd0041h(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0041h() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, (None, None, None)) + ([1], (None, None, None)), + ([64, 64, 64], (None, None, None)), ]) def test_cmd0100h(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0100h() assert result == expected @pytest.mark.parametrize("input_param, mock_response, expected", [ - ([3, bytearray(b'\x00\x00\x00'), 1000000], 1, 1) + ([3, bytearray(b'\x00\x00\x00'), 1000000], [1], 1), + ([3, bytearray(b'\x00\x00\x00'), 1000000], [64, 64, 64], 64) ]) def test_cmd0101h(self, input_param, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0101h(*input_param) assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, 1) + ([1], 1), + ([64, 64, 64], 64), ]) def test_cmd0102h(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0102h() assert result == expected @pytest.mark.parametrize("input_param, mock_response, expected", [ - ([100, bytearray(116)], 1, 1) + ([100, bytearray(116)], [1], 1), + ([100, bytearray(116)], [64, 64, 64], 64) ]) def test_cmd0103h(self, input_param, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0103h(*input_param) assert result == expected @pytest.mark.parametrize("input_param, mock_response, expected", [ - ([100, bytearray(2048), True, 2048], 1, 1) + ([100, bytearray(2048), True, 100], [1], 1), + ([100, bytearray(2047), False, 100], [64, 64, 64], 64), ]) def test_cmd0104h(self, input_param, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0104h(*input_param) assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, 1) + ([1], 1), + ([64, 64, 64], 64), ]) def test_cmd0107h(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0107h() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, 1) + ([1], 1), + ([64, 64, 64], 64), ]) def test_cmd0109h(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd0109h() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ - (1, 1) + ([1], 1), + ([64, 64, 64], 64), ]) def test_cmd010Ah(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() - cdb.cdb1_chkstatus.return_value = mock_response + cdb.cdb1_chkstatus.side_effect = mock_response result = cdb.cmd010Ah() assert result == expected diff --git a/tests/sonic_xcvr/test_cmisVDM.py b/tests/sonic_xcvr/test_cmisVDM.py index 520e0f245..c98bf06d0 100644 --- a/tests/sonic_xcvr/test_cmisVDM.py +++ b/tests/sonic_xcvr/test_cmisVDM.py @@ -32,9 +32,9 @@ def test_get_F16(self, input_param, expected): [0x20, [0]*128], # input_param [ # mock_response ( - 16, 9, 16, 11, 16, 13, 16, 15, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 9, 16, 11, 16, 13, 16, 15, 32, 10, 33, 10, 0, 0, 0, 0, + 80,128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 160,143,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -46,13 +46,22 @@ def test_get_F16(self, input_param, expected): bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), + bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), + bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), + bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), + bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), bytearray(b'\x00\x00'), ], { 'Pre-FEC BER Minimum Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, 'Pre-FEC BER Maximum Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, 'Pre-FEC BER Average Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, 'Pre-FEC BER Current Value Media Input': {1: [0, 0, 0, 0, 0, False, False, False, False]}, - + 'Pre-FEC BER Minimum Host Input': { + 1: [0, 0, 0, 0, 0, False, False, False, False], + 2: [0, 0, 0, 0, 0, False, False, False, False], + }, + 'Modulator Bias X/I [%]': {1: [0, 0, 0, 0, 0, False, False, False, False]}, + 'Tx Power [dBm]': {1: [0, 0, 0, 0, 0, False, False, False, False]}, } ) ]) From b6734608689b73960496c1f362c8c3d9d37c03f9 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Fri, 22 Oct 2021 12:57:16 -0700 Subject: [PATCH 14/16] 1. move all ZR specific functions to ccmis; 2. ccmis now inherits from cmis; 3. split cmis and ccmis api when creating xcvr_api in xcvr_api_factory; 4. remove print and add logger to collect info for syslog --- .../sonic_xcvr/api/public/c_cmis.py | 1023 +++++++++++++- .../sonic_xcvr/api/public/cmis.py | 1219 ++--------------- .../sonic_xcvr/api/public/cmisCDB.py | 100 +- .../sonic_xcvr/api/public/cmisVDM.py | 56 +- .../sonic_xcvr/codes/public/cmis_code.py | 4 +- .../sonic_xcvr/mem_maps/public/cmis.py | 25 +- .../sonic_xcvr/xcvr_api_factory.py | 25 +- sonic_platform_base/sonic_xcvr/xcvr_eeprom.py | 10 +- tests/sonic_xcvr/test_ccmis.py | 744 +++++++++- tests/sonic_xcvr/test_cmis.py | 807 +---------- tests/sonic_xcvr/test_cmisCDB.py | 6 +- tests/sonic_xcvr/test_cmisVDM.py | 22 +- 12 files changed, 2046 insertions(+), 1995 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index d84b8f772..ae086d621 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -4,16 +4,127 @@ Implementation of XcvrApi that corresponds to C-CMIS """ from ...fields import consts -from ..xcvr_api import XcvrApi +from .cmis import CmisApi import time BYTELENGTH = 8 -class CCmisApi(XcvrApi): - NUM_CHANNELS = 8 +class CCmisApi(CmisApi): def __init__(self, xcvr_eeprom): super(CCmisApi, self).__init__(xcvr_eeprom) - def get_PM_all(self): + def get_freq_grid(self): + ''' + This function returns the configured frequency grid. Unit in GHz + ''' + freq_grid = self.xcvr_eeprom.read(consts.GRID_SPACING) >> 4 + if freq_grid == 7: + return 75 + elif freq_grid == 6: + return 33 + elif freq_grid == 5: + return 100 + elif freq_grid == 4: + return 50 + elif freq_grid == 3: + return 25 + elif freq_grid == 2: + return 12.5 + elif freq_grid == 1: + return 6.25 + elif freq_grid == 0: + return 3.125 + + def get_laser_config_freq(self): + ''' + This function returns the configured laser frequency. Unit in GHz + ''' + freq_grid = self.get_freq_grid() + channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) + if freq_grid == 75: + config_freq = 193100 + channel * freq_grid/3 + else: + config_freq = 193100 + channel * freq_grid + return config_freq + + def get_current_laser_freq(self): + ''' + This function returns the monitored laser frequency. Unit in GHz + ''' + return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ)/1000 + + def get_tuning_in_progress(self): + ''' + This function returns tunning in progress status on media lane + 0 means tuning not in progress + 1 means tuning in progress + ''' + return bool(self.xcvr_eeprom.read(consts.TUNING_IN_PROGRESS)) + + def get_wavelength_unlocked(self): + ''' + This function returns wavelength unlocked status on media lane + 0 means wavelength locked + 1 means wavelength unlocked + ''' + return bool(self.xcvr_eeprom.read(consts.WAVELENGTH_UNLOCKED)) + + def get_laser_tuning_summary(self): + ''' + This function returns laser tuning status summary on media lane + ''' + result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) + laser_tuning_summary = [] + if (result >> 5) & 0x1: + laser_tuning_summary.append("TargetOutputPowerOOR") + if (result >> 4) & 0x1: + laser_tuning_summary.append("FineTuningOutOfRange") + if (result >> 3) & 0x1: + laser_tuning_summary.append("TuningNotAccepted") + if (result >> 2) & 0x1: + laser_tuning_summary.append("InvalidChannel") + if (result >> 1) & 0x1: + laser_tuning_summary.append("WavelengthUnlocked") + if (result >> 0) & 0x1: + laser_tuning_summary.append("TuningComplete") + return laser_tuning_summary + + def get_supported_freq_config(self): + ''' + This function returns the supported freq grid, low and high supported channel in 75GHz grid, + and low and high frequency supported in GHz. + allowed channel number bound in 75 GHz grid + allowed frequency bound in 75 GHz grid + ''' + grid_supported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) + low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) + hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) + low_freq_supported = 193100 + low_ch_num * 25 + high_freq_supported = 193100 + hi_ch_num * 25 + return grid_supported, low_ch_num, hi_ch_num, low_freq_supported, high_freq_supported + + def set_laser_freq(self, freq): + ''' + This function sets the laser frequency. Unit in GHz + ZR application will not support fine tuning of the laser + Microsoft will only supports 75 GHz frequency grid + ''' + grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() + grid_supported_75GHz = (grid_supported >> 7) & 0x1 + assert grid_supported_75GHz + freq_grid = 0x70 + self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) + channel_number = int(round((freq - 193100)/25)) + assert channel_number % 3 == 0 + if channel_number > hi_ch_num or channel_number < low_ch_num: + raise ValueError('Provisioned frequency out of range. Max Freq: 196100; Min Freq: 191300 GHz.') + self.set_low_power(True) + time.sleep(5) + self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) + time.sleep(1) + self.set_low_power(False) + time.sleep(1) + + def get_pm_all(self): ''' This function returns the PMs reported in Page 34h and 35h in OIF C-CMIS document CD: unit in ps/nm @@ -108,3 +219,907 @@ def get_PM_all(self): PM_dict['rx_mer_min'] = self.xcvr_eeprom.read(consts.RX_MIN_MER_PM) PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM) return PM_dict + + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_INFO|ifname ; information for module on port + ; field = value + module_media_type = 1*255VCHAR ; module media interface ID + host_electrical_interface = 1*255VCHAR ; host electrical interface ID + media_interface_code = 1*255VCHAR ; media interface code + host_lane_count = INTEGER ; host lane count + media_lane_count = INTEGER ; media lane count + host_lane_assignment_option = INTEGER ; permissible first host lane number for application + media_lane_assignment_option = INTEGER ; permissible first media lane number for application + active_apsel_hostlane1 = INTEGER ; active application selected code assigned to host lane 1 + active_apsel_hostlane2 = INTEGER ; active application selected code assigned to host lane 2 + active_apsel_hostlane3 = INTEGER ; active application selected code assigned to host lane 3 + active_apsel_hostlane4 = INTEGER ; active application selected code assigned to host lane 4 + active_apsel_hostlane5 = INTEGER ; active application selected code assigned to host lane 5 + active_apsel_hostlane6 = INTEGER ; active application selected code assigned to host lane 6 + active_apsel_hostlane7 = INTEGER ; active application selected code assigned to host lane 7 + active_apsel_hostlane8 = INTEGER ; active application selected code assigned to host lane 8 + media_interface_technology = 1*255VCHAR ; media interface technology + hardwarerev = 1*255VCHAR ; module hardware revision + serialnum = 1*255VCHAR ; module serial number + manufacturename = 1*255VCHAR ; module venndor name + modelname = 1*255VCHAR ; module model name + vendor_rev = 1*255VCHAR ; module vendor revision + vendor_oui = 1*255VCHAR ; vendor organizationally unique identifier + vendor_date = 1*255VCHAR ; module manufacture date + connector_type = 1*255VCHAR ; connector type + specification_compliance = 1*255VCHAR ; electronic or optical interfaces that supported + active_firmware = 1*255VCHAR ; active firmware + inactive_firmware = 1*255VCHAR ; inactive firmware + supported_max_tx_power = FLOAT ; support maximum tx power + supported_min_tx_power = FLOAT ; support minimum tx power + supported_max_laser_freq = FLOAT ; support maximum laser frequency + supported_min_laser_freq = FLOAT ; support minimum laser frequency + ================================================================================ + """ + trans_info = dict() + trans_info['module_media_type'] = self.get_module_media_type() + trans_info['host_electrical_interface'] = self.get_host_electrical_interface() + trans_info['media_interface_code'] = self.get_module_media_interface() + trans_info['host_lane_count'] = self.get_host_lane_count() + trans_info['media_lane_count'] = self.get_media_lane_count() + trans_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option() + trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() + apsel_dict = self.get_active_apsel_hostlane() + trans_info['active_apsel_hostlane1'] = apsel_dict['hostlane1'] + trans_info['active_apsel_hostlane2'] = apsel_dict['hostlane2'] + trans_info['active_apsel_hostlane3'] = apsel_dict['hostlane3'] + trans_info['active_apsel_hostlane4'] = apsel_dict['hostlane4'] + trans_info['active_apsel_hostlane5'] = apsel_dict['hostlane5'] + trans_info['active_apsel_hostlane6'] = apsel_dict['hostlane6'] + trans_info['active_apsel_hostlane7'] = apsel_dict['hostlane7'] + trans_info['active_apsel_hostlane8'] = apsel_dict['hostlane8'] + trans_info['media_interface_technology'] = self.get_media_interface_technology() + trans_info['hardwarerev'] = self.get_module_hardware_revision() + trans_info['serialnum'] = self.get_vendor_serial() + trans_info['manufacturename'] = self.get_vendor_name() + trans_info['vendor_rev'] = self.get_vendor_rev() + trans_info['vendor_oui'] = self.get_vendor_OUI() + trans_info['vendor_date'] = self.get_vendor_date() + trans_info['connector_type'] = self.get_connector_type() + trans_info['specification_compliance'] = self.get_cmis_rev() + trans_info['active_firmware'] = self.get_module_active_firmware() + trans_info['inactive_firmware'] = self.get_module_inactive_firmware() + min_power, max_power = self.get_supported_power_config() + trans_info['supported_max_tx_power'] = max_power + trans_info['supported_min_tx_power'] = min_power + _, _, _, low_freq_supported, high_freq_supported = self.get_supported_freq_config() + trans_info['supported_max_laser_freq'] = high_freq_supported + trans_info['supported_min_laser_freq'] = low_freq_supported + return trans_info + + def get_transceiver_bulk_status(self): + """ + Retrieves bulk status info for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_DOM_SENSOR|ifname ; information module DOM sensors on port + ; field = value + temperature = FLOAT ; temperature value in Celsius + voltage = FLOAT ; voltage value + txpower = FLOAT ; tx power in mW + rxpower = FLOAT ; rx power in mW + txbias = FLOAT ; tx bias in mA + laser_temperature = FLOAT ; laser temperature value in Celsius + prefec_ber = FLOAT ; prefec ber + postfec_ber = FLOAT ; postfec ber + cd_shortlink = FLOAT ; chromatic dispersion, high granularity, short link in ps/nm + cd_longlink = FLOAT ; chromatic dispersion, low granularity, long link in ps/nm + dgd = FLOAT ; differential group delay in ps + sopmd = FLOAT ; second order polarization mode dispersion in ps^2 + pdl = FLOAT ; polarization dependent loss in db + osnr = FLOAT ; optical signal to noise ratio in db + esnr = FLOAT ; electrical signal to noise ratio in db + cfo = FLOAT ; carrier frequency offset in MHz + soproc = FLOAT ; state of polarization rate of change in krad/s + laser_config_freq = FLOAT ; laser configured frequency in MHz + laser_curr_freq = FLOAT ; laser current frequency in MHz + tx_config_power = FLOAT ; configured tx output power in dbm + tx_curr_power = FLOAT ; tx current output power in dbm + rx_tot_power = FLOAT ; rx total power in dbm + rx_sig_power = FLOAT ; rx signal power in dbm + bias_xi = FLOAT ; modulator bias xi + bias_xq = FLOAT ; modulator bias xq + bias_xp = FLOAT ; modulator bias xp + bias_yi = FLOAT ; modulator bias yi + bias_yq = FLOAT ; modulator bias yq + bias_yp = FLOAT ; modulator bias yp + ======================================================================== + """ + trans_dom = dict() + case_temp_dict = self.get_module_temperature() + trans_dom['temperature'] = case_temp_dict['monitor value'] + voltage_dict = self.get_module_voltage() + trans_dom['voltage'] = voltage_dict['monitor value'] + tx_power_dict = self.get_txpower() + trans_dom['txpower'] = tx_power_dict['monitor value lane1'] + rx_power_dict = self.get_rxpower() + trans_dom['rxpower'] = rx_power_dict['monitor value lane1'] + tx_bias_current_dict = self.get_txbias() + trans_dom['txbias'] = tx_bias_current_dict['monitor value lane1'] + laser_temp_dict = self.get_laser_temperature() + trans_dom['laser_temperature'] = laser_temp_dict['monitor value'] + vdm_dict = self.get_vdm() + trans_dom['prefec_ber'] = vdm_dict['Pre-FEC BER Average Media Input'][1][0] + trans_dom['postfec_ber'] = vdm_dict['Errored Frames Average Media Input'][1][0] + trans_dom['bias_xi'] = vdm_dict['Modulator Bias X/I [%]'][1][0] + trans_dom['bias_xq'] = vdm_dict['Modulator Bias X/Q [%]'][1][0] + trans_dom['bias_xp'] = vdm_dict['Modulator Bias X_Phase [%]'][1][0] + trans_dom['bias_yi'] = vdm_dict['Modulator Bias Y/I [%]'][1][0] + trans_dom['bias_yq'] = vdm_dict['Modulator Bias Y/Q [%]'][1][0] + trans_dom['bias_yp'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][0] + trans_dom['cd_shortlink'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][0] + try: + trans_dom['cd_longlink'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][0] + except KeyError: + pass + trans_dom['dgd'] = vdm_dict['DGD [ps]'][1][0] + try: + trans_dom['sopmd'] = vdm_dict['SOPMD [ps^2]'][1][0] + except KeyError: + pass + trans_dom['pdl'] = vdm_dict['PDL [dB]'][1][0] + trans_dom['osnr'] = vdm_dict['OSNR [dB]'][1][0] + trans_dom['esnr'] = vdm_dict['eSNR [dB]'][1][0] + trans_dom['cfo'] = vdm_dict['CFO [MHz]'][1][0] + trans_dom['tx_curr_power'] = vdm_dict['Tx Power [dBm]'][1][0] + trans_dom['rx_tot_power'] = vdm_dict['Rx Total Power [dBm]'][1][0] + trans_dom['rx_sig_power'] = vdm_dict['Rx Signal Power [dBm]'][1][0] + trans_dom['laser_config_freq'] = self.get_laser_config_freq() + trans_dom['laser_curr_freq'] = self.get_current_laser_freq() + trans_dom['tx_config_power'] = self.get_tx_config_power() + return trans_dom + + def get_transceiver_threshold_info(self): + """ + Retrieves threshold info for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_STATUS|ifname ; DOM threshold information for module on port + ; field = value + temphighalarm = FLOAT ; temperature high alarm threshold in Celsius + temphighwarning = FLOAT ; temperature high warning threshold in Celsius + templowalarm = FLOAT ; temperature low alarm threshold in Celsius + templowwarning = FLOAT ; temperature low warning threshold in Celsius + vcchighalarm = FLOAT ; vcc high alarm threshold in V + vcchighwarning = FLOAT ; vcc high warning threshold in V + vcclowalarm = FLOAT ; vcc low alarm threshold in V + vcclowwarning = FLOAT ; vcc low warning threshold in V + txpowerhighalarm = FLOAT ; tx power high alarm threshold in mW + txpowerlowalarm = FLOAT ; tx power low alarm threshold in mW + txpowerhighwarning = FLOAT ; tx power high warning threshold in mW + txpowerlowwarning = FLOAT ; tx power low alarm threshold in mW + rxpowerhighalarm = FLOAT ; rx power high alarm threshold in mW + rxpowerlowalarm = FLOAT ; rx power low alarm threshold in mW + rxpowerhighwarning = FLOAT ; rx power high warning threshold in mW + rxpowerlowwarning = FLOAT ; rx power low warning threshold in mW + txbiashighalarm = FLOAT ; tx bias high alarm threshold in mA + txbiaslowalarm = FLOAT ; tx bias low alarm threshold in mA + txbiashighwarning = FLOAT ; tx bias high warning threshold in mA + txbiaslowwarning = FLOAT ; tx bias low warning threshold in mA + lasertemphighalarm = FLOAT ; laser temperature high alarm threshold in Celsius + lasertemplowalarm = FLOAT ; laser temperature low alarm threshold in Celsius + lasertemphighwarning = FLOAT ; laser temperature high warning threshold in Celsius + lasertemplowwarning = FLOAT ; laser temperature low warning threshold in Celsius + prefecberhighalarm = FLOAT ; prefec ber high alarm threshold + prefecberlowalarm = FLOAT ; prefec ber low alarm threshold + prefecberhighwarning = FLOAT ; prefec ber high warning threshold + prefecberlowwarning = FLOAT ; prefec ber low warning threshold + postfecberhighalarm = FLOAT ; postfec ber high alarm threshold + postfecberlowalarm = FLOAT ; postfec ber low alarm threshold + postfecberhighwarning = FLOAT ; postfec ber high warning threshold + postfecberlowwarning = FLOAT ; postfec ber low warning threshold + biasxihighalarm = FLOAT ; bias xi high alarm threshold in percent + biasxilowalarm = FLOAT ; bias xi low alarm threshold in percent + biasxihighwarning = FLOAT ; bias xi high warning threshold in percent + biasxilowwarning = FLOAT ; bias xi low warning threshold in percent + biasxqhighalarm = FLOAT ; bias xq high alarm threshold in percent + biasxqlowalarm = FLOAT ; bias xq low alarm threshold in percent + biasxqhighwarning = FLOAT ; bias xq high warning threshold in percent + biasxqlowwarning = FLOAT ; bias xq low warning threshold in percent + biasxphighalarm = FLOAT ; bias xp high alarm threshold in percent + biasxplowalarm = FLOAT ; bias xp low alarm threshold in percent + biasxphighwarning = FLOAT ; bias xp high warning threshold in percent + biasxplowwarning = FLOAT ; bias xp low warning threshold in percent + biasyihighalarm = FLOAT ; bias yi high alarm threshold in percent + biasyilowalarm = FLOAT ; bias yi low alarm threshold in percent + biasyihighwarning = FLOAT ; bias yi high warning threshold in percent + biasyilowwarning = FLOAT ; bias yi low warning threshold in percent + biasyqhighalarm = FLOAT ; bias yq high alarm threshold in percent + biasyqlowalarm = FLOAT ; bias yq low alarm threshold in percent + biasyqhighwarning = FLOAT ; bias yq high warning threshold in percent + biasyqlowwarning = FLOAT ; bias yq low warning threshold in percent + biasyphighalarm = FLOAT ; bias yp high alarm threshold in percent + biasyplowalarm = FLOAT ; bias yp low alarm threshold in percent + biasyphighwarning = FLOAT ; bias yp high warning threshold in percent + biasyplowwarning = FLOAT ; bias yp low warning threshold in percent + cdshorthighalarm = FLOAT ; cd short high alarm threshold in ps/nm + cdshortlowalarm = FLOAT ; cd short low alarm threshold in ps/nm + cdshorthighwarning = FLOAT ; cd short high warning threshold in ps/nm + cdshortlowwarning = FLOAT ; cd short low warning threshold in ps/nm + cdlonghighalarm = FLOAT ; cd long high alarm threshold in ps/nm + cdlonglowalarm = FLOAT ; cd long low alarm threshold in ps/nm + cdlonghighwarning = FLOAT ; cd long high warning threshold in ps/nm + cdlonglowwarning = FLOAT ; cd long low warning threshold in ps/nm + dgdhighalarm = FLOAT ; dgd high alarm threshold in ps + dgdlowalarm = FLOAT ; dgd low alarm threshold in ps + dgdhighwarning = FLOAT ; dgd high warning threshold in ps + dgdlowwarning = FLOAT ; dgd low warning threshold in ps + sopmdhighalarm = FLOAT ; sopmd high alarm threshold in ps^2 + sopmdlowalarm = FLOAT ; sopmd low alarm threshold in ps^2 + sopmdhighwarning = FLOAT ; sopmd high warning threshold in ps^2 + sopmdlowwarning = FLOAT ; sopmd low warning threshold in ps^2 + pdlhighalarm = FLOAT ; pdl high alarm threshold in db + pdllowalarm = FLOAT ; pdl low alarm threshold in db + pdlhighwarning = FLOAT ; pdl high warning threshold in db + pdllowwarning = FLOAT ; pdl low warning threshold in db + osnrhighalarm = FLOAT ; osnr high alarm threshold in db + osnrlowalarm = FLOAT ; osnr low alarm threshold in db + osnrhighwarning = FLOAT ; osnr high warning threshold in db + osnrlowwarning = FLOAT ; osnr low warning threshold in db + esnrhighalarm = FLOAT ; esnr high alarm threshold in db + esnrlowalarm = FLOAT ; esnr low alarm threshold in db + esnrhighwarning = FLOAT ; esnr high warning threshold in db + esnrlowwarning = FLOAT ; esnr low warning threshold in db + cfohighalarm = FLOAT ; cfo high alarm threshold in MHz + cfolowalarm = FLOAT ; cfo low alarm threshold in MHz + cfohighwarning = FLOAT ; cfo high warning threshold in MHz + cfolowwarning = FLOAT ; cfo low warning threshold in MHz + txcurrpowerhighalarm = FLOAT ; txcurrpower high alarm threshold in dbm + txcurrpowerlowalarm = FLOAT ; txcurrpower low alarm threshold in dbm + txcurrpowerhighwarning = FLOAT ; txcurrpower high warning threshold in dbm + txcurrpowerlowwarning = FLOAT ; txcurrpower low warning threshold in dbm + rxtotpowerhighalarm = FLOAT ; rxtotpower high alarm threshold in dbm + rxtotpowerlowalarm = FLOAT ; rxtotpower low alarm threshold in dbm + rxtotpowerhighwarning = FLOAT ; rxtotpower high warning threshold in dbm + rxtotpowerlowwarning = FLOAT ; rxtotpower low warning threshold in dbm + rxsigpowerhighalarm = FLOAT ; rxsigpower high alarm threshold in dbm + rxsigpowerlowalarm = FLOAT ; rxsigpower low alarm threshold in dbm + rxsigpowerhighwarning = FLOAT ; rxsigpower high warning threshold in dbm + rxsigpowerlowwarning = FLOAT ; rxsigpower low warning threshold in dbm + ======================================================================== + """ + trans_dom_th = dict() + case_temp_dict = self.get_module_temperature() + trans_dom_th['temphighalarm'] = case_temp_dict['high alarm'] + trans_dom_th['templowalarm'] = case_temp_dict['low alarm'] + trans_dom_th['temphighwarning'] = case_temp_dict['high warn'] + trans_dom_th['templowwarning'] = case_temp_dict['low warn'] + voltage_dict = self.get_module_voltage() + trans_dom_th['vcchighalarm'] = voltage_dict['high alarm'] + trans_dom_th['vcclowalarm'] = voltage_dict['low alarm'] + trans_dom_th['vcchighwarning'] = voltage_dict['high warn'] + trans_dom_th['vcclowwarning'] = voltage_dict['low warn'] + tx_power_dict = self.get_txpower() + trans_dom_th['txpowerhighalarm'] = tx_power_dict['high alarm'] + trans_dom_th['txpowerlowalarm'] = tx_power_dict['low alarm'] + trans_dom_th['txpowerhighwarning'] = tx_power_dict['high warn'] + trans_dom_th['txpowerlowwarning'] = tx_power_dict['low warn'] + rx_power_dict = self.get_rxpower() + trans_dom_th['rxpowerhighalarm'] = rx_power_dict['high alarm'] + trans_dom_th['rxpowerlowalarm'] = rx_power_dict['low alarm'] + trans_dom_th['rxpowerhighwarning'] = rx_power_dict['high warn'] + trans_dom_th['rxpowerlowwarning'] = rx_power_dict['low warn'] + tx_bias_current_dict = self.get_txbias() + trans_dom_th['txbiashighalarm'] = tx_bias_current_dict['high alarm'] + trans_dom_th['txbiaslowalarm'] = tx_bias_current_dict['low alarm'] + trans_dom_th['txbiashighwarning'] = tx_bias_current_dict['high warn'] + trans_dom_th['txbiaslowwarning'] = tx_bias_current_dict['low warn'] + laser_temp_dict = self.get_laser_temperature() + trans_dom_th['lasertemphighalarm'] = laser_temp_dict['high alarm'] + trans_dom_th['lasertemplowalarm'] = laser_temp_dict['low alarm'] + trans_dom_th['lasertemphighwarning'] = laser_temp_dict['high warn'] + trans_dom_th['lasertemplowwarning'] = laser_temp_dict['low warn'] + vdm_dict = self.get_vdm() + trans_dom_th['prefecberhighalarm'] = vdm_dict['Pre-FEC BER Average Media Input'][1][1] + trans_dom_th['prefecberlowalarm'] = vdm_dict['Pre-FEC BER Average Media Input'][1][2] + trans_dom_th['prefecberhighwarning'] = vdm_dict['Pre-FEC BER Average Media Input'][1][3] + trans_dom_th['prefecberlowwarning'] = vdm_dict['Pre-FEC BER Average Media Input'][1][4] + trans_dom_th['postfecberhighalarm'] = vdm_dict['Errored Frames Average Media Input'][1][1] + trans_dom_th['postfecberlowalarm'] = vdm_dict['Errored Frames Average Media Input'][1][2] + trans_dom_th['postfecberhighwarning'] = vdm_dict['Errored Frames Average Media Input'][1][3] + trans_dom_th['postfecberlowwarning'] = vdm_dict['Errored Frames Average Media Input'][1][4] + trans_dom_th['biasxihighalarm'] = vdm_dict['Modulator Bias X/I [%]'][1][1] + trans_dom_th['biasxilowalarm'] = vdm_dict['Modulator Bias X/I [%]'][1][2] + trans_dom_th['biasxihighwarning'] = vdm_dict['Modulator Bias X/I [%]'][1][3] + trans_dom_th['biasxilowwarning'] = vdm_dict['Modulator Bias X/I [%]'][1][4] + trans_dom_th['biasxqhighalarm'] = vdm_dict['Modulator Bias X/Q [%]'][1][1] + trans_dom_th['biasxqlowalarm'] = vdm_dict['Modulator Bias X/Q [%]'][1][2] + trans_dom_th['biasxqhighwarning'] = vdm_dict['Modulator Bias X/Q [%]'][1][3] + trans_dom_th['biasxqlowwarning'] = vdm_dict['Modulator Bias X/Q [%]'][1][4] + trans_dom_th['biasxphighalarm'] = vdm_dict['Modulator Bias X_Phase [%]'][1][1] + trans_dom_th['biasxplowalarm'] = vdm_dict['Modulator Bias X_Phase [%]'][1][2] + trans_dom_th['biasxphighwarning'] = vdm_dict['Modulator Bias X_Phase [%]'][1][3] + trans_dom_th['biasxplowwarning'] = vdm_dict['Modulator Bias X_Phase [%]'][1][4] + trans_dom_th['biasyihighalarm'] = vdm_dict['Modulator Bias Y/I [%]'][1][1] + trans_dom_th['biasyilowalarm'] = vdm_dict['Modulator Bias Y/I [%]'][1][2] + trans_dom_th['biasyihighwarning'] = vdm_dict['Modulator Bias Y/I [%]'][1][3] + trans_dom_th['biasyilowwarning'] = vdm_dict['Modulator Bias Y/I [%]'][1][4] + trans_dom_th['biasyqhighalarm'] = vdm_dict['Modulator Bias Y/Q [%]'][1][1] + trans_dom_th['biasyqlowalarm'] = vdm_dict['Modulator Bias Y/Q [%]'][1][2] + trans_dom_th['biasyqhighwarning'] = vdm_dict['Modulator Bias Y/Q [%]'][1][3] + trans_dom_th['biasyqlowwarning'] = vdm_dict['Modulator Bias Y/Q [%]'][1][4] + trans_dom_th['biasyphighalarm'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][1] + trans_dom_th['biasyplowalarm'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][2] + trans_dom_th['biasyphighwarning'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][3] + trans_dom_th['biasyplowwarning'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][4] + trans_dom_th['cdshorthighalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][1] + trans_dom_th['cdshortlowalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][2] + trans_dom_th['cdshorthighwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][3] + trans_dom_th['cdshortlowwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][4] + try: + trans_dom_th['cdlonghighalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][1] + trans_dom_th['cdlonglowalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][2] + trans_dom_th['cdlonghighwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][3] + trans_dom_th['cdlonglowwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][4] + except KeyError: + pass + trans_dom_th['dgdhighalarm'] = vdm_dict['DGD [ps]'][1][1] + trans_dom_th['dgdlowalarm'] = vdm_dict['DGD [ps]'][1][2] + trans_dom_th['dgdhighwarning'] = vdm_dict['DGD [ps]'][1][3] + trans_dom_th['dgdlowwarning'] = vdm_dict['DGD [ps]'][1][4] + try: + trans_dom_th['sopmdhighalarm'] = vdm_dict['SOPMD [ps^2]'][1][1] + trans_dom_th['sopmdlowalarm'] = vdm_dict['SOPMD [ps^2]'][1][2] + trans_dom_th['sopmdhighwarning'] = vdm_dict['SOPMD [ps^2]'][1][3] + trans_dom_th['sopmdlowwarning'] = vdm_dict['SOPMD [ps^2]'][1][4] + except KeyError: + pass + trans_dom_th['pdlhighalarm'] = vdm_dict['PDL [dB]'][1][1] + trans_dom_th['pdllowalarm'] = vdm_dict['PDL [dB]'][1][2] + trans_dom_th['pdlhighwarning'] = vdm_dict['PDL [dB]'][1][3] + trans_dom_th['pdllowwarning'] = vdm_dict['PDL [dB]'][1][4] + trans_dom_th['osnrhighalarm'] = vdm_dict['OSNR [dB]'][1][1] + trans_dom_th['osnrlowalarm'] = vdm_dict['OSNR [dB]'][1][2] + trans_dom_th['osnrhighwarning'] = vdm_dict['OSNR [dB]'][1][3] + trans_dom_th['osnrlowwarning'] = vdm_dict['OSNR [dB]'][1][4] + trans_dom_th['esnrhighalarm'] = vdm_dict['eSNR [dB]'][1][1] + trans_dom_th['esnrlowalarm'] = vdm_dict['eSNR [dB]'][1][2] + trans_dom_th['esnrhighwarning'] = vdm_dict['eSNR [dB]'][1][3] + trans_dom_th['esnrlowwarning'] = vdm_dict['eSNR [dB]'][1][4] + trans_dom_th['cfohighalarm'] = vdm_dict['CFO [MHz]'][1][1] + trans_dom_th['cfolowalarm'] = vdm_dict['CFO [MHz]'][1][2] + trans_dom_th['cfohighwarning'] = vdm_dict['CFO [MHz]'][1][3] + trans_dom_th['cfolowwarning'] = vdm_dict['CFO [MHz]'][1][4] + trans_dom_th['txcurrpowerhighalarm'] = vdm_dict['Tx Power [dBm]'][1][1] + trans_dom_th['txcurrpowerlowalarm'] = vdm_dict['Tx Power [dBm]'][1][2] + trans_dom_th['txcurrpowerhighwarning'] = vdm_dict['Tx Power [dBm]'][1][3] + trans_dom_th['txcurrpowerlowwarning'] = vdm_dict['Tx Power [dBm]'][1][4] + trans_dom_th['rxtotpowerhighalarm'] = vdm_dict['Rx Total Power [dBm]'][1][1] + trans_dom_th['rxtotpowerlowalarm'] = vdm_dict['Rx Total Power [dBm]'][1][2] + trans_dom_th['rxtotpowerhighwarning'] = vdm_dict['Rx Total Power [dBm]'][1][3] + trans_dom_th['rxtotpowerlowwarning'] = vdm_dict['Rx Total Power [dBm]'][1][4] + trans_dom_th['rxsigpowerhighalarm'] = vdm_dict['Rx Signal Power [dBm]'][1][1] + trans_dom_th['rxsigpowerlowalarm'] = vdm_dict['Rx Signal Power [dBm]'][1][2] + trans_dom_th['rxsigpowerhighwarning'] = vdm_dict['Rx Signal Power [dBm]'][1][3] + trans_dom_th['rxsigpowerlowwarning'] = vdm_dict['Rx Signal Power [dBm]'][1][4] + return trans_dom_th + + def get_transceiver_status(self): + """ + Retrieves transceiver status of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_STATUS|ifname ; Error information for module on port + ; field = value + status = 1*255VCHAR ; code of the module status (plug in, plug out) + error = 1*255VCHAR ; module error (N/A or a string consisting of error descriptions joined by "|", like "error1 | error2" ) + module_state = 1*255VCHAR ; current module state (ModuleLowPwr, ModulePwrUp, ModuleReady, ModulePwrDn, Fault) + module_fault_cause = 1*255VCHAR ; reason of entering the module fault state + datapath_firmware_fault = BOOLEAN ; datapath (DSP) firmware fault + module_firmware_fault = BOOLEAN ; module firmware fault + module_state_changed = BOOLEAN ; module state changed + datapath_hostlane1 = 1*255VCHAR ; data path state indicator on host lane 1 + datapath_hostlane2 = 1*255VCHAR ; data path state indicator on host lane 2 + datapath_hostlane3 = 1*255VCHAR ; data path state indicator on host lane 3 + datapath_hostlane4 = 1*255VCHAR ; data path state indicator on host lane 4 + datapath_hostlane5 = 1*255VCHAR ; data path state indicator on host lane 5 + datapath_hostlane6 = 1*255VCHAR ; data path state indicator on host lane 6 + datapath_hostlane7 = 1*255VCHAR ; data path state indicator on host lane 7 + datapath_hostlane8 = 1*255VCHAR ; data path state indicator on host lane 8 + txoutput_status = BOOLEAN ; tx output status on media lane + rxoutput_status_hostlane1 = BOOLEAN ; rx output status on host lane 1 + rxoutput_status_hostlane2 = BOOLEAN ; rx output status on host lane 2 + rxoutput_status_hostlane3 = BOOLEAN ; rx output status on host lane 3 + rxoutput_status_hostlane4 = BOOLEAN ; rx output status on host lane 4 + rxoutput_status_hostlane5 = BOOLEAN ; rx output status on host lane 5 + rxoutput_status_hostlane6 = BOOLEAN ; rx output status on host lane 6 + rxoutput_status_hostlane7 = BOOLEAN ; rx output status on host lane 7 + rxoutput_status_hostlane8 = BOOLEAN ; rx output status on host lane 8 + txfault = BOOLEAN ; tx fault flag on media lane + txlos_hostlane1 = BOOLEAN ; tx loss of signal flag on host lane 1 + txlos_hostlane2 = BOOLEAN ; tx loss of signal flag on host lane 2 + txlos_hostlane3 = BOOLEAN ; tx loss of signal flag on host lane 3 + txlos_hostlane4 = BOOLEAN ; tx loss of signal flag on host lane 4 + txlos_hostlane5 = BOOLEAN ; tx loss of signal flag on host lane 5 + txlos_hostlane6 = BOOLEAN ; tx loss of signal flag on host lane 6 + txlos_hostlane7 = BOOLEAN ; tx loss of signal flag on host lane 7 + txlos_hostlane8 = BOOLEAN ; tx loss of signal flag on host lane 8 + txcdrlol_hostlane1 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 1 + txcdrlol_hostlane2 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 2 + txcdrlol_hostlane3 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 3 + txcdrlol_hostlane4 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 4 + txcdrlol_hostlane5 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 5 + txcdrlol_hostlane6 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 6 + txcdrlol_hostlane7 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 7 + txcdrlol_hostlane8 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 8 + rxlos = BOOLEAN ; rx loss of signal flag on media lane + rxcdrlol = BOOLEAN ; rx clock and data recovery loss of lock on media lane + config_state_hostlane1 = 1*255VCHAR ; configuration status for the data path of host line 1 + config_state_hostlane2 = 1*255VCHAR ; configuration status for the data path of host line 2 + config_state_hostlane3 = 1*255VCHAR ; configuration status for the data path of host line 3 + config_state_hostlane4 = 1*255VCHAR ; configuration status for the data path of host line 4 + config_state_hostlane5 = 1*255VCHAR ; configuration status for the data path of host line 5 + config_state_hostlane6 = 1*255VCHAR ; configuration status for the data path of host line 6 + config_state_hostlane7 = 1*255VCHAR ; configuration status for the data path of host line 7 + config_state_hostlane8 = 1*255VCHAR ; configuration status for the data path of host line 8 + dpinit_pending_hostlane1 = BOOLEAN ; data path configuration updated on host lane 1 + dpinit_pending_hostlane2 = BOOLEAN ; data path configuration updated on host lane 2 + dpinit_pending_hostlane3 = BOOLEAN ; data path configuration updated on host lane 3 + dpinit_pending_hostlane4 = BOOLEAN ; data path configuration updated on host lane 4 + dpinit_pending_hostlane5 = BOOLEAN ; data path configuration updated on host lane 5 + dpinit_pending_hostlane6 = BOOLEAN ; data path configuration updated on host lane 6 + dpinit_pending_hostlane7 = BOOLEAN ; data path configuration updated on host lane 7 + dpinit_pending_hostlane8 = BOOLEAN ; data path configuration updated on host lane 8 + tuning_in_progress = BOOLEAN ; tuning in progress status + wavelength_unlock_status = BOOLEAN ; laser unlocked status + target_output_power_oor = BOOLEAN ; target output power out of range flag + fine_tuning_oor = BOOLEAN ; fine tuning out of range flag + tuning_not_accepted = BOOLEAN ; tuning not accepted flag + invalid_channel_num = BOOLEAN ; invalid channel number flag + tuning_complete = BOOLEAN ; tuning complete flag + temphighalarm_flag = BOOLEAN ; temperature high alarm flag + temphighwarning_flag = BOOLEAN ; temperature high warning flag + templowalarm_flag = BOOLEAN ; temperature low alarm flag + templowwarning_flag = BOOLEAN ; temperature low warning flag + vcchighalarm_flag = BOOLEAN ; vcc high alarm flag + vcchighwarning_flag = BOOLEAN ; vcc high warning flag + vcclowalarm_flag = BOOLEAN ; vcc low alarm flag + vcclowwarning_flag = BOOLEAN ; vcc low warning flag + txpowerhighalarm_flag = BOOLEAN ; tx power high alarm flag + txpowerlowalarm_flag = BOOLEAN ; tx power low alarm flag + txpowerhighwarning_flag = BOOLEAN ; tx power high warning flag + txpowerlowwarning_flag = BOOLEAN ; tx power low alarm flag + rxpowerhighalarm_flag = BOOLEAN ; rx power high alarm flag + rxpowerlowalarm_flag = BOOLEAN ; rx power low alarm flag + rxpowerhighwarning_flag = BOOLEAN ; rx power high warning flag + rxpowerlowwarning_flag = BOOLEAN ; rx power low warning flag + txbiashighalarm_flag = BOOLEAN ; tx bias high alarm flag + txbiaslowalarm_flag = BOOLEAN ; tx bias low alarm flag + txbiashighwarning_flag = BOOLEAN ; tx bias high warning flag + txbiaslowwarning_flag = BOOLEAN ; tx bias low warning flag + lasertemphighalarm_flag = BOOLEAN ; laser temperature high alarm flag + lasertemplowalarm_flag = BOOLEAN ; laser temperature low alarm flag + lasertemphighwarning_flag = BOOLEAN ; laser temperature high warning flag + lasertemplowwarning_flag = BOOLEAN ; laser temperature low warning flag + prefecberhighalarm_flag = BOOLEAN ; prefec ber high alarm flag + prefecberlowalarm_flag = BOOLEAN ; prefec ber low alarm flag + prefecberhighwarning_flag = BOOLEAN ; prefec ber high warning flag + prefecberlowwarning_flag = BOOLEAN ; prefec ber low warning flag + postfecberhighalarm_flag = BOOLEAN ; postfec ber high alarm flag + postfecberlowalarm_flag = BOOLEAN ; postfec ber low alarm flag + postfecberhighwarning_flag = BOOLEAN ; postfec ber high warning flag + postfecberlowwarning_flag = BOOLEAN ; postfec ber low warning flag + biasxihighalarm_flag = BOOLEAN ; bias xi high alarm flag + biasxilowalarm_flag = BOOLEAN ; bias xi low alarm flag + biasxihighwarning_flag = BOOLEAN ; bias xi high warning flag + biasxilowwarning_flag = BOOLEAN ; bias xi low warning flag + biasxqhighalarm_flag = BOOLEAN ; bias xq high alarm flag + biasxqlowalarm_flag = BOOLEAN ; bias xq low alarm flag + biasxqhighwarning_flag = BOOLEAN ; bias xq high warning flag + biasxqlowwarning_flag = BOOLEAN ; bias xq low warning flag + biasxphighalarm_flag = BOOLEAN ; bias xp high alarm flag + biasxplowalarm_flag = BOOLEAN ; bias xp low alarm flag + biasxphighwarning_flag = BOOLEAN ; bias xp high warning flag + biasxplowwarning_flag = BOOLEAN ; bias xp low warning flag + biasyihighalarm_flag = BOOLEAN ; bias yi high alarm flag + biasyilowalarm_flag = BOOLEAN ; bias yi low alarm flag + biasyihighwarning_flag = BOOLEAN ; bias yi high warning flag + biasyilowwarning_flag = BOOLEAN ; bias yi low warning flag + biasyqhighalarm_flag = BOOLEAN ; bias yq high alarm flag + biasyqlowalarm_flag = BOOLEAN ; bias yq low alarm flag + biasyqhighwarning_flag = BOOLEAN ; bias yq high warning flag + biasyqlowwarning_flag = BOOLEAN ; bias yq low warning flag + biasyphighalarm_flag = BOOLEAN ; bias yp high alarm flag + biasyplowalarm_flag = BOOLEAN ; bias yp low alarm flag + biasyphighwarning_flag = BOOLEAN ; bias yp high warning flag + biasyplowwarning_flag = BOOLEAN ; bias yp low warning flag + cdshorthighalarm_flag = BOOLEAN ; cd short high alarm flag + cdshortlowalarm_flag = BOOLEAN ; cd short low alarm flag + cdshorthighwarning_flag = BOOLEAN ; cd short high warning flag + cdshortlowwarning_flag = BOOLEAN ; cd short low warning flag + cdlonghighalarm_flag = BOOLEAN ; cd long high alarm flag + cdlonglowalarm_flag = BOOLEAN ; cd long low alarm flag + cdlonghighwarning_flag = BOOLEAN ; cd long high warning flag + cdlonglowwarning_flag = BOOLEAN ; cd long low warning flag + dgdhighalarm_flag = BOOLEAN ; dgd high alarm flag + dgdlowalarm_flag = BOOLEAN ; dgd low alarm flag + dgdhighwarning_flag = BOOLEAN ; dgd high warning flag + dgdlowwarning_flag = BOOLEAN ; dgd low warning flag + sopmdhighalarm_flag = BOOLEAN ; sopmd high alarm flag + sopmdlowalarm_flag = BOOLEAN ; sopmd low alarm flag + sopmdhighwarning_flag = BOOLEAN ; sopmd high warning flag + sopmdlowwarning_flag = BOOLEAN ; sopmd low warning flag + pdlhighalarm_flag = BOOLEAN ; pdl high alarm flag + pdllowalarm_flag = BOOLEAN ; pdl low alarm flag + pdlhighwarning_flag = BOOLEAN ; pdl high warning flag + pdllowwarning_flag = BOOLEAN ; pdl low warning flag + osnrhighalarm_flag = BOOLEAN ; osnr high alarm flag + osnrlowalarm_flag = BOOLEAN ; osnr low alarm flag + osnrhighwarning_flag = BOOLEAN ; osnr high warning flag + osnrlowwarning_flag = BOOLEAN ; osnr low warning flag + esnrhighalarm_flag = BOOLEAN ; esnr high alarm flag + esnrlowalarm_flag = BOOLEAN ; esnr low alarm flag + esnrhighwarning_flag = BOOLEAN ; esnr high warning flag + esnrlowwarning_flag = BOOLEAN ; esnr low warning flag + cfohighalarm_flag = BOOLEAN ; cfo high alarm flag + cfolowalarm_flag = BOOLEAN ; cfo low alarm flag + cfohighwarning_flag = BOOLEAN ; cfo high warning flag + cfolowwarning_flag = BOOLEAN ; cfo low warning flag + txcurrpowerhighalarm_flag = BOOLEAN ; txcurrpower high alarm flag + txcurrpowerlowalarm_flag = BOOLEAN ; txcurrpower low alarm flag + txcurrpowerhighwarning_flag = BOOLEAN ; txcurrpower high warning flag + txcurrpowerlowwarning_flag = BOOLEAN ; txcurrpower low warning flag + rxtotpowerhighalarm_flag = BOOLEAN ; rxtotpower high alarm flag + rxtotpowerlowalarm_flag = BOOLEAN ; rxtotpower low alarm flag + rxtotpowerhighwarning_flag = BOOLEAN ; rxtotpower high warning flag + rxtotpowerlowwarning_flag = BOOLEAN ; rxtotpower low warning flag + rxsigpowerhighalarm_flag = BOOLEAN ; rxsigpower high alarm flag + rxsigpowerlowalarm_flag = BOOLEAN ; rxsigpower low alarm flag + rxsigpowerhighwarning_flag = BOOLEAN ; rxsigpower high warning flag + rxsigpowerlowwarning_flag = BOOLEAN ; rxsigpower low warning flag + ================================================================================ + """ + trans_status = dict() + trans_status['module_state'] = self.get_module_state() + trans_status['module_fault_cause'] = self.get_module_fault_cause() + dp_fw_fault, module_fw_fault, module_state_changed = self.get_module_firmware_fault_state_changed() + trans_status['datapath_firmware_fault'] = dp_fw_fault + trans_status['module_firmware_fault'] = module_fw_fault + trans_status['module_state_changed'] = module_state_changed + dp_state_dict = self.get_datapath_state() + trans_status['datapath_hostlane1'] = dp_state_dict['dp_lane1'] + trans_status['datapath_hostlane2'] = dp_state_dict['dp_lane2'] + trans_status['datapath_hostlane3'] = dp_state_dict['dp_lane3'] + trans_status['datapath_hostlane4'] = dp_state_dict['dp_lane4'] + trans_status['datapath_hostlane5'] = dp_state_dict['dp_lane5'] + trans_status['datapath_hostlane6'] = dp_state_dict['dp_lane6'] + trans_status['datapath_hostlane7'] = dp_state_dict['dp_lane7'] + trans_status['datapath_hostlane8'] = dp_state_dict['dp_lane8'] + tx_output_status_dict = self.get_tx_output_status() + trans_status['txoutput_status'] = tx_output_status_dict['TX_lane1'] + rx_output_status_dict = self.get_rx_output_status() + trans_status['rxoutput_status_hostlane1'] = rx_output_status_dict['RX_lane1'] + trans_status['rxoutput_status_hostlane2'] = rx_output_status_dict['RX_lane2'] + trans_status['rxoutput_status_hostlane3'] = rx_output_status_dict['RX_lane3'] + trans_status['rxoutput_status_hostlane4'] = rx_output_status_dict['RX_lane4'] + trans_status['rxoutput_status_hostlane5'] = rx_output_status_dict['RX_lane5'] + trans_status['rxoutput_status_hostlane6'] = rx_output_status_dict['RX_lane6'] + trans_status['rxoutput_status_hostlane7'] = rx_output_status_dict['RX_lane7'] + trans_status['rxoutput_status_hostlane8'] = rx_output_status_dict['RX_lane8'] + tx_fault_dict = self.get_tx_fault() + trans_status['txfault'] = tx_fault_dict['TX_lane1'] + tx_los_dict = self.get_tx_los() + trans_status['txlos_hostlane1'] = tx_los_dict['TX_lane1'] + trans_status['txlos_hostlane2'] = tx_los_dict['TX_lane2'] + trans_status['txlos_hostlane3'] = tx_los_dict['TX_lane3'] + trans_status['txlos_hostlane4'] = tx_los_dict['TX_lane4'] + trans_status['txlos_hostlane5'] = tx_los_dict['TX_lane5'] + trans_status['txlos_hostlane6'] = tx_los_dict['TX_lane6'] + trans_status['txlos_hostlane7'] = tx_los_dict['TX_lane7'] + trans_status['txlos_hostlane8'] = tx_los_dict['TX_lane8'] + tx_lol_dict = self.get_tx_cdr_lol() + trans_status['txcdrlol_hostlane1'] = tx_lol_dict['TX_lane1'] + trans_status['txcdrlol_hostlane2'] = tx_lol_dict['TX_lane2'] + trans_status['txcdrlol_hostlane3'] = tx_lol_dict['TX_lane3'] + trans_status['txcdrlol_hostlane4'] = tx_lol_dict['TX_lane4'] + trans_status['txcdrlol_hostlane5'] = tx_lol_dict['TX_lane5'] + trans_status['txcdrlol_hostlane6'] = tx_lol_dict['TX_lane6'] + trans_status['txcdrlol_hostlane7'] = tx_lol_dict['TX_lane7'] + trans_status['txcdrlol_hostlane8'] = tx_lol_dict['TX_lane8'] + rx_los_dict = self.get_rx_los() + trans_status['rxlos'] = rx_los_dict['RX_lane1'] + rx_lol_dict = self.get_rx_cdr_lol() + trans_status['rxcdrlol'] = rx_lol_dict['RX_lane1'] + config_status_dict = self.get_config_datapath_hostlane_status() + trans_status['config_state_hostlane1'] = config_status_dict['config_DP_status_hostlane1'] + trans_status['config_state_hostlane2'] = config_status_dict['config_DP_status_hostlane2'] + trans_status['config_state_hostlane3'] = config_status_dict['config_DP_status_hostlane3'] + trans_status['config_state_hostlane4'] = config_status_dict['config_DP_status_hostlane4'] + trans_status['config_state_hostlane5'] = config_status_dict['config_DP_status_hostlane5'] + trans_status['config_state_hostlane6'] = config_status_dict['config_DP_status_hostlane6'] + trans_status['config_state_hostlane7'] = config_status_dict['config_DP_status_hostlane7'] + trans_status['config_state_hostlane8'] = config_status_dict['config_DP_status_hostlane8'] + dpinit_pending_dict = self.get_dpinit_pending() + trans_status['dpinit_pending_hostlane1'] = dpinit_pending_dict['hostlane1'] + trans_status['dpinit_pending_hostlane2'] = dpinit_pending_dict['hostlane2'] + trans_status['dpinit_pending_hostlane3'] = dpinit_pending_dict['hostlane3'] + trans_status['dpinit_pending_hostlane4'] = dpinit_pending_dict['hostlane4'] + trans_status['dpinit_pending_hostlane5'] = dpinit_pending_dict['hostlane5'] + trans_status['dpinit_pending_hostlane6'] = dpinit_pending_dict['hostlane6'] + trans_status['dpinit_pending_hostlane7'] = dpinit_pending_dict['hostlane7'] + trans_status['dpinit_pending_hostlane8'] = dpinit_pending_dict['hostlane8'] + trans_status['tuning_in_progress'] = self.get_tuning_in_progress() + trans_status['wavelength_unlock_status'] = self.get_wavelength_unlocked() + laser_tuning_summary = self.get_laser_tuning_summary() + trans_status['target_output_power_oor'] = 'TargetOutputPowerOOR' in laser_tuning_summary + trans_status['fine_tuning_oor'] = 'FineTuningOutOfRange' in laser_tuning_summary + trans_status['tuning_not_accepted'] = 'TuningNotAccepted' in laser_tuning_summary + trans_status['invalid_channel_num'] = 'InvalidChannel' in laser_tuning_summary + trans_status['tuning_complete'] = 'TuningComplete' in laser_tuning_summary + module_flag = self.get_module_level_flag() + trans_status['temphighalarm_flag'] = module_flag['case_temp_flags']['case_temp_high_alarm_flag'] + trans_status['templowalarm_flag'] = module_flag['case_temp_flags']['case_temp_low_alarm_flag'] + trans_status['temphighwarning_flag'] = module_flag['case_temp_flags']['case_temp_high_warn_flag'] + trans_status['templowwarning_flag'] = module_flag['case_temp_flags']['case_temp_low_warn_flag'] + trans_status['vcchighalarm_flag'] = module_flag['voltage_flags']['voltage_high_alarm_flag'] + trans_status['vcclowalarm_flag'] = module_flag['voltage_flags']['voltage_low_alarm_flag'] + trans_status['vcchighwarning_flag'] = module_flag['voltage_flags']['voltage_high_warn_flag'] + trans_status['vcclowwarning_flag'] = module_flag['voltage_flags']['voltage_low_warn_flag'] + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + if aux2_mon_type == 0: + trans_status['lasertemphighalarm_flag'] = module_flag['aux2_flags']['aux2_high_alarm_flag'] + trans_status['lasertemplowalarm_flag'] = module_flag['aux2_flags']['aux2_low_alarm_flag'] + trans_status['lasertemphighwarning_flag'] = module_flag['aux2_flags']['aux2_high_warn_flag'] + trans_status['lasertemplowwarning_flag'] = module_flag['aux2_flags']['aux2_low_warn_flag'] + elif aux2_mon_type == 1 and aux3_mon_type == 0: + trans_status['lasertemphighalarm_flag'] = module_flag['aux3_flags']['aux3_high_alarm_flag'] + trans_status['lasertemplowalarm_flag'] = module_flag['aux3_flags']['aux3_low_alarm_flag'] + trans_status['lasertemphighwarning_flag'] = module_flag['aux3_flags']['aux3_high_warn_flag'] + trans_status['lasertemplowwarning_flag'] = module_flag['aux3_flags']['aux3_low_warn_flag'] + + tx_power_flag_dict = self.get_tx_power_flag() + trans_status['txpowerhighalarm_flag'] = tx_power_flag_dict['tx_power_high_alarm']['TX_lane1'] + trans_status['txpowerlowalarm_flag'] = tx_power_flag_dict['tx_power_low_alarm']['TX_lane1'] + trans_status['txpowerhighwarning_flag'] = tx_power_flag_dict['tx_power_high_warn']['TX_lane1'] + trans_status['txpowerlowwarning_flag'] = tx_power_flag_dict['tx_power_low_warn']['TX_lane1'] + rx_power_flag_dict = self.get_rx_power_flag() + trans_status['rxpowerhighalarm_flag'] = rx_power_flag_dict['rx_power_high_alarm']['RX_lane1'] + trans_status['rxpowerlowalarm_flag'] = rx_power_flag_dict['rx_power_low_alarm']['RX_lane1'] + trans_status['rxpowerhighwarning_flag'] = rx_power_flag_dict['rx_power_high_warn']['RX_lane1'] + trans_status['rxpowerlowwarning_flag'] = rx_power_flag_dict['rx_power_low_warn']['RX_lane1'] + tx_bias_flag_dict = self.get_tx_bias_flag() + trans_status['txbiashighalarm_flag'] = tx_bias_flag_dict['tx_bias_high_alarm']['TX_lane1'] + trans_status['txbiaslowalarm_flag'] = tx_bias_flag_dict['tx_bias_low_alarm']['TX_lane1'] + trans_status['txbiashighwarning_flag'] = tx_bias_flag_dict['tx_bias_high_warn']['TX_lane1'] + trans_status['txbiaslowwarning_flag'] = tx_bias_flag_dict['tx_bias_low_warn']['TX_lane1'] + vdm_dict = self.get_vdm() + trans_status['prefecberhighalarm_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][5] + trans_status['prefecberlowalarm_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][6] + trans_status['prefecberhighwarning_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][7] + trans_status['prefecberlowwarning_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][8] + trans_status['postfecberhighalarm_flag'] = vdm_dict['Errored Frames Average Media Input'][1][5] + trans_status['postfecberlowalarm_flag'] = vdm_dict['Errored Frames Average Media Input'][1][6] + trans_status['postfecberhighwarning_flag'] = vdm_dict['Errored Frames Average Media Input'][1][7] + trans_status['postfecberlowwarning_flag'] = vdm_dict['Errored Frames Average Media Input'][1][8] + trans_status['biasxihighalarm_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][5] + trans_status['biasxilowalarm_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][6] + trans_status['biasxihighwarning_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][7] + trans_status['biasxilowwarning_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][8] + trans_status['biasxqhighalarm_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][5] + trans_status['biasxqlowalarm_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][6] + trans_status['biasxqhighwarning_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][7] + trans_status['biasxqlowwarning_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][8] + trans_status['biasxphighalarm_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][5] + trans_status['biasxplowalarm_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][6] + trans_status['biasxphighwarning_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][7] + trans_status['biasxplowwarning_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][8] + trans_status['biasyihighalarm_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][5] + trans_status['biasyilowalarm_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][6] + trans_status['biasyihighwarning_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][7] + trans_status['biasyilowwarning_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][8] + trans_status['biasyqhighalarm_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][5] + trans_status['biasyqlowalarm_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][6] + trans_status['biasyqhighwarning_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][7] + trans_status['biasyqlowwarning_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][8] + trans_status['biasyphighalarm_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][5] + trans_status['biasyplowalarm_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][6] + trans_status['biasyphighwarning_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][7] + trans_status['biasyplowwarning_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][8] + trans_status['cdshorthighalarm_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][5] + trans_status['cdshortlowalarm_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][6] + trans_status['cdshorthighwarning_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][7] + trans_status['cdshortlowwarning_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][8] + trans_status['cdlonghighalarm_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][5] + trans_status['cdlonglowalarm_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][6] + trans_status['cdlonghighwarning_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][7] + trans_status['cdlonglowwarning_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][8] + trans_status['dgdhighalarm_flag'] = vdm_dict['DGD [ps]'][1][5] + trans_status['dgdlowalarm_flag'] = vdm_dict['DGD [ps]'][1][6] + trans_status['dgdhighwarning_flag'] = vdm_dict['DGD [ps]'][1][7] + trans_status['dgdlowwarning_flag'] = vdm_dict['DGD [ps]'][1][8] + trans_status['sopmdhighalarm_flag'] = vdm_dict['SOPMD [ps^2]'][1][5] + trans_status['sopmdlowalarm_flag'] = vdm_dict['SOPMD [ps^2]'][1][6] + trans_status['sopmdhighwarning_flag'] = vdm_dict['SOPMD [ps^2]'][1][7] + trans_status['sopmdlowwarning_flag'] = vdm_dict['SOPMD [ps^2]'][1][8] + trans_status['pdlhighalarm_flag'] = vdm_dict['PDL [dB]'][1][5] + trans_status['pdllowalarm_flag'] = vdm_dict['PDL [dB]'][1][6] + trans_status['pdlhighwarning_flag'] = vdm_dict['PDL [dB]'][1][7] + trans_status['pdllowwarning_flag'] = vdm_dict['PDL [dB]'][1][8] + trans_status['osnrhighalarm_flag'] = vdm_dict['OSNR [dB]'][1][5] + trans_status['osnrlowalarm_flag'] = vdm_dict['OSNR [dB]'][1][6] + trans_status['osnrhighwarning_flag'] = vdm_dict['OSNR [dB]'][1][7] + trans_status['osnrlowwarning_flag'] = vdm_dict['OSNR [dB]'][1][8] + trans_status['esnrhighalarm_flag'] = vdm_dict['eSNR [dB]'][1][5] + trans_status['esnrlowalarm_flag'] = vdm_dict['eSNR [dB]'][1][6] + trans_status['esnrhighwarning_flag'] = vdm_dict['eSNR [dB]'][1][7] + trans_status['esnrlowwarning_flag'] = vdm_dict['eSNR [dB]'][1][8] + trans_status['cfohighalarm_flag'] = vdm_dict['CFO [MHz]'][1][5] + trans_status['cfolowalarm_flag'] = vdm_dict['CFO [MHz]'][1][6] + trans_status['cfohighwarning_flag'] = vdm_dict['CFO [MHz]'][1][7] + trans_status['cfolowwarning_flag'] = vdm_dict['CFO [MHz]'][1][8] + trans_status['txcurrpowerhighalarm_flag'] = vdm_dict['Tx Power [dBm]'][1][5] + trans_status['txcurrpowerlowalarm_flag'] = vdm_dict['Tx Power [dBm]'][1][6] + trans_status['txcurrpowerhighwarning_flag'] = vdm_dict['Tx Power [dBm]'][1][7] + trans_status['txcurrpowerlowwarning_flag'] = vdm_dict['Tx Power [dBm]'][1][8] + trans_status['rxtotpowerhighalarm_flag'] = vdm_dict['Rx Total Power [dBm]'][1][5] + trans_status['rxtotpowerlowalarm_flag'] = vdm_dict['Rx Total Power [dBm]'][1][6] + trans_status['rxtotpowerhighwarning_flag'] = vdm_dict['Rx Total Power [dBm]'][1][7] + trans_status['rxtotpowerlowwarning_flag'] = vdm_dict['Rx Total Power [dBm]'][1][8] + trans_status['rxsigpowerhighalarm_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][5] + trans_status['rxsigpowerlowalarm_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][6] + trans_status['rxsigpowerhighwarning_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][7] + trans_status['rxsigpowerlowwarning_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][8] + return trans_status + + def get_transceiver_pm(self): + """ + Retrieves PM for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_PM|ifname ; information of PM on port + ; field = value + prefec_ber_avg = FLOAT ; prefec ber avg + prefec_ber_min = FLOAT ; prefec ber min + prefec_ber_max = FLOAT ; prefec ber max + uncorr_frames_avg = FLOAT ; uncorrected frames ratio avg + uncorr_frames_min = FLOAT ; uncorrected frames ratio min + uncorr_frames_max = FLOAT ; uncorrected frames ratio max + cd_avg = FLOAT ; chromatic dispersion avg + cd_min = FLOAT ; chromatic dispersion min + cd_max = FLOAT ; chromatic dispersion max + dgd_avg = FLOAT ; differential group delay avg + dgd_min = FLOAT ; differential group delay min + dgd_max = FLOAT ; differential group delay max + sopmd_avg = FLOAT ; second order polarization mode dispersion avg + sopmd_min = FLOAT ; second order polarization mode dispersion min + sopmd_max = FLOAT ; second order polarization mode dispersion max + pdl_avg = FLOAT ; polarization dependent loss avg + pdl_min = FLOAT ; polarization dependent loss min + pdl_max = FLOAT ; polarization dependent loss max + osnr_avg = FLOAT ; optical signal to noise ratio avg + osnr_min = FLOAT ; optical signal to noise ratio min + osnr_max = FLOAT ; optical signal to noise ratio max + esnr_avg = FLOAT ; electrical signal to noise ratio avg + esnr_min = FLOAT ; electrical signal to noise ratio min + esnr_max = FLOAT ; electrical signal to noise ratio max + cfo_avg = FLOAT ; carrier frequency offset avg + cfo_min = FLOAT ; carrier frequency offset min + cfo_max = FLOAT ; carrier frequency offset max + soproc_avg = FLOAT ; state of polarization rate of change avg + soproc_min = FLOAT ; state of polarization rate of change min + soproc_max = FLOAT ; state of polarization rate of change max + tx_power_avg = FLOAT ; tx output power avg + tx_power_min = FLOAT ; tx output power min + tx_power_max = FLOAT ; tx output power max + rx_tot_power_avg = FLOAT ; rx total power avg + rx_tot_power_min = FLOAT ; rx total power min + rx_tot_power_max = FLOAT ; rx total power max + rx_sig_power_avg = FLOAT ; rx signal power avg + rx_sig_power_min = FLOAT ; rx signal power min + rx_sig_power_max = FLOAT ; rx signal power max + ======================================================================== + """ + trans_pm = dict() + PM_dict = self.get_pm_all() + trans_pm['prefec_ber_avg'] = PM_dict['preFEC_BER_avg'] + trans_pm['prefec_ber_min'] = PM_dict['preFEC_BER_min'] + trans_pm['prefec_ber_max'] = PM_dict['preFEC_BER_max'] + trans_pm['uncorr_frames_avg'] = PM_dict['preFEC_uncorr_frame_ratio_avg'] + trans_pm['uncorr_frames_min'] = PM_dict['preFEC_uncorr_frame_ratio_min'] + trans_pm['uncorr_frames_max'] = PM_dict['preFEC_uncorr_frame_ratio_max'] + trans_pm['cd_avg'] = PM_dict['rx_cd_avg'] + trans_pm['cd_min'] = PM_dict['rx_cd_min'] + trans_pm['cd_max'] = PM_dict['rx_cd_max'] + trans_pm['dgd_avg'] = PM_dict['rx_dgd_avg'] + trans_pm['dgd_min'] = PM_dict['rx_dgd_min'] + trans_pm['dgd_max'] = PM_dict['rx_dgd_max'] + trans_pm['sopmd_avg'] = PM_dict['rx_sopmd_avg'] + trans_pm['sopmd_min'] = PM_dict['rx_sopmd_min'] + trans_pm['sopmd_max'] = PM_dict['rx_sopmd_max'] + trans_pm['pdl_avg'] = PM_dict['rx_pdl_avg'] + trans_pm['pdl_min'] = PM_dict['rx_pdl_min'] + trans_pm['pdl_max'] = PM_dict['rx_pdl_max'] + trans_pm['osnr_avg'] = PM_dict['rx_osnr_avg'] + trans_pm['osnr_min'] = PM_dict['rx_osnr_min'] + trans_pm['osnr_max'] = PM_dict['rx_osnr_max'] + trans_pm['esnr_avg'] = PM_dict['rx_esnr_avg'] + trans_pm['esnr_min'] = PM_dict['rx_esnr_min'] + trans_pm['esnr_max'] = PM_dict['rx_esnr_max'] + trans_pm['cfo_avg'] = PM_dict['rx_cfo_avg'] + trans_pm['cfo_min'] = PM_dict['rx_cfo_min'] + trans_pm['cfo_max'] = PM_dict['rx_cfo_max'] + trans_pm['soproc_avg'] = PM_dict['rx_soproc_avg'] + trans_pm['soproc_min'] = PM_dict['rx_soproc_min'] + trans_pm['soproc_max'] = PM_dict['rx_soproc_max'] + trans_pm['tx_power_avg'] = PM_dict['tx_power_avg'] + trans_pm['tx_power_min'] = PM_dict['tx_power_min'] + trans_pm['tx_power_max'] = PM_dict['tx_power_max'] + trans_pm['rx_tot_power_avg'] = PM_dict['rx_power_avg'] + trans_pm['rx_tot_power_min'] = PM_dict['rx_power_min'] + trans_pm['rx_tot_power_max'] = PM_dict['rx_power_max'] + trans_pm['rx_sig_power_avg'] = PM_dict['rx_sigpwr_avg'] + trans_pm['rx_sig_power_min'] = PM_dict['rx_sigpwr_min'] + trans_pm['rx_sig_power_max'] = PM_dict['rx_sigpwr_max'] + return trans_pm + + def get_transceiver_loopback(self): + """ + Retrieves loopback mode for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_PM|ifname ; information of loopback on port + ; field = value + media_output_loopback = BOOLEAN ; media side output loopback enable + media_input_loopback = BOOLEAN ; media side input loopback enable + host_output_loopback_lane1 = BOOLEAN ; host side output loopback enable lane1 + host_output_loopback_lane2 = BOOLEAN ; host side output loopback enable lane2 + host_output_loopback_lane3 = BOOLEAN ; host side output loopback enable lane3 + host_output_loopback_lane4 = BOOLEAN ; host side output loopback enable lane4 + host_output_loopback_lane5 = BOOLEAN ; host side output loopback enable lane5 + host_output_loopback_lane6 = BOOLEAN ; host side output loopback enable lane6 + host_output_loopback_lane7 = BOOLEAN ; host side output loopback enable lane7 + host_output_loopback_lane8 = BOOLEAN ; host side output loopback enable lane8 + host_input_loopback_lane1 = BOOLEAN ; host side input loopback enable lane1 + host_input_loopback_lane2 = BOOLEAN ; host side input loopback enable lane2 + host_input_loopback_lane3 = BOOLEAN ; host side input loopback enable lane3 + host_input_loopback_lane4 = BOOLEAN ; host side input loopback enable lane4 + host_input_loopback_lane5 = BOOLEAN ; host side input loopback enable lane5 + host_input_loopback_lane6 = BOOLEAN ; host side input loopback enable lane6 + host_input_loopback_lane7 = BOOLEAN ; host side input loopback enable lane7 + host_input_loopback_lane8 = BOOLEAN ; host side input loopback enable lane8 + ======================================================================== + """ + trans_loopback = dict() + trans_loopback['media_output_loopback'] = self.get_media_output_loopback() + trans_loopback['media_input_loopback'] = self.get_media_input_loopback() + host_output_loopback_status = self.get_host_output_loopback() + trans_loopback['host_output_loopback_lane1'] = host_output_loopback_status[0] + trans_loopback['host_output_loopback_lane2'] = host_output_loopback_status[1] + trans_loopback['host_output_loopback_lane3'] = host_output_loopback_status[2] + trans_loopback['host_output_loopback_lane4'] = host_output_loopback_status[3] + trans_loopback['host_output_loopback_lane5'] = host_output_loopback_status[4] + trans_loopback['host_output_loopback_lane6'] = host_output_loopback_status[5] + trans_loopback['host_output_loopback_lane7'] = host_output_loopback_status[6] + trans_loopback['host_output_loopback_lane8'] = host_output_loopback_status[7] + host_input_loopback_status = self.get_host_input_loopback() + trans_loopback['host_input_loopback_lane1'] = host_input_loopback_status[0] + trans_loopback['host_input_loopback_lane2'] = host_input_loopback_status[1] + trans_loopback['host_input_loopback_lane3'] = host_input_loopback_status[2] + trans_loopback['host_input_loopback_lane4'] = host_input_loopback_status[3] + trans_loopback['host_input_loopback_lane5'] = host_input_loopback_status[4] + trans_loopback['host_input_loopback_lane6'] = host_input_loopback_status[5] + trans_loopback['host_input_loopback_lane7'] = host_input_loopback_status[6] + trans_loopback['host_input_loopback_lane8'] = host_input_loopback_status[7] + return trans_loopback diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index 124126cac..2b441d296 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -3,13 +3,16 @@ Implementation of XcvrApi that corresponds to CMIS """ - +import logging from ...fields import consts from ..xcvr_api import XcvrApi from .cmisCDB import CmisCdbApi from .cmisVDM import CmisVdmApi -from .c_cmis import CCmisApi import time + +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) + BYTELENGTH = 8 class CmisApi(XcvrApi): NUM_CHANNELS = 8 @@ -270,47 +273,7 @@ def get_txbias(self): 'low warn': tx_bias_current_low_warn} return tx_bias_current_dict - def get_freq_grid(self): - ''' - This function returns the configured frequency grid. Unit in GHz - ''' - freq_grid = self.xcvr_eeprom.read(consts.GRID_SPACING) >> 4 - if freq_grid == 7: - return 75 - elif freq_grid == 6: - return 33 - elif freq_grid == 5: - return 100 - elif freq_grid == 4: - return 50 - elif freq_grid == 3: - return 25 - elif freq_grid == 2: - return 12.5 - elif freq_grid == 1: - return 6.25 - elif freq_grid == 0: - return 3.125 - - def get_laser_config_freq(self): - ''' - This function returns the configured laser frequency. Unit in GHz - ''' - freq_grid = self.get_freq_grid() - channel = self.xcvr_eeprom.read(consts.LASER_CONFIG_CHANNEL) - if freq_grid == 75: - config_freq = 193100 + channel * freq_grid/3 - else: - config_freq = 193100 + channel * freq_grid - return config_freq - - def get_current_laser_freq(self): - ''' - This function returns the monitored laser frequency. Unit in GHz - ''' - return self.xcvr_eeprom.read(consts.LASER_CURRENT_FREQ)/1000 - - def get_TX_config_power(self): + def get_tx_config_power(self): ''' This function returns the configured TX output power. Unit in dBm ''' @@ -425,35 +388,20 @@ def get_custom_field(self, signed = False, scale = 1.0): return result - def get_VDM_api(self): + def get_vdm_api(self): self.vdm = CmisVdmApi(self.xcvr_eeprom) + return self.vdm - def get_VDM(self): + def get_vdm(self): ''' This function returns all the VDM items, including real time monitor value, threholds and flags ''' try: self.vdm except AttributeError: - self.get_VDM_api() - VDM = self.vdm.get_VDM_allpage() - return VDM - - def get_ccmis_api(self): - self.ccmis = CCmisApi(self.xcvr_eeprom) - - def get_PM(self): - - ''' - This function returns all the PMs. For more detailed info check get_PM_all in CCmisApi - ''' - try: - self.ccmis - except AttributeError: - self.get_ccmis_api() - PM_dict = self.ccmis.get_PM_all() - return PM_dict - + self.get_vdm_api() + vdm = self.vdm.get_vdm_allpage() + return vdm # Transceiver status def get_module_state(self): @@ -461,7 +409,7 @@ def get_module_state(self): This function returns the module state ''' result = self.xcvr_eeprom.read(consts.MODULE_STATE) >> 1 - DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].MODULE_STATE + DICT = self.xcvr_eeprom.mem_map.codes.MODULE_STATE return DICT.get(result, "Unknown") def get_module_fault_cause(self): @@ -570,7 +518,7 @@ def get_datapath_state(self): dp_lane4 = (result >> 20) & 0xf dp_lane1 = (result >> 24) & 0xf dp_lane2 = (result >> 28) & 0xf - DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].DATAPATH_STATE + DICT = self.xcvr_eeprom.mem_map.codes.DATAPATH_STATE dp_state_dict = {'dp_lane1': DICT.get(dp_lane1, "Unknown"), 'dp_lane2': DICT.get(dp_lane2, "Unknown"), 'dp_lane3': DICT.get(dp_lane3, "Unknown"), @@ -738,7 +686,7 @@ def get_config_datapath_hostlane_status(self): config_status_lane4 = (result >> 20) & 0xf config_status_lane1 = (result >> 24) & 0xf config_status_lane2 = (result >> 28) & 0xf - DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].CONFIG_STATUS + DICT = self.xcvr_eeprom.mem_map.codes.CONFIG_STATUS config_status_dict = {'config_DP_status_hostlane1': DICT.get(config_status_lane1, "Unknown"), 'config_DP_status_hostlane2': DICT.get(config_status_lane2, "Unknown"), 'config_DP_status_hostlane3': DICT.get(config_status_lane3, "Unknown"), @@ -763,56 +711,6 @@ def get_dpinit_pending(self): dpinit_pending_dict['hostlane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) return dpinit_pending_dict - def get_tuning_in_progress(self): - ''' - This function returns tunning in progress status on media lane - 0 means tuning not in progress - 1 means tuning in progress - ''' - return bool(self.xcvr_eeprom.read(consts.TUNING_IN_PROGRESS)) - - def get_wavelength_unlocked(self): - ''' - This function returns wavelength unlocked status on media lane - 0 means wavelength locked - 1 means wavelength unlocked - ''' - return bool(self.xcvr_eeprom.read(consts.WAVELENGTH_UNLOCKED)) - - def get_laser_tuning_summary(self): - ''' - This function returns laser tuning status summary on media lane - ''' - result = self.xcvr_eeprom.read(consts.LASER_TUNING_DETAIL) - laser_tuning_summary = [] - if (result >> 5) & 0x1: - laser_tuning_summary.append("TargetOutputPowerOOR") - if (result >> 4) & 0x1: - laser_tuning_summary.append("FineTuningOutOfRange") - if (result >> 3) & 0x1: - laser_tuning_summary.append("TuningNotAccepted") - if (result >> 2) & 0x1: - laser_tuning_summary.append("InvalidChannel") - if (result >> 1) & 0x1: - laser_tuning_summary.append("WavelengthUnlocked") - if (result >> 0) & 0x1: - laser_tuning_summary.append("TuningComplete") - return laser_tuning_summary - - def get_supported_freq_config(self): - ''' - This function returns the supported freq grid, low and high supported channel in 75GHz grid, - and low and high frequency supported in GHz. - allowed channel number bound in 75 GHz grid - allowed frequency bound in 75 GHz grid - ''' - grid_supported = self.xcvr_eeprom.read(consts.SUPPORT_GRID) - low_ch_num = self.xcvr_eeprom.read(consts.LOW_CHANNEL) - hi_ch_num = self.xcvr_eeprom.read(consts.HIGH_CHANNEL) - low_freq_supported = 193100 + low_ch_num * 25 - high_freq_supported = 193100 + hi_ch_num * 25 - return grid_supported, low_ch_num, hi_ch_num, low_freq_supported, high_freq_supported - def get_supported_power_config(self): ''' This function returns the supported TX power range @@ -837,38 +735,16 @@ def set_low_power(self, AssertLowPower): ''' low_power_control = AssertLowPower << 6 self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control) - - def set_laser_freq(self, freq): - ''' - This function sets the laser frequency. Unit in GHz - ZR application will not support fine tuning of the laser - Microsoft will only supports 75 GHz frequency grid - ''' - grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() - grid_supported_75GHz = (grid_supported >> 7) & 0x1 - assert grid_supported_75GHz - freq_grid = 0x70 - self.xcvr_eeprom.write(consts.GRID_SPACING, freq_grid) - channel_number = int(round((freq - 193100)/25)) - assert channel_number % 3 == 0 - if channel_number > hi_ch_num or channel_number < low_ch_num: - raise ValueError('Provisioned frequency out of range. Max Freq: 196100; Min Freq: 191300 GHz.') - self.set_low_power(True) - time.sleep(5) - self.xcvr_eeprom.write(consts.LASER_CONFIG_CHANNEL, channel_number) - time.sleep(1) - self.set_low_power(False) - time.sleep(1) - def set_TX_power(self, TX_power): + def set_tx_power(self, tx_power): ''' This function sets the TX output power. Unit in dBm ''' min_prog_tx_output_power, max_prog_tx_output_power = self.get_supported_power_config() - if TX_power > max_prog_tx_output_power or TX_power < min_prog_tx_output_power: + if tx_power > max_prog_tx_output_power or tx_power < min_prog_tx_output_power: raise ValueError('Provisioned TX power out of range. Max: %.1f; Min: %.1f dBm.' %(max_prog_tx_output_power, min_prog_tx_output_power)) - self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, TX_power) + self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, tx_power) time.sleep(1) def get_loopback_capability(self): @@ -917,10 +793,11 @@ def set_loopback_mode(self, loopback_mode): self.xcvr_eeprom.write(consts.MEDIA_OUTPUT_LOOPBACK, 0xff) - def get_CDB_api(self): + def get_cdb_api(self): self.cdb = CmisCdbApi(self.xcvr_eeprom) + return self.cdb - def get_module_FW_upgrade_feature(self, verbose = False): + def get_module_fw_upgrade_feature(self, verbose = False): """ This function obtains CDB features supported by the module from CDB command 0041h, such as start header size, maximum block size, whether extended payload messaging @@ -930,43 +807,51 @@ def get_module_FW_upgrade_feature(self, verbose = False): try: self.cdb except AttributeError: - self.get_CDB_api() + self.get_cdb_api() # get fw upgrade features (CMD 0041h) starttime = time.time() autopaging_flag = bool((self.xcvr_eeprom.read(consts.CDB_SUPPORT) >> 4) & 0x1) writelength = (self.xcvr_eeprom.read(consts.CDB_SEQ_WRITE_LENGTH_EXT) + 1) * 8 - print('Auto page support: %s' %autopaging_flag) - print('Max write length: %d' %writelength) + logger.info('Auto page support: %s' %autopaging_flag) + logger.info('Max write length: %d' %writelength) rpllen, rpl_chkcode, rpl = self.cdb.cmd0041h() if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: + password_type = { + 0x00 : 'vendorPassword', + 0x01 : 'vendorPasswordSeq', + 0x80 : 'msaPassword' + } + self.cdb.password_type = password_type[rpl[0]] + logger.info('Download password type: %s' %self.cdb.password_type) + startLPLsize = rpl[2] - print('Start payload size %d' % startLPLsize) + logger.info('Start payload size %d' % startLPLsize) maxblocksize = (rpl[4] + 1) * 8 - print('Max block size %d' % maxblocksize) + logger.info('Max block size %d' % maxblocksize) lplEplSupport = {0x00 : 'No write to LPL/EPL supported', 0x01 : 'Write to LPL supported', 0x10 : 'Write to EPL supported', 0x11 : 'Write to LPL/EPL supported'} - print('{}'.format(lplEplSupport[rpl[5]])) + logger.info('{}'.format(lplEplSupport[rpl[5]])) if rpl[5] == 1: lplonly_flag = True else: lplonly_flag = False - print('Abort CMD102h supported %s' %bool(rpl[1] & 0x01)) + logger.info('Abort CMD102h supported %s' %bool(rpl[1] & 0x01)) if verbose: - print('Copy CMD108h supported %s' %bool((rpl[1] >> 1) & 0x01)) - print('Skipping erased blocks supported %s' %bool((rpl[1] >> 2) & 0x01)) - print('Full image readback supported %s' %bool((rpl[1] >> 7) & 0x01)) - print('Default erase byte {:#x}'.format(rpl[3])) - print('Read to LPL/EPL {:#x}'.format(rpl[6])) + logger.info('Copy CMD108h supported %s' %bool((rpl[1] >> 1) & 0x01)) + logger.info('Skipping erased blocks supported %s' %bool((rpl[1] >> 2) & 0x01)) + logger.info('Full image readback supported %s' %bool((rpl[1] >> 7) & 0x01)) + logger.info('Default erase byte {:#x}'.format(rpl[3])) + logger.info('Read to LPL/EPL {:#x}'.format(rpl[6])) else: raise ValueError('Reply payload check code error') elapsedtime = time.time()-starttime - print('Get module FW upgrade features time: %.2f s' %elapsedtime) + logger.info('Get module FW upgrade features time: %.2f s' %elapsedtime) return startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength - def get_module_FW_info(self): + def get_module_fw_info(self): """ This function returns firmware Image A and B version, running version, committed version and whether both firmware images are valid. @@ -977,20 +862,20 @@ def get_module_FW_info(self): try: self.cdb except AttributeError: - self.get_CDB_api() + self.get_cdb_api() # get fw info (CMD 0100h) starttime = time.time() - print('\nGet module FW info') + logger.info('\nGet module FW info') rpllen, rpl_chkcode, rpl = self.cdb.cmd0100h() if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: # Regiter 9Fh:136 fwStatus = rpl[0] # Registers 9Fh:138,139; 140,141 ImageA = '%d.%d.%d' %(rpl[2], rpl[3], ((rpl[4]<< 8) | rpl[5])) - print('Image A Version: %s' %ImageA) + logger.info('Image A Version: %s' %ImageA) # Registers 9Fh:174,175; 176.177 ImageB = '%d.%d.%d' %(rpl[38], rpl[39], ((rpl[40]<< 8) | rpl[41])) - print('Image B Version: %s' %ImageB) + logger.info('Image B Version: %s' %ImageB) ImageARunning = (fwStatus & 0x01) # bit 0 - image A is running ImageACommitted = ((fwStatus >> 1) & 0x01) # bit 1 - image A is committed @@ -1007,14 +892,14 @@ def get_module_FW_info(self): CommittedImage = 'A' elif ImageBCommitted == 1: CommittedImage = 'B' - print('Running Image: %s; Committed Image: %s' %(RunningImage, CommittedImage)) + logger.info('Running Image: %s; Committed Image: %s' %(RunningImage, CommittedImage)) else: raise ValueError('Reply payload check code error') elapsedtime = time.time()-starttime - print('Get module FW info time: %.2f s' %elapsedtime) + logger.info('Get module FW info time: %.2f s' %elapsedtime) return ImageA, ImageARunning, ImageACommitted, ImageAValid, ImageB, ImageBRunning, ImageBCommitted, ImageBValid - def module_FW_run(self, mode = 0x01): + def module_fw_run(self, mode = 0x01): """ This command is used to start and run a selected image. This command transfers control from the currently @@ -1030,19 +915,19 @@ def module_FW_run(self, mode = 0x01): try: self.cdb except AttributeError: - self.get_CDB_api() + self.get_cdb_api() # run module FW (CMD 0109h) starttime = time.time() - FW_run_status = self.cdb.cmd0109h(mode) - if FW_run_status == 1: - print('Module FW run: Success') + fw_run_status = self.cdb.cmd0109h(mode) + if fw_run_status == 1: + logger.info('Module FW run: Success') else: self.cdb.cmd0102h() - print('Module FW run: Fail') + logger.info('Module FW run: Fail') elapsedtime = time.time()-starttime - print('Module FW run time: %.2f s\n' %elapsedtime) + logger.info('Module FW run time: %.2f s\n' %elapsedtime) - def module_FW_commit(self): + def module_fw_commit(self): """ The host uses this command to commit the running image so that the module will boot from it on future boots. @@ -1050,19 +935,19 @@ def module_FW_commit(self): try: self.cdb except AttributeError: - self.get_CDB_api() + self.get_cdb_api() # commit module FW (CMD 010Ah) starttime = time.time() - FW_commit_status= self.cdb.cmd010Ah() - if FW_commit_status == 1: - print('Module FW commit: Success') + fw_commit_status= self.cdb.cmd010Ah() + if fw_commit_status == 1: + logger.info('Module FW commit: Success') else: self.cdb.cmd0102h() - print('Module FW commit: Fail') + logger.info('Module FW commit: Fail') elapsedtime = time.time()-starttime - print('Module FW commit time: %.2f s\n' %elapsedtime) + logger.info('Module FW commit time: %.2f s\n' %elapsedtime) - def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath): + def module_fw_download(self, startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath): """ This function performs the download of a firmware image to module eeprom It starts CDB download by writing the header of start header size @@ -1081,7 +966,7 @@ def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin try: self.cdb except AttributeError: - self.get_CDB_api() + self.get_cdb_api() # start fw download (CMD 0101h) starttime = time.time() f = open(imagepath, 'rb') @@ -1089,17 +974,19 @@ def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin imagesize = f.tell() f.seek(0, 0) startdata = f.read(startLPLsize) - print('\nStart FW downloading') - print("startLPLsize is %d" %startLPLsize) - FW_start_status = self.cdb.cmd0101h(startLPLsize, bytearray(startdata), imagesize) - if FW_start_status == 1: - print('Start module FW download: Success') + if self.cdb.password_type == 'msaPassword': + self.xcvr_eeprom.write_raw(122, 4, b'\x00\x00\x10\x11') + logger.info('\nStart FW downloading') + logger.info("startLPLsize is %d" %startLPLsize) + fw_start_status = self.cdb.cmd0101h(startLPLsize, bytearray(startdata), imagesize) + if fw_start_status == 1: + logger.info('Start module FW download: Success') else: - print('Start module FW download: Fail') + logger.info('Start module FW download: Fail') self.cdb.cmd0102h() - raise ValueError('FW_start_status %d' %FW_start_status) + raise ValueError('FW_start_status %d' %fw_start_status) elapsedtime = time.time()-starttime - print('Start module FW download time: %.2f s' %elapsedtime) + logger.info('Start module FW download time: %.2f s' %elapsedtime) # start periodically writing (CMD 0103h or 0104h) assert maxblocksize == 2048 or lplonly_flag @@ -1109,7 +996,7 @@ def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin BLOCK_SIZE = maxblocksize address = 0 remaining = imagesize - startLPLsize - print("\nTotal size: {} start bytes: {} remaining: {}".format(imagesize, startLPLsize, remaining)) + logger.info("\nTotal size: {} start bytes: {} remaining: {}".format(imagesize, startLPLsize, remaining)) while remaining > 0: if remaining < BLOCK_SIZE: count = remaining @@ -1118,30 +1005,30 @@ def module_FW_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin data = f.read(count) progress = (imagesize - remaining) * 100.0 / imagesize if lplonly_flag: - FW_download_status = self.cdb.cmd0103h(address, data) + fw_download_status = self.cdb.cmd0103h(address, data) else: - FW_download_status = self.cdb.cmd0104h(address, data, autopaging_flag, writelength) - if FW_download_status != 1: - print('CDB download failed. CDB Status: %d' %FW_download_status) + fw_download_status = self.cdb.cmd0104h(address, data, autopaging_flag, writelength) + if fw_download_status != 1: + logger.info('CDB download failed. CDB Status: %d' %fw_download_status) exit(1) elapsedtime = time.time()-starttime - print('Address: {:#08x}; Count: {}; Progress: {:.2f}%; Time: {:.2f}s'.format(address, count, progress, elapsedtime)) + logger.info('Address: {:#08x}; Count: {}; Progress: {:.2f}%; Time: {:.2f}s'.format(address, count, progress, elapsedtime)) address += count remaining -= count elapsedtime = time.time()-starttime - print('Total module FW download time: %.2f s' %elapsedtime) + logger.info('Total module FW download time: %.2f s' %elapsedtime) time.sleep(2) # complete FW download (CMD 0107h) - FW_complete_status = self.cdb.cmd0107h() - if FW_complete_status == 1: - print('Module FW download complete: Success') + fw_complete_status = self.cdb.cmd0107h() + if fw_complete_status == 1: + logger.info('Module FW download complete: Success') else: - print('Module FW download complete: Fail') + logger.info('Module FW download complete: Fail') elapsedtime = time.time()-elapsedtime-starttime - print('Complete module FW download time: %.2f s\n' %elapsedtime) + logger.info('Complete module FW download time: %.2f s\n' %elapsedtime) - def module_firmware_upgrade(self, imagepath): + def module_fw_upgrade(self, imagepath): """ This function performs firmware upgrade. 1. show FW version in the beginning @@ -1152,930 +1039,26 @@ def module_firmware_upgrade(self, imagepath): 6. configure commit downloaded firmware 7. show FW version in the end """ - self.get_module_FW_info() - startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength = self.get_module_FW_upgrade_feature() - self.module_FW_download(startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath) - self.module_FW_run(mode = 0x01) + self.get_module_fw_info() + startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength = self.get_module_fw_upgrade_feature() + self.module_fw_download(startLPLsize, maxblocksize, lplonly_flag, autopaging_flag, writelength, imagepath) + self.module_fw_run(mode = 0x01) time.sleep(60) - self.module_FW_commit() - self.get_module_FW_info() + self.module_fw_commit() + self.get_module_fw_info() - def module_firmware_switch(self): + def module_fw_switch(self): """ - This function switch the active/inactive module firmwarein the current module memory + This function switch the active/inactive module firmware in the current module memory """ - _, _, _, ImageAValid, _, _, _, ImageBValid = self.get_module_FW_info() + _, _, _, ImageAValid, _, _, _, ImageBValid = self.get_module_fw_info() if ImageAValid == 0 and ImageBValid == 0: - self.module_FW_run(mode = 0x01) + self.module_fw_run(mode = 0x01) time.sleep(60) - self.module_FW_commit() - self.get_module_FW_info() + self.module_fw_commit() + self.get_module_fw_info() else: - print('Not both images are valid.') - - - def get_transceiver_info(self): - """ - Retrieves transceiver info of this SFP - - Returns: - A dict which contains following keys/values : - ================================================================================ - key = TRANSCEIVER_INFO|ifname ; information for module on port - ; field = value - module_media_type = 1*255VCHAR ; module media interface ID - host_electrical_interface = 1*255VCHAR ; host electrical interface ID - media_interface_code = 1*255VCHAR ; media interface code - host_lane_count = INTEGER ; host lane count - media_lane_count = INTEGER ; media lane count - host_lane_assignment_option = INTEGER ; permissible first host lane number for application - media_lane_assignment_option = INTEGER ; permissible first media lane number for application - active_apsel_hostlane1 = INTEGER ; active application selected code assigned to host lane 1 - active_apsel_hostlane2 = INTEGER ; active application selected code assigned to host lane 2 - active_apsel_hostlane3 = INTEGER ; active application selected code assigned to host lane 3 - active_apsel_hostlane4 = INTEGER ; active application selected code assigned to host lane 4 - active_apsel_hostlane5 = INTEGER ; active application selected code assigned to host lane 5 - active_apsel_hostlane6 = INTEGER ; active application selected code assigned to host lane 6 - active_apsel_hostlane7 = INTEGER ; active application selected code assigned to host lane 7 - active_apsel_hostlane8 = INTEGER ; active application selected code assigned to host lane 8 - media_interface_technology = 1*255VCHAR ; media interface technology - hardwarerev = 1*255VCHAR ; module hardware revision - serialnum = 1*255VCHAR ; module serial number - manufacturename = 1*255VCHAR ; module venndor name - modelname = 1*255VCHAR ; module model name - vendor_rev = 1*255VCHAR ; module vendor revision - vendor_oui = 1*255VCHAR ; vendor organizationally unique identifier - vendor_date = 1*255VCHAR ; module manufacture date - connector_type = 1*255VCHAR ; connector type - specification_compliance = 1*255VCHAR ; electronic or optical interfaces that supported - active_firmware = 1*255VCHAR ; active firmware - inactive_firmware = 1*255VCHAR ; inactive firmware - supported_max_tx_power = FLOAT ; support maximum tx power - supported_min_tx_power = FLOAT ; support minimum tx power - supported_max_laser_freq = FLOAT ; support maximum laser frequency - supported_min_laser_freq = FLOAT ; support minimum laser frequency - ================================================================================ - """ - trans_info = dict() - trans_info['module_media_type'] = self.get_module_media_type() - trans_info['host_electrical_interface'] = self.get_host_electrical_interface() - trans_info['media_interface_code'] = self.get_module_media_interface() - trans_info['host_lane_count'] = self.get_host_lane_count() - trans_info['media_lane_count'] = self.get_media_lane_count() - trans_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option() - trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() - apsel_dict = self.get_active_apsel_hostlane() - trans_info['active_apsel_hostlane1'] = apsel_dict['hostlane1'] - trans_info['active_apsel_hostlane2'] = apsel_dict['hostlane2'] - trans_info['active_apsel_hostlane3'] = apsel_dict['hostlane3'] - trans_info['active_apsel_hostlane4'] = apsel_dict['hostlane4'] - trans_info['active_apsel_hostlane5'] = apsel_dict['hostlane5'] - trans_info['active_apsel_hostlane6'] = apsel_dict['hostlane6'] - trans_info['active_apsel_hostlane7'] = apsel_dict['hostlane7'] - trans_info['active_apsel_hostlane8'] = apsel_dict['hostlane8'] - trans_info['media_interface_technology'] = self.get_media_interface_technology() - trans_info['hardwarerev'] = self.get_module_hardware_revision() - trans_info['serialnum'] = self.get_vendor_serial() - trans_info['manufacturename'] = self.get_vendor_name() - trans_info['vendor_rev'] = self.get_vendor_rev() - trans_info['vendor_oui'] = self.get_vendor_OUI() - trans_info['vendor_date'] = self.get_vendor_date() - trans_info['connector_type'] = self.get_connector_type() - trans_info['specification_compliance'] = self.get_cmis_rev() - trans_info['active_firmware'] = self.get_module_active_firmware() - trans_info['inactive_firmware'] = self.get_module_inactive_firmware() - min_power, max_power = self.get_supported_power_config() - trans_info['supported_max_tx_power'] = max_power - trans_info['supported_min_tx_power'] = min_power - _, _, _, low_freq_supported, high_freq_supported = self.get_supported_freq_config() - trans_info['supported_max_laser_freq'] = high_freq_supported - trans_info['supported_min_laser_freq'] = low_freq_supported - return trans_info - - def get_transceiver_bulk_status(self): - """ - Retrieves bulk status info for this xcvr - - Returns: - A dict containing the following keys/values : - ======================================================================== - key = TRANSCEIVER_DOM_SENSOR|ifname ; information module DOM sensors on port - ; field = value - temperature = FLOAT ; temperature value in Celsius - voltage = FLOAT ; voltage value - txpower = FLOAT ; tx power in mW - rxpower = FLOAT ; rx power in mW - txbias = FLOAT ; tx bias in mA - laser_temperature = FLOAT ; laser temperature value in Celsius - prefec_ber = FLOAT ; prefec ber - postfec_ber = FLOAT ; postfec ber - cd_shortlink = FLOAT ; chromatic dispersion, high granularity, short link in ps/nm - cd_longlink = FLOAT ; chromatic dispersion, low granularity, long link in ps/nm - dgd = FLOAT ; differential group delay in ps - sopmd = FLOAT ; second order polarization mode dispersion in ps^2 - pdl = FLOAT ; polarization dependent loss in db - osnr = FLOAT ; optical signal to noise ratio in db - esnr = FLOAT ; electrical signal to noise ratio in db - cfo = FLOAT ; carrier frequency offset in MHz - soproc = FLOAT ; state of polarization rate of change in krad/s - laser_config_freq = FLOAT ; laser configured frequency in MHz - laser_curr_freq = FLOAT ; laser current frequency in MHz - tx_config_power = FLOAT ; configured tx output power in dbm - tx_curr_power = FLOAT ; tx current output power in dbm - rx_tot_power = FLOAT ; rx total power in dbm - rx_sig_power = FLOAT ; rx signal power in dbm - bias_xi = FLOAT ; modulator bias xi - bias_xq = FLOAT ; modulator bias xq - bias_xp = FLOAT ; modulator bias xp - bias_yi = FLOAT ; modulator bias yi - bias_yq = FLOAT ; modulator bias yq - bias_yp = FLOAT ; modulator bias yp - ======================================================================== - """ - trans_dom = dict() - case_temp_dict = self.get_module_temperature() - trans_dom['temperature'] = case_temp_dict['monitor value'] - voltage_dict = self.get_module_voltage() - trans_dom['voltage'] = voltage_dict['monitor value'] - tx_power_dict = self.get_txpower() - trans_dom['txpower'] = tx_power_dict['monitor value lane1'] - rx_power_dict = self.get_rxpower() - trans_dom['rxpower'] = rx_power_dict['monitor value lane1'] - tx_bias_current_dict = self.get_txbias() - trans_dom['txbias'] = tx_bias_current_dict['monitor value lane1'] - laser_temp_dict = self.get_laser_temperature() - trans_dom['laser_temperature'] = laser_temp_dict['monitor value'] - vdm_dict = self.get_VDM() - trans_dom['prefec_ber'] = vdm_dict['Pre-FEC BER Average Media Input'][1][0] - trans_dom['postfec_ber'] = vdm_dict['Errored Frames Average Media Input'][1][0] - trans_dom['bias_xi'] = vdm_dict['Modulator Bias X/I [%]'][1][0] - trans_dom['bias_xq'] = vdm_dict['Modulator Bias X/Q [%]'][1][0] - trans_dom['bias_xp'] = vdm_dict['Modulator Bias X_Phase [%]'][1][0] - trans_dom['bias_yi'] = vdm_dict['Modulator Bias Y/I [%]'][1][0] - trans_dom['bias_yq'] = vdm_dict['Modulator Bias Y/Q [%]'][1][0] - trans_dom['bias_yp'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][0] - trans_dom['cd_shortlink'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][0] - try: - trans_dom['cd_longlink'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][0] - except KeyError: - pass - trans_dom['dgd'] = vdm_dict['DGD [ps]'][1][0] - try: - trans_dom['sopmd'] = vdm_dict['SOPMD [ps^2]'][1][0] - except KeyError: - pass - trans_dom['pdl'] = vdm_dict['PDL [dB]'][1][0] - trans_dom['osnr'] = vdm_dict['OSNR [dB]'][1][0] - trans_dom['esnr'] = vdm_dict['eSNR [dB]'][1][0] - trans_dom['cfo'] = vdm_dict['CFO [MHz]'][1][0] - trans_dom['tx_curr_power'] = vdm_dict['Tx Power [dBm]'][1][0] - trans_dom['rx_tot_power'] = vdm_dict['Rx Total Power [dBm]'][1][0] - trans_dom['rx_sig_power'] = vdm_dict['Rx Signal Power [dBm]'][1][0] - trans_dom['laser_config_freq'] = self.get_laser_config_freq() - trans_dom['laser_curr_freq'] = self.get_current_laser_freq() - trans_dom['tx_config_power'] = self.get_TX_config_power() - return trans_dom - - def get_transceiver_threshold_info(self): - """ - Retrieves threshold info for this xcvr - - Returns: - A dict containing the following keys/values : - ======================================================================== - key = TRANSCEIVER_STATUS|ifname ; DOM threshold information for module on port - ; field = value - temphighalarm = FLOAT ; temperature high alarm threshold in Celsius - temphighwarning = FLOAT ; temperature high warning threshold in Celsius - templowalarm = FLOAT ; temperature low alarm threshold in Celsius - templowwarning = FLOAT ; temperature low warning threshold in Celsius - vcchighalarm = FLOAT ; vcc high alarm threshold in V - vcchighwarning = FLOAT ; vcc high warning threshold in V - vcclowalarm = FLOAT ; vcc low alarm threshold in V - vcclowwarning = FLOAT ; vcc low warning threshold in V - txpowerhighalarm = FLOAT ; tx power high alarm threshold in mW - txpowerlowalarm = FLOAT ; tx power low alarm threshold in mW - txpowerhighwarning = FLOAT ; tx power high warning threshold in mW - txpowerlowwarning = FLOAT ; tx power low alarm threshold in mW - rxpowerhighalarm = FLOAT ; rx power high alarm threshold in mW - rxpowerlowalarm = FLOAT ; rx power low alarm threshold in mW - rxpowerhighwarning = FLOAT ; rx power high warning threshold in mW - rxpowerlowwarning = FLOAT ; rx power low warning threshold in mW - txbiashighalarm = FLOAT ; tx bias high alarm threshold in mA - txbiaslowalarm = FLOAT ; tx bias low alarm threshold in mA - txbiashighwarning = FLOAT ; tx bias high warning threshold in mA - txbiaslowwarning = FLOAT ; tx bias low warning threshold in mA - lasertemphighalarm = FLOAT ; laser temperature high alarm threshold in Celsius - lasertemplowalarm = FLOAT ; laser temperature low alarm threshold in Celsius - lasertemphighwarning = FLOAT ; laser temperature high warning threshold in Celsius - lasertemplowwarning = FLOAT ; laser temperature low warning threshold in Celsius - prefecberhighalarm = FLOAT ; prefec ber high alarm threshold - prefecberlowalarm = FLOAT ; prefec ber low alarm threshold - prefecberhighwarning = FLOAT ; prefec ber high warning threshold - prefecberlowwarning = FLOAT ; prefec ber low warning threshold - postfecberhighalarm = FLOAT ; postfec ber high alarm threshold - postfecberlowalarm = FLOAT ; postfec ber low alarm threshold - postfecberhighwarning = FLOAT ; postfec ber high warning threshold - postfecberlowwarning = FLOAT ; postfec ber low warning threshold - biasxihighalarm = FLOAT ; bias xi high alarm threshold in percent - biasxilowalarm = FLOAT ; bias xi low alarm threshold in percent - biasxihighwarning = FLOAT ; bias xi high warning threshold in percent - biasxilowwarning = FLOAT ; bias xi low warning threshold in percent - biasxqhighalarm = FLOAT ; bias xq high alarm threshold in percent - biasxqlowalarm = FLOAT ; bias xq low alarm threshold in percent - biasxqhighwarning = FLOAT ; bias xq high warning threshold in percent - biasxqlowwarning = FLOAT ; bias xq low warning threshold in percent - biasxphighalarm = FLOAT ; bias xp high alarm threshold in percent - biasxplowalarm = FLOAT ; bias xp low alarm threshold in percent - biasxphighwarning = FLOAT ; bias xp high warning threshold in percent - biasxplowwarning = FLOAT ; bias xp low warning threshold in percent - biasyihighalarm = FLOAT ; bias yi high alarm threshold in percent - biasyilowalarm = FLOAT ; bias yi low alarm threshold in percent - biasyihighwarning = FLOAT ; bias yi high warning threshold in percent - biasyilowwarning = FLOAT ; bias yi low warning threshold in percent - biasyqhighalarm = FLOAT ; bias yq high alarm threshold in percent - biasyqlowalarm = FLOAT ; bias yq low alarm threshold in percent - biasyqhighwarning = FLOAT ; bias yq high warning threshold in percent - biasyqlowwarning = FLOAT ; bias yq low warning threshold in percent - biasyphighalarm = FLOAT ; bias yp high alarm threshold in percent - biasyplowalarm = FLOAT ; bias yp low alarm threshold in percent - biasyphighwarning = FLOAT ; bias yp high warning threshold in percent - biasyplowwarning = FLOAT ; bias yp low warning threshold in percent - cdshorthighalarm = FLOAT ; cd short high alarm threshold in ps/nm - cdshortlowalarm = FLOAT ; cd short low alarm threshold in ps/nm - cdshorthighwarning = FLOAT ; cd short high warning threshold in ps/nm - cdshortlowwarning = FLOAT ; cd short low warning threshold in ps/nm - cdlonghighalarm = FLOAT ; cd long high alarm threshold in ps/nm - cdlonglowalarm = FLOAT ; cd long low alarm threshold in ps/nm - cdlonghighwarning = FLOAT ; cd long high warning threshold in ps/nm - cdlonglowwarning = FLOAT ; cd long low warning threshold in ps/nm - dgdhighalarm = FLOAT ; dgd high alarm threshold in ps - dgdlowalarm = FLOAT ; dgd low alarm threshold in ps - dgdhighwarning = FLOAT ; dgd high warning threshold in ps - dgdlowwarning = FLOAT ; dgd low warning threshold in ps - sopmdhighalarm = FLOAT ; sopmd high alarm threshold in ps^2 - sopmdlowalarm = FLOAT ; sopmd low alarm threshold in ps^2 - sopmdhighwarning = FLOAT ; sopmd high warning threshold in ps^2 - sopmdlowwarning = FLOAT ; sopmd low warning threshold in ps^2 - pdlhighalarm = FLOAT ; pdl high alarm threshold in db - pdllowalarm = FLOAT ; pdl low alarm threshold in db - pdlhighwarning = FLOAT ; pdl high warning threshold in db - pdllowwarning = FLOAT ; pdl low warning threshold in db - osnrhighalarm = FLOAT ; osnr high alarm threshold in db - osnrlowalarm = FLOAT ; osnr low alarm threshold in db - osnrhighwarning = FLOAT ; osnr high warning threshold in db - osnrlowwarning = FLOAT ; osnr low warning threshold in db - esnrhighalarm = FLOAT ; esnr high alarm threshold in db - esnrlowalarm = FLOAT ; esnr low alarm threshold in db - esnrhighwarning = FLOAT ; esnr high warning threshold in db - esnrlowwarning = FLOAT ; esnr low warning threshold in db - cfohighalarm = FLOAT ; cfo high alarm threshold in MHz - cfolowalarm = FLOAT ; cfo low alarm threshold in MHz - cfohighwarning = FLOAT ; cfo high warning threshold in MHz - cfolowwarning = FLOAT ; cfo low warning threshold in MHz - txcurrpowerhighalarm = FLOAT ; txcurrpower high alarm threshold in dbm - txcurrpowerlowalarm = FLOAT ; txcurrpower low alarm threshold in dbm - txcurrpowerhighwarning = FLOAT ; txcurrpower high warning threshold in dbm - txcurrpowerlowwarning = FLOAT ; txcurrpower low warning threshold in dbm - rxtotpowerhighalarm = FLOAT ; rxtotpower high alarm threshold in dbm - rxtotpowerlowalarm = FLOAT ; rxtotpower low alarm threshold in dbm - rxtotpowerhighwarning = FLOAT ; rxtotpower high warning threshold in dbm - rxtotpowerlowwarning = FLOAT ; rxtotpower low warning threshold in dbm - rxsigpowerhighalarm = FLOAT ; rxsigpower high alarm threshold in dbm - rxsigpowerlowalarm = FLOAT ; rxsigpower low alarm threshold in dbm - rxsigpowerhighwarning = FLOAT ; rxsigpower high warning threshold in dbm - rxsigpowerlowwarning = FLOAT ; rxsigpower low warning threshold in dbm - ======================================================================== - """ - trans_dom_th = dict() - case_temp_dict = self.get_module_temperature() - trans_dom_th['temphighalarm'] = case_temp_dict['high alarm'] - trans_dom_th['templowalarm'] = case_temp_dict['low alarm'] - trans_dom_th['temphighwarning'] = case_temp_dict['high warn'] - trans_dom_th['templowwarning'] = case_temp_dict['low warn'] - voltage_dict = self.get_module_voltage() - trans_dom_th['vcchighalarm'] = voltage_dict['high alarm'] - trans_dom_th['vcclowalarm'] = voltage_dict['low alarm'] - trans_dom_th['vcchighwarning'] = voltage_dict['high warn'] - trans_dom_th['vcclowwarning'] = voltage_dict['low warn'] - tx_power_dict = self.get_txpower() - trans_dom_th['txpowerhighalarm'] = tx_power_dict['high alarm'] - trans_dom_th['txpowerlowalarm'] = tx_power_dict['low alarm'] - trans_dom_th['txpowerhighwarning'] = tx_power_dict['high warn'] - trans_dom_th['txpowerlowwarning'] = tx_power_dict['low warn'] - rx_power_dict = self.get_rxpower() - trans_dom_th['rxpowerhighalarm'] = rx_power_dict['high alarm'] - trans_dom_th['rxpowerlowalarm'] = rx_power_dict['low alarm'] - trans_dom_th['rxpowerhighwarning'] = rx_power_dict['high warn'] - trans_dom_th['rxpowerlowwarning'] = rx_power_dict['low warn'] - tx_bias_current_dict = self.get_txbias() - trans_dom_th['txbiashighalarm'] = tx_bias_current_dict['high alarm'] - trans_dom_th['txbiaslowalarm'] = tx_bias_current_dict['low alarm'] - trans_dom_th['txbiashighwarning'] = tx_bias_current_dict['high warn'] - trans_dom_th['txbiaslowwarning'] = tx_bias_current_dict['low warn'] - laser_temp_dict = self.get_laser_temperature() - trans_dom_th['lasertemphighalarm'] = laser_temp_dict['high alarm'] - trans_dom_th['lasertemplowalarm'] = laser_temp_dict['low alarm'] - trans_dom_th['lasertemphighwarning'] = laser_temp_dict['high warn'] - trans_dom_th['lasertemplowwarning'] = laser_temp_dict['low warn'] - vdm_dict = self.get_VDM() - trans_dom_th['prefecberhighalarm'] = vdm_dict['Pre-FEC BER Average Media Input'][1][1] - trans_dom_th['prefecberlowalarm'] = vdm_dict['Pre-FEC BER Average Media Input'][1][2] - trans_dom_th['prefecberhighwarning'] = vdm_dict['Pre-FEC BER Average Media Input'][1][3] - trans_dom_th['prefecberlowwarning'] = vdm_dict['Pre-FEC BER Average Media Input'][1][4] - trans_dom_th['postfecberhighalarm'] = vdm_dict['Errored Frames Average Media Input'][1][1] - trans_dom_th['postfecberlowalarm'] = vdm_dict['Errored Frames Average Media Input'][1][2] - trans_dom_th['postfecberhighwarning'] = vdm_dict['Errored Frames Average Media Input'][1][3] - trans_dom_th['postfecberlowwarning'] = vdm_dict['Errored Frames Average Media Input'][1][4] - trans_dom_th['biasxihighalarm'] = vdm_dict['Modulator Bias X/I [%]'][1][1] - trans_dom_th['biasxilowalarm'] = vdm_dict['Modulator Bias X/I [%]'][1][2] - trans_dom_th['biasxihighwarning'] = vdm_dict['Modulator Bias X/I [%]'][1][3] - trans_dom_th['biasxilowwarning'] = vdm_dict['Modulator Bias X/I [%]'][1][4] - trans_dom_th['biasxqhighalarm'] = vdm_dict['Modulator Bias X/Q [%]'][1][1] - trans_dom_th['biasxqlowalarm'] = vdm_dict['Modulator Bias X/Q [%]'][1][2] - trans_dom_th['biasxqhighwarning'] = vdm_dict['Modulator Bias X/Q [%]'][1][3] - trans_dom_th['biasxqlowwarning'] = vdm_dict['Modulator Bias X/Q [%]'][1][4] - trans_dom_th['biasxphighalarm'] = vdm_dict['Modulator Bias X_Phase [%]'][1][1] - trans_dom_th['biasxplowalarm'] = vdm_dict['Modulator Bias X_Phase [%]'][1][2] - trans_dom_th['biasxphighwarning'] = vdm_dict['Modulator Bias X_Phase [%]'][1][3] - trans_dom_th['biasxplowwarning'] = vdm_dict['Modulator Bias X_Phase [%]'][1][4] - trans_dom_th['biasyihighalarm'] = vdm_dict['Modulator Bias Y/I [%]'][1][1] - trans_dom_th['biasyilowalarm'] = vdm_dict['Modulator Bias Y/I [%]'][1][2] - trans_dom_th['biasyihighwarning'] = vdm_dict['Modulator Bias Y/I [%]'][1][3] - trans_dom_th['biasyilowwarning'] = vdm_dict['Modulator Bias Y/I [%]'][1][4] - trans_dom_th['biasyqhighalarm'] = vdm_dict['Modulator Bias Y/Q [%]'][1][1] - trans_dom_th['biasyqlowalarm'] = vdm_dict['Modulator Bias Y/Q [%]'][1][2] - trans_dom_th['biasyqhighwarning'] = vdm_dict['Modulator Bias Y/Q [%]'][1][3] - trans_dom_th['biasyqlowwarning'] = vdm_dict['Modulator Bias Y/Q [%]'][1][4] - trans_dom_th['biasyphighalarm'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][1] - trans_dom_th['biasyplowalarm'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][2] - trans_dom_th['biasyphighwarning'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][3] - trans_dom_th['biasyplowwarning'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][4] - trans_dom_th['cdshorthighalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][1] - trans_dom_th['cdshortlowalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][2] - trans_dom_th['cdshorthighwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][3] - trans_dom_th['cdshortlowwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][4] - try: - trans_dom_th['cdlonghighalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][1] - trans_dom_th['cdlonglowalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][2] - trans_dom_th['cdlonghighwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][3] - trans_dom_th['cdlonglowwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][4] - except KeyError: - pass - trans_dom_th['dgdhighalarm'] = vdm_dict['DGD [ps]'][1][1] - trans_dom_th['dgdlowalarm'] = vdm_dict['DGD [ps]'][1][2] - trans_dom_th['dgdhighwarning'] = vdm_dict['DGD [ps]'][1][3] - trans_dom_th['dgdlowwarning'] = vdm_dict['DGD [ps]'][1][4] - try: - trans_dom_th['sopmdhighalarm'] = vdm_dict['SOPMD [ps^2]'][1][1] - trans_dom_th['sopmdlowalarm'] = vdm_dict['SOPMD [ps^2]'][1][2] - trans_dom_th['sopmdhighwarning'] = vdm_dict['SOPMD [ps^2]'][1][3] - trans_dom_th['sopmdlowwarning'] = vdm_dict['SOPMD [ps^2]'][1][4] - except KeyError: - pass - trans_dom_th['pdlhighalarm'] = vdm_dict['PDL [dB]'][1][1] - trans_dom_th['pdllowalarm'] = vdm_dict['PDL [dB]'][1][2] - trans_dom_th['pdlhighwarning'] = vdm_dict['PDL [dB]'][1][3] - trans_dom_th['pdllowwarning'] = vdm_dict['PDL [dB]'][1][4] - trans_dom_th['osnrhighalarm'] = vdm_dict['OSNR [dB]'][1][1] - trans_dom_th['osnrlowalarm'] = vdm_dict['OSNR [dB]'][1][2] - trans_dom_th['osnrhighwarning'] = vdm_dict['OSNR [dB]'][1][3] - trans_dom_th['osnrlowwarning'] = vdm_dict['OSNR [dB]'][1][4] - trans_dom_th['esnrhighalarm'] = vdm_dict['eSNR [dB]'][1][1] - trans_dom_th['esnrlowalarm'] = vdm_dict['eSNR [dB]'][1][2] - trans_dom_th['esnrhighwarning'] = vdm_dict['eSNR [dB]'][1][3] - trans_dom_th['esnrlowwarning'] = vdm_dict['eSNR [dB]'][1][4] - trans_dom_th['cfohighalarm'] = vdm_dict['CFO [MHz]'][1][1] - trans_dom_th['cfolowalarm'] = vdm_dict['CFO [MHz]'][1][2] - trans_dom_th['cfohighwarning'] = vdm_dict['CFO [MHz]'][1][3] - trans_dom_th['cfolowwarning'] = vdm_dict['CFO [MHz]'][1][4] - trans_dom_th['txcurrpowerhighalarm'] = vdm_dict['Tx Power [dBm]'][1][1] - trans_dom_th['txcurrpowerlowalarm'] = vdm_dict['Tx Power [dBm]'][1][2] - trans_dom_th['txcurrpowerhighwarning'] = vdm_dict['Tx Power [dBm]'][1][3] - trans_dom_th['txcurrpowerlowwarning'] = vdm_dict['Tx Power [dBm]'][1][4] - trans_dom_th['rxtotpowerhighalarm'] = vdm_dict['Rx Total Power [dBm]'][1][1] - trans_dom_th['rxtotpowerlowalarm'] = vdm_dict['Rx Total Power [dBm]'][1][2] - trans_dom_th['rxtotpowerhighwarning'] = vdm_dict['Rx Total Power [dBm]'][1][3] - trans_dom_th['rxtotpowerlowwarning'] = vdm_dict['Rx Total Power [dBm]'][1][4] - trans_dom_th['rxsigpowerhighalarm'] = vdm_dict['Rx Signal Power [dBm]'][1][1] - trans_dom_th['rxsigpowerlowalarm'] = vdm_dict['Rx Signal Power [dBm]'][1][2] - trans_dom_th['rxsigpowerhighwarning'] = vdm_dict['Rx Signal Power [dBm]'][1][3] - trans_dom_th['rxsigpowerlowwarning'] = vdm_dict['Rx Signal Power [dBm]'][1][4] - return trans_dom_th - - def get_transceiver_status(self): - """ - Retrieves transceiver status of this SFP - - Returns: - A dict which contains following keys/values : - ================================================================================ - key = TRANSCEIVER_STATUS|ifname ; Error information for module on port - ; field = value - status = 1*255VCHAR ; code of the module status (plug in, plug out) - error = 1*255VCHAR ; module error (N/A or a string consisting of error descriptions joined by "|", like "error1 | error2" ) - module_state = 1*255VCHAR ; current module state (ModuleLowPwr, ModulePwrUp, ModuleReady, ModulePwrDn, Fault) - module_fault_cause = 1*255VCHAR ; reason of entering the module fault state - datapath_firmware_fault = BOOLEAN ; datapath (DSP) firmware fault - module_firmware_fault = BOOLEAN ; module firmware fault - module_state_changed = BOOLEAN ; module state changed - datapath_hostlane1 = 1*255VCHAR ; data path state indicator on host lane 1 - datapath_hostlane2 = 1*255VCHAR ; data path state indicator on host lane 2 - datapath_hostlane3 = 1*255VCHAR ; data path state indicator on host lane 3 - datapath_hostlane4 = 1*255VCHAR ; data path state indicator on host lane 4 - datapath_hostlane5 = 1*255VCHAR ; data path state indicator on host lane 5 - datapath_hostlane6 = 1*255VCHAR ; data path state indicator on host lane 6 - datapath_hostlane7 = 1*255VCHAR ; data path state indicator on host lane 7 - datapath_hostlane8 = 1*255VCHAR ; data path state indicator on host lane 8 - txoutput_status = BOOLEAN ; tx output status on media lane - rxoutput_status_hostlane1 = BOOLEAN ; rx output status on host lane 1 - rxoutput_status_hostlane2 = BOOLEAN ; rx output status on host lane 2 - rxoutput_status_hostlane3 = BOOLEAN ; rx output status on host lane 3 - rxoutput_status_hostlane4 = BOOLEAN ; rx output status on host lane 4 - rxoutput_status_hostlane5 = BOOLEAN ; rx output status on host lane 5 - rxoutput_status_hostlane6 = BOOLEAN ; rx output status on host lane 6 - rxoutput_status_hostlane7 = BOOLEAN ; rx output status on host lane 7 - rxoutput_status_hostlane8 = BOOLEAN ; rx output status on host lane 8 - txfault = BOOLEAN ; tx fault flag on media lane - txlos_hostlane1 = BOOLEAN ; tx loss of signal flag on host lane 1 - txlos_hostlane2 = BOOLEAN ; tx loss of signal flag on host lane 2 - txlos_hostlane3 = BOOLEAN ; tx loss of signal flag on host lane 3 - txlos_hostlane4 = BOOLEAN ; tx loss of signal flag on host lane 4 - txlos_hostlane5 = BOOLEAN ; tx loss of signal flag on host lane 5 - txlos_hostlane6 = BOOLEAN ; tx loss of signal flag on host lane 6 - txlos_hostlane7 = BOOLEAN ; tx loss of signal flag on host lane 7 - txlos_hostlane8 = BOOLEAN ; tx loss of signal flag on host lane 8 - txcdrlol_hostlane1 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 1 - txcdrlol_hostlane2 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 2 - txcdrlol_hostlane3 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 3 - txcdrlol_hostlane4 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 4 - txcdrlol_hostlane5 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 5 - txcdrlol_hostlane6 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 6 - txcdrlol_hostlane7 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 7 - txcdrlol_hostlane8 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 8 - rxlos = BOOLEAN ; rx loss of signal flag on media lane - rxcdrlol = BOOLEAN ; rx clock and data recovery loss of lock on media lane - config_state_hostlane1 = 1*255VCHAR ; configuration status for the data path of host line 1 - config_state_hostlane2 = 1*255VCHAR ; configuration status for the data path of host line 2 - config_state_hostlane3 = 1*255VCHAR ; configuration status for the data path of host line 3 - config_state_hostlane4 = 1*255VCHAR ; configuration status for the data path of host line 4 - config_state_hostlane5 = 1*255VCHAR ; configuration status for the data path of host line 5 - config_state_hostlane6 = 1*255VCHAR ; configuration status for the data path of host line 6 - config_state_hostlane7 = 1*255VCHAR ; configuration status for the data path of host line 7 - config_state_hostlane8 = 1*255VCHAR ; configuration status for the data path of host line 8 - dpinit_pending_hostlane1 = BOOLEAN ; data path configuration updated on host lane 1 - dpinit_pending_hostlane2 = BOOLEAN ; data path configuration updated on host lane 2 - dpinit_pending_hostlane3 = BOOLEAN ; data path configuration updated on host lane 3 - dpinit_pending_hostlane4 = BOOLEAN ; data path configuration updated on host lane 4 - dpinit_pending_hostlane5 = BOOLEAN ; data path configuration updated on host lane 5 - dpinit_pending_hostlane6 = BOOLEAN ; data path configuration updated on host lane 6 - dpinit_pending_hostlane7 = BOOLEAN ; data path configuration updated on host lane 7 - dpinit_pending_hostlane8 = BOOLEAN ; data path configuration updated on host lane 8 - tuning_in_progress = BOOLEAN ; tuning in progress status - wavelength_unlock_status = BOOLEAN ; laser unlocked status - target_output_power_oor = BOOLEAN ; target output power out of range flag - fine_tuning_oor = BOOLEAN ; fine tuning out of range flag - tuning_not_accepted = BOOLEAN ; tuning not accepted flag - invalid_channel_num = BOOLEAN ; invalid channel number flag - tuning_complete = BOOLEAN ; tuning complete flag - temphighalarm_flag = BOOLEAN ; temperature high alarm flag - temphighwarning_flag = BOOLEAN ; temperature high warning flag - templowalarm_flag = BOOLEAN ; temperature low alarm flag - templowwarning_flag = BOOLEAN ; temperature low warning flag - vcchighalarm_flag = BOOLEAN ; vcc high alarm flag - vcchighwarning_flag = BOOLEAN ; vcc high warning flag - vcclowalarm_flag = BOOLEAN ; vcc low alarm flag - vcclowwarning_flag = BOOLEAN ; vcc low warning flag - txpowerhighalarm_flag = BOOLEAN ; tx power high alarm flag - txpowerlowalarm_flag = BOOLEAN ; tx power low alarm flag - txpowerhighwarning_flag = BOOLEAN ; tx power high warning flag - txpowerlowwarning_flag = BOOLEAN ; tx power low alarm flag - rxpowerhighalarm_flag = BOOLEAN ; rx power high alarm flag - rxpowerlowalarm_flag = BOOLEAN ; rx power low alarm flag - rxpowerhighwarning_flag = BOOLEAN ; rx power high warning flag - rxpowerlowwarning_flag = BOOLEAN ; rx power low warning flag - txbiashighalarm_flag = BOOLEAN ; tx bias high alarm flag - txbiaslowalarm_flag = BOOLEAN ; tx bias low alarm flag - txbiashighwarning_flag = BOOLEAN ; tx bias high warning flag - txbiaslowwarning_flag = BOOLEAN ; tx bias low warning flag - lasertemphighalarm_flag = BOOLEAN ; laser temperature high alarm flag - lasertemplowalarm_flag = BOOLEAN ; laser temperature low alarm flag - lasertemphighwarning_flag = BOOLEAN ; laser temperature high warning flag - lasertemplowwarning_flag = BOOLEAN ; laser temperature low warning flag - prefecberhighalarm_flag = BOOLEAN ; prefec ber high alarm flag - prefecberlowalarm_flag = BOOLEAN ; prefec ber low alarm flag - prefecberhighwarning_flag = BOOLEAN ; prefec ber high warning flag - prefecberlowwarning_flag = BOOLEAN ; prefec ber low warning flag - postfecberhighalarm_flag = BOOLEAN ; postfec ber high alarm flag - postfecberlowalarm_flag = BOOLEAN ; postfec ber low alarm flag - postfecberhighwarning_flag = BOOLEAN ; postfec ber high warning flag - postfecberlowwarning_flag = BOOLEAN ; postfec ber low warning flag - biasxihighalarm_flag = BOOLEAN ; bias xi high alarm flag - biasxilowalarm_flag = BOOLEAN ; bias xi low alarm flag - biasxihighwarning_flag = BOOLEAN ; bias xi high warning flag - biasxilowwarning_flag = BOOLEAN ; bias xi low warning flag - biasxqhighalarm_flag = BOOLEAN ; bias xq high alarm flag - biasxqlowalarm_flag = BOOLEAN ; bias xq low alarm flag - biasxqhighwarning_flag = BOOLEAN ; bias xq high warning flag - biasxqlowwarning_flag = BOOLEAN ; bias xq low warning flag - biasxphighalarm_flag = BOOLEAN ; bias xp high alarm flag - biasxplowalarm_flag = BOOLEAN ; bias xp low alarm flag - biasxphighwarning_flag = BOOLEAN ; bias xp high warning flag - biasxplowwarning_flag = BOOLEAN ; bias xp low warning flag - biasyihighalarm_flag = BOOLEAN ; bias yi high alarm flag - biasyilowalarm_flag = BOOLEAN ; bias yi low alarm flag - biasyihighwarning_flag = BOOLEAN ; bias yi high warning flag - biasyilowwarning_flag = BOOLEAN ; bias yi low warning flag - biasyqhighalarm_flag = BOOLEAN ; bias yq high alarm flag - biasyqlowalarm_flag = BOOLEAN ; bias yq low alarm flag - biasyqhighwarning_flag = BOOLEAN ; bias yq high warning flag - biasyqlowwarning_flag = BOOLEAN ; bias yq low warning flag - biasyphighalarm_flag = BOOLEAN ; bias yp high alarm flag - biasyplowalarm_flag = BOOLEAN ; bias yp low alarm flag - biasyphighwarning_flag = BOOLEAN ; bias yp high warning flag - biasyplowwarning_flag = BOOLEAN ; bias yp low warning flag - cdshorthighalarm_flag = BOOLEAN ; cd short high alarm flag - cdshortlowalarm_flag = BOOLEAN ; cd short low alarm flag - cdshorthighwarning_flag = BOOLEAN ; cd short high warning flag - cdshortlowwarning_flag = BOOLEAN ; cd short low warning flag - cdlonghighalarm_flag = BOOLEAN ; cd long high alarm flag - cdlonglowalarm_flag = BOOLEAN ; cd long low alarm flag - cdlonghighwarning_flag = BOOLEAN ; cd long high warning flag - cdlonglowwarning_flag = BOOLEAN ; cd long low warning flag - dgdhighalarm_flag = BOOLEAN ; dgd high alarm flag - dgdlowalarm_flag = BOOLEAN ; dgd low alarm flag - dgdhighwarning_flag = BOOLEAN ; dgd high warning flag - dgdlowwarning_flag = BOOLEAN ; dgd low warning flag - sopmdhighalarm_flag = BOOLEAN ; sopmd high alarm flag - sopmdlowalarm_flag = BOOLEAN ; sopmd low alarm flag - sopmdhighwarning_flag = BOOLEAN ; sopmd high warning flag - sopmdlowwarning_flag = BOOLEAN ; sopmd low warning flag - pdlhighalarm_flag = BOOLEAN ; pdl high alarm flag - pdllowalarm_flag = BOOLEAN ; pdl low alarm flag - pdlhighwarning_flag = BOOLEAN ; pdl high warning flag - pdllowwarning_flag = BOOLEAN ; pdl low warning flag - osnrhighalarm_flag = BOOLEAN ; osnr high alarm flag - osnrlowalarm_flag = BOOLEAN ; osnr low alarm flag - osnrhighwarning_flag = BOOLEAN ; osnr high warning flag - osnrlowwarning_flag = BOOLEAN ; osnr low warning flag - esnrhighalarm_flag = BOOLEAN ; esnr high alarm flag - esnrlowalarm_flag = BOOLEAN ; esnr low alarm flag - esnrhighwarning_flag = BOOLEAN ; esnr high warning flag - esnrlowwarning_flag = BOOLEAN ; esnr low warning flag - cfohighalarm_flag = BOOLEAN ; cfo high alarm flag - cfolowalarm_flag = BOOLEAN ; cfo low alarm flag - cfohighwarning_flag = BOOLEAN ; cfo high warning flag - cfolowwarning_flag = BOOLEAN ; cfo low warning flag - txcurrpowerhighalarm_flag = BOOLEAN ; txcurrpower high alarm flag - txcurrpowerlowalarm_flag = BOOLEAN ; txcurrpower low alarm flag - txcurrpowerhighwarning_flag = BOOLEAN ; txcurrpower high warning flag - txcurrpowerlowwarning_flag = BOOLEAN ; txcurrpower low warning flag - rxtotpowerhighalarm_flag = BOOLEAN ; rxtotpower high alarm flag - rxtotpowerlowalarm_flag = BOOLEAN ; rxtotpower low alarm flag - rxtotpowerhighwarning_flag = BOOLEAN ; rxtotpower high warning flag - rxtotpowerlowwarning_flag = BOOLEAN ; rxtotpower low warning flag - rxsigpowerhighalarm_flag = BOOLEAN ; rxsigpower high alarm flag - rxsigpowerlowalarm_flag = BOOLEAN ; rxsigpower low alarm flag - rxsigpowerhighwarning_flag = BOOLEAN ; rxsigpower high warning flag - rxsigpowerlowwarning_flag = BOOLEAN ; rxsigpower low warning flag - ================================================================================ - """ - trans_status = dict() - trans_status['module_state'] = self.get_module_state() - trans_status['module_fault_cause'] = self.get_module_fault_cause() - dp_fw_fault, module_fw_fault, module_state_changed = self.get_module_firmware_fault_state_changed() - trans_status['datapath_firmware_fault'] = dp_fw_fault - trans_status['module_firmware_fault'] = module_fw_fault - trans_status['module_state_changed'] = module_state_changed - dp_state_dict = self.get_datapath_state() - trans_status['datapath_hostlane1'] = dp_state_dict['dp_lane1'] - trans_status['datapath_hostlane2'] = dp_state_dict['dp_lane2'] - trans_status['datapath_hostlane3'] = dp_state_dict['dp_lane3'] - trans_status['datapath_hostlane4'] = dp_state_dict['dp_lane4'] - trans_status['datapath_hostlane5'] = dp_state_dict['dp_lane5'] - trans_status['datapath_hostlane6'] = dp_state_dict['dp_lane6'] - trans_status['datapath_hostlane7'] = dp_state_dict['dp_lane7'] - trans_status['datapath_hostlane8'] = dp_state_dict['dp_lane8'] - tx_output_status_dict = self.get_tx_output_status() - trans_status['txoutput_status'] = tx_output_status_dict['TX_lane1'] - rx_output_status_dict = self.get_rx_output_status() - trans_status['rxoutput_status_hostlane1'] = rx_output_status_dict['RX_lane1'] - trans_status['rxoutput_status_hostlane2'] = rx_output_status_dict['RX_lane2'] - trans_status['rxoutput_status_hostlane3'] = rx_output_status_dict['RX_lane3'] - trans_status['rxoutput_status_hostlane4'] = rx_output_status_dict['RX_lane4'] - trans_status['rxoutput_status_hostlane5'] = rx_output_status_dict['RX_lane5'] - trans_status['rxoutput_status_hostlane6'] = rx_output_status_dict['RX_lane6'] - trans_status['rxoutput_status_hostlane7'] = rx_output_status_dict['RX_lane7'] - trans_status['rxoutput_status_hostlane8'] = rx_output_status_dict['RX_lane8'] - tx_fault_dict = self.get_tx_fault() - trans_status['txfault'] = tx_fault_dict['TX_lane1'] - tx_los_dict = self.get_tx_los() - trans_status['txlos_hostlane1'] = tx_los_dict['TX_lane1'] - trans_status['txlos_hostlane2'] = tx_los_dict['TX_lane2'] - trans_status['txlos_hostlane3'] = tx_los_dict['TX_lane3'] - trans_status['txlos_hostlane4'] = tx_los_dict['TX_lane4'] - trans_status['txlos_hostlane5'] = tx_los_dict['TX_lane5'] - trans_status['txlos_hostlane6'] = tx_los_dict['TX_lane6'] - trans_status['txlos_hostlane7'] = tx_los_dict['TX_lane7'] - trans_status['txlos_hostlane8'] = tx_los_dict['TX_lane8'] - tx_lol_dict = self.get_tx_cdr_lol() - trans_status['txcdrlol_hostlane1'] = tx_lol_dict['TX_lane1'] - trans_status['txcdrlol_hostlane2'] = tx_lol_dict['TX_lane2'] - trans_status['txcdrlol_hostlane3'] = tx_lol_dict['TX_lane3'] - trans_status['txcdrlol_hostlane4'] = tx_lol_dict['TX_lane4'] - trans_status['txcdrlol_hostlane5'] = tx_lol_dict['TX_lane5'] - trans_status['txcdrlol_hostlane6'] = tx_lol_dict['TX_lane6'] - trans_status['txcdrlol_hostlane7'] = tx_lol_dict['TX_lane7'] - trans_status['txcdrlol_hostlane8'] = tx_lol_dict['TX_lane8'] - rx_los_dict = self.get_rx_los() - trans_status['rxlos'] = rx_los_dict['RX_lane1'] - rx_lol_dict = self.get_rx_cdr_lol() - trans_status['rxcdrlol'] = rx_lol_dict['RX_lane1'] - config_status_dict = self.get_config_datapath_hostlane_status() - trans_status['config_state_hostlane1'] = config_status_dict['config_DP_status_hostlane1'] - trans_status['config_state_hostlane2'] = config_status_dict['config_DP_status_hostlane2'] - trans_status['config_state_hostlane3'] = config_status_dict['config_DP_status_hostlane3'] - trans_status['config_state_hostlane4'] = config_status_dict['config_DP_status_hostlane4'] - trans_status['config_state_hostlane5'] = config_status_dict['config_DP_status_hostlane5'] - trans_status['config_state_hostlane6'] = config_status_dict['config_DP_status_hostlane6'] - trans_status['config_state_hostlane7'] = config_status_dict['config_DP_status_hostlane7'] - trans_status['config_state_hostlane8'] = config_status_dict['config_DP_status_hostlane8'] - dpinit_pending_dict = self.get_dpinit_pending() - trans_status['dpinit_pending_hostlane1'] = dpinit_pending_dict['hostlane1'] - trans_status['dpinit_pending_hostlane2'] = dpinit_pending_dict['hostlane2'] - trans_status['dpinit_pending_hostlane3'] = dpinit_pending_dict['hostlane3'] - trans_status['dpinit_pending_hostlane4'] = dpinit_pending_dict['hostlane4'] - trans_status['dpinit_pending_hostlane5'] = dpinit_pending_dict['hostlane5'] - trans_status['dpinit_pending_hostlane6'] = dpinit_pending_dict['hostlane6'] - trans_status['dpinit_pending_hostlane7'] = dpinit_pending_dict['hostlane7'] - trans_status['dpinit_pending_hostlane8'] = dpinit_pending_dict['hostlane8'] - trans_status['tuning_in_progress'] = self.get_tuning_in_progress() - trans_status['wavelength_unlock_status'] = self.get_wavelength_unlocked() - laser_tuning_summary = self.get_laser_tuning_summary() - trans_status['target_output_power_oor'] = 'TargetOutputPowerOOR' in laser_tuning_summary - trans_status['fine_tuning_oor'] = 'FineTuningOutOfRange' in laser_tuning_summary - trans_status['tuning_not_accepted'] = 'TuningNotAccepted' in laser_tuning_summary - trans_status['invalid_channel_num'] = 'InvalidChannel' in laser_tuning_summary - trans_status['tuning_complete'] = 'TuningComplete' in laser_tuning_summary - module_flag = self.get_module_level_flag() - trans_status['temphighalarm_flag'] = module_flag['case_temp_flags']['case_temp_high_alarm_flag'] - trans_status['templowalarm_flag'] = module_flag['case_temp_flags']['case_temp_low_alarm_flag'] - trans_status['temphighwarning_flag'] = module_flag['case_temp_flags']['case_temp_high_warn_flag'] - trans_status['templowwarning_flag'] = module_flag['case_temp_flags']['case_temp_low_warn_flag'] - trans_status['vcchighalarm_flag'] = module_flag['voltage_flags']['voltage_high_alarm_flag'] - trans_status['vcclowalarm_flag'] = module_flag['voltage_flags']['voltage_low_alarm_flag'] - trans_status['vcchighwarning_flag'] = module_flag['voltage_flags']['voltage_high_warn_flag'] - trans_status['vcclowwarning_flag'] = module_flag['voltage_flags']['voltage_low_warn_flag'] - aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() - if aux2_mon_type == 0: - trans_status['lasertemphighalarm_flag'] = module_flag['aux2_flags']['aux2_high_alarm_flag'] - trans_status['lasertemplowalarm_flag'] = module_flag['aux2_flags']['aux2_low_alarm_flag'] - trans_status['lasertemphighwarning_flag'] = module_flag['aux2_flags']['aux2_high_warn_flag'] - trans_status['lasertemplowwarning_flag'] = module_flag['aux2_flags']['aux2_low_warn_flag'] - elif aux2_mon_type == 1 and aux3_mon_type == 0: - trans_status['lasertemphighalarm_flag'] = module_flag['aux3_flags']['aux3_high_alarm_flag'] - trans_status['lasertemplowalarm_flag'] = module_flag['aux3_flags']['aux3_low_alarm_flag'] - trans_status['lasertemphighwarning_flag'] = module_flag['aux3_flags']['aux3_high_warn_flag'] - trans_status['lasertemplowwarning_flag'] = module_flag['aux3_flags']['aux3_low_warn_flag'] - - tx_power_flag_dict = self.get_tx_power_flag() - trans_status['txpowerhighalarm_flag'] = tx_power_flag_dict['tx_power_high_alarm']['TX_lane1'] - trans_status['txpowerlowalarm_flag'] = tx_power_flag_dict['tx_power_low_alarm']['TX_lane1'] - trans_status['txpowerhighwarning_flag'] = tx_power_flag_dict['tx_power_high_warn']['TX_lane1'] - trans_status['txpowerlowwarning_flag'] = tx_power_flag_dict['tx_power_low_warn']['TX_lane1'] - rx_power_flag_dict = self.get_rx_power_flag() - trans_status['rxpowerhighalarm_flag'] = rx_power_flag_dict['rx_power_high_alarm']['RX_lane1'] - trans_status['rxpowerlowalarm_flag'] = rx_power_flag_dict['rx_power_low_alarm']['RX_lane1'] - trans_status['rxpowerhighwarning_flag'] = rx_power_flag_dict['rx_power_high_warn']['RX_lane1'] - trans_status['rxpowerlowwarning_flag'] = rx_power_flag_dict['rx_power_low_warn']['RX_lane1'] - tx_bias_flag_dict = self.get_tx_bias_flag() - trans_status['txbiashighalarm_flag'] = tx_bias_flag_dict['tx_bias_high_alarm']['TX_lane1'] - trans_status['txbiaslowalarm_flag'] = tx_bias_flag_dict['tx_bias_low_alarm']['TX_lane1'] - trans_status['txbiashighwarning_flag'] = tx_bias_flag_dict['tx_bias_high_warn']['TX_lane1'] - trans_status['txbiaslowwarning_flag'] = tx_bias_flag_dict['tx_bias_low_warn']['TX_lane1'] - vdm_dict = self.get_VDM() - trans_status['prefecberhighalarm_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][5] - trans_status['prefecberlowalarm_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][6] - trans_status['prefecberhighwarning_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][7] - trans_status['prefecberlowwarning_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][8] - trans_status['postfecberhighalarm_flag'] = vdm_dict['Errored Frames Average Media Input'][1][5] - trans_status['postfecberlowalarm_flag'] = vdm_dict['Errored Frames Average Media Input'][1][6] - trans_status['postfecberhighwarning_flag'] = vdm_dict['Errored Frames Average Media Input'][1][7] - trans_status['postfecberlowwarning_flag'] = vdm_dict['Errored Frames Average Media Input'][1][8] - trans_status['biasxihighalarm_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][5] - trans_status['biasxilowalarm_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][6] - trans_status['biasxihighwarning_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][7] - trans_status['biasxilowwarning_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][8] - trans_status['biasxqhighalarm_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][5] - trans_status['biasxqlowalarm_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][6] - trans_status['biasxqhighwarning_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][7] - trans_status['biasxqlowwarning_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][8] - trans_status['biasxphighalarm_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][5] - trans_status['biasxplowalarm_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][6] - trans_status['biasxphighwarning_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][7] - trans_status['biasxplowwarning_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][8] - trans_status['biasyihighalarm_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][5] - trans_status['biasyilowalarm_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][6] - trans_status['biasyihighwarning_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][7] - trans_status['biasyilowwarning_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][8] - trans_status['biasyqhighalarm_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][5] - trans_status['biasyqlowalarm_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][6] - trans_status['biasyqhighwarning_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][7] - trans_status['biasyqlowwarning_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][8] - trans_status['biasyphighalarm_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][5] - trans_status['biasyplowalarm_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][6] - trans_status['biasyphighwarning_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][7] - trans_status['biasyplowwarning_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][8] - trans_status['cdshorthighalarm_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][5] - trans_status['cdshortlowalarm_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][6] - trans_status['cdshorthighwarning_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][7] - trans_status['cdshortlowwarning_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][8] - trans_status['cdlonghighalarm_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][5] - trans_status['cdlonglowalarm_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][6] - trans_status['cdlonghighwarning_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][7] - trans_status['cdlonglowwarning_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][8] - trans_status['dgdhighalarm_flag'] = vdm_dict['DGD [ps]'][1][5] - trans_status['dgdlowalarm_flag'] = vdm_dict['DGD [ps]'][1][6] - trans_status['dgdhighwarning_flag'] = vdm_dict['DGD [ps]'][1][7] - trans_status['dgdlowwarning_flag'] = vdm_dict['DGD [ps]'][1][8] - trans_status['sopmdhighalarm_flag'] = vdm_dict['SOPMD [ps^2]'][1][5] - trans_status['sopmdlowalarm_flag'] = vdm_dict['SOPMD [ps^2]'][1][6] - trans_status['sopmdhighwarning_flag'] = vdm_dict['SOPMD [ps^2]'][1][7] - trans_status['sopmdlowwarning_flag'] = vdm_dict['SOPMD [ps^2]'][1][8] - trans_status['pdlhighalarm_flag'] = vdm_dict['PDL [dB]'][1][5] - trans_status['pdllowalarm_flag'] = vdm_dict['PDL [dB]'][1][6] - trans_status['pdlhighwarning_flag'] = vdm_dict['PDL [dB]'][1][7] - trans_status['pdllowwarning_flag'] = vdm_dict['PDL [dB]'][1][8] - trans_status['osnrhighalarm_flag'] = vdm_dict['OSNR [dB]'][1][5] - trans_status['osnrlowalarm_flag'] = vdm_dict['OSNR [dB]'][1][6] - trans_status['osnrhighwarning_flag'] = vdm_dict['OSNR [dB]'][1][7] - trans_status['osnrlowwarning_flag'] = vdm_dict['OSNR [dB]'][1][8] - trans_status['esnrhighalarm_flag'] = vdm_dict['eSNR [dB]'][1][5] - trans_status['esnrlowalarm_flag'] = vdm_dict['eSNR [dB]'][1][6] - trans_status['esnrhighwarning_flag'] = vdm_dict['eSNR [dB]'][1][7] - trans_status['esnrlowwarning_flag'] = vdm_dict['eSNR [dB]'][1][8] - trans_status['cfohighalarm_flag'] = vdm_dict['CFO [MHz]'][1][5] - trans_status['cfolowalarm_flag'] = vdm_dict['CFO [MHz]'][1][6] - trans_status['cfohighwarning_flag'] = vdm_dict['CFO [MHz]'][1][7] - trans_status['cfolowwarning_flag'] = vdm_dict['CFO [MHz]'][1][8] - trans_status['txcurrpowerhighalarm_flag'] = vdm_dict['Tx Power [dBm]'][1][5] - trans_status['txcurrpowerlowalarm_flag'] = vdm_dict['Tx Power [dBm]'][1][6] - trans_status['txcurrpowerhighwarning_flag'] = vdm_dict['Tx Power [dBm]'][1][7] - trans_status['txcurrpowerlowwarning_flag'] = vdm_dict['Tx Power [dBm]'][1][8] - trans_status['rxtotpowerhighalarm_flag'] = vdm_dict['Rx Total Power [dBm]'][1][5] - trans_status['rxtotpowerlowalarm_flag'] = vdm_dict['Rx Total Power [dBm]'][1][6] - trans_status['rxtotpowerhighwarning_flag'] = vdm_dict['Rx Total Power [dBm]'][1][7] - trans_status['rxtotpowerlowwarning_flag'] = vdm_dict['Rx Total Power [dBm]'][1][8] - trans_status['rxsigpowerhighalarm_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][5] - trans_status['rxsigpowerlowalarm_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][6] - trans_status['rxsigpowerhighwarning_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][7] - trans_status['rxsigpowerlowwarning_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][8] - return trans_status - - def get_transceiver_PM(self): - """ - Retrieves PM for this xcvr - - Returns: - A dict containing the following keys/values : - ======================================================================== - key = TRANSCEIVER_PM|ifname ; information of PM on port - ; field = value - prefec_ber_avg = FLOAT ; prefec ber avg - prefec_ber_min = FLOAT ; prefec ber min - prefec_ber_max = FLOAT ; prefec ber max - uncorr_frames_avg = FLOAT ; uncorrected frames ratio avg - uncorr_frames_min = FLOAT ; uncorrected frames ratio min - uncorr_frames_max = FLOAT ; uncorrected frames ratio max - cd_avg = FLOAT ; chromatic dispersion avg - cd_min = FLOAT ; chromatic dispersion min - cd_max = FLOAT ; chromatic dispersion max - dgd_avg = FLOAT ; differential group delay avg - dgd_min = FLOAT ; differential group delay min - dgd_max = FLOAT ; differential group delay max - sopmd_avg = FLOAT ; second order polarization mode dispersion avg - sopmd_min = FLOAT ; second order polarization mode dispersion min - sopmd_max = FLOAT ; second order polarization mode dispersion max - pdl_avg = FLOAT ; polarization dependent loss avg - pdl_min = FLOAT ; polarization dependent loss min - pdl_max = FLOAT ; polarization dependent loss max - osnr_avg = FLOAT ; optical signal to noise ratio avg - osnr_min = FLOAT ; optical signal to noise ratio min - osnr_max = FLOAT ; optical signal to noise ratio max - esnr_avg = FLOAT ; electrical signal to noise ratio avg - esnr_min = FLOAT ; electrical signal to noise ratio min - esnr_max = FLOAT ; electrical signal to noise ratio max - cfo_avg = FLOAT ; carrier frequency offset avg - cfo_min = FLOAT ; carrier frequency offset min - cfo_max = FLOAT ; carrier frequency offset max - soproc_avg = FLOAT ; state of polarization rate of change avg - soproc_min = FLOAT ; state of polarization rate of change min - soproc_max = FLOAT ; state of polarization rate of change max - tx_power_avg = FLOAT ; tx output power avg - tx_power_min = FLOAT ; tx output power min - tx_power_max = FLOAT ; tx output power max - rx_tot_power_avg = FLOAT ; rx total power avg - rx_tot_power_min = FLOAT ; rx total power min - rx_tot_power_max = FLOAT ; rx total power max - rx_sig_power_avg = FLOAT ; rx signal power avg - rx_sig_power_min = FLOAT ; rx signal power min - rx_sig_power_max = FLOAT ; rx signal power max - ======================================================================== - """ - trans_pm = dict() - PM_dict = self.get_PM() - trans_pm['prefec_ber_avg'] = PM_dict['preFEC_BER_avg'] - trans_pm['prefec_ber_min'] = PM_dict['preFEC_BER_min'] - trans_pm['prefec_ber_max'] = PM_dict['preFEC_BER_max'] - trans_pm['uncorr_frames_avg'] = PM_dict['preFEC_uncorr_frame_ratio_avg'] - trans_pm['uncorr_frames_min'] = PM_dict['preFEC_uncorr_frame_ratio_min'] - trans_pm['uncorr_frames_max'] = PM_dict['preFEC_uncorr_frame_ratio_max'] - trans_pm['cd_avg'] = PM_dict['rx_cd_avg'] - trans_pm['cd_min'] = PM_dict['rx_cd_min'] - trans_pm['cd_max'] = PM_dict['rx_cd_max'] - trans_pm['dgd_avg'] = PM_dict['rx_dgd_avg'] - trans_pm['dgd_min'] = PM_dict['rx_dgd_min'] - trans_pm['dgd_max'] = PM_dict['rx_dgd_max'] - trans_pm['sopmd_avg'] = PM_dict['rx_sopmd_avg'] - trans_pm['sopmd_min'] = PM_dict['rx_sopmd_min'] - trans_pm['sopmd_max'] = PM_dict['rx_sopmd_max'] - trans_pm['pdl_avg'] = PM_dict['rx_pdl_avg'] - trans_pm['pdl_min'] = PM_dict['rx_pdl_min'] - trans_pm['pdl_max'] = PM_dict['rx_pdl_max'] - trans_pm['osnr_avg'] = PM_dict['rx_osnr_avg'] - trans_pm['osnr_min'] = PM_dict['rx_osnr_min'] - trans_pm['osnr_max'] = PM_dict['rx_osnr_max'] - trans_pm['esnr_avg'] = PM_dict['rx_esnr_avg'] - trans_pm['esnr_min'] = PM_dict['rx_esnr_min'] - trans_pm['esnr_max'] = PM_dict['rx_esnr_max'] - trans_pm['cfo_avg'] = PM_dict['rx_cfo_avg'] - trans_pm['cfo_min'] = PM_dict['rx_cfo_min'] - trans_pm['cfo_max'] = PM_dict['rx_cfo_max'] - trans_pm['soproc_avg'] = PM_dict['rx_soproc_avg'] - trans_pm['soproc_min'] = PM_dict['rx_soproc_min'] - trans_pm['soproc_max'] = PM_dict['rx_soproc_max'] - trans_pm['tx_power_avg'] = PM_dict['tx_power_avg'] - trans_pm['tx_power_min'] = PM_dict['tx_power_min'] - trans_pm['tx_power_max'] = PM_dict['tx_power_max'] - trans_pm['rx_tot_power_avg'] = PM_dict['rx_power_avg'] - trans_pm['rx_tot_power_min'] = PM_dict['rx_power_min'] - trans_pm['rx_tot_power_max'] = PM_dict['rx_power_max'] - trans_pm['rx_sig_power_avg'] = PM_dict['rx_sigpwr_avg'] - trans_pm['rx_sig_power_min'] = PM_dict['rx_sigpwr_min'] - trans_pm['rx_sig_power_max'] = PM_dict['rx_sigpwr_max'] - return trans_pm - - def get_transceiver_loopback(self): - """ - Retrieves loopback mode for this xcvr - - Returns: - A dict containing the following keys/values : - ======================================================================== - key = TRANSCEIVER_PM|ifname ; information of loopback on port - ; field = value - media_output_loopback = BOOLEAN ; media side output loopback enable - media_input_loopback = BOOLEAN ; media side input loopback enable - host_output_loopback_lane1 = BOOLEAN ; host side output loopback enable lane1 - host_output_loopback_lane2 = BOOLEAN ; host side output loopback enable lane2 - host_output_loopback_lane3 = BOOLEAN ; host side output loopback enable lane3 - host_output_loopback_lane4 = BOOLEAN ; host side output loopback enable lane4 - host_output_loopback_lane5 = BOOLEAN ; host side output loopback enable lane5 - host_output_loopback_lane6 = BOOLEAN ; host side output loopback enable lane6 - host_output_loopback_lane7 = BOOLEAN ; host side output loopback enable lane7 - host_output_loopback_lane8 = BOOLEAN ; host side output loopback enable lane8 - host_input_loopback_lane1 = BOOLEAN ; host side input loopback enable lane1 - host_input_loopback_lane2 = BOOLEAN ; host side input loopback enable lane2 - host_input_loopback_lane3 = BOOLEAN ; host side input loopback enable lane3 - host_input_loopback_lane4 = BOOLEAN ; host side input loopback enable lane4 - host_input_loopback_lane5 = BOOLEAN ; host side input loopback enable lane5 - host_input_loopback_lane6 = BOOLEAN ; host side input loopback enable lane6 - host_input_loopback_lane7 = BOOLEAN ; host side input loopback enable lane7 - host_input_loopback_lane8 = BOOLEAN ; host side input loopback enable lane8 - ======================================================================== - """ - trans_loopback = dict() - trans_loopback['media_output_loopback'] = self.get_media_output_loopback() - trans_loopback['media_input_loopback'] = self.get_media_input_loopback() - host_output_loopback_status = self.get_host_output_loopback() - trans_loopback['host_output_loopback_lane1'] = host_output_loopback_status[0] - trans_loopback['host_output_loopback_lane2'] = host_output_loopback_status[1] - trans_loopback['host_output_loopback_lane3'] = host_output_loopback_status[2] - trans_loopback['host_output_loopback_lane4'] = host_output_loopback_status[3] - trans_loopback['host_output_loopback_lane5'] = host_output_loopback_status[4] - trans_loopback['host_output_loopback_lane6'] = host_output_loopback_status[5] - trans_loopback['host_output_loopback_lane7'] = host_output_loopback_status[6] - trans_loopback['host_output_loopback_lane8'] = host_output_loopback_status[7] - host_input_loopback_status = self.get_host_input_loopback() - trans_loopback['host_input_loopback_lane1'] = host_input_loopback_status[0] - trans_loopback['host_input_loopback_lane2'] = host_input_loopback_status[1] - trans_loopback['host_input_loopback_lane3'] = host_input_loopback_status[2] - trans_loopback['host_input_loopback_lane4'] = host_input_loopback_status[3] - trans_loopback['host_input_loopback_lane5'] = host_input_loopback_status[4] - trans_loopback['host_input_loopback_lane6'] = host_input_loopback_status[5] - trans_loopback['host_input_loopback_lane7'] = host_input_loopback_status[6] - trans_loopback['host_input_loopback_lane8'] = host_input_loopback_status[7] - return trans_loopback + logger.info('Not both images are valid.') # TODO: other XcvrApi methods diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py index 872427cf2..3928330f0 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py @@ -1,8 +1,17 @@ +""" + cmisCDB.py + + Implementation of APIs related to CDB commands +""" +import logging from ...fields import consts from ..xcvr_api import XcvrApi import struct import time +logger = logging.getLogger(__name__) +logger.addHandler(logging.NullHandler()) + LPLPAGE = 0x9f CDB_RPL_OFFSET = 136 CDB_WRITE_MSG_START = 130 @@ -121,8 +130,8 @@ def write_cdb(self, cmd): ''' This function writes a CDB command to page 0x9f ''' - self.xcvr_eeprom.write_flexible(LPLPAGE*PAGE_LENGTH+CDB_WRITE_MSG_START, len(cmd)-CMDLEN, cmd[CMDLEN:]) - self.xcvr_eeprom.write_flexible(LPLPAGE*PAGE_LENGTH+INIT_OFFSET, CMDLEN, cmd[:CMDLEN]) + self.xcvr_eeprom.write_raw(LPLPAGE*PAGE_LENGTH+CDB_WRITE_MSG_START, len(cmd)-CMDLEN, cmd[CMDLEN:]) + self.xcvr_eeprom.write_raw(LPLPAGE*PAGE_LENGTH+INIT_OFFSET, CMDLEN, cmd[:CMDLEN]) def read_cdb(self): ''' @@ -130,7 +139,7 @@ def read_cdb(self): ''' rpllen = self.xcvr_eeprom.read(consts.CDB_RPL_LENGTH) rpl_chkcode = self.xcvr_eeprom.read(consts.CDB_RPL_CHKCODE) - rpl = self.xcvr_eeprom.read_flexible(LPLPAGE*PAGE_LENGTH+CDB_RPL_OFFSET, rpllen) + rpl = self.xcvr_eeprom.read_raw(LPLPAGE*PAGE_LENGTH+CDB_RPL_OFFSET, rpllen) return rpllen, rpl_chkcode, rpl # Query status @@ -142,7 +151,7 @@ def cmd0000h(self): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break @@ -157,13 +166,16 @@ def cmd0001h(self): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break return status def cmd0040h(self): + ''' + This command is used to query which CDB commands are supported + ''' cmd = bytearray(b'\x00\x40\x00\x00\x00\x00\x00\x00') cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): @@ -171,7 +183,7 @@ def cmd0040h(self): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break @@ -179,6 +191,9 @@ def cmd0040h(self): # Firmware Update Features Supported def cmd0041h(self): + ''' + This command is used to query supported firmware update features + ''' cmd = bytearray(b'\x00\x41\x00\x00\x00\x00\x00\x00') cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): @@ -186,7 +201,7 @@ def cmd0041h(self): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break @@ -194,6 +209,10 @@ def cmd0041h(self): # Get FW info def cmd0100h(self): + ''' + This command returns the firmware versions and firmware default running + images that reside in the module + ''' cmd = bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00') cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): @@ -201,7 +220,7 @@ def cmd0100h(self): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break @@ -209,7 +228,10 @@ def cmd0100h(self): # Start FW download def cmd0101h(self, startLPLsize, header, imagesize): - print("Image size is {}".format(imagesize)) + ''' + This command starts the firmware download + ''' + logger.info("Image size is {}".format(imagesize)) cmd = bytearray(b'\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') cmd[132-INIT_OFFSET] = startLPLsize + 8 cmd[136-INIT_OFFSET] = (imagesize >> 24) & 0xff @@ -220,10 +242,10 @@ def cmd0101h(self, startLPLsize, header, imagesize): cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): self.write_cdb(cmd) - time.sleep(2) + time.sleep(10) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break @@ -231,6 +253,9 @@ def cmd0101h(self, startLPLsize, header, imagesize): # Abort FW download def cmd0102h(self): + ''' + This command aborts the firmware download + ''' cmd = bytearray(b'\x01\x02\x00\x00\x00\x00\x00\x00') cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): @@ -238,7 +263,7 @@ def cmd0102h(self): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break @@ -246,6 +271,9 @@ def cmd0102h(self): # Download FW with LPL def cmd0103h(self, addr, data): + ''' + This command writes one block of the firmware image into the LPL + ''' # lpl_len includes 136-139, four bytes, data is 116-byte long. lpl_len = len(data) + 4 cmd = bytearray(b'\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') @@ -263,7 +291,7 @@ def cmd0103h(self, addr, data): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break @@ -271,6 +299,9 @@ def cmd0103h(self, addr, data): # Download FW with EPL def cmd0104h(self, addr, data, autopaging_flag, writelength): + ''' + This command writes one block of the firmware image into the EPL + ''' epl_len = 2048 subtime = time.time() if not autopaging_flag: @@ -282,10 +313,10 @@ def cmd0104h(self, addr, data, autopaging_flag, writelength): next_page = 0xa0 + pageoffset if PAGE_LENGTH*(pageoffset + 1) <= epl_len: datachunk = data[PAGE_LENGTH*pageoffset : PAGE_LENGTH*(pageoffset + 1)] - self.xcvr_eeprom.write_flexible(next_page*PAGE_LENGTH+INIT_OFFSET, PAGE_LENGTH, datachunk) + self.xcvr_eeprom.write_raw(next_page*PAGE_LENGTH+INIT_OFFSET, PAGE_LENGTH, datachunk) else: datachunk = data[INIT_OFFSET*pageoffset : ] - self.xcvr_eeprom.write_flexible(next_page*PAGE_LENGTH+INIT_OFFSET, len(datachunk), datachunk) + self.xcvr_eeprom.write_raw(next_page*PAGE_LENGTH+INIT_OFFSET, len(datachunk), datachunk) else: sections = epl_len // writelength if (epl_len % writelength) != 0: @@ -294,12 +325,12 @@ def cmd0104h(self, addr, data, autopaging_flag, writelength): for offset in range(0, epl_len, writelength): if offset + writelength <= epl_len: datachunk = data[offset : offset + writelength] - self.xcvr_eeprom.write_flexible(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, writelength, datachunk) + self.xcvr_eeprom.write_raw(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, writelength, datachunk) else: datachunk = data[offset : ] - self.xcvr_eeprom.write_flexible(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, len(datachunk), datachunk) + self.xcvr_eeprom.write_raw(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, len(datachunk), datachunk) subtimeint = time.time()-subtime - print('2048B write time: %.2fs' %subtimeint) + logger.info('2048B write time: %.2fs' %subtimeint) cmd = bytearray(b'\x01\x04\x08\x00\x04\x00\x00\x00') addr_byte = struct.pack('>L',addr) cmd += addr_byte @@ -309,13 +340,18 @@ def cmd0104h(self, addr, data, autopaging_flag, writelength): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break return status + # FW download complete def cmd0107h(self): + ''' + When this command is issued, the module shall validate the complete + image and then return success or failure + ''' cmd = bytearray(b'\x01\x07\x00\x00\x00\x00\x00\x00') cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): @@ -323,7 +359,7 @@ def cmd0107h(self): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) continue else: break @@ -336,6 +372,9 @@ def cmd0107h(self): # 02h = Traffic affecting Reset to Running Image. # 03h = Attempt Hitless Reset to Running Image def cmd0109h(self, mode = 0x01): + ''' + The host uses this command to run a selected image from module internal firmware banks + ''' cmd = bytearray(b'\x01\x09\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00') cmd[137-INIT_OFFSET] = mode cmd[138-INIT_OFFSET] = 2 # Delay to Reset 512 ms @@ -345,7 +384,9 @@ def cmd0109h(self, mode = 0x01): time.sleep(2) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) + if status == 0x46 and self.password_type == 'msaPassword': + self.xcvr_eeprom.write_raw(122, 4, b'\x00\x00\x10\x11') continue else: break @@ -353,14 +394,27 @@ def cmd0109h(self, mode = 0x01): # Commit FW image def cmd010Ah(self): + ''' + A Commit is the process where the running image is set to be the image to be used on exit from module + reset. In other words, a committed image is the image that will run and is expected to be a 'good' firmware + version to run upon any resets (including watch dog). + + This command is used to switch the committed image after the firmware update process, when the new + firmware is running and when the host has determined that the new firmware is working properly. The module + shall only execute a Commit Image command on the image that it is currently running. If a non-running image + is allowed to be committed, it is possible that a bad version may be committed and attempted to run after the + next module reset. + ''' cmd = bytearray(b'\x01\x0A\x00\x00\x00\x00\x00\x00') cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): self.write_cdb(cmd) - time.sleep(2) + time.sleep(5) status = self.cdb1_chkstatus() if (status != 0x1): - print('CDB1 status: Fail. CDB1 status %d' %status) + logger.info('CDB1 status: Fail. CDB1 status %d' %status) + if status == 0x46 and self.password_type == 'msaPassword': + self.xcvr_eeprom.write_raw(122, 4, b'\x00\x00\x10\x11') continue else: break diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py index 05a2de767..8a0b189cf 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py @@ -19,23 +19,23 @@ def get_F16(self, value): result = mantissa*10**(scale_exponent-24) return result - def get_VDM_page(self, page, VDM_flag_page): + def get_vdm_page(self, page, VDM_flag_page): if page not in [0x20, 0x21, 0x22, 0x23]: raise ValueError('Page not in VDM Descriptor range!') - VDM_descriptor = self.xcvr_eeprom.read_flexible(page * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) + vdm_descriptor = self.xcvr_eeprom.read_raw(page * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) # Odd Adress VDM observable type ID, real-time monitored value in Page + 4 - VDM_typeID = VDM_descriptor[1::2] + vdm_typeID = vdm_descriptor[1::2] # Even Address # Bit 7-4: Threshold set ID in Page + 8, in group of 8 bytes, 16 sets/page # Bit 3-0: n. Monitored lane n+1 - VDM_lane = [(elem & 0xf) for elem in VDM_descriptor[0::2]] - VDM_thresholdID = [(elem>>4) for elem in VDM_descriptor[0::2]] - VDM_valuePage = page + 4 - VDM_thrshPage = page + 8 - VDM_Page_data = {} - VDM_TYPE_DICT = self.xcvr_eeprom.mem_map.codes['cmis_code'].VDM_TYPE - for index, typeID in enumerate(VDM_typeID): + vdm_lane = [(elem & 0xf) for elem in vdm_descriptor[0::2]] + VDM_thresholdID = [(elem>>4) for elem in vdm_descriptor[0::2]] + vdm_valuePage = page + 4 + vdm_thrshPage = page + 8 + vdm_Page_data = {} + VDM_TYPE_DICT = self.xcvr_eeprom.mem_map.codes.VDM_TYPE + for index, typeID in enumerate(vdm_typeID): if typeID not in VDM_TYPE_DICT: continue else: @@ -45,17 +45,17 @@ def get_VDM_page(self, page, VDM_flag_page): vdm_format = vdm_info_dict[1] scale = vdm_info_dict[2] - vdm_value_offset = VDM_valuePage * PAGE_SIZE + PAGE_OFFSET + VDM_SIZE * index - vdm_high_alarm_offset = VDM_thrshPage * PAGE_SIZE + PAGE_OFFSET + THRSH_SPACING * thrshID + vdm_value_offset = vdm_valuePage * PAGE_SIZE + PAGE_OFFSET + VDM_SIZE * index + vdm_high_alarm_offset = vdm_thrshPage * PAGE_SIZE + PAGE_OFFSET + THRSH_SPACING * thrshID vdm_low_alarm_offset = vdm_high_alarm_offset + 2 vdm_high_warn_offset = vdm_high_alarm_offset + 4 vdm_low_warn_offset = vdm_high_alarm_offset + 6 - vdm_value_raw = self.xcvr_eeprom.read_flexible(vdm_value_offset, VDM_SIZE, True) - vdm_thrsh_high_alarm_raw = self.xcvr_eeprom.read_flexible(vdm_high_alarm_offset, VDM_SIZE, True) - vdm_thrsh_low_alarm_raw = self.xcvr_eeprom.read_flexible(vdm_low_alarm_offset, VDM_SIZE, True) - vdm_thrsh_high_warn_raw = self.xcvr_eeprom.read_flexible(vdm_high_warn_offset, VDM_SIZE, True) - vdm_thrsh_low_warn_raw = self.xcvr_eeprom.read_flexible(vdm_low_warn_offset, VDM_SIZE, True) + vdm_value_raw = self.xcvr_eeprom.read_raw(vdm_value_offset, VDM_SIZE, True) + vdm_thrsh_high_alarm_raw = self.xcvr_eeprom.read_raw(vdm_high_alarm_offset, VDM_SIZE, True) + vdm_thrsh_low_alarm_raw = self.xcvr_eeprom.read_raw(vdm_low_alarm_offset, VDM_SIZE, True) + vdm_thrsh_high_warn_raw = self.xcvr_eeprom.read_raw(vdm_high_warn_offset, VDM_SIZE, True) + vdm_thrsh_low_warn_raw = self.xcvr_eeprom.read_raw(vdm_low_warn_offset, VDM_SIZE, True) if vdm_format == 'S16': vdm_value = struct.unpack('>h',vdm_value_raw)[0] * scale vdm_thrsh_high_alarm = struct.unpack('>h', vdm_thrsh_high_alarm_raw)[0] * scale @@ -89,9 +89,9 @@ def get_VDM_page(self, page, VDM_flag_page): vdm_high_warn_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset+2)) & 0x1) vdm_low_warn_flag = bool((VDM_flag_page[vdm_flag_offset] >> (bit_offset+3)) & 0x1) - if vdm_type not in VDM_Page_data: - VDM_Page_data[vdm_type] = { - VDM_lane[index]+1: [ + if vdm_type not in vdm_Page_data: + vdm_Page_data[vdm_type] = { + vdm_lane[index]+1: [ vdm_value, vdm_thrsh_high_alarm, vdm_thrsh_low_alarm, @@ -104,7 +104,7 @@ def get_VDM_page(self, page, VDM_flag_page): } else: - VDM_Page_data[vdm_info_dict[0]][VDM_lane[index]+1] = [ + vdm_Page_data[vdm_info_dict[0]][vdm_lane[index]+1] = [ vdm_value, vdm_thrsh_high_alarm, vdm_thrsh_low_alarm, @@ -114,18 +114,18 @@ def get_VDM_page(self, page, VDM_flag_page): vdm_low_alarm_flag, vdm_high_warn_flag, vdm_low_warn_flag] - return VDM_Page_data + return vdm_Page_data - def get_VDM_allpage(self): + def get_vdm_allpage(self): vdm_page_supported_raw = self.xcvr_eeprom.read(consts.VDM_SUPPORTED_PAGE) & 0x3 VDM_START_PAGE = 0x20 - VDM = dict() + vdm = dict() self.xcvr_eeprom.write(consts.VDM_CONTROL, 128) time.sleep(5) self.xcvr_eeprom.write(consts.VDM_CONTROL, 0) time.sleep(1) - VDM_flag_page = self.xcvr_eeprom.read_flexible(VDM_FLAG_PAGE * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) + vdm_flag_page = self.xcvr_eeprom.read_raw(VDM_FLAG_PAGE * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) for page in range(VDM_START_PAGE, VDM_START_PAGE + vdm_page_supported_raw + 1): - VDM_current_page = self.get_VDM_page(page, VDM_flag_page) - VDM.update(VDM_current_page) - return VDM \ No newline at end of file + vdm_current_page = self.get_vdm_page(page, vdm_flag_page) + vdm.update(vdm_current_page) + return vdm \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py b/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py index 2beaecbe7..176a49b84 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/cmis_code.py @@ -3,9 +3,9 @@ Implementation of dictionaries used in CMIS """ -from ..xcvr_codes import XcvrCodes +from .sff8024 import Sff8024 -class CmisCode(XcvrCodes): +class CmisCode(Sff8024): MEDIA_INTERFACE_TECH = { 0: '850 nm VCSEL', 1: '1310 nm VCSEL', 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 681c6cc86..6f95d5bc0 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -26,21 +26,21 @@ def __init__(self, codes): super(CmisMemMap, self).__init__(codes) self.ADMIN_INFO = RegGroupField(consts.ADMIN_INFO_FIELD, - CodeRegField(consts.ID_FIELD, get_addr(0x0, 128), self.codes['sff8024'].XCVR_IDENTIFIERS), + CodeRegField(consts.ID_FIELD, get_addr(0x0, 128), self.codes.XCVR_IDENTIFIERS), StringRegField(consts.VENDOR_NAME_FIELD, get_addr(0x0, 129), size=16), HexRegField(consts.VENDOR_OUI_FIELD, get_addr(0x0, 145), size=3), StringRegField(consts.VENDOR_PART_NO_FIELD, get_addr(0x0, 148), size=16), StringRegField(consts.VENDOR_REV_FIELD, get_addr(0x0, 164), size=2), StringRegField(consts.VENDOR_SERIAL_NO_FIELD, get_addr(0x0, 166), size=16), StringRegField(consts.VENDOR_DATE_FIELD,get_addr(0x0,182), size = 8), - CodeRegField(consts.CONNECTOR_FIELD, get_addr(0x0, 203), self.codes['sff8024'].CONNECTORS), - CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, get_addr(0x0, 86), self.codes['sff8024'].HOST_ELECTRICAL_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_TYPE, get_addr(0x0, 85), self.codes['sff8024'].MODULE_MEDIA_TYPE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, get_addr(0x0, 87), self.codes['sff8024'].NM_850_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_SM, get_addr(0x0, 87), self.codes['sff8024'].SM_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, get_addr(0x0, 87), self.codes['sff8024'].PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, get_addr(0x0, 87), self.codes['sff8024'].ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, get_addr(0x0, 87), self.codes['sff8024'].BASE_T_MEDIA_INTERFACE), + CodeRegField(consts.CONNECTOR_FIELD, get_addr(0x0, 203), self.codes.CONNECTORS), + CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, get_addr(0x0, 86), self.codes.HOST_ELECTRICAL_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_TYPE, get_addr(0x0, 85), self.codes.MODULE_MEDIA_TYPE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, get_addr(0x0, 87), self.codes.NM_850_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_SM, get_addr(0x0, 87), self.codes.SM_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, get_addr(0x0, 87), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, get_addr(0x0, 87), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, get_addr(0x0, 87), self.codes.BASE_T_MEDIA_INTERFACE), NumberRegField(consts.LANE_COUNT, get_addr(0x0, 88), format="B", size=1), NumberRegField(consts.HOST_LANE_ASSIGNMENT_OPTION, get_addr(0x0, 89), format="B", size=1), NumberRegField(consts.MEDIA_LANE_ASSIGNMENT_OPTION, get_addr(0x1, 176), format="B", size=1), @@ -52,7 +52,7 @@ def __init__(self, codes): NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_6, get_addr(0x11, 211), format="B", size=1), NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_7, get_addr(0x11, 212), format="B", size=1), NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_8, get_addr(0x11, 213), format="B", size=1), - CodeRegField(consts.MEDIA_INTERFACE_TECH, get_addr(0x0, 212), self.codes['cmis_code'].MEDIA_INTERFACE_TECH), + CodeRegField(consts.MEDIA_INTERFACE_TECH, get_addr(0x0, 212), self.codes.MEDIA_INTERFACE_TECH), NumberRegField(consts.HW_MAJOR_REV, get_addr(0x1, 130), size=1), NumberRegField(consts.HW_MINOR_REV, get_addr(0x1, 131), size=1), NumberRegField(consts.CMIS_REVISION, get_addr(0x0, 1), format="B", size=1), @@ -135,7 +135,7 @@ def __init__(self, codes): NumberRegField(consts.MODULE_FLAG_BYTE2, get_addr(0x0, 10), size=1), NumberRegField(consts.MODULE_FLAG_BYTE3, get_addr(0x0, 11), size=1), NumberRegField(consts.CDB1_STATUS, get_addr(0x0, 37), size=1), - CodeRegField(consts.MODULE_FAULT_CAUSE, get_addr(0x0, 41), self.codes['cmis_code'].MODULE_FAULT_CAUSE), + CodeRegField(consts.MODULE_FAULT_CAUSE, get_addr(0x0, 41), self.codes.MODULE_FAULT_CAUSE), ) self.TRANS_LANE_STATUS = RegGroupField(consts.TRANS_LANE_STATUS_FIELD, @@ -241,8 +241,5 @@ def __init__(self, codes): NumberRegField(consts.CDB_SEQ_WRITE_LENGTH_EXT, get_addr(0x01, 164), size=1), NumberRegField(consts.CDB_RPL_LENGTH, get_addr(0x9f, 134), size=1, ro=False), NumberRegField(consts.CDB_RPL_CHKCODE, get_addr(0x9f, 135), size=1, ro=False), - ListRegField(consts.CDB_LPL, get_addr(0x9f, 136), format='120B', size=120, ro=False), - ListRegField(consts.CDB_CMD, get_addr(0x9f, 128), format='2B', size=2, ro=False), - ListRegField(consts.CDB_WRITE_MSG, get_addr(0x9f, 130), format='126B', size=126, ro=False), ) # TODO: add remaining fields diff --git a/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py b/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py index 3e7ac01f0..1306017da 100644 --- a/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py +++ b/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py @@ -10,6 +10,7 @@ from .codes.public.sff8024 import Sff8024 from .codes.public.cmis_code import CmisCode from .api.public.cmis import CmisApi +from .api.public.c_cmis import CCmisApi from .mem_maps.public.cmis import CmisMemMap from .codes.public.sff8436 import Sff8436Codes @@ -20,6 +21,8 @@ from .api.public.sff8636 import Sff8636Api from .mem_maps.public.sff8636 import Sff8636MemMap +ZR_MEDIA_INTERFACE_CODE = [62, 63, 70, 71, 72, 73] + class XcvrApiFactory(object): def __init__(self, reader, writer): self.reader = reader @@ -30,16 +33,34 @@ def _get_id(self): if id_byte_raw is None: return None return id_byte_raw[0] + + def _get_module_type(self): + module_type = self.reader(85, 1) + if module_type is None: + return None + return module_type[0] + + def _get_module_media_interface(self): + module_media_interface = self.reader(87, 1) + if module_media_interface is None: + return None + return module_media_interface[0] def create_xcvr_api(self): # TODO: load correct classes from id_mapping file id = self._get_id() # QSFP-DD or OSFP if id == 0x18 or id == 0x19: - codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + codes = CmisCode mem_map = CmisMemMap(codes) xcvr_eeprom = XcvrEeprom(self.reader, self.writer, mem_map) - api = CmisApi(xcvr_eeprom) + + module_type = self._get_module_type() + module_media_interface = self._get_module_media_interface() + if (module_type == 2) and (module_media_interface in ZR_MEDIA_INTERFACE_CODE): + api = CCmisApi(xcvr_eeprom) + else: + api = CmisApi(xcvr_eeprom) # QSFP28 elif id == 0x11: codes = Sff8636Codes diff --git a/sonic_platform_base/sonic_xcvr/xcvr_eeprom.py b/sonic_platform_base/sonic_xcvr/xcvr_eeprom.py index 607eb0197..20712b777 100644 --- a/sonic_platform_base/sonic_xcvr/xcvr_eeprom.py +++ b/sonic_platform_base/sonic_xcvr/xcvr_eeprom.py @@ -25,7 +25,7 @@ def read(self, field_name): raw_data = self.reader(field.get_offset(), field.get_size()) return field.decode(raw_data) if raw_data else None - def read_flexible(self, offset, size, return_raw = False): + def read_raw(self, offset, size, return_raw = False): """ Read values from a field in EEPROM in a more flexible way @@ -38,10 +38,10 @@ def read_flexible(self, offset, size, return_raw = False): The value(s) of the field, if the read is successful and None otherwise """ raw_data = self.reader(offset, size) - if return_raw: - return raw_data if raw_data is None: return None + if return_raw: + return raw_data else: if size == 1: data = struct.unpack("%dB" %size, raw_data)[0] @@ -69,7 +69,7 @@ def write(self, field_name, value): encoded_data = field.encode(value) return self.writer(field.get_offset(), field.get_size(), encoded_data) - def write_flexible(self, offset, size, bytearray_data): + def write_raw(self, offset, size, bytearray_data): """ Write values to a field in EEPROM in a more flexible way @@ -79,7 +79,7 @@ def write_flexible(self, offset, size, bytearray_data): size: an integer indicating how many bytes to write to - bytearray_data: a bytearray as write bugger to be written into EEPROM + bytearray_data: a bytearray as write buffer to be written into EEPROM Returns: Boolean, True if the write is successful and False otherwise diff --git a/tests/sonic_xcvr/test_ccmis.py b/tests/sonic_xcvr/test_ccmis.py index d99875792..9009c2070 100644 --- a/tests/sonic_xcvr/test_ccmis.py +++ b/tests/sonic_xcvr/test_ccmis.py @@ -1,6 +1,5 @@ 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.c_cmis import CCmisApi from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom @@ -10,14 +9,106 @@ class TestCCmis(object): def mock_ccmis_api(self): - codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + codes = CmisCode mem_map = CmisMemMap(codes) reader = MagicMock(return_value=None) writer = MagicMock() xcvr_eeprom = XcvrEeprom(reader, writer, mem_map) - api = CmisApi(xcvr_eeprom) - api.ccmis = CCmisApi(xcvr_eeprom) - return api.ccmis + api = CCmisApi(xcvr_eeprom) + return api + + @pytest.mark.parametrize("mock_response, expected", [ + (0x70, 75), + (0x60, 33), + (0x50, 100), + (0x40, 50), + (0x30, 25), + (0x20, 12.5), + (0x10, 6.25), + (0x0, 3.125), + ]) + def test_get_freq_grid(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.xcvr_eeprom.read = MagicMock() + ccmis.xcvr_eeprom.read.return_value = mock_response + result = ccmis.get_freq_grid() + assert result == expected + + @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ + (75, 12, 193400), + (75, -30, 192350), + (100, 10, 194100), + ]) + def test_get_laser_config_freq(self, mock_response1, mock_response2, expected): + ccmis = self.mock_ccmis_api() + ccmis.get_freq_grid = MagicMock() + ccmis.get_freq_grid.return_value = mock_response1 + ccmis.xcvr_eeprom.read = MagicMock() + ccmis.xcvr_eeprom.read.return_value = mock_response2 + result = ccmis.get_laser_config_freq() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (193100000, 193100) + ]) + def test_get_current_laser_freq(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.xcvr_eeprom.read = MagicMock() + ccmis.xcvr_eeprom.read.return_value = mock_response + result = ccmis.get_current_laser_freq() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False) + ]) + def test_get_tuning_in_progress(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.xcvr_eeprom.read = MagicMock() + ccmis.xcvr_eeprom.read.return_value = mock_response + result = ccmis.get_tuning_in_progress() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (0, False) + ]) + def test_get_wavelength_unlocked(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.xcvr_eeprom.read = MagicMock() + ccmis.xcvr_eeprom.read.return_value = mock_response + result = ccmis.get_wavelength_unlocked() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + (1, ['TuningComplete']), + (62, ['TargetOutputPowerOOR', 'FineTuningOutOfRange', 'TuningNotAccepted', + 'InvalidChannel', 'WavelengthUnlocked']), + ]) + def test_get_laser_tuning_summary(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.xcvr_eeprom.read = MagicMock() + ccmis.xcvr_eeprom.read.return_value = mock_response + result = ccmis.get_laser_tuning_summary() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ([190, -72, 120], (190, -72, 120, 191300, 196100)) + ]) + def test_get_supported_freq_config(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.xcvr_eeprom.read = MagicMock() + ccmis.xcvr_eeprom.read.side_effect = mock_response + result = ccmis.get_supported_freq_config() + assert result == expected + + @pytest.mark.parametrize("input_param, mock_response",[ + (193100, (0xff, -72, 120, 191300, 196100)), + (195950, (0xff, -72, 120, 191300, 196100)), + ]) + def test_set_laser_freq(self, input_param, mock_response): + ccmis = self.mock_ccmis_api() + ccmis.get_supported_freq_config = MagicMock() + ccmis.get_supported_freq_config.return_value = mock_response + ccmis.set_laser_freq(input_param) @pytest.mark.parametrize("mock_response, expected", [ ( @@ -57,10 +148,649 @@ def mock_ccmis_api(self): } ) ]) - def test_get_PM_all(self, mock_response, expected): + def test_get_pm_all(self, mock_response, expected): ccmis = self.mock_ccmis_api() ccmis.xcvr_eeprom.read = MagicMock() ccmis.xcvr_eeprom.read.side_effect = mock_response - result = ccmis.get_PM_all() + result = ccmis.get_pm_all() + assert result == expected + + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + 'Single Mode Fiber (SMF)', + '400GAUI-8 C2M (Annex 120E)', + '400ZR, DWDM, amplified', + 8, 1, 1, 1, + {'hostlane1': 1, 'hostlane2': 1, 'hostlane3': 1, 'hostlane4': 1, + 'hostlane5': 1, 'hostlane6': 1, 'hostlane7': 1, 'hostlane8': 1}, + '1550 nm DFB', + '0.0', + '00000000', + 'VENDOR_NAME', + '0.0', + 'xx-xx-xx', + '21010100', + 'LC', + '5.0', + '0.1', + '0.0', + (-20, 0), + (0xff, -72, 120, 191300, 196100) + ], + { + 'active_firmware': '0.1', + 'media_lane_count': 1, + 'supported_min_laser_freq': 191300, + 'inactive_firmware': '0.0', + 'vendor_rev': '0.0', + 'host_electrical_interface': '400GAUI-8 C2M (Annex 120E)', + 'vendor_oui': 'xx-xx-xx', + 'manufacturename': 'VENDOR_NAME', + 'media_interface_technology': '1550 nm DFB', + 'media_interface_code': '400ZR, DWDM, amplified', + 'serialnum': '00000000', + 'module_media_type': 'Single Mode Fiber (SMF)', + 'host_lane_count': 8, + 'active_apsel_hostlane1': 1, + 'active_apsel_hostlane3': 1, + 'active_apsel_hostlane2': 1, + 'active_apsel_hostlane5': 1, + 'active_apsel_hostlane4': 1, + 'active_apsel_hostlane7': 1, + 'active_apsel_hostlane6': 1, + 'supported_max_laser_freq': 196100, + 'active_apsel_hostlane8': 1, + 'hardwarerev': '0.0', + 'specification_compliance': '5.0', + 'media_lane_assignment_option': 1, + 'connector_type': 'LC', + 'host_lane_assignment_option': 1, + 'supported_max_tx_power': 0, + 'supported_min_tx_power': -20, + 'vendor_date': '21010100' + } + ) + ]) + def test_get_transceiver_info(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.get_module_media_type = MagicMock() + ccmis.get_module_media_type.return_value = mock_response[0] + ccmis.get_host_electrical_interface = MagicMock() + ccmis.get_host_electrical_interface.return_value = mock_response[1] + ccmis.get_module_media_interface = MagicMock() + ccmis.get_module_media_interface.return_value = mock_response[2] + ccmis.get_host_lane_count = MagicMock() + ccmis.get_host_lane_count.return_value = mock_response[3] + ccmis.get_media_lane_count = MagicMock() + ccmis.get_media_lane_count.return_value = mock_response[4] + ccmis.get_host_lane_assignment_option = MagicMock() + ccmis.get_host_lane_assignment_option.return_value = mock_response[5] + ccmis.get_media_lane_assignment_option = MagicMock() + ccmis.get_media_lane_assignment_option.return_value = mock_response[6] + ccmis.get_active_apsel_hostlane = MagicMock() + ccmis.get_active_apsel_hostlane.return_value = mock_response[7] + ccmis.get_media_interface_technology = MagicMock() + ccmis.get_media_interface_technology.return_value = mock_response[8] + ccmis.get_module_hardware_revision = MagicMock() + ccmis.get_module_hardware_revision.return_value = mock_response[9] + ccmis.get_vendor_serial = MagicMock() + ccmis.get_vendor_serial.return_value = mock_response[10] + ccmis.get_vendor_name = MagicMock() + ccmis.get_vendor_name.return_value = mock_response[11] + ccmis.get_vendor_rev = MagicMock() + ccmis.get_vendor_rev.return_value = mock_response[12] + ccmis.get_vendor_OUI = MagicMock() + ccmis.get_vendor_OUI.return_value = mock_response[13] + ccmis.get_vendor_date = MagicMock() + ccmis.get_vendor_date.return_value = mock_response[14] + ccmis.get_connector_type = MagicMock() + ccmis.get_connector_type.return_value = mock_response[15] + ccmis.get_cmis_rev = MagicMock() + ccmis.get_cmis_rev.return_value = mock_response[16] + ccmis.get_module_active_firmware = MagicMock() + ccmis.get_module_active_firmware.return_value = mock_response[17] + ccmis.get_module_inactive_firmware = MagicMock() + ccmis.get_module_inactive_firmware.return_value = mock_response[18] + ccmis.get_supported_power_config = MagicMock() + ccmis.get_supported_power_config.return_value = mock_response[19] + ccmis.get_supported_freq_config = MagicMock() + ccmis.get_supported_freq_config.return_value = mock_response[20] + result = ccmis.get_transceiver_info() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + {'monitor value': 50}, + {'monitor value': 3.3}, + {'monitor value lane1': 0.1}, + {'monitor value lane1': 0.09}, + {'monitor value lane1': 70}, + {'monitor value': 40}, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, + 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, + 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, + 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, + 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, + 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, + 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, + 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, + 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} + }, + 193100, 193100, -10 + ], + { + 'temperature': 50, + 'voltage': 3.3, + 'txpower': 0.1, + 'rxpower': 0.09, + 'txbias': 70, + 'laser_temperature': 40, + 'prefec_ber': 0.001, + 'postfec_ber': 0, + 'bias_xi': 50, + 'bias_xq': 50, + 'bias_xp': 50, + 'bias_yi': 50, + 'bias_yq': 50, + 'bias_yp': 50, + 'cd_shortlink': 1000, + 'cd_longlink': 1000, + 'dgd': 5, + 'sopmd': 5, + 'pdl': 0.5, + 'osnr': 30, + 'esnr': 16, + 'cfo': 100, + 'tx_curr_power': -10, + 'rx_tot_power': -10, + 'rx_sig_power': -10, + 'laser_config_freq': 193100, + 'laser_curr_freq': 193100, + 'tx_config_power': -10 + } + ) + ]) + def test_get_transceiver_bulk_status(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.get_module_temperature = MagicMock() + ccmis.get_module_temperature.return_value = mock_response[0] + ccmis.get_module_voltage = MagicMock() + ccmis.get_module_voltage.return_value = mock_response[1] + ccmis.get_txpower = MagicMock() + ccmis.get_txpower.return_value = mock_response[2] + ccmis.get_rxpower = MagicMock() + ccmis.get_rxpower.return_value = mock_response[3] + ccmis.get_txbias = MagicMock() + ccmis.get_txbias.return_value = mock_response[4] + ccmis.get_laser_temperature = MagicMock() + ccmis.get_laser_temperature.return_value = mock_response[5] + ccmis.get_vdm = MagicMock() + ccmis.get_vdm.return_value = mock_response[6] + ccmis.get_laser_config_freq = MagicMock() + ccmis.get_laser_config_freq.return_value = mock_response[7] + ccmis.get_current_laser_freq = MagicMock() + ccmis.get_current_laser_freq.return_value = mock_response[8] + ccmis.get_tx_config_power = MagicMock() + ccmis.get_tx_config_power.return_value = mock_response[9] + result = ccmis.get_transceiver_bulk_status() + assert result == expected + + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + {'high alarm': 80, 'low alarm': 0, 'high warn': 75, 'low warn': 10}, + {'high alarm': 3.5, 'low alarm': 3.1, 'high warn': 3.45, 'low warn': 3.15}, + {'high alarm': 1.0, 'low alarm': 0.01, 'high warn': 0.7, 'low warn': 0.02}, + {'high alarm': 2.0, 'low alarm': 0.01, 'high warn': 1.0, 'low warn': 0.02}, + {'high alarm': 90, 'low alarm': 10, 'high warn': 80, 'low warn': 20}, + {'high alarm': 80, 'low alarm': 10, 'high warn': 75, 'low warn': 20}, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, + 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, + 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, + 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, + 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, + 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, + 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, + 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, + 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} + } + ], + { + 'temphighalarm': 80, 'templowalarm': 0, 'temphighwarning': 75, 'templowwarning': 10, + 'vcchighalarm': 3.5, 'vcclowalarm': 3.1, 'vcchighwarning': 3.45, 'vcclowwarning': 3.15, + 'txpowerhighalarm': 1.0, 'txpowerlowalarm': 0.01, 'txpowerhighwarning': 0.7, 'txpowerlowwarning': 0.02, + 'rxpowerhighalarm': 2.0, 'rxpowerlowalarm': 0.01, 'rxpowerhighwarning': 1.0, 'rxpowerlowwarning': 0.02, + 'txbiashighalarm': 90, 'txbiaslowalarm': 10, 'txbiashighwarning': 80, 'txbiaslowwarning': 20, + 'lasertemphighalarm': 80, 'lasertemplowalarm': 10, 'lasertemphighwarning': 75, 'lasertemplowwarning': 20, + 'prefecberhighalarm': 0.0125, 'prefecberlowalarm': 0, 'prefecberhighwarning': 0.01, 'prefecberlowwarning': 0, + 'postfecberhighalarm': 1, 'postfecberlowalarm': 0, 'postfecberhighwarning': 1, 'postfecberlowwarning': 0, + 'biasxihighalarm': 90, 'biasxilowalarm': 10, 'biasxihighwarning': 85, 'biasxilowwarning': 15, + 'biasxqhighalarm': 90, 'biasxqlowalarm': 10, 'biasxqhighwarning': 85, 'biasxqlowwarning': 15, + 'biasxphighalarm': 90, 'biasxplowalarm': 10, 'biasxphighwarning': 85, 'biasxplowwarning': 15, + 'biasyihighalarm': 90, 'biasyilowalarm': 10, 'biasyihighwarning': 85, 'biasyilowwarning': 15, + 'biasyqhighalarm': 90, 'biasyqlowalarm': 10, 'biasyqhighwarning': 85, 'biasyqlowwarning': 15, + 'biasyphighalarm': 90, 'biasyplowalarm': 10, 'biasyphighwarning': 85, 'biasyplowwarning': 15, + 'cdshorthighalarm': 2000, 'cdshortlowalarm': 0, 'cdshorthighwarning': 1800, 'cdshortlowwarning': 0, + 'cdlonghighalarm': 2000, 'cdlonglowalarm': 0, 'cdlonghighwarning': 1800, 'cdlonglowwarning': 0, + 'dgdhighalarm': 30, 'dgdlowalarm': 0, 'dgdhighwarning': 25, 'dgdlowwarning': 0, + 'sopmdhighalarm': 100, 'sopmdlowalarm': 0, 'sopmdhighwarning': 80, 'sopmdlowwarning': 0, + 'pdlhighalarm': 3, 'pdllowalarm': 0, 'pdlhighwarning': 2.5, 'pdllowwarning': 0, + 'osnrhighalarm': 100, 'osnrlowalarm': 26, 'osnrhighwarning': 80, 'osnrlowwarning': 27, + 'esnrhighalarm': 100, 'esnrlowalarm': 13, 'esnrhighwarning': 80, 'esnrlowwarning': 14, + 'cfohighalarm': 5000, 'cfolowalarm': -5000, 'cfohighwarning': 4000, 'cfolowwarning': -4000, + 'txcurrpowerhighalarm': 0, 'txcurrpowerlowalarm': -18, 'txcurrpowerhighwarning': -2, 'txcurrpowerlowwarning': -16, + 'rxtotpowerhighalarm': 3, 'rxtotpowerlowalarm': -18, 'rxtotpowerhighwarning': 0, 'rxtotpowerlowwarning': -15, + 'rxsigpowerhighalarm': 3, 'rxsigpowerlowalarm': -18, 'rxsigpowerhighwarning': 0, 'rxsigpowerlowwarning': -15 + } + ) + ]) + def test_get_transceiver_threshold_info(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.get_module_temperature = MagicMock() + ccmis.get_module_temperature.return_value = mock_response[0] + ccmis.get_module_voltage = MagicMock() + ccmis.get_module_voltage.return_value = mock_response[1] + ccmis.get_txpower = MagicMock() + ccmis.get_txpower.return_value = mock_response[2] + ccmis.get_rxpower = MagicMock() + ccmis.get_rxpower.return_value = mock_response[3] + ccmis.get_txbias = MagicMock() + ccmis.get_txbias.return_value = mock_response[4] + ccmis.get_laser_temperature = MagicMock() + ccmis.get_laser_temperature.return_value = mock_response[5] + ccmis.get_vdm = MagicMock() + ccmis.get_vdm.return_value = mock_response[6] + result = ccmis.get_transceiver_threshold_info() assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + 'ModuleReady', 'No Fault detected', (False, False, True), + { + 'dp_lane1': 'DataPathActivated', 'dp_lane2': 'DataPathActivated', + 'dp_lane3': 'DataPathActivated', 'dp_lane4': 'DataPathActivated', + 'dp_lane5': 'DataPathActivated', 'dp_lane6': 'DataPathActivated', + 'dp_lane7': 'DataPathActivated', 'dp_lane8': 'DataPathActivated' + }, + {'TX_lane1': True}, + { + 'RX_lane1': True, 'RX_lane2': True, 'RX_lane3': True, 'RX_lane4': True, + 'RX_lane5': True, 'RX_lane6': True, 'RX_lane7': True, 'RX_lane8': True + }, + {'TX_lane1': False}, + { + 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, + 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False + }, + { + 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, + 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False + }, + {'RX_lane1': False}, + {'RX_lane1': False}, + { + 'config_DP_status_hostlane1': 'ConfigSuccess', 'config_DP_status_hostlane2': 'ConfigSuccess', + 'config_DP_status_hostlane3': 'ConfigSuccess', 'config_DP_status_hostlane4': 'ConfigSuccess', + 'config_DP_status_hostlane5': 'ConfigSuccess', 'config_DP_status_hostlane6': 'ConfigSuccess', + 'config_DP_status_hostlane7': 'ConfigSuccess', 'config_DP_status_hostlane8': 'ConfigSuccess' + }, + { + 'hostlane1': False, 'hostlane2': False, + 'hostlane3': False, 'hostlane4': False, + 'hostlane5': False, 'hostlane6': False, + 'hostlane7': False, 'hostlane8': False + }, + False, False, ['TuningComplete'], + { + 'case_temp_flags': { + 'case_temp_high_alarm_flag': False, + 'case_temp_low_alarm_flag': False, + 'case_temp_high_warn_flag': False, + 'case_temp_low_warn_flag': False, + }, + 'voltage_flags': { + 'voltage_high_alarm_flag': False, + 'voltage_low_alarm_flag': False, + 'voltage_high_warn_flag': False, + 'voltage_low_warn_flag': False, + }, + 'aux1_flags': { + 'aux1_high_alarm_flag': False, + 'aux1_low_alarm_flag': False, + 'aux1_high_warn_flag': False, + 'aux1_low_warn_flag': False, + }, + 'aux2_flags': { + 'aux2_high_alarm_flag': False, + 'aux2_low_alarm_flag': False, + 'aux2_high_warn_flag': False, + 'aux2_low_warn_flag': False, + }, + 'aux3_flags': { + 'aux3_high_alarm_flag': False, + 'aux3_low_alarm_flag': False, + 'aux3_high_warn_flag': False, + 'aux3_low_warn_flag': False, + } + }, + (0, 0, 0), + { + 'tx_power_high_alarm': {'TX_lane1': False}, + 'tx_power_low_alarm': {'TX_lane1': False}, + 'tx_power_high_warn': {'TX_lane1': False}, + 'tx_power_low_warn': {'TX_lane1': False}, + }, + { + 'rx_power_high_alarm': {'RX_lane1': False}, + 'rx_power_low_alarm': {'RX_lane1': False}, + 'rx_power_high_warn': {'RX_lane1': False}, + 'rx_power_low_warn': {'RX_lane1': False}, + }, + { + 'tx_bias_high_alarm': {'TX_lane1': False}, + 'tx_bias_low_alarm': {'TX_lane1': False}, + 'tx_bias_high_warn': {'TX_lane1': False}, + 'tx_bias_low_warn': {'TX_lane1': False}, + }, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, + 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, + 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, + 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, + 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, + 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, + 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, + 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, + 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, + 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, + 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} + } + ], + { + 'module_state': 'ModuleReady', + 'module_fault_cause': 'No Fault detected', + 'datapath_firmware_fault': False, + 'module_firmware_fault': False, + 'module_state_changed': True, + 'datapath_hostlane1': 'DataPathActivated', + 'datapath_hostlane2': 'DataPathActivated', + 'datapath_hostlane3': 'DataPathActivated', + 'datapath_hostlane4': 'DataPathActivated', + 'datapath_hostlane5': 'DataPathActivated', + 'datapath_hostlane6': 'DataPathActivated', + 'datapath_hostlane7': 'DataPathActivated', + 'datapath_hostlane8': 'DataPathActivated', + 'txoutput_status': True, + 'rxoutput_status_hostlane1': True, + 'rxoutput_status_hostlane2': True, + 'rxoutput_status_hostlane3': True, + 'rxoutput_status_hostlane4': True, + 'rxoutput_status_hostlane5': True, + 'rxoutput_status_hostlane6': True, + 'rxoutput_status_hostlane7': True, + 'rxoutput_status_hostlane8': True, + 'txfault': False, + 'txlos_hostlane1': False, + 'txlos_hostlane2': False, + 'txlos_hostlane3': False, + 'txlos_hostlane4': False, + 'txlos_hostlane5': False, + 'txlos_hostlane6': False, + 'txlos_hostlane7': False, + 'txlos_hostlane8': False, + 'txcdrlol_hostlane1': False, + 'txcdrlol_hostlane2': False, + 'txcdrlol_hostlane3': False, + 'txcdrlol_hostlane4': False, + 'txcdrlol_hostlane5': False, + 'txcdrlol_hostlane6': False, + 'txcdrlol_hostlane7': False, + 'txcdrlol_hostlane8': False, + 'rxlos': False, + 'rxcdrlol': False, + 'config_state_hostlane1': 'ConfigSuccess', + 'config_state_hostlane2': 'ConfigSuccess', + 'config_state_hostlane3': 'ConfigSuccess', + 'config_state_hostlane4': 'ConfigSuccess', + 'config_state_hostlane5': 'ConfigSuccess', + 'config_state_hostlane6': 'ConfigSuccess', + 'config_state_hostlane7': 'ConfigSuccess', + 'config_state_hostlane8': 'ConfigSuccess', + 'dpinit_pending_hostlane1': False, + 'dpinit_pending_hostlane2': False, + 'dpinit_pending_hostlane3': False, + 'dpinit_pending_hostlane4': False, + 'dpinit_pending_hostlane5': False, + 'dpinit_pending_hostlane6': False, + 'dpinit_pending_hostlane7': False, + 'dpinit_pending_hostlane8': False, + 'tuning_in_progress': False, + 'wavelength_unlock_status': False, + 'target_output_power_oor': False, + 'fine_tuning_oor': False, + 'tuning_not_accepted': False, + 'invalid_channel_num': False, + 'tuning_complete': True, + 'temphighalarm_flag': False, 'templowalarm_flag': False, + 'temphighwarning_flag': False, 'templowwarning_flag': False, + 'vcchighalarm_flag': False, 'vcclowalarm_flag': False, + 'vcchighwarning_flag': False, 'vcclowwarning_flag': False, + 'lasertemphighalarm_flag': False, 'lasertemplowalarm_flag': False, + 'lasertemphighwarning_flag': False, 'lasertemplowwarning_flag': False, + 'txpowerhighalarm_flag': False, 'txpowerlowalarm_flag': False, + 'txpowerhighwarning_flag': False, 'txpowerlowwarning_flag': False, + 'rxpowerhighalarm_flag': False, 'rxpowerlowalarm_flag': False, + 'rxpowerhighwarning_flag': False, 'rxpowerlowwarning_flag': False, + 'txbiashighalarm_flag': False, 'txbiaslowalarm_flag': False, + 'txbiashighwarning_flag': False, 'txbiaslowwarning_flag': False, + 'prefecberhighalarm_flag': False, 'prefecberlowalarm_flag': False, + 'prefecberhighwarning_flag': False, 'prefecberlowwarning_flag': False, + 'postfecberhighalarm_flag': False, 'postfecberlowalarm_flag': False, + 'postfecberhighwarning_flag': False, 'postfecberlowwarning_flag': False, + 'biasxihighalarm_flag': False, 'biasxilowalarm_flag': False, + 'biasxihighwarning_flag': False, 'biasxilowwarning_flag': False, + 'biasxqhighalarm_flag': False, 'biasxqlowalarm_flag': False, + 'biasxqhighwarning_flag': False, 'biasxqlowwarning_flag': False, + 'biasxphighalarm_flag': False, 'biasxplowalarm_flag': False, + 'biasxphighwarning_flag': False, 'biasxplowwarning_flag': False, + 'biasyihighalarm_flag': False, 'biasyilowalarm_flag': False, + 'biasyihighwarning_flag': False, 'biasyilowwarning_flag': False, + 'biasyqhighalarm_flag': False, 'biasyqlowalarm_flag': False, + 'biasyqhighwarning_flag': False, 'biasyqlowwarning_flag': False, + 'biasyphighalarm_flag': False, 'biasyplowalarm_flag': False, + 'biasyphighwarning_flag': False, 'biasyplowwarning_flag': False, + 'cdshorthighalarm_flag': False, 'cdshortlowalarm_flag': False, + 'cdshorthighwarning_flag': False, 'cdshortlowwarning_flag': False, + 'cdlonghighalarm_flag': False, 'cdlonglowalarm_flag': False, + 'cdlonghighwarning_flag': False, 'cdlonglowwarning_flag': False, + 'dgdhighalarm_flag': False, 'dgdlowalarm_flag': False, + 'dgdhighwarning_flag': False, 'dgdlowwarning_flag': False, + 'sopmdhighalarm_flag': False, 'sopmdlowalarm_flag': False, + 'sopmdhighwarning_flag': False, 'sopmdlowwarning_flag': False, + 'pdlhighalarm_flag': False, 'pdllowalarm_flag': False, + 'pdlhighwarning_flag': False, 'pdllowwarning_flag': False, + 'osnrhighalarm_flag': False, 'osnrlowalarm_flag': False, + 'osnrhighwarning_flag': False, 'osnrlowwarning_flag': False, + 'esnrhighalarm_flag': False, 'esnrlowalarm_flag': False, + 'esnrhighwarning_flag': False, 'esnrlowwarning_flag': False, + 'cfohighalarm_flag': False, 'cfolowalarm_flag': False, + 'cfohighwarning_flag': False, 'cfolowwarning_flag': False, + 'txcurrpowerhighalarm_flag': False, 'txcurrpowerlowalarm_flag': False, + 'txcurrpowerhighwarning_flag': False, 'txcurrpowerlowwarning_flag': False, + 'rxtotpowerhighalarm_flag': False, 'rxtotpowerlowalarm_flag': False, + 'rxtotpowerhighwarning_flag': False, 'rxtotpowerlowwarning_flag': False, + 'rxsigpowerhighalarm_flag': False, 'rxsigpowerlowalarm_flag': False, + 'rxsigpowerhighwarning_flag': False, 'rxsigpowerlowwarning_flag': False, + + } + ) + ]) + def test_get_transceiver_status(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.get_module_state = MagicMock() + ccmis.get_module_state.return_value = mock_response[0] + ccmis.get_module_fault_cause = MagicMock() + ccmis.get_module_fault_cause.return_value = mock_response[1] + ccmis.get_module_firmware_fault_state_changed = MagicMock() + ccmis.get_module_firmware_fault_state_changed.return_value = mock_response[2] + ccmis.get_datapath_state = MagicMock() + ccmis.get_datapath_state.return_value = mock_response[3] + ccmis.get_tx_output_status = MagicMock() + ccmis.get_tx_output_status.return_value = mock_response[4] + ccmis.get_rx_output_status = MagicMock() + ccmis.get_rx_output_status.return_value = mock_response[5] + ccmis.get_tx_fault = MagicMock() + ccmis.get_tx_fault.return_value = mock_response[6] + ccmis.get_tx_los = MagicMock() + ccmis.get_tx_los.return_value = mock_response[7] + ccmis.get_tx_cdr_lol = MagicMock() + ccmis.get_tx_cdr_lol.return_value = mock_response[8] + ccmis.get_rx_los = MagicMock() + ccmis.get_rx_los.return_value = mock_response[9] + ccmis.get_rx_cdr_lol = MagicMock() + ccmis.get_rx_cdr_lol.return_value = mock_response[10] + ccmis.get_config_datapath_hostlane_status = MagicMock() + ccmis.get_config_datapath_hostlane_status.return_value = mock_response[11] + ccmis.get_dpinit_pending = MagicMock() + ccmis.get_dpinit_pending.return_value = mock_response[12] + ccmis.get_tuning_in_progress = MagicMock() + ccmis.get_tuning_in_progress.return_value = mock_response[13] + ccmis.get_wavelength_unlocked = MagicMock() + ccmis.get_wavelength_unlocked.return_value = mock_response[14] + ccmis.get_laser_tuning_summary = MagicMock() + ccmis.get_laser_tuning_summary.return_value = mock_response[15] + ccmis.get_module_level_flag = MagicMock() + ccmis.get_module_level_flag.return_value = mock_response[16] + ccmis.get_aux_mon_type = MagicMock() + ccmis.get_aux_mon_type.return_value = mock_response[17] + ccmis.get_tx_power_flag = MagicMock() + ccmis.get_tx_power_flag.return_value = mock_response[18] + ccmis.get_rx_power_flag = MagicMock() + ccmis.get_rx_power_flag.return_value = mock_response[19] + ccmis.get_tx_bias_flag = MagicMock() + ccmis.get_tx_bias_flag.return_value = mock_response[20] + ccmis.get_vdm = MagicMock() + ccmis.get_vdm.return_value = mock_response[21] + result = ccmis.get_transceiver_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected", [ + ( + { + 'preFEC_BER_avg': 0.001, 'preFEC_BER_min': 0.0008, 'preFEC_BER_max': 0.0012, + 'preFEC_uncorr_frame_ratio_avg': 0, 'preFEC_uncorr_frame_ratio_min': 0, 'preFEC_uncorr_frame_ratio_max': 0, + 'rx_cd_avg': 1400, 'rx_cd_min': 1300, 'rx_cd_max': 1500, + 'rx_dgd_avg': 7.0, 'rx_dgd_min': 5.5, 'rx_dgd_max': 9.2, + 'rx_sopmd_avg': 40, 'rx_sopmd_min': 20, 'rx_sopmd_max': 60, + 'rx_pdl_avg': 1.0, 'rx_pdl_min': 0.8, 'rx_pdl_max': 1.2, + 'rx_osnr_avg': 28, 'rx_osnr_min': 26, 'rx_osnr_max': 30, + 'rx_esnr_avg': 17, 'rx_esnr_min': 15, 'rx_esnr_max': 18, + 'rx_cfo_avg': 200, 'rx_cfo_min': 150, 'rx_cfo_max': 250, + 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, + 'rx_power_avg': -8, 'rx_power_min': -7, 'rx_power_max': -9, + 'rx_sigpwr_avg': -8, 'rx_sigpwr_min': -7, 'rx_sigpwr_max': -9, + 'rx_soproc_avg': 5, 'rx_soproc_min': 3, 'rx_soproc_max': 8, + }, + { + 'prefec_ber_avg': 0.001, 'prefec_ber_min': 0.0008, 'prefec_ber_max': 0.0012, + 'uncorr_frames_avg': 0, 'uncorr_frames_min': 0, 'uncorr_frames_max': 0, + 'cd_avg': 1400, 'cd_min': 1300, 'cd_max': 1500, + 'dgd_avg': 7.0, 'dgd_min': 5.5, 'dgd_max': 9.2, + 'sopmd_avg': 40, 'sopmd_min': 20, 'sopmd_max': 60, + 'pdl_avg': 1.0, 'pdl_min': 0.8, 'pdl_max': 1.2, + 'osnr_avg': 28, 'osnr_min': 26, 'osnr_max': 30, + 'esnr_avg': 17, 'esnr_min': 15, 'esnr_max': 18, + 'cfo_avg': 200, 'cfo_min': 150, 'cfo_max': 250, + 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, + 'rx_tot_power_avg': -8, 'rx_tot_power_min': -7, 'rx_tot_power_max': -9, + 'rx_sig_power_avg': -8, 'rx_sig_power_min': -7, 'rx_sig_power_max': -9, + 'soproc_avg': 5, 'soproc_min': 3, 'soproc_max': 8, + } + ) + ]) + def test_get_transceiver_pm(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.get_pm_all = MagicMock() + ccmis.get_pm_all.return_value = mock_response + result = ccmis.get_transceiver_pm() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + False, + False, + [False, False, False, False, False, False, False, False], + [False, False, False, False, False, False, False, False] + ], + { + 'media_output_loopback': False, + 'media_input_loopback': False, + 'host_output_loopback_lane1': False, + 'host_output_loopback_lane2': False, + 'host_output_loopback_lane3': False, + 'host_output_loopback_lane4': False, + 'host_output_loopback_lane5': False, + 'host_output_loopback_lane6': False, + 'host_output_loopback_lane7': False, + 'host_output_loopback_lane8': False, + 'host_input_loopback_lane1': False, + 'host_input_loopback_lane2': False, + 'host_input_loopback_lane3': False, + 'host_input_loopback_lane4': False, + 'host_input_loopback_lane5': False, + 'host_input_loopback_lane6': False, + 'host_input_loopback_lane7': False, + 'host_input_loopback_lane8': False + } + ) + ]) + def test_get_transceiver_loopback(self, mock_response, expected): + ccmis = self.mock_ccmis_api() + ccmis.get_media_output_loopback = MagicMock() + ccmis.get_media_output_loopback.return_value = mock_response[0] + ccmis.get_media_input_loopback = MagicMock() + ccmis.get_media_input_loopback.return_value = mock_response[1] + ccmis.get_host_output_loopback = MagicMock() + ccmis.get_host_output_loopback.return_value = mock_response[2] + ccmis.get_host_input_loopback = MagicMock() + ccmis.get_host_input_loopback.return_value = mock_response[3] + result = ccmis.get_transceiver_loopback() + assert result == expected + # TODO: call other methods in the api diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 8758d8a39..83e658cae 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -9,7 +9,7 @@ class TestCmis(object): def mock_cmis_api(self): - codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + codes = CmisCode mem_map = CmisMemMap(codes) reader = MagicMock(return_value=None) writer = MagicMock() @@ -299,55 +299,14 @@ def test_get_txbias(self, mock_response, expected): result = api.get_txbias() assert result == expected - @pytest.mark.parametrize("mock_response, expected", [ - (0x70, 75), - (0x60, 33), - (0x50, 100), - (0x40, 50), - (0x30, 25), - (0x20, 12.5), - (0x10, 6.25), - (0x0, 3.125), - ]) - def test_get_freq_grid(self, mock_response, expected): - api = self.mock_cmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_freq_grid() - assert result == expected - - @pytest.mark.parametrize("mock_response1, mock_response2, expected", [ - (75, 12, 193400), - (75, -30, 192350), - (100, 10, 194100), - ]) - def test_get_laser_config_freq(self, mock_response1, mock_response2, expected): - api = self.mock_cmis_api() - api.get_freq_grid = MagicMock() - api.get_freq_grid.return_value = mock_response1 - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response2 - result = api.get_laser_config_freq() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (193100000, 193100) - ]) - def test_get_current_laser_freq(self, mock_response, expected): - api = self.mock_cmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_current_laser_freq() - assert result == expected - @pytest.mark.parametrize("mock_response, expected", [ (-10, -10) ]) - def test_get_TX_config_power(self, mock_response, expected): + def test_get_tx_config_power(self, mock_response, expected): api = self.mock_cmis_api() api.xcvr_eeprom.read = MagicMock() api.xcvr_eeprom.read.return_value = mock_response - result = api.get_TX_config_power() + result = api.get_tx_config_power() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ @@ -465,24 +424,9 @@ def test_get_custom_field(self, input_param, mock_response, expected): result = api.get_custom_field(*input_param) assert result == expected - @pytest.mark.parametrize("mock_response, expected",[ - ( - {'preFEC_BER_avg': 0.001}, - {'preFEC_BER_avg': 0.001} - ) - ]) - def test_get_PM(self, mock_response, expected): - api = self.mock_cmis_api() - api.ccmis = MagicMock() - api.ccmis.get_PM_all = MagicMock() - api.ccmis.get_PM_all.return_value = mock_response - result = api.get_PM() - assert result == expected - - - def test_get_VDM_api(self): + def test_get_vdm_api(self): api = self.mock_cmis_api() - api.vdm = api.get_VDM_api() + api.vdm = api.get_vdm_api() @pytest.mark.parametrize("mock_response, expected",[ @@ -491,18 +435,14 @@ def test_get_VDM_api(self): {'Pre-FEC BER Average Media Input': {1: [0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}} ) ]) - def test_get_VDM(self, mock_response, expected): + def test_get_vdm(self, mock_response, expected): api = self.mock_cmis_api() api.vdm = MagicMock() - api.vdm.get_VDM_allpage = MagicMock() - api.vdm.get_VDM_allpage.return_value = mock_response - result = api.get_VDM() + api.vdm.get_vdm_allpage = MagicMock() + api.vdm.get_vdm_allpage.return_value = mock_response + result = api.get_vdm() assert result == expected - def test_get_ccmis_api(self): - api = self.mock_cmis_api() - api.ccmis = api.get_ccmis_api() - @pytest.mark.parametrize("mock_response, expected", [ (6, "ModuleReady") ]) @@ -937,48 +877,6 @@ def test_get_dpinit_pending(self, mock_response, expected): result = api.get_dpinit_pending() assert result == expected - @pytest.mark.parametrize("mock_response, expected", [ - (0, False) - ]) - def test_get_tuning_in_progress(self, mock_response, expected): - api = self.mock_cmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_tuning_in_progress() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (0, False) - ]) - def test_get_wavelength_unlocked(self, mock_response, expected): - api = self.mock_cmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_wavelength_unlocked() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - (1, ['TuningComplete']), - (62, ['TargetOutputPowerOOR', 'FineTuningOutOfRange', 'TuningNotAccepted', - 'InvalidChannel', 'WavelengthUnlocked']), - ]) - def test_get_laser_tuning_summary(self, mock_response, expected): - api = self.mock_cmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.return_value = mock_response - result = api.get_laser_tuning_summary() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected", [ - ([190, -72, 120], (190, -72, 120, 191300, 196100)) - ]) - def test_get_supported_freq_config(self, mock_response, expected): - api = self.mock_cmis_api() - api.xcvr_eeprom.read = MagicMock() - api.xcvr_eeprom.read.side_effect = mock_response - result = api.get_supported_freq_config() - assert result == expected - @pytest.mark.parametrize("mock_response, expected", [ ([-20, 0], (-20,0)) ]) @@ -1003,25 +901,15 @@ def test_set_low_power(self, input_param): api = self.mock_cmis_api() api.set_low_power(input_param) - @pytest.mark.parametrize("input_param, mock_response",[ - (193100, (0xff, -72, 120, 191300, 196100)), - (195950, (0xff, -72, 120, 191300, 196100)), - ]) - def test_set_laser_freq(self, input_param, mock_response): - api = self.mock_cmis_api() - api.get_supported_freq_config = MagicMock() - api.get_supported_freq_config.return_value = mock_response - api.set_laser_freq(input_param) - @pytest.mark.parametrize("input_param, mock_response",[ (-10, (-14, -9)), (-8, (-12, -8)), ]) - def test_set_TX_power(self, input_param, mock_response): + def test_set_tx_power(self, input_param, mock_response): api = self.mock_cmis_api() api.get_supported_power_config = MagicMock() api.get_supported_power_config.return_value = mock_response - api.set_TX_power(input_param) + api.set_tx_power(input_param) @pytest.mark.parametrize("mock_response, expected", [ (127, @@ -1080,9 +968,9 @@ def test_set_loopback_mode(self, input_param, mock_response): api.get_loopback_capability.return_value = mock_response api.set_loopback_mode(input_param) - def test_get_CDB_api(self): + def test_get_cdb_api(self): api = self.mock_cmis_api() - api.cdb = api.get_CDB_api() + api.cdb = api.get_cdb_api() @pytest.mark.parametrize("input_param, mock_response1, mock_response2, expected", [ ( @@ -1098,7 +986,7 @@ def test_get_CDB_api(self): (112, 2048, True, True, 2048) ), ]) - def test_get_module_FW_upgrade_feature(self, input_param, mock_response1, mock_response2, expected): + def test_get_module_fw_upgrade_feature(self, input_param, mock_response1, mock_response2, expected): api = self.mock_cmis_api() api.xcvr_eeprom.read = MagicMock() api.xcvr_eeprom.read.side_effect = mock_response1 @@ -1107,7 +995,7 @@ def test_get_module_FW_upgrade_feature(self, input_param, mock_response1, mock_r api.cdb.cmd0041h.return_value = mock_response2 api.cdb.cdb_chkcode = MagicMock() api.cdb.cdb_chkcode.return_value = mock_response2[1] - result = api.get_module_FW_upgrade_feature(input_param) + result = api.get_module_fw_upgrade_feature(input_param) assert result == expected @pytest.mark.parametrize("mock_response, expected", [ @@ -1120,36 +1008,36 @@ def test_get_module_FW_upgrade_feature(self, input_param, mock_response1, mock_r ('0.0.1', 0, 0, 0, '0.0.0', 1, 1, 0) ), ]) - def test_get_module_FW_info(self, mock_response, expected): + def test_get_module_fw_info(self, mock_response, expected): api = self.mock_cmis_api() api.cdb = MagicMock() api.cdb.cmd0100h = MagicMock() api.cdb.cmd0100h.return_value = mock_response api.cdb.cdb_chkcode = MagicMock() api.cdb.cdb_chkcode.return_value = mock_response[1] - result = api.get_module_FW_info() + result = api.get_module_fw_info() assert result == expected @pytest.mark.parametrize("input_param, mock_response", [ (1, 1), (1, 64) ]) - def test_module_FW_run(self, input_param, mock_response): + def test_module_fw_run(self, input_param, mock_response): api = self.mock_cmis_api() api.cdb = MagicMock() api.cdb.cmd0109h = MagicMock() api.cdb.cmd0109h.return_value = mock_response - api.module_FW_run(input_param) + api.module_fw_run(input_param) @pytest.mark.parametrize("mock_response", [ (1), (64) ]) - def test_module_FW_commit(self, mock_response): + def test_module_fw_commit(self, mock_response): api = self.mock_cmis_api() api.cdb = MagicMock() api.cdb.cmd010Ah = MagicMock() api.cdb.cmd010Ah.return_value = mock_response - api.module_FW_commit() + api.module_fw_commit() # @pytest.mark.parametrize("input_param", [ # (112, 2048, True, True, 2048, 'abc'), @@ -1167,12 +1055,12 @@ def test_module_FW_commit(self, mock_response): (112, 2048, True, True, 2048) ) ]) - def test_module_firmware_upgrade(self, input_param, mock_response): + def test_module_fw_upgrade(self, input_param, mock_response): api = self.mock_cmis_api() api.cdb = MagicMock() - api.cdb.get_module_FW_upgrade_feature = MagicMock() - api.cdb.get_module_FW_upgrade_feature.return_value = mock_response - api.cdb.module_firmware_upgrade(input_param) + api.cdb.get_module_fw_upgrade_feature = MagicMock() + api.cdb.get_module_fw_upgrade_feature.return_value = mock_response + api.cdb.module_fw_upgrade(input_param) @pytest.mark.parametrize("mock_response", [ ( @@ -1180,648 +1068,11 @@ def test_module_firmware_upgrade(self, input_param, mock_response): ('0.0.0', 1, 1, 0, '0.0.1', 0, 0, 1), ) ]) - def test_module_firmware_switch(self, mock_response): + def test_module_fw_switch(self, mock_response): api = self.mock_cmis_api() api.cdb = MagicMock() - api.cdb.get_module_FW_info = MagicMock() - api.cdb.get_module_FW_info.return_value = mock_response - api.cdb.module_firmware_switch() - - - - @pytest.mark.parametrize("mock_response, expected",[ - ( - [ - 'Single Mode Fiber (SMF)', - '400GAUI-8 C2M (Annex 120E)', - '400ZR, DWDM, amplified', - 8, 1, 1, 1, - {'hostlane1': 1, 'hostlane2': 1, 'hostlane3': 1, 'hostlane4': 1, - 'hostlane5': 1, 'hostlane6': 1, 'hostlane7': 1, 'hostlane8': 1}, - '1550 nm DFB', - '0.0', - '00000000', - 'VENDOR_NAME', - '0.0', - 'xx-xx-xx', - '21010100', - 'LC', - '5.0', - '0.1', - '0.0', - (-20, 0), - (0xff, -72, 120, 191300, 196100) - ], - { - 'active_firmware': '0.1', - 'media_lane_count': 1, - 'supported_min_laser_freq': 191300, - 'inactive_firmware': '0.0', - 'vendor_rev': '0.0', - 'host_electrical_interface': '400GAUI-8 C2M (Annex 120E)', - 'vendor_oui': 'xx-xx-xx', - 'manufacturename': 'VENDOR_NAME', - 'media_interface_technology': '1550 nm DFB', - 'media_interface_code': '400ZR, DWDM, amplified', - 'serialnum': '00000000', - 'module_media_type': 'Single Mode Fiber (SMF)', - 'host_lane_count': 8, - 'active_apsel_hostlane1': 1, - 'active_apsel_hostlane3': 1, - 'active_apsel_hostlane2': 1, - 'active_apsel_hostlane5': 1, - 'active_apsel_hostlane4': 1, - 'active_apsel_hostlane7': 1, - 'active_apsel_hostlane6': 1, - 'supported_max_laser_freq': 196100, - 'active_apsel_hostlane8': 1, - 'hardwarerev': '0.0', - 'specification_compliance': '5.0', - 'media_lane_assignment_option': 1, - 'connector_type': 'LC', - 'host_lane_assignment_option': 1, - 'supported_max_tx_power': 0, - 'supported_min_tx_power': -20, - 'vendor_date': '21010100' - } - ) - ]) - def test_get_transceiver_info(self, mock_response, expected): - api = self.mock_cmis_api() - api.get_module_media_type = MagicMock() - api.get_module_media_type.return_value = mock_response[0] - api.get_host_electrical_interface = MagicMock() - api.get_host_electrical_interface.return_value = mock_response[1] - api.get_module_media_interface = MagicMock() - api.get_module_media_interface.return_value = mock_response[2] - api.get_host_lane_count = MagicMock() - api.get_host_lane_count.return_value = mock_response[3] - api.get_media_lane_count = MagicMock() - api.get_media_lane_count.return_value = mock_response[4] - api.get_host_lane_assignment_option = MagicMock() - api.get_host_lane_assignment_option.return_value = mock_response[5] - api.get_media_lane_assignment_option = MagicMock() - api.get_media_lane_assignment_option.return_value = mock_response[6] - api.get_active_apsel_hostlane = MagicMock() - api.get_active_apsel_hostlane.return_value = mock_response[7] - api.get_media_interface_technology = MagicMock() - api.get_media_interface_technology.return_value = mock_response[8] - api.get_module_hardware_revision = MagicMock() - api.get_module_hardware_revision.return_value = mock_response[9] - api.get_vendor_serial = MagicMock() - api.get_vendor_serial.return_value = mock_response[10] - api.get_vendor_name = MagicMock() - api.get_vendor_name.return_value = mock_response[11] - api.get_vendor_rev = MagicMock() - api.get_vendor_rev.return_value = mock_response[12] - api.get_vendor_OUI = MagicMock() - api.get_vendor_OUI.return_value = mock_response[13] - api.get_vendor_date = MagicMock() - api.get_vendor_date.return_value = mock_response[14] - api.get_connector_type = MagicMock() - api.get_connector_type.return_value = mock_response[15] - api.get_cmis_rev = MagicMock() - api.get_cmis_rev.return_value = mock_response[16] - api.get_module_active_firmware = MagicMock() - api.get_module_active_firmware.return_value = mock_response[17] - api.get_module_inactive_firmware = MagicMock() - api.get_module_inactive_firmware.return_value = mock_response[18] - api.get_supported_power_config = MagicMock() - api.get_supported_power_config.return_value = mock_response[19] - api.get_supported_freq_config = MagicMock() - api.get_supported_freq_config.return_value = mock_response[20] - result = api.get_transceiver_info() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected",[ - ( - [ - {'monitor value': 50}, - {'monitor value': 3.3}, - {'monitor value lane1': 0.1}, - {'monitor value lane1': 0.09}, - {'monitor value lane1': 70}, - {'monitor value': 40}, - { - 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, - 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, - 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, - 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, - 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, - 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, - 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, - 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, - 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, - 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, - 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, - 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, - 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} - }, - 193100, 193100, -10 - ], - { - 'temperature': 50, - 'voltage': 3.3, - 'txpower': 0.1, - 'rxpower': 0.09, - 'txbias': 70, - 'laser_temperature': 40, - 'prefec_ber': 0.001, - 'postfec_ber': 0, - 'bias_xi': 50, - 'bias_xq': 50, - 'bias_xp': 50, - 'bias_yi': 50, - 'bias_yq': 50, - 'bias_yp': 50, - 'cd_shortlink': 1000, - 'cd_longlink': 1000, - 'dgd': 5, - 'sopmd': 5, - 'pdl': 0.5, - 'osnr': 30, - 'esnr': 16, - 'cfo': 100, - 'tx_curr_power': -10, - 'rx_tot_power': -10, - 'rx_sig_power': -10, - 'laser_config_freq': 193100, - 'laser_curr_freq': 193100, - 'tx_config_power': -10 - } - ) - ]) - def test_get_transceiver_bulk_status(self, mock_response, expected): - api = self.mock_cmis_api() - api.get_module_temperature = MagicMock() - api.get_module_temperature.return_value = mock_response[0] - api.get_module_voltage = MagicMock() - api.get_module_voltage.return_value = mock_response[1] - api.get_txpower = MagicMock() - api.get_txpower.return_value = mock_response[2] - api.get_rxpower = MagicMock() - api.get_rxpower.return_value = mock_response[3] - api.get_txbias = MagicMock() - api.get_txbias.return_value = mock_response[4] - api.get_laser_temperature = MagicMock() - api.get_laser_temperature.return_value = mock_response[5] - api.get_VDM = MagicMock() - api.get_VDM.return_value = mock_response[6] - api.get_laser_config_freq = MagicMock() - api.get_laser_config_freq.return_value = mock_response[7] - api.get_current_laser_freq = MagicMock() - api.get_current_laser_freq.return_value = mock_response[8] - api.get_TX_config_power = MagicMock() - api.get_TX_config_power.return_value = mock_response[9] - result = api.get_transceiver_bulk_status() - assert result == expected - - - @pytest.mark.parametrize("mock_response, expected",[ - ( - [ - {'high alarm': 80, 'low alarm': 0, 'high warn': 75, 'low warn': 10}, - {'high alarm': 3.5, 'low alarm': 3.1, 'high warn': 3.45, 'low warn': 3.15}, - {'high alarm': 1.0, 'low alarm': 0.01, 'high warn': 0.7, 'low warn': 0.02}, - {'high alarm': 2.0, 'low alarm': 0.01, 'high warn': 1.0, 'low warn': 0.02}, - {'high alarm': 90, 'low alarm': 10, 'high warn': 80, 'low warn': 20}, - {'high alarm': 80, 'low alarm': 10, 'high warn': 75, 'low warn': 20}, - { - 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, - 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, - 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, - 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, - 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, - 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, - 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, - 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, - 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, - 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, - 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, - 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, - 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} - } - ], - { - 'temphighalarm': 80, 'templowalarm': 0, 'temphighwarning': 75, 'templowwarning': 10, - 'vcchighalarm': 3.5, 'vcclowalarm': 3.1, 'vcchighwarning': 3.45, 'vcclowwarning': 3.15, - 'txpowerhighalarm': 1.0, 'txpowerlowalarm': 0.01, 'txpowerhighwarning': 0.7, 'txpowerlowwarning': 0.02, - 'rxpowerhighalarm': 2.0, 'rxpowerlowalarm': 0.01, 'rxpowerhighwarning': 1.0, 'rxpowerlowwarning': 0.02, - 'txbiashighalarm': 90, 'txbiaslowalarm': 10, 'txbiashighwarning': 80, 'txbiaslowwarning': 20, - 'lasertemphighalarm': 80, 'lasertemplowalarm': 10, 'lasertemphighwarning': 75, 'lasertemplowwarning': 20, - 'prefecberhighalarm': 0.0125, 'prefecberlowalarm': 0, 'prefecberhighwarning': 0.01, 'prefecberlowwarning': 0, - 'postfecberhighalarm': 1, 'postfecberlowalarm': 0, 'postfecberhighwarning': 1, 'postfecberlowwarning': 0, - 'biasxihighalarm': 90, 'biasxilowalarm': 10, 'biasxihighwarning': 85, 'biasxilowwarning': 15, - 'biasxqhighalarm': 90, 'biasxqlowalarm': 10, 'biasxqhighwarning': 85, 'biasxqlowwarning': 15, - 'biasxphighalarm': 90, 'biasxplowalarm': 10, 'biasxphighwarning': 85, 'biasxplowwarning': 15, - 'biasyihighalarm': 90, 'biasyilowalarm': 10, 'biasyihighwarning': 85, 'biasyilowwarning': 15, - 'biasyqhighalarm': 90, 'biasyqlowalarm': 10, 'biasyqhighwarning': 85, 'biasyqlowwarning': 15, - 'biasyphighalarm': 90, 'biasyplowalarm': 10, 'biasyphighwarning': 85, 'biasyplowwarning': 15, - 'cdshorthighalarm': 2000, 'cdshortlowalarm': 0, 'cdshorthighwarning': 1800, 'cdshortlowwarning': 0, - 'cdlonghighalarm': 2000, 'cdlonglowalarm': 0, 'cdlonghighwarning': 1800, 'cdlonglowwarning': 0, - 'dgdhighalarm': 30, 'dgdlowalarm': 0, 'dgdhighwarning': 25, 'dgdlowwarning': 0, - 'sopmdhighalarm': 100, 'sopmdlowalarm': 0, 'sopmdhighwarning': 80, 'sopmdlowwarning': 0, - 'pdlhighalarm': 3, 'pdllowalarm': 0, 'pdlhighwarning': 2.5, 'pdllowwarning': 0, - 'osnrhighalarm': 100, 'osnrlowalarm': 26, 'osnrhighwarning': 80, 'osnrlowwarning': 27, - 'esnrhighalarm': 100, 'esnrlowalarm': 13, 'esnrhighwarning': 80, 'esnrlowwarning': 14, - 'cfohighalarm': 5000, 'cfolowalarm': -5000, 'cfohighwarning': 4000, 'cfolowwarning': -4000, - 'txcurrpowerhighalarm': 0, 'txcurrpowerlowalarm': -18, 'txcurrpowerhighwarning': -2, 'txcurrpowerlowwarning': -16, - 'rxtotpowerhighalarm': 3, 'rxtotpowerlowalarm': -18, 'rxtotpowerhighwarning': 0, 'rxtotpowerlowwarning': -15, - 'rxsigpowerhighalarm': 3, 'rxsigpowerlowalarm': -18, 'rxsigpowerhighwarning': 0, 'rxsigpowerlowwarning': -15 - } - ) - ]) - def test_get_transceiver_threshold_info(self, mock_response, expected): - api = self.mock_cmis_api() - api.get_module_temperature = MagicMock() - api.get_module_temperature.return_value = mock_response[0] - api.get_module_voltage = MagicMock() - api.get_module_voltage.return_value = mock_response[1] - api.get_txpower = MagicMock() - api.get_txpower.return_value = mock_response[2] - api.get_rxpower = MagicMock() - api.get_rxpower.return_value = mock_response[3] - api.get_txbias = MagicMock() - api.get_txbias.return_value = mock_response[4] - api.get_laser_temperature = MagicMock() - api.get_laser_temperature.return_value = mock_response[5] - api.get_VDM = MagicMock() - api.get_VDM.return_value = mock_response[6] - result = api.get_transceiver_threshold_info() - assert result == expected - - @pytest.mark.parametrize("mock_response, expected",[ - ( - [ - 'ModuleReady', 'No Fault detected', (False, False, True), - { - 'dp_lane1': 'DataPathActivated', 'dp_lane2': 'DataPathActivated', - 'dp_lane3': 'DataPathActivated', 'dp_lane4': 'DataPathActivated', - 'dp_lane5': 'DataPathActivated', 'dp_lane6': 'DataPathActivated', - 'dp_lane7': 'DataPathActivated', 'dp_lane8': 'DataPathActivated' - }, - {'TX_lane1': True}, - { - 'RX_lane1': True, 'RX_lane2': True, 'RX_lane3': True, 'RX_lane4': True, - 'RX_lane5': True, 'RX_lane6': True, 'RX_lane7': True, 'RX_lane8': True - }, - {'TX_lane1': False}, - { - 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, - 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False - }, - { - 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, - 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False - }, - {'RX_lane1': False}, - {'RX_lane1': False}, - { - 'config_DP_status_hostlane1': 'ConfigSuccess', 'config_DP_status_hostlane2': 'ConfigSuccess', - 'config_DP_status_hostlane3': 'ConfigSuccess', 'config_DP_status_hostlane4': 'ConfigSuccess', - 'config_DP_status_hostlane5': 'ConfigSuccess', 'config_DP_status_hostlane6': 'ConfigSuccess', - 'config_DP_status_hostlane7': 'ConfigSuccess', 'config_DP_status_hostlane8': 'ConfigSuccess' - }, - { - 'hostlane1': False, 'hostlane2': False, - 'hostlane3': False, 'hostlane4': False, - 'hostlane5': False, 'hostlane6': False, - 'hostlane7': False, 'hostlane8': False - }, - False, False, ['TuningComplete'], - { - 'case_temp_flags': { - 'case_temp_high_alarm_flag': False, - 'case_temp_low_alarm_flag': False, - 'case_temp_high_warn_flag': False, - 'case_temp_low_warn_flag': False, - }, - 'voltage_flags': { - 'voltage_high_alarm_flag': False, - 'voltage_low_alarm_flag': False, - 'voltage_high_warn_flag': False, - 'voltage_low_warn_flag': False, - }, - 'aux1_flags': { - 'aux1_high_alarm_flag': False, - 'aux1_low_alarm_flag': False, - 'aux1_high_warn_flag': False, - 'aux1_low_warn_flag': False, - }, - 'aux2_flags': { - 'aux2_high_alarm_flag': False, - 'aux2_low_alarm_flag': False, - 'aux2_high_warn_flag': False, - 'aux2_low_warn_flag': False, - }, - 'aux3_flags': { - 'aux3_high_alarm_flag': False, - 'aux3_low_alarm_flag': False, - 'aux3_high_warn_flag': False, - 'aux3_low_warn_flag': False, - } - }, - (0, 0, 0), - { - 'tx_power_high_alarm': {'TX_lane1': False}, - 'tx_power_low_alarm': {'TX_lane1': False}, - 'tx_power_high_warn': {'TX_lane1': False}, - 'tx_power_low_warn': {'TX_lane1': False}, - }, - { - 'rx_power_high_alarm': {'RX_lane1': False}, - 'rx_power_low_alarm': {'RX_lane1': False}, - 'rx_power_high_warn': {'RX_lane1': False}, - 'rx_power_low_warn': {'RX_lane1': False}, - }, - { - 'tx_bias_high_alarm': {'TX_lane1': False}, - 'tx_bias_low_alarm': {'TX_lane1': False}, - 'tx_bias_high_warn': {'TX_lane1': False}, - 'tx_bias_low_warn': {'TX_lane1': False}, - }, - { - 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, - 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, - 'Modulator Bias X/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias X/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias X_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y/I [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y/Q [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'Modulator Bias Y_Phase [%]':{1:[50, 90, 10, 85, 15, False, False, False, False]}, - 'CD high granularity, short link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, - 'CD low granularity, long link [ps/nm]':{1:[1000, 2000, 0, 1800, 0, False, False, False, False]}, - 'DGD [ps]':{1:[5, 30, 0, 25, 0, False, False, False, False]}, - 'SOPMD [ps^2]':{1:[5, 100, 0, 80, 0, False, False, False, False]}, - 'PDL [dB]':{1:[0.5, 3, 0, 2.5, 0, False, False, False, False]}, - 'OSNR [dB]':{1:[30, 100, 26, 80, 27, False, False, False, False]}, - 'eSNR [dB]':{1:[16, 100, 13, 80, 14, False, False, False, False]}, - 'CFO [MHz]':{1:[100, 5000, -5000, 4000, -4000, False, False, False, False]}, - 'Tx Power [dBm]':{1:[-10, 0, -18, -2, -16, False, False, False, False]}, - 'Rx Total Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]}, - 'Rx Signal Power [dBm]':{1:[-10, 3, -18, 0, -15, False, False, False, False]} - } - ], - { - 'module_state': 'ModuleReady', - 'module_fault_cause': 'No Fault detected', - 'datapath_firmware_fault': False, - 'module_firmware_fault': False, - 'module_state_changed': True, - 'datapath_hostlane1': 'DataPathActivated', - 'datapath_hostlane2': 'DataPathActivated', - 'datapath_hostlane3': 'DataPathActivated', - 'datapath_hostlane4': 'DataPathActivated', - 'datapath_hostlane5': 'DataPathActivated', - 'datapath_hostlane6': 'DataPathActivated', - 'datapath_hostlane7': 'DataPathActivated', - 'datapath_hostlane8': 'DataPathActivated', - 'txoutput_status': True, - 'rxoutput_status_hostlane1': True, - 'rxoutput_status_hostlane2': True, - 'rxoutput_status_hostlane3': True, - 'rxoutput_status_hostlane4': True, - 'rxoutput_status_hostlane5': True, - 'rxoutput_status_hostlane6': True, - 'rxoutput_status_hostlane7': True, - 'rxoutput_status_hostlane8': True, - 'txfault': False, - 'txlos_hostlane1': False, - 'txlos_hostlane2': False, - 'txlos_hostlane3': False, - 'txlos_hostlane4': False, - 'txlos_hostlane5': False, - 'txlos_hostlane6': False, - 'txlos_hostlane7': False, - 'txlos_hostlane8': False, - 'txcdrlol_hostlane1': False, - 'txcdrlol_hostlane2': False, - 'txcdrlol_hostlane3': False, - 'txcdrlol_hostlane4': False, - 'txcdrlol_hostlane5': False, - 'txcdrlol_hostlane6': False, - 'txcdrlol_hostlane7': False, - 'txcdrlol_hostlane8': False, - 'rxlos': False, - 'rxcdrlol': False, - 'config_state_hostlane1': 'ConfigSuccess', - 'config_state_hostlane2': 'ConfigSuccess', - 'config_state_hostlane3': 'ConfigSuccess', - 'config_state_hostlane4': 'ConfigSuccess', - 'config_state_hostlane5': 'ConfigSuccess', - 'config_state_hostlane6': 'ConfigSuccess', - 'config_state_hostlane7': 'ConfigSuccess', - 'config_state_hostlane8': 'ConfigSuccess', - 'dpinit_pending_hostlane1': False, - 'dpinit_pending_hostlane2': False, - 'dpinit_pending_hostlane3': False, - 'dpinit_pending_hostlane4': False, - 'dpinit_pending_hostlane5': False, - 'dpinit_pending_hostlane6': False, - 'dpinit_pending_hostlane7': False, - 'dpinit_pending_hostlane8': False, - 'tuning_in_progress': False, - 'wavelength_unlock_status': False, - 'target_output_power_oor': False, - 'fine_tuning_oor': False, - 'tuning_not_accepted': False, - 'invalid_channel_num': False, - 'tuning_complete': True, - 'temphighalarm_flag': False, 'templowalarm_flag': False, - 'temphighwarning_flag': False, 'templowwarning_flag': False, - 'vcchighalarm_flag': False, 'vcclowalarm_flag': False, - 'vcchighwarning_flag': False, 'vcclowwarning_flag': False, - 'lasertemphighalarm_flag': False, 'lasertemplowalarm_flag': False, - 'lasertemphighwarning_flag': False, 'lasertemplowwarning_flag': False, - 'txpowerhighalarm_flag': False, 'txpowerlowalarm_flag': False, - 'txpowerhighwarning_flag': False, 'txpowerlowwarning_flag': False, - 'rxpowerhighalarm_flag': False, 'rxpowerlowalarm_flag': False, - 'rxpowerhighwarning_flag': False, 'rxpowerlowwarning_flag': False, - 'txbiashighalarm_flag': False, 'txbiaslowalarm_flag': False, - 'txbiashighwarning_flag': False, 'txbiaslowwarning_flag': False, - 'prefecberhighalarm_flag': False, 'prefecberlowalarm_flag': False, - 'prefecberhighwarning_flag': False, 'prefecberlowwarning_flag': False, - 'postfecberhighalarm_flag': False, 'postfecberlowalarm_flag': False, - 'postfecberhighwarning_flag': False, 'postfecberlowwarning_flag': False, - 'biasxihighalarm_flag': False, 'biasxilowalarm_flag': False, - 'biasxihighwarning_flag': False, 'biasxilowwarning_flag': False, - 'biasxqhighalarm_flag': False, 'biasxqlowalarm_flag': False, - 'biasxqhighwarning_flag': False, 'biasxqlowwarning_flag': False, - 'biasxphighalarm_flag': False, 'biasxplowalarm_flag': False, - 'biasxphighwarning_flag': False, 'biasxplowwarning_flag': False, - 'biasyihighalarm_flag': False, 'biasyilowalarm_flag': False, - 'biasyihighwarning_flag': False, 'biasyilowwarning_flag': False, - 'biasyqhighalarm_flag': False, 'biasyqlowalarm_flag': False, - 'biasyqhighwarning_flag': False, 'biasyqlowwarning_flag': False, - 'biasyphighalarm_flag': False, 'biasyplowalarm_flag': False, - 'biasyphighwarning_flag': False, 'biasyplowwarning_flag': False, - 'cdshorthighalarm_flag': False, 'cdshortlowalarm_flag': False, - 'cdshorthighwarning_flag': False, 'cdshortlowwarning_flag': False, - 'cdlonghighalarm_flag': False, 'cdlonglowalarm_flag': False, - 'cdlonghighwarning_flag': False, 'cdlonglowwarning_flag': False, - 'dgdhighalarm_flag': False, 'dgdlowalarm_flag': False, - 'dgdhighwarning_flag': False, 'dgdlowwarning_flag': False, - 'sopmdhighalarm_flag': False, 'sopmdlowalarm_flag': False, - 'sopmdhighwarning_flag': False, 'sopmdlowwarning_flag': False, - 'pdlhighalarm_flag': False, 'pdllowalarm_flag': False, - 'pdlhighwarning_flag': False, 'pdllowwarning_flag': False, - 'osnrhighalarm_flag': False, 'osnrlowalarm_flag': False, - 'osnrhighwarning_flag': False, 'osnrlowwarning_flag': False, - 'esnrhighalarm_flag': False, 'esnrlowalarm_flag': False, - 'esnrhighwarning_flag': False, 'esnrlowwarning_flag': False, - 'cfohighalarm_flag': False, 'cfolowalarm_flag': False, - 'cfohighwarning_flag': False, 'cfolowwarning_flag': False, - 'txcurrpowerhighalarm_flag': False, 'txcurrpowerlowalarm_flag': False, - 'txcurrpowerhighwarning_flag': False, 'txcurrpowerlowwarning_flag': False, - 'rxtotpowerhighalarm_flag': False, 'rxtotpowerlowalarm_flag': False, - 'rxtotpowerhighwarning_flag': False, 'rxtotpowerlowwarning_flag': False, - 'rxsigpowerhighalarm_flag': False, 'rxsigpowerlowalarm_flag': False, - 'rxsigpowerhighwarning_flag': False, 'rxsigpowerlowwarning_flag': False, - - } - ) - ]) - def test_get_transceiver_status(self, mock_response, expected): - api = self.mock_cmis_api() - api.get_module_state = MagicMock() - api.get_module_state.return_value = mock_response[0] - api.get_module_fault_cause = MagicMock() - api.get_module_fault_cause.return_value = mock_response[1] - api.get_module_firmware_fault_state_changed = MagicMock() - api.get_module_firmware_fault_state_changed.return_value = mock_response[2] - api.get_datapath_state = MagicMock() - api.get_datapath_state.return_value = mock_response[3] - api.get_tx_output_status = MagicMock() - api.get_tx_output_status.return_value = mock_response[4] - api.get_rx_output_status = MagicMock() - api.get_rx_output_status.return_value = mock_response[5] - api.get_tx_fault = MagicMock() - api.get_tx_fault.return_value = mock_response[6] - api.get_tx_los = MagicMock() - api.get_tx_los.return_value = mock_response[7] - api.get_tx_cdr_lol = MagicMock() - api.get_tx_cdr_lol.return_value = mock_response[8] - api.get_rx_los = MagicMock() - api.get_rx_los.return_value = mock_response[9] - api.get_rx_cdr_lol = MagicMock() - api.get_rx_cdr_lol.return_value = mock_response[10] - api.get_config_datapath_hostlane_status = MagicMock() - api.get_config_datapath_hostlane_status.return_value = mock_response[11] - api.get_dpinit_pending = MagicMock() - api.get_dpinit_pending.return_value = mock_response[12] - api.get_tuning_in_progress = MagicMock() - api.get_tuning_in_progress.return_value = mock_response[13] - api.get_wavelength_unlocked = MagicMock() - api.get_wavelength_unlocked.return_value = mock_response[14] - api.get_laser_tuning_summary = MagicMock() - api.get_laser_tuning_summary.return_value = mock_response[15] - api.get_module_level_flag = MagicMock() - api.get_module_level_flag.return_value = mock_response[16] - api.get_aux_mon_type = MagicMock() - api.get_aux_mon_type.return_value = mock_response[17] - api.get_tx_power_flag = MagicMock() - api.get_tx_power_flag.return_value = mock_response[18] - api.get_rx_power_flag = MagicMock() - api.get_rx_power_flag.return_value = mock_response[19] - api.get_tx_bias_flag = MagicMock() - api.get_tx_bias_flag.return_value = mock_response[20] - api.get_VDM = MagicMock() - api.get_VDM.return_value = mock_response[21] - result = api.get_transceiver_status() - assert result == expected + api.cdb.get_module_fw_info = MagicMock() + api.cdb.get_module_fw_info.return_value = mock_response + api.cdb.module_fw_switch() - @pytest.mark.parametrize("mock_response, expected", [ - ( - { - 'preFEC_BER_avg': 0.001, 'preFEC_BER_min': 0.0008, 'preFEC_BER_max': 0.0012, - 'preFEC_uncorr_frame_ratio_avg': 0, 'preFEC_uncorr_frame_ratio_min': 0, 'preFEC_uncorr_frame_ratio_max': 0, - 'rx_cd_avg': 1400, 'rx_cd_min': 1300, 'rx_cd_max': 1500, - 'rx_dgd_avg': 7.0, 'rx_dgd_min': 5.5, 'rx_dgd_max': 9.2, - 'rx_sopmd_avg': 40, 'rx_sopmd_min': 20, 'rx_sopmd_max': 60, - 'rx_pdl_avg': 1.0, 'rx_pdl_min': 0.8, 'rx_pdl_max': 1.2, - 'rx_osnr_avg': 28, 'rx_osnr_min': 26, 'rx_osnr_max': 30, - 'rx_esnr_avg': 17, 'rx_esnr_min': 15, 'rx_esnr_max': 18, - 'rx_cfo_avg': 200, 'rx_cfo_min': 150, 'rx_cfo_max': 250, - 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, - 'rx_power_avg': -8, 'rx_power_min': -7, 'rx_power_max': -9, - 'rx_sigpwr_avg': -8, 'rx_sigpwr_min': -7, 'rx_sigpwr_max': -9, - 'rx_soproc_avg': 5, 'rx_soproc_min': 3, 'rx_soproc_max': 8, - }, - { - 'prefec_ber_avg': 0.001, 'prefec_ber_min': 0.0008, 'prefec_ber_max': 0.0012, - 'uncorr_frames_avg': 0, 'uncorr_frames_min': 0, 'uncorr_frames_max': 0, - 'cd_avg': 1400, 'cd_min': 1300, 'cd_max': 1500, - 'dgd_avg': 7.0, 'dgd_min': 5.5, 'dgd_max': 9.2, - 'sopmd_avg': 40, 'sopmd_min': 20, 'sopmd_max': 60, - 'pdl_avg': 1.0, 'pdl_min': 0.8, 'pdl_max': 1.2, - 'osnr_avg': 28, 'osnr_min': 26, 'osnr_max': 30, - 'esnr_avg': 17, 'esnr_min': 15, 'esnr_max': 18, - 'cfo_avg': 200, 'cfo_min': 150, 'cfo_max': 250, - 'tx_power_avg': -10, 'tx_power_min': -9.5, 'tx_power_max': -10.5, - 'rx_tot_power_avg': -8, 'rx_tot_power_min': -7, 'rx_tot_power_max': -9, - 'rx_sig_power_avg': -8, 'rx_sig_power_min': -7, 'rx_sig_power_max': -9, - 'soproc_avg': 5, 'soproc_min': 3, 'soproc_max': 8, - } - ) - ]) - def test_get_transceiver_PM(self, mock_response, expected): - api = self.mock_cmis_api() - api.get_PM = MagicMock() - api.get_PM.return_value = mock_response - result = api.get_transceiver_PM() - assert result == expected - @pytest.mark.parametrize("mock_response, expected",[ - ( - [ - False, - False, - [False, False, False, False, False, False, False, False], - [False, False, False, False, False, False, False, False] - ], - { - 'media_output_loopback': False, - 'media_input_loopback': False, - 'host_output_loopback_lane1': False, - 'host_output_loopback_lane2': False, - 'host_output_loopback_lane3': False, - 'host_output_loopback_lane4': False, - 'host_output_loopback_lane5': False, - 'host_output_loopback_lane6': False, - 'host_output_loopback_lane7': False, - 'host_output_loopback_lane8': False, - 'host_input_loopback_lane1': False, - 'host_input_loopback_lane2': False, - 'host_input_loopback_lane3': False, - 'host_input_loopback_lane4': False, - 'host_input_loopback_lane5': False, - 'host_input_loopback_lane6': False, - 'host_input_loopback_lane7': False, - 'host_input_loopback_lane8': False - } - ) - ]) - def test_get_transceiver_loopback(self, mock_response, expected): - api = self.mock_cmis_api() - api.get_media_output_loopback = MagicMock() - api.get_media_output_loopback.return_value = mock_response[0] - api.get_media_input_loopback = MagicMock() - api.get_media_input_loopback.return_value = mock_response[1] - api.get_host_output_loopback = MagicMock() - api.get_host_output_loopback.return_value = mock_response[2] - api.get_host_input_loopback = MagicMock() - api.get_host_input_loopback.return_value = mock_response[3] - result = api.get_transceiver_loopback() - assert result == expected diff --git a/tests/sonic_xcvr/test_cmisCDB.py b/tests/sonic_xcvr/test_cmisCDB.py index 497ae256c..ce0a88813 100644 --- a/tests/sonic_xcvr/test_cmisCDB.py +++ b/tests/sonic_xcvr/test_cmisCDB.py @@ -10,7 +10,7 @@ class TestCDB(object): def mock_cdb_api(self): - codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + codes = CmisCode mem_map = CmisMemMap(codes) reader = MagicMock(return_value=None) writer = MagicMock() @@ -59,8 +59,8 @@ def test_read_cdb(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.xcvr_eeprom.read = MagicMock() cdb.xcvr_eeprom.read.side_effect = mock_response[0:2] - cdb.xcvr_eeprom.read_flexible = MagicMock() - cdb.xcvr_eeprom.read_flexible.return_value = mock_response[2] + cdb.xcvr_eeprom.read_raw = MagicMock() + cdb.xcvr_eeprom.read_raw.return_value = mock_response[2] result = cdb.read_cdb() assert result == expected diff --git a/tests/sonic_xcvr/test_cmisVDM.py b/tests/sonic_xcvr/test_cmisVDM.py index c98bf06d0..f1258ecb7 100644 --- a/tests/sonic_xcvr/test_cmisVDM.py +++ b/tests/sonic_xcvr/test_cmisVDM.py @@ -10,7 +10,7 @@ class TestVDM(object): def mock_vdm_api(self): - codes = {'sff8024':Sff8024, 'cmis_code':CmisCode} + codes = CmisCode mem_map = CmisMemMap(codes) reader = MagicMock(return_value=None) writer = MagicMock() @@ -65,11 +65,11 @@ def test_get_F16(self, input_param, expected): } ) ]) - def test_get_VDM_page(self, input_param, mock_response, expected): + def test_get_vdm_page(self, input_param, mock_response, expected): vdm = self.mock_vdm_api() - vdm.xcvr_eeprom.read_flexible = MagicMock() - vdm.xcvr_eeprom.read_flexible.side_effect = mock_response - result = vdm.get_VDM_page(*input_param) + vdm.xcvr_eeprom.read_raw = MagicMock() + vdm.xcvr_eeprom.read_raw.side_effect = mock_response + result = vdm.get_vdm_page(*input_param) assert result == expected @pytest.mark.parametrize("mock_response, expected", [ @@ -102,14 +102,14 @@ def test_get_VDM_page(self, input_param, mock_response, expected): ) ]) - def test_get_VDM_allpage(self, mock_response, expected): + def test_get_vdm_allpage(self, mock_response, expected): vdm = self.mock_vdm_api() vdm.xcvr_eeprom.read = MagicMock() vdm.xcvr_eeprom.read.return_value = mock_response[0] - vdm.xcvr_eeprom.read_flexible = MagicMock() - vdm.xcvr_eeprom.read_flexible.return_value = mock_response[1] + vdm.xcvr_eeprom.read_raw = MagicMock() + vdm.xcvr_eeprom.read_raw.return_value = mock_response[1] # input_param = [0x20, mock_response[1]] - vdm.get_VDM_page = MagicMock() - vdm.get_VDM_page.side_effect = mock_response[2:] - result = vdm.get_VDM_allpage() + vdm.get_vdm_page = MagicMock() + vdm.get_vdm_page.side_effect = mock_response[2:] + result = vdm.get_vdm_allpage() assert result == expected \ No newline at end of file From 44c241276c7cf366c184a8d5ebf1ceed6c743fc7 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Wed, 27 Oct 2021 14:16:16 -0700 Subject: [PATCH 15/16] 1. split get_transceiver_xxx functions to cmis.py and c_cmis.py with only relevant functions. 2. resolved other comments --- .../sonic_xcvr/api/public/c_cmis.py | 579 ++++++------------ .../sonic_xcvr/api/public/cmis.py | 495 ++++++++++++++- .../sonic_xcvr/api/public/cmisCDB.py | 31 +- .../sonic_xcvr/api/public/cmisVDM.py | 41 ++ .../sonic_xcvr/codes/public/sff8024.py | 4 +- .../sonic_xcvr/xcvr_api_factory.py | 2 +- tests/sonic_xcvr/test_ccmis.py | 430 +++++-------- tests/sonic_xcvr/test_cmis.py | 465 +++++++++++++- tests/sonic_xcvr/test_cmisCDB.py | 36 +- 9 files changed, 1332 insertions(+), 751 deletions(-) diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index ae086d621..e29d6bfbb 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -106,7 +106,7 @@ def set_laser_freq(self, freq): ''' This function sets the laser frequency. Unit in GHz ZR application will not support fine tuning of the laser - Microsoft will only supports 75 GHz frequency grid + SONiC will only support 75 GHz frequency grid ''' grid_supported, low_ch_num, hi_ch_num, _, _ = self.get_supported_freq_config() grid_supported_75GHz = (grid_supported >> 7) & 0x1 @@ -124,6 +124,17 @@ def set_laser_freq(self, freq): self.set_low_power(False) time.sleep(1) + def set_tx_power(self, tx_power): + ''' + This function sets the TX output power. Unit in dBm + ''' + min_prog_tx_output_power, max_prog_tx_output_power = self.get_supported_power_config() + if tx_power > max_prog_tx_output_power or tx_power < min_prog_tx_output_power: + raise ValueError('Provisioned TX power out of range. Max: %.1f; Min: %.1f dBm.' + %(max_prog_tx_output_power, min_prog_tx_output_power)) + self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, tx_power) + time.sleep(1) + def get_pm_all(self): ''' This function returns the PMs reported in Page 34h and 35h in OIF C-CMIS document @@ -263,34 +274,7 @@ def get_transceiver_info(self): supported_min_laser_freq = FLOAT ; support minimum laser frequency ================================================================================ """ - trans_info = dict() - trans_info['module_media_type'] = self.get_module_media_type() - trans_info['host_electrical_interface'] = self.get_host_electrical_interface() - trans_info['media_interface_code'] = self.get_module_media_interface() - trans_info['host_lane_count'] = self.get_host_lane_count() - trans_info['media_lane_count'] = self.get_media_lane_count() - trans_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option() - trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() - apsel_dict = self.get_active_apsel_hostlane() - trans_info['active_apsel_hostlane1'] = apsel_dict['hostlane1'] - trans_info['active_apsel_hostlane2'] = apsel_dict['hostlane2'] - trans_info['active_apsel_hostlane3'] = apsel_dict['hostlane3'] - trans_info['active_apsel_hostlane4'] = apsel_dict['hostlane4'] - trans_info['active_apsel_hostlane5'] = apsel_dict['hostlane5'] - trans_info['active_apsel_hostlane6'] = apsel_dict['hostlane6'] - trans_info['active_apsel_hostlane7'] = apsel_dict['hostlane7'] - trans_info['active_apsel_hostlane8'] = apsel_dict['hostlane8'] - trans_info['media_interface_technology'] = self.get_media_interface_technology() - trans_info['hardwarerev'] = self.get_module_hardware_revision() - trans_info['serialnum'] = self.get_vendor_serial() - trans_info['manufacturename'] = self.get_vendor_name() - trans_info['vendor_rev'] = self.get_vendor_rev() - trans_info['vendor_oui'] = self.get_vendor_OUI() - trans_info['vendor_date'] = self.get_vendor_date() - trans_info['connector_type'] = self.get_connector_type() - trans_info['specification_compliance'] = self.get_cmis_rev() - trans_info['active_firmware'] = self.get_module_active_firmware() - trans_info['inactive_firmware'] = self.get_module_inactive_firmware() + trans_info = super(CCmisApi,self).get_transceiver_info() min_power, max_power = self.get_supported_power_config() trans_info['supported_max_tx_power'] = max_power trans_info['supported_min_tx_power'] = min_power @@ -339,45 +323,30 @@ def get_transceiver_bulk_status(self): bias_yp = FLOAT ; modulator bias yp ======================================================================== """ - trans_dom = dict() - case_temp_dict = self.get_module_temperature() - trans_dom['temperature'] = case_temp_dict['monitor value'] - voltage_dict = self.get_module_voltage() - trans_dom['voltage'] = voltage_dict['monitor value'] - tx_power_dict = self.get_txpower() - trans_dom['txpower'] = tx_power_dict['monitor value lane1'] - rx_power_dict = self.get_rxpower() - trans_dom['rxpower'] = rx_power_dict['monitor value lane1'] - tx_bias_current_dict = self.get_txbias() - trans_dom['txbias'] = tx_bias_current_dict['monitor value lane1'] - laser_temp_dict = self.get_laser_temperature() - trans_dom['laser_temperature'] = laser_temp_dict['monitor value'] - vdm_dict = self.get_vdm() - trans_dom['prefec_ber'] = vdm_dict['Pre-FEC BER Average Media Input'][1][0] - trans_dom['postfec_ber'] = vdm_dict['Errored Frames Average Media Input'][1][0] - trans_dom['bias_xi'] = vdm_dict['Modulator Bias X/I [%]'][1][0] - trans_dom['bias_xq'] = vdm_dict['Modulator Bias X/Q [%]'][1][0] - trans_dom['bias_xp'] = vdm_dict['Modulator Bias X_Phase [%]'][1][0] - trans_dom['bias_yi'] = vdm_dict['Modulator Bias Y/I [%]'][1][0] - trans_dom['bias_yq'] = vdm_dict['Modulator Bias Y/Q [%]'][1][0] - trans_dom['bias_yp'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][0] - trans_dom['cd_shortlink'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][0] + trans_dom = super(CCmisApi,self).get_transceiver_bulk_status() + trans_dom['bias_xi'] = self.vdm_dict['Modulator Bias X/I [%]'][1][0] + trans_dom['bias_xq'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][0] + trans_dom['bias_xp'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][0] + trans_dom['bias_yi'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][0] + trans_dom['bias_yq'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][0] + trans_dom['bias_yp'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][0] + trans_dom['cd_shortlink'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][0] try: - trans_dom['cd_longlink'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][0] + trans_dom['cd_longlink'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][0] except KeyError: pass - trans_dom['dgd'] = vdm_dict['DGD [ps]'][1][0] + trans_dom['dgd'] = self.vdm_dict['DGD [ps]'][1][0] try: - trans_dom['sopmd'] = vdm_dict['SOPMD [ps^2]'][1][0] + trans_dom['sopmd'] = self.vdm_dict['SOPMD [ps^2]'][1][0] except KeyError: pass - trans_dom['pdl'] = vdm_dict['PDL [dB]'][1][0] - trans_dom['osnr'] = vdm_dict['OSNR [dB]'][1][0] - trans_dom['esnr'] = vdm_dict['eSNR [dB]'][1][0] - trans_dom['cfo'] = vdm_dict['CFO [MHz]'][1][0] - trans_dom['tx_curr_power'] = vdm_dict['Tx Power [dBm]'][1][0] - trans_dom['rx_tot_power'] = vdm_dict['Rx Total Power [dBm]'][1][0] - trans_dom['rx_sig_power'] = vdm_dict['Rx Signal Power [dBm]'][1][0] + trans_dom['pdl'] = self.vdm_dict['PDL [dB]'][1][0] + trans_dom['osnr'] = self.vdm_dict['OSNR [dB]'][1][0] + trans_dom['esnr'] = self.vdm_dict['eSNR [dB]'][1][0] + trans_dom['cfo'] = self.vdm_dict['CFO [MHz]'][1][0] + trans_dom['tx_curr_power'] = self.vdm_dict['Tx Power [dBm]'][1][0] + trans_dom['rx_tot_power'] = self.vdm_dict['Rx Total Power [dBm]'][1][0] + trans_dom['rx_sig_power'] = self.vdm_dict['Rx Signal Power [dBm]'][1][0] trans_dom['laser_config_freq'] = self.get_laser_config_freq() trans_dom['laser_curr_freq'] = self.get_current_laser_freq() trans_dom['tx_config_power'] = self.get_tx_config_power() @@ -494,120 +463,81 @@ def get_transceiver_threshold_info(self): rxsigpowerlowwarning = FLOAT ; rxsigpower low warning threshold in dbm ======================================================================== """ - trans_dom_th = dict() - case_temp_dict = self.get_module_temperature() - trans_dom_th['temphighalarm'] = case_temp_dict['high alarm'] - trans_dom_th['templowalarm'] = case_temp_dict['low alarm'] - trans_dom_th['temphighwarning'] = case_temp_dict['high warn'] - trans_dom_th['templowwarning'] = case_temp_dict['low warn'] - voltage_dict = self.get_module_voltage() - trans_dom_th['vcchighalarm'] = voltage_dict['high alarm'] - trans_dom_th['vcclowalarm'] = voltage_dict['low alarm'] - trans_dom_th['vcchighwarning'] = voltage_dict['high warn'] - trans_dom_th['vcclowwarning'] = voltage_dict['low warn'] - tx_power_dict = self.get_txpower() - trans_dom_th['txpowerhighalarm'] = tx_power_dict['high alarm'] - trans_dom_th['txpowerlowalarm'] = tx_power_dict['low alarm'] - trans_dom_th['txpowerhighwarning'] = tx_power_dict['high warn'] - trans_dom_th['txpowerlowwarning'] = tx_power_dict['low warn'] - rx_power_dict = self.get_rxpower() - trans_dom_th['rxpowerhighalarm'] = rx_power_dict['high alarm'] - trans_dom_th['rxpowerlowalarm'] = rx_power_dict['low alarm'] - trans_dom_th['rxpowerhighwarning'] = rx_power_dict['high warn'] - trans_dom_th['rxpowerlowwarning'] = rx_power_dict['low warn'] - tx_bias_current_dict = self.get_txbias() - trans_dom_th['txbiashighalarm'] = tx_bias_current_dict['high alarm'] - trans_dom_th['txbiaslowalarm'] = tx_bias_current_dict['low alarm'] - trans_dom_th['txbiashighwarning'] = tx_bias_current_dict['high warn'] - trans_dom_th['txbiaslowwarning'] = tx_bias_current_dict['low warn'] - laser_temp_dict = self.get_laser_temperature() - trans_dom_th['lasertemphighalarm'] = laser_temp_dict['high alarm'] - trans_dom_th['lasertemplowalarm'] = laser_temp_dict['low alarm'] - trans_dom_th['lasertemphighwarning'] = laser_temp_dict['high warn'] - trans_dom_th['lasertemplowwarning'] = laser_temp_dict['low warn'] - vdm_dict = self.get_vdm() - trans_dom_th['prefecberhighalarm'] = vdm_dict['Pre-FEC BER Average Media Input'][1][1] - trans_dom_th['prefecberlowalarm'] = vdm_dict['Pre-FEC BER Average Media Input'][1][2] - trans_dom_th['prefecberhighwarning'] = vdm_dict['Pre-FEC BER Average Media Input'][1][3] - trans_dom_th['prefecberlowwarning'] = vdm_dict['Pre-FEC BER Average Media Input'][1][4] - trans_dom_th['postfecberhighalarm'] = vdm_dict['Errored Frames Average Media Input'][1][1] - trans_dom_th['postfecberlowalarm'] = vdm_dict['Errored Frames Average Media Input'][1][2] - trans_dom_th['postfecberhighwarning'] = vdm_dict['Errored Frames Average Media Input'][1][3] - trans_dom_th['postfecberlowwarning'] = vdm_dict['Errored Frames Average Media Input'][1][4] - trans_dom_th['biasxihighalarm'] = vdm_dict['Modulator Bias X/I [%]'][1][1] - trans_dom_th['biasxilowalarm'] = vdm_dict['Modulator Bias X/I [%]'][1][2] - trans_dom_th['biasxihighwarning'] = vdm_dict['Modulator Bias X/I [%]'][1][3] - trans_dom_th['biasxilowwarning'] = vdm_dict['Modulator Bias X/I [%]'][1][4] - trans_dom_th['biasxqhighalarm'] = vdm_dict['Modulator Bias X/Q [%]'][1][1] - trans_dom_th['biasxqlowalarm'] = vdm_dict['Modulator Bias X/Q [%]'][1][2] - trans_dom_th['biasxqhighwarning'] = vdm_dict['Modulator Bias X/Q [%]'][1][3] - trans_dom_th['biasxqlowwarning'] = vdm_dict['Modulator Bias X/Q [%]'][1][4] - trans_dom_th['biasxphighalarm'] = vdm_dict['Modulator Bias X_Phase [%]'][1][1] - trans_dom_th['biasxplowalarm'] = vdm_dict['Modulator Bias X_Phase [%]'][1][2] - trans_dom_th['biasxphighwarning'] = vdm_dict['Modulator Bias X_Phase [%]'][1][3] - trans_dom_th['biasxplowwarning'] = vdm_dict['Modulator Bias X_Phase [%]'][1][4] - trans_dom_th['biasyihighalarm'] = vdm_dict['Modulator Bias Y/I [%]'][1][1] - trans_dom_th['biasyilowalarm'] = vdm_dict['Modulator Bias Y/I [%]'][1][2] - trans_dom_th['biasyihighwarning'] = vdm_dict['Modulator Bias Y/I [%]'][1][3] - trans_dom_th['biasyilowwarning'] = vdm_dict['Modulator Bias Y/I [%]'][1][4] - trans_dom_th['biasyqhighalarm'] = vdm_dict['Modulator Bias Y/Q [%]'][1][1] - trans_dom_th['biasyqlowalarm'] = vdm_dict['Modulator Bias Y/Q [%]'][1][2] - trans_dom_th['biasyqhighwarning'] = vdm_dict['Modulator Bias Y/Q [%]'][1][3] - trans_dom_th['biasyqlowwarning'] = vdm_dict['Modulator Bias Y/Q [%]'][1][4] - trans_dom_th['biasyphighalarm'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][1] - trans_dom_th['biasyplowalarm'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][2] - trans_dom_th['biasyphighwarning'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][3] - trans_dom_th['biasyplowwarning'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][4] - trans_dom_th['cdshorthighalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][1] - trans_dom_th['cdshortlowalarm'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][2] - trans_dom_th['cdshorthighwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][3] - trans_dom_th['cdshortlowwarning'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][4] + trans_dom_th = super(CCmisApi,self).get_transceiver_threshold_info() + trans_dom_th['biasxihighalarm'] = self.vdm_dict['Modulator Bias X/I [%]'][1][1] + trans_dom_th['biasxilowalarm'] = self.vdm_dict['Modulator Bias X/I [%]'][1][2] + trans_dom_th['biasxihighwarning'] = self.vdm_dict['Modulator Bias X/I [%]'][1][3] + trans_dom_th['biasxilowwarning'] = self.vdm_dict['Modulator Bias X/I [%]'][1][4] + trans_dom_th['biasxqhighalarm'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][1] + trans_dom_th['biasxqlowalarm'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][2] + trans_dom_th['biasxqhighwarning'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][3] + trans_dom_th['biasxqlowwarning'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][4] + trans_dom_th['biasxphighalarm'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][1] + trans_dom_th['biasxplowalarm'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][2] + trans_dom_th['biasxphighwarning'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][3] + trans_dom_th['biasxplowwarning'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][4] + trans_dom_th['biasyihighalarm'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][1] + trans_dom_th['biasyilowalarm'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][2] + trans_dom_th['biasyihighwarning'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][3] + trans_dom_th['biasyilowwarning'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][4] + trans_dom_th['biasyqhighalarm'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][1] + trans_dom_th['biasyqlowalarm'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][2] + trans_dom_th['biasyqhighwarning'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][3] + trans_dom_th['biasyqlowwarning'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][4] + trans_dom_th['biasyphighalarm'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][1] + trans_dom_th['biasyplowalarm'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][2] + trans_dom_th['biasyphighwarning'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][3] + trans_dom_th['biasyplowwarning'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][4] + trans_dom_th['cdshorthighalarm'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][1] + trans_dom_th['cdshortlowalarm'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][2] + trans_dom_th['cdshorthighwarning'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][3] + trans_dom_th['cdshortlowwarning'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][4] try: - trans_dom_th['cdlonghighalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][1] - trans_dom_th['cdlonglowalarm'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][2] - trans_dom_th['cdlonghighwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][3] - trans_dom_th['cdlonglowwarning'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][4] + trans_dom_th['cdlonghighalarm'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][1] + trans_dom_th['cdlonglowalarm'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][2] + trans_dom_th['cdlonghighwarning'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][3] + trans_dom_th['cdlonglowwarning'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][4] except KeyError: pass - trans_dom_th['dgdhighalarm'] = vdm_dict['DGD [ps]'][1][1] - trans_dom_th['dgdlowalarm'] = vdm_dict['DGD [ps]'][1][2] - trans_dom_th['dgdhighwarning'] = vdm_dict['DGD [ps]'][1][3] - trans_dom_th['dgdlowwarning'] = vdm_dict['DGD [ps]'][1][4] + trans_dom_th['dgdhighalarm'] = self.vdm_dict['DGD [ps]'][1][1] + trans_dom_th['dgdlowalarm'] = self.vdm_dict['DGD [ps]'][1][2] + trans_dom_th['dgdhighwarning'] = self.vdm_dict['DGD [ps]'][1][3] + trans_dom_th['dgdlowwarning'] = self.vdm_dict['DGD [ps]'][1][4] try: - trans_dom_th['sopmdhighalarm'] = vdm_dict['SOPMD [ps^2]'][1][1] - trans_dom_th['sopmdlowalarm'] = vdm_dict['SOPMD [ps^2]'][1][2] - trans_dom_th['sopmdhighwarning'] = vdm_dict['SOPMD [ps^2]'][1][3] - trans_dom_th['sopmdlowwarning'] = vdm_dict['SOPMD [ps^2]'][1][4] + trans_dom_th['sopmdhighalarm'] = self.vdm_dict['SOPMD [ps^2]'][1][1] + trans_dom_th['sopmdlowalarm'] = self.vdm_dict['SOPMD [ps^2]'][1][2] + trans_dom_th['sopmdhighwarning'] = self.vdm_dict['SOPMD [ps^2]'][1][3] + trans_dom_th['sopmdlowwarning'] = self.vdm_dict['SOPMD [ps^2]'][1][4] except KeyError: pass - trans_dom_th['pdlhighalarm'] = vdm_dict['PDL [dB]'][1][1] - trans_dom_th['pdllowalarm'] = vdm_dict['PDL [dB]'][1][2] - trans_dom_th['pdlhighwarning'] = vdm_dict['PDL [dB]'][1][3] - trans_dom_th['pdllowwarning'] = vdm_dict['PDL [dB]'][1][4] - trans_dom_th['osnrhighalarm'] = vdm_dict['OSNR [dB]'][1][1] - trans_dom_th['osnrlowalarm'] = vdm_dict['OSNR [dB]'][1][2] - trans_dom_th['osnrhighwarning'] = vdm_dict['OSNR [dB]'][1][3] - trans_dom_th['osnrlowwarning'] = vdm_dict['OSNR [dB]'][1][4] - trans_dom_th['esnrhighalarm'] = vdm_dict['eSNR [dB]'][1][1] - trans_dom_th['esnrlowalarm'] = vdm_dict['eSNR [dB]'][1][2] - trans_dom_th['esnrhighwarning'] = vdm_dict['eSNR [dB]'][1][3] - trans_dom_th['esnrlowwarning'] = vdm_dict['eSNR [dB]'][1][4] - trans_dom_th['cfohighalarm'] = vdm_dict['CFO [MHz]'][1][1] - trans_dom_th['cfolowalarm'] = vdm_dict['CFO [MHz]'][1][2] - trans_dom_th['cfohighwarning'] = vdm_dict['CFO [MHz]'][1][3] - trans_dom_th['cfolowwarning'] = vdm_dict['CFO [MHz]'][1][4] - trans_dom_th['txcurrpowerhighalarm'] = vdm_dict['Tx Power [dBm]'][1][1] - trans_dom_th['txcurrpowerlowalarm'] = vdm_dict['Tx Power [dBm]'][1][2] - trans_dom_th['txcurrpowerhighwarning'] = vdm_dict['Tx Power [dBm]'][1][3] - trans_dom_th['txcurrpowerlowwarning'] = vdm_dict['Tx Power [dBm]'][1][4] - trans_dom_th['rxtotpowerhighalarm'] = vdm_dict['Rx Total Power [dBm]'][1][1] - trans_dom_th['rxtotpowerlowalarm'] = vdm_dict['Rx Total Power [dBm]'][1][2] - trans_dom_th['rxtotpowerhighwarning'] = vdm_dict['Rx Total Power [dBm]'][1][3] - trans_dom_th['rxtotpowerlowwarning'] = vdm_dict['Rx Total Power [dBm]'][1][4] - trans_dom_th['rxsigpowerhighalarm'] = vdm_dict['Rx Signal Power [dBm]'][1][1] - trans_dom_th['rxsigpowerlowalarm'] = vdm_dict['Rx Signal Power [dBm]'][1][2] - trans_dom_th['rxsigpowerhighwarning'] = vdm_dict['Rx Signal Power [dBm]'][1][3] - trans_dom_th['rxsigpowerlowwarning'] = vdm_dict['Rx Signal Power [dBm]'][1][4] + trans_dom_th['pdlhighalarm'] = self.vdm_dict['PDL [dB]'][1][1] + trans_dom_th['pdllowalarm'] = self.vdm_dict['PDL [dB]'][1][2] + trans_dom_th['pdlhighwarning'] = self.vdm_dict['PDL [dB]'][1][3] + trans_dom_th['pdllowwarning'] = self.vdm_dict['PDL [dB]'][1][4] + trans_dom_th['osnrhighalarm'] = self.vdm_dict['OSNR [dB]'][1][1] + trans_dom_th['osnrlowalarm'] = self.vdm_dict['OSNR [dB]'][1][2] + trans_dom_th['osnrhighwarning'] = self.vdm_dict['OSNR [dB]'][1][3] + trans_dom_th['osnrlowwarning'] = self.vdm_dict['OSNR [dB]'][1][4] + trans_dom_th['esnrhighalarm'] = self.vdm_dict['eSNR [dB]'][1][1] + trans_dom_th['esnrlowalarm'] = self.vdm_dict['eSNR [dB]'][1][2] + trans_dom_th['esnrhighwarning'] = self.vdm_dict['eSNR [dB]'][1][3] + trans_dom_th['esnrlowwarning'] = self.vdm_dict['eSNR [dB]'][1][4] + trans_dom_th['cfohighalarm'] = self.vdm_dict['CFO [MHz]'][1][1] + trans_dom_th['cfolowalarm'] = self.vdm_dict['CFO [MHz]'][1][2] + trans_dom_th['cfohighwarning'] = self.vdm_dict['CFO [MHz]'][1][3] + trans_dom_th['cfolowwarning'] = self.vdm_dict['CFO [MHz]'][1][4] + trans_dom_th['txcurrpowerhighalarm'] = self.vdm_dict['Tx Power [dBm]'][1][1] + trans_dom_th['txcurrpowerlowalarm'] = self.vdm_dict['Tx Power [dBm]'][1][2] + trans_dom_th['txcurrpowerhighwarning'] = self.vdm_dict['Tx Power [dBm]'][1][3] + trans_dom_th['txcurrpowerlowwarning'] = self.vdm_dict['Tx Power [dBm]'][1][4] + trans_dom_th['rxtotpowerhighalarm'] = self.vdm_dict['Rx Total Power [dBm]'][1][1] + trans_dom_th['rxtotpowerlowalarm'] = self.vdm_dict['Rx Total Power [dBm]'][1][2] + trans_dom_th['rxtotpowerhighwarning'] = self.vdm_dict['Rx Total Power [dBm]'][1][3] + trans_dom_th['rxtotpowerlowwarning'] = self.vdm_dict['Rx Total Power [dBm]'][1][4] + trans_dom_th['rxsigpowerhighalarm'] = self.vdm_dict['Rx Signal Power [dBm]'][1][1] + trans_dom_th['rxsigpowerlowalarm'] = self.vdm_dict['Rx Signal Power [dBm]'][1][2] + trans_dom_th['rxsigpowerhighwarning'] = self.vdm_dict['Rx Signal Power [dBm]'][1][3] + trans_dom_th['rxsigpowerlowwarning'] = self.vdm_dict['Rx Signal Power [dBm]'][1][4] return trans_dom_th def get_transceiver_status(self): @@ -787,75 +717,7 @@ def get_transceiver_status(self): rxsigpowerlowwarning_flag = BOOLEAN ; rxsigpower low warning flag ================================================================================ """ - trans_status = dict() - trans_status['module_state'] = self.get_module_state() - trans_status['module_fault_cause'] = self.get_module_fault_cause() - dp_fw_fault, module_fw_fault, module_state_changed = self.get_module_firmware_fault_state_changed() - trans_status['datapath_firmware_fault'] = dp_fw_fault - trans_status['module_firmware_fault'] = module_fw_fault - trans_status['module_state_changed'] = module_state_changed - dp_state_dict = self.get_datapath_state() - trans_status['datapath_hostlane1'] = dp_state_dict['dp_lane1'] - trans_status['datapath_hostlane2'] = dp_state_dict['dp_lane2'] - trans_status['datapath_hostlane3'] = dp_state_dict['dp_lane3'] - trans_status['datapath_hostlane4'] = dp_state_dict['dp_lane4'] - trans_status['datapath_hostlane5'] = dp_state_dict['dp_lane5'] - trans_status['datapath_hostlane6'] = dp_state_dict['dp_lane6'] - trans_status['datapath_hostlane7'] = dp_state_dict['dp_lane7'] - trans_status['datapath_hostlane8'] = dp_state_dict['dp_lane8'] - tx_output_status_dict = self.get_tx_output_status() - trans_status['txoutput_status'] = tx_output_status_dict['TX_lane1'] - rx_output_status_dict = self.get_rx_output_status() - trans_status['rxoutput_status_hostlane1'] = rx_output_status_dict['RX_lane1'] - trans_status['rxoutput_status_hostlane2'] = rx_output_status_dict['RX_lane2'] - trans_status['rxoutput_status_hostlane3'] = rx_output_status_dict['RX_lane3'] - trans_status['rxoutput_status_hostlane4'] = rx_output_status_dict['RX_lane4'] - trans_status['rxoutput_status_hostlane5'] = rx_output_status_dict['RX_lane5'] - trans_status['rxoutput_status_hostlane6'] = rx_output_status_dict['RX_lane6'] - trans_status['rxoutput_status_hostlane7'] = rx_output_status_dict['RX_lane7'] - trans_status['rxoutput_status_hostlane8'] = rx_output_status_dict['RX_lane8'] - tx_fault_dict = self.get_tx_fault() - trans_status['txfault'] = tx_fault_dict['TX_lane1'] - tx_los_dict = self.get_tx_los() - trans_status['txlos_hostlane1'] = tx_los_dict['TX_lane1'] - trans_status['txlos_hostlane2'] = tx_los_dict['TX_lane2'] - trans_status['txlos_hostlane3'] = tx_los_dict['TX_lane3'] - trans_status['txlos_hostlane4'] = tx_los_dict['TX_lane4'] - trans_status['txlos_hostlane5'] = tx_los_dict['TX_lane5'] - trans_status['txlos_hostlane6'] = tx_los_dict['TX_lane6'] - trans_status['txlos_hostlane7'] = tx_los_dict['TX_lane7'] - trans_status['txlos_hostlane8'] = tx_los_dict['TX_lane8'] - tx_lol_dict = self.get_tx_cdr_lol() - trans_status['txcdrlol_hostlane1'] = tx_lol_dict['TX_lane1'] - trans_status['txcdrlol_hostlane2'] = tx_lol_dict['TX_lane2'] - trans_status['txcdrlol_hostlane3'] = tx_lol_dict['TX_lane3'] - trans_status['txcdrlol_hostlane4'] = tx_lol_dict['TX_lane4'] - trans_status['txcdrlol_hostlane5'] = tx_lol_dict['TX_lane5'] - trans_status['txcdrlol_hostlane6'] = tx_lol_dict['TX_lane6'] - trans_status['txcdrlol_hostlane7'] = tx_lol_dict['TX_lane7'] - trans_status['txcdrlol_hostlane8'] = tx_lol_dict['TX_lane8'] - rx_los_dict = self.get_rx_los() - trans_status['rxlos'] = rx_los_dict['RX_lane1'] - rx_lol_dict = self.get_rx_cdr_lol() - trans_status['rxcdrlol'] = rx_lol_dict['RX_lane1'] - config_status_dict = self.get_config_datapath_hostlane_status() - trans_status['config_state_hostlane1'] = config_status_dict['config_DP_status_hostlane1'] - trans_status['config_state_hostlane2'] = config_status_dict['config_DP_status_hostlane2'] - trans_status['config_state_hostlane3'] = config_status_dict['config_DP_status_hostlane3'] - trans_status['config_state_hostlane4'] = config_status_dict['config_DP_status_hostlane4'] - trans_status['config_state_hostlane5'] = config_status_dict['config_DP_status_hostlane5'] - trans_status['config_state_hostlane6'] = config_status_dict['config_DP_status_hostlane6'] - trans_status['config_state_hostlane7'] = config_status_dict['config_DP_status_hostlane7'] - trans_status['config_state_hostlane8'] = config_status_dict['config_DP_status_hostlane8'] - dpinit_pending_dict = self.get_dpinit_pending() - trans_status['dpinit_pending_hostlane1'] = dpinit_pending_dict['hostlane1'] - trans_status['dpinit_pending_hostlane2'] = dpinit_pending_dict['hostlane2'] - trans_status['dpinit_pending_hostlane3'] = dpinit_pending_dict['hostlane3'] - trans_status['dpinit_pending_hostlane4'] = dpinit_pending_dict['hostlane4'] - trans_status['dpinit_pending_hostlane5'] = dpinit_pending_dict['hostlane5'] - trans_status['dpinit_pending_hostlane6'] = dpinit_pending_dict['hostlane6'] - trans_status['dpinit_pending_hostlane7'] = dpinit_pending_dict['hostlane7'] - trans_status['dpinit_pending_hostlane8'] = dpinit_pending_dict['hostlane8'] + trans_status = super(CCmisApi,self).get_transceiver_status() trans_status['tuning_in_progress'] = self.get_tuning_in_progress() trans_status['wavelength_unlock_status'] = self.get_wavelength_unlocked() laser_tuning_summary = self.get_laser_tuning_summary() @@ -864,119 +726,80 @@ def get_transceiver_status(self): trans_status['tuning_not_accepted'] = 'TuningNotAccepted' in laser_tuning_summary trans_status['invalid_channel_num'] = 'InvalidChannel' in laser_tuning_summary trans_status['tuning_complete'] = 'TuningComplete' in laser_tuning_summary - module_flag = self.get_module_level_flag() - trans_status['temphighalarm_flag'] = module_flag['case_temp_flags']['case_temp_high_alarm_flag'] - trans_status['templowalarm_flag'] = module_flag['case_temp_flags']['case_temp_low_alarm_flag'] - trans_status['temphighwarning_flag'] = module_flag['case_temp_flags']['case_temp_high_warn_flag'] - trans_status['templowwarning_flag'] = module_flag['case_temp_flags']['case_temp_low_warn_flag'] - trans_status['vcchighalarm_flag'] = module_flag['voltage_flags']['voltage_high_alarm_flag'] - trans_status['vcclowalarm_flag'] = module_flag['voltage_flags']['voltage_low_alarm_flag'] - trans_status['vcchighwarning_flag'] = module_flag['voltage_flags']['voltage_high_warn_flag'] - trans_status['vcclowwarning_flag'] = module_flag['voltage_flags']['voltage_low_warn_flag'] - aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() - if aux2_mon_type == 0: - trans_status['lasertemphighalarm_flag'] = module_flag['aux2_flags']['aux2_high_alarm_flag'] - trans_status['lasertemplowalarm_flag'] = module_flag['aux2_flags']['aux2_low_alarm_flag'] - trans_status['lasertemphighwarning_flag'] = module_flag['aux2_flags']['aux2_high_warn_flag'] - trans_status['lasertemplowwarning_flag'] = module_flag['aux2_flags']['aux2_low_warn_flag'] - elif aux2_mon_type == 1 and aux3_mon_type == 0: - trans_status['lasertemphighalarm_flag'] = module_flag['aux3_flags']['aux3_high_alarm_flag'] - trans_status['lasertemplowalarm_flag'] = module_flag['aux3_flags']['aux3_low_alarm_flag'] - trans_status['lasertemphighwarning_flag'] = module_flag['aux3_flags']['aux3_high_warn_flag'] - trans_status['lasertemplowwarning_flag'] = module_flag['aux3_flags']['aux3_low_warn_flag'] - - tx_power_flag_dict = self.get_tx_power_flag() - trans_status['txpowerhighalarm_flag'] = tx_power_flag_dict['tx_power_high_alarm']['TX_lane1'] - trans_status['txpowerlowalarm_flag'] = tx_power_flag_dict['tx_power_low_alarm']['TX_lane1'] - trans_status['txpowerhighwarning_flag'] = tx_power_flag_dict['tx_power_high_warn']['TX_lane1'] - trans_status['txpowerlowwarning_flag'] = tx_power_flag_dict['tx_power_low_warn']['TX_lane1'] - rx_power_flag_dict = self.get_rx_power_flag() - trans_status['rxpowerhighalarm_flag'] = rx_power_flag_dict['rx_power_high_alarm']['RX_lane1'] - trans_status['rxpowerlowalarm_flag'] = rx_power_flag_dict['rx_power_low_alarm']['RX_lane1'] - trans_status['rxpowerhighwarning_flag'] = rx_power_flag_dict['rx_power_high_warn']['RX_lane1'] - trans_status['rxpowerlowwarning_flag'] = rx_power_flag_dict['rx_power_low_warn']['RX_lane1'] - tx_bias_flag_dict = self.get_tx_bias_flag() - trans_status['txbiashighalarm_flag'] = tx_bias_flag_dict['tx_bias_high_alarm']['TX_lane1'] - trans_status['txbiaslowalarm_flag'] = tx_bias_flag_dict['tx_bias_low_alarm']['TX_lane1'] - trans_status['txbiashighwarning_flag'] = tx_bias_flag_dict['tx_bias_high_warn']['TX_lane1'] - trans_status['txbiaslowwarning_flag'] = tx_bias_flag_dict['tx_bias_low_warn']['TX_lane1'] - vdm_dict = self.get_vdm() - trans_status['prefecberhighalarm_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][5] - trans_status['prefecberlowalarm_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][6] - trans_status['prefecberhighwarning_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][7] - trans_status['prefecberlowwarning_flag'] = vdm_dict['Pre-FEC BER Average Media Input'][1][8] - trans_status['postfecberhighalarm_flag'] = vdm_dict['Errored Frames Average Media Input'][1][5] - trans_status['postfecberlowalarm_flag'] = vdm_dict['Errored Frames Average Media Input'][1][6] - trans_status['postfecberhighwarning_flag'] = vdm_dict['Errored Frames Average Media Input'][1][7] - trans_status['postfecberlowwarning_flag'] = vdm_dict['Errored Frames Average Media Input'][1][8] - trans_status['biasxihighalarm_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][5] - trans_status['biasxilowalarm_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][6] - trans_status['biasxihighwarning_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][7] - trans_status['biasxilowwarning_flag'] = vdm_dict['Modulator Bias X/I [%]'][1][8] - trans_status['biasxqhighalarm_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][5] - trans_status['biasxqlowalarm_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][6] - trans_status['biasxqhighwarning_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][7] - trans_status['biasxqlowwarning_flag'] = vdm_dict['Modulator Bias X/Q [%]'][1][8] - trans_status['biasxphighalarm_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][5] - trans_status['biasxplowalarm_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][6] - trans_status['biasxphighwarning_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][7] - trans_status['biasxplowwarning_flag'] = vdm_dict['Modulator Bias X_Phase [%]'][1][8] - trans_status['biasyihighalarm_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][5] - trans_status['biasyilowalarm_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][6] - trans_status['biasyihighwarning_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][7] - trans_status['biasyilowwarning_flag'] = vdm_dict['Modulator Bias Y/I [%]'][1][8] - trans_status['biasyqhighalarm_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][5] - trans_status['biasyqlowalarm_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][6] - trans_status['biasyqhighwarning_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][7] - trans_status['biasyqlowwarning_flag'] = vdm_dict['Modulator Bias Y/Q [%]'][1][8] - trans_status['biasyphighalarm_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][5] - trans_status['biasyplowalarm_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][6] - trans_status['biasyphighwarning_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][7] - trans_status['biasyplowwarning_flag'] = vdm_dict['Modulator Bias Y_Phase [%]'][1][8] - trans_status['cdshorthighalarm_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][5] - trans_status['cdshortlowalarm_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][6] - trans_status['cdshorthighwarning_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][7] - trans_status['cdshortlowwarning_flag'] = vdm_dict['CD high granularity, short link [ps/nm]'][1][8] - trans_status['cdlonghighalarm_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][5] - trans_status['cdlonglowalarm_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][6] - trans_status['cdlonghighwarning_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][7] - trans_status['cdlonglowwarning_flag'] = vdm_dict['CD low granularity, long link [ps/nm]'][1][8] - trans_status['dgdhighalarm_flag'] = vdm_dict['DGD [ps]'][1][5] - trans_status['dgdlowalarm_flag'] = vdm_dict['DGD [ps]'][1][6] - trans_status['dgdhighwarning_flag'] = vdm_dict['DGD [ps]'][1][7] - trans_status['dgdlowwarning_flag'] = vdm_dict['DGD [ps]'][1][8] - trans_status['sopmdhighalarm_flag'] = vdm_dict['SOPMD [ps^2]'][1][5] - trans_status['sopmdlowalarm_flag'] = vdm_dict['SOPMD [ps^2]'][1][6] - trans_status['sopmdhighwarning_flag'] = vdm_dict['SOPMD [ps^2]'][1][7] - trans_status['sopmdlowwarning_flag'] = vdm_dict['SOPMD [ps^2]'][1][8] - trans_status['pdlhighalarm_flag'] = vdm_dict['PDL [dB]'][1][5] - trans_status['pdllowalarm_flag'] = vdm_dict['PDL [dB]'][1][6] - trans_status['pdlhighwarning_flag'] = vdm_dict['PDL [dB]'][1][7] - trans_status['pdllowwarning_flag'] = vdm_dict['PDL [dB]'][1][8] - trans_status['osnrhighalarm_flag'] = vdm_dict['OSNR [dB]'][1][5] - trans_status['osnrlowalarm_flag'] = vdm_dict['OSNR [dB]'][1][6] - trans_status['osnrhighwarning_flag'] = vdm_dict['OSNR [dB]'][1][7] - trans_status['osnrlowwarning_flag'] = vdm_dict['OSNR [dB]'][1][8] - trans_status['esnrhighalarm_flag'] = vdm_dict['eSNR [dB]'][1][5] - trans_status['esnrlowalarm_flag'] = vdm_dict['eSNR [dB]'][1][6] - trans_status['esnrhighwarning_flag'] = vdm_dict['eSNR [dB]'][1][7] - trans_status['esnrlowwarning_flag'] = vdm_dict['eSNR [dB]'][1][8] - trans_status['cfohighalarm_flag'] = vdm_dict['CFO [MHz]'][1][5] - trans_status['cfolowalarm_flag'] = vdm_dict['CFO [MHz]'][1][6] - trans_status['cfohighwarning_flag'] = vdm_dict['CFO [MHz]'][1][7] - trans_status['cfolowwarning_flag'] = vdm_dict['CFO [MHz]'][1][8] - trans_status['txcurrpowerhighalarm_flag'] = vdm_dict['Tx Power [dBm]'][1][5] - trans_status['txcurrpowerlowalarm_flag'] = vdm_dict['Tx Power [dBm]'][1][6] - trans_status['txcurrpowerhighwarning_flag'] = vdm_dict['Tx Power [dBm]'][1][7] - trans_status['txcurrpowerlowwarning_flag'] = vdm_dict['Tx Power [dBm]'][1][8] - trans_status['rxtotpowerhighalarm_flag'] = vdm_dict['Rx Total Power [dBm]'][1][5] - trans_status['rxtotpowerlowalarm_flag'] = vdm_dict['Rx Total Power [dBm]'][1][6] - trans_status['rxtotpowerhighwarning_flag'] = vdm_dict['Rx Total Power [dBm]'][1][7] - trans_status['rxtotpowerlowwarning_flag'] = vdm_dict['Rx Total Power [dBm]'][1][8] - trans_status['rxsigpowerhighalarm_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][5] - trans_status['rxsigpowerlowalarm_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][6] - trans_status['rxsigpowerhighwarning_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][7] - trans_status['rxsigpowerlowwarning_flag'] = vdm_dict['Rx Signal Power [dBm]'][1][8] + trans_status['biasxihighalarm_flag'] = self.vdm_dict['Modulator Bias X/I [%]'][1][5] + trans_status['biasxilowalarm_flag'] = self.vdm_dict['Modulator Bias X/I [%]'][1][6] + trans_status['biasxihighwarning_flag'] = self.vdm_dict['Modulator Bias X/I [%]'][1][7] + trans_status['biasxilowwarning_flag'] = self.vdm_dict['Modulator Bias X/I [%]'][1][8] + trans_status['biasxqhighalarm_flag'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][5] + trans_status['biasxqlowalarm_flag'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][6] + trans_status['biasxqhighwarning_flag'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][7] + trans_status['biasxqlowwarning_flag'] = self.vdm_dict['Modulator Bias X/Q [%]'][1][8] + trans_status['biasxphighalarm_flag'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][5] + trans_status['biasxplowalarm_flag'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][6] + trans_status['biasxphighwarning_flag'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][7] + trans_status['biasxplowwarning_flag'] = self.vdm_dict['Modulator Bias X_Phase [%]'][1][8] + trans_status['biasyihighalarm_flag'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][5] + trans_status['biasyilowalarm_flag'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][6] + trans_status['biasyihighwarning_flag'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][7] + trans_status['biasyilowwarning_flag'] = self.vdm_dict['Modulator Bias Y/I [%]'][1][8] + trans_status['biasyqhighalarm_flag'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][5] + trans_status['biasyqlowalarm_flag'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][6] + trans_status['biasyqhighwarning_flag'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][7] + trans_status['biasyqlowwarning_flag'] = self.vdm_dict['Modulator Bias Y/Q [%]'][1][8] + trans_status['biasyphighalarm_flag'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][5] + trans_status['biasyplowalarm_flag'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][6] + trans_status['biasyphighwarning_flag'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][7] + trans_status['biasyplowwarning_flag'] = self.vdm_dict['Modulator Bias Y_Phase [%]'][1][8] + trans_status['cdshorthighalarm_flag'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][5] + trans_status['cdshortlowalarm_flag'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][6] + trans_status['cdshorthighwarning_flag'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][7] + trans_status['cdshortlowwarning_flag'] = self.vdm_dict['CD high granularity, short link [ps/nm]'][1][8] + try: + trans_status['cdlonghighalarm_flag'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][5] + trans_status['cdlonglowalarm_flag'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][6] + trans_status['cdlonghighwarning_flag'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][7] + trans_status['cdlonglowwarning_flag'] = self.vdm_dict['CD low granularity, long link [ps/nm]'][1][8] + except KeyError: + pass + trans_status['dgdhighalarm_flag'] = self.vdm_dict['DGD [ps]'][1][5] + trans_status['dgdlowalarm_flag'] = self.vdm_dict['DGD [ps]'][1][6] + trans_status['dgdhighwarning_flag'] = self.vdm_dict['DGD [ps]'][1][7] + trans_status['dgdlowwarning_flag'] = self.vdm_dict['DGD [ps]'][1][8] + try: + trans_status['sopmdhighalarm_flag'] = self.vdm_dict['SOPMD [ps^2]'][1][5] + trans_status['sopmdlowalarm_flag'] = self.vdm_dict['SOPMD [ps^2]'][1][6] + trans_status['sopmdhighwarning_flag'] = self.vdm_dict['SOPMD [ps^2]'][1][7] + trans_status['sopmdlowwarning_flag'] = self.vdm_dict['SOPMD [ps^2]'][1][8] + except KeyError: + pass + trans_status['pdlhighalarm_flag'] = self.vdm_dict['PDL [dB]'][1][5] + trans_status['pdllowalarm_flag'] = self.vdm_dict['PDL [dB]'][1][6] + trans_status['pdlhighwarning_flag'] = self.vdm_dict['PDL [dB]'][1][7] + trans_status['pdllowwarning_flag'] = self.vdm_dict['PDL [dB]'][1][8] + trans_status['osnrhighalarm_flag'] = self.vdm_dict['OSNR [dB]'][1][5] + trans_status['osnrlowalarm_flag'] = self.vdm_dict['OSNR [dB]'][1][6] + trans_status['osnrhighwarning_flag'] = self.vdm_dict['OSNR [dB]'][1][7] + trans_status['osnrlowwarning_flag'] = self.vdm_dict['OSNR [dB]'][1][8] + trans_status['esnrhighalarm_flag'] = self.vdm_dict['eSNR [dB]'][1][5] + trans_status['esnrlowalarm_flag'] = self.vdm_dict['eSNR [dB]'][1][6] + trans_status['esnrhighwarning_flag'] = self.vdm_dict['eSNR [dB]'][1][7] + trans_status['esnrlowwarning_flag'] = self.vdm_dict['eSNR [dB]'][1][8] + trans_status['cfohighalarm_flag'] = self.vdm_dict['CFO [MHz]'][1][5] + trans_status['cfolowalarm_flag'] = self.vdm_dict['CFO [MHz]'][1][6] + trans_status['cfohighwarning_flag'] = self.vdm_dict['CFO [MHz]'][1][7] + trans_status['cfolowwarning_flag'] = self.vdm_dict['CFO [MHz]'][1][8] + trans_status['txcurrpowerhighalarm_flag'] = self.vdm_dict['Tx Power [dBm]'][1][5] + trans_status['txcurrpowerlowalarm_flag'] = self.vdm_dict['Tx Power [dBm]'][1][6] + trans_status['txcurrpowerhighwarning_flag'] = self.vdm_dict['Tx Power [dBm]'][1][7] + trans_status['txcurrpowerlowwarning_flag'] = self.vdm_dict['Tx Power [dBm]'][1][8] + trans_status['rxtotpowerhighalarm_flag'] = self.vdm_dict['Rx Total Power [dBm]'][1][5] + trans_status['rxtotpowerlowalarm_flag'] = self.vdm_dict['Rx Total Power [dBm]'][1][6] + trans_status['rxtotpowerhighwarning_flag'] = self.vdm_dict['Rx Total Power [dBm]'][1][7] + trans_status['rxtotpowerlowwarning_flag'] = self.vdm_dict['Rx Total Power [dBm]'][1][8] + trans_status['rxsigpowerhighalarm_flag'] = self.vdm_dict['Rx Signal Power [dBm]'][1][5] + trans_status['rxsigpowerlowalarm_flag'] = self.vdm_dict['Rx Signal Power [dBm]'][1][6] + trans_status['rxsigpowerhighwarning_flag'] = self.vdm_dict['Rx Signal Power [dBm]'][1][7] + trans_status['rxsigpowerlowwarning_flag'] = self.vdm_dict['Rx Signal Power [dBm]'][1][8] return trans_status def get_transceiver_pm(self): @@ -1071,55 +894,3 @@ def get_transceiver_pm(self): trans_pm['rx_sig_power_min'] = PM_dict['rx_sigpwr_min'] trans_pm['rx_sig_power_max'] = PM_dict['rx_sigpwr_max'] return trans_pm - - def get_transceiver_loopback(self): - """ - Retrieves loopback mode for this xcvr - - Returns: - A dict containing the following keys/values : - ======================================================================== - key = TRANSCEIVER_PM|ifname ; information of loopback on port - ; field = value - media_output_loopback = BOOLEAN ; media side output loopback enable - media_input_loopback = BOOLEAN ; media side input loopback enable - host_output_loopback_lane1 = BOOLEAN ; host side output loopback enable lane1 - host_output_loopback_lane2 = BOOLEAN ; host side output loopback enable lane2 - host_output_loopback_lane3 = BOOLEAN ; host side output loopback enable lane3 - host_output_loopback_lane4 = BOOLEAN ; host side output loopback enable lane4 - host_output_loopback_lane5 = BOOLEAN ; host side output loopback enable lane5 - host_output_loopback_lane6 = BOOLEAN ; host side output loopback enable lane6 - host_output_loopback_lane7 = BOOLEAN ; host side output loopback enable lane7 - host_output_loopback_lane8 = BOOLEAN ; host side output loopback enable lane8 - host_input_loopback_lane1 = BOOLEAN ; host side input loopback enable lane1 - host_input_loopback_lane2 = BOOLEAN ; host side input loopback enable lane2 - host_input_loopback_lane3 = BOOLEAN ; host side input loopback enable lane3 - host_input_loopback_lane4 = BOOLEAN ; host side input loopback enable lane4 - host_input_loopback_lane5 = BOOLEAN ; host side input loopback enable lane5 - host_input_loopback_lane6 = BOOLEAN ; host side input loopback enable lane6 - host_input_loopback_lane7 = BOOLEAN ; host side input loopback enable lane7 - host_input_loopback_lane8 = BOOLEAN ; host side input loopback enable lane8 - ======================================================================== - """ - trans_loopback = dict() - trans_loopback['media_output_loopback'] = self.get_media_output_loopback() - trans_loopback['media_input_loopback'] = self.get_media_input_loopback() - host_output_loopback_status = self.get_host_output_loopback() - trans_loopback['host_output_loopback_lane1'] = host_output_loopback_status[0] - trans_loopback['host_output_loopback_lane2'] = host_output_loopback_status[1] - trans_loopback['host_output_loopback_lane3'] = host_output_loopback_status[2] - trans_loopback['host_output_loopback_lane4'] = host_output_loopback_status[3] - trans_loopback['host_output_loopback_lane5'] = host_output_loopback_status[4] - trans_loopback['host_output_loopback_lane6'] = host_output_loopback_status[5] - trans_loopback['host_output_loopback_lane7'] = host_output_loopback_status[6] - trans_loopback['host_output_loopback_lane8'] = host_output_loopback_status[7] - host_input_loopback_status = self.get_host_input_loopback() - trans_loopback['host_input_loopback_lane1'] = host_input_loopback_status[0] - trans_loopback['host_input_loopback_lane2'] = host_input_loopback_status[1] - trans_loopback['host_input_loopback_lane3'] = host_input_loopback_status[2] - trans_loopback['host_input_loopback_lane4'] = host_input_loopback_status[3] - trans_loopback['host_input_loopback_lane5'] = host_input_loopback_status[4] - trans_loopback['host_input_loopback_lane6'] = host_input_loopback_status[5] - trans_loopback['host_input_loopback_lane7'] = host_input_loopback_status[6] - trans_loopback['host_input_loopback_lane8'] = host_input_loopback_status[7] - return trans_loopback diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index 2b441d296..01cc324ed 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -735,17 +735,6 @@ def set_low_power(self, AssertLowPower): ''' low_power_control = AssertLowPower << 6 self.xcvr_eeprom.write(consts.MODULE_LEVEL_CONTROL, low_power_control) - - def set_tx_power(self, tx_power): - ''' - This function sets the TX output power. Unit in dBm - ''' - min_prog_tx_output_power, max_prog_tx_output_power = self.get_supported_power_config() - if tx_power > max_prog_tx_output_power or tx_power < min_prog_tx_output_power: - raise ValueError('Provisioned TX power out of range. Max: %.1f; Min: %.1f dBm.' - %(max_prog_tx_output_power, min_prog_tx_output_power)) - self.xcvr_eeprom.write(consts.TX_CONFIG_POWER, tx_power) - time.sleep(1) def get_loopback_capability(self): ''' @@ -814,7 +803,7 @@ def get_module_fw_upgrade_feature(self, verbose = False): writelength = (self.xcvr_eeprom.read(consts.CDB_SEQ_WRITE_LENGTH_EXT) + 1) * 8 logger.info('Auto page support: %s' %autopaging_flag) logger.info('Max write length: %d' %writelength) - rpllen, rpl_chkcode, rpl = self.cdb.cmd0041h() + rpllen, rpl_chkcode, rpl = self.cdb.get_fw_management_features() if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: password_type = { 0x00 : 'vendorPassword', @@ -866,7 +855,7 @@ def get_module_fw_info(self): # get fw info (CMD 0100h) starttime = time.time() logger.info('\nGet module FW info') - rpllen, rpl_chkcode, rpl = self.cdb.cmd0100h() + rpllen, rpl_chkcode, rpl = self.cdb.get_fw_info() if self.cdb.cdb_chkcode(rpl) == rpl_chkcode: # Regiter 9Fh:136 fwStatus = rpl[0] @@ -918,11 +907,11 @@ def module_fw_run(self, mode = 0x01): self.get_cdb_api() # run module FW (CMD 0109h) starttime = time.time() - fw_run_status = self.cdb.cmd0109h(mode) + fw_run_status = self.cdb.run_fw_image(mode) if fw_run_status == 1: logger.info('Module FW run: Success') else: - self.cdb.cmd0102h() + self.cdb.abort_fw_download() logger.info('Module FW run: Fail') elapsedtime = time.time()-starttime logger.info('Module FW run time: %.2f s\n' %elapsedtime) @@ -938,11 +927,11 @@ def module_fw_commit(self): self.get_cdb_api() # commit module FW (CMD 010Ah) starttime = time.time() - fw_commit_status= self.cdb.cmd010Ah() + fw_commit_status= self.cdb.commit_fw_image() if fw_commit_status == 1: logger.info('Module FW commit: Success') else: - self.cdb.cmd0102h() + self.cdb.abort_fw_download() logger.info('Module FW commit: Fail') elapsedtime = time.time()-starttime logger.info('Module FW commit time: %.2f s\n' %elapsedtime) @@ -978,18 +967,18 @@ def module_fw_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin self.xcvr_eeprom.write_raw(122, 4, b'\x00\x00\x10\x11') logger.info('\nStart FW downloading') logger.info("startLPLsize is %d" %startLPLsize) - fw_start_status = self.cdb.cmd0101h(startLPLsize, bytearray(startdata), imagesize) + fw_start_status = self.cdb.start_fw_download(startLPLsize, bytearray(startdata), imagesize) if fw_start_status == 1: logger.info('Start module FW download: Success') else: logger.info('Start module FW download: Fail') - self.cdb.cmd0102h() + self.cdb.abort_fw_download() raise ValueError('FW_start_status %d' %fw_start_status) elapsedtime = time.time()-starttime logger.info('Start module FW download time: %.2f s' %elapsedtime) # start periodically writing (CMD 0103h or 0104h) - assert maxblocksize == 2048 or lplonly_flag + # assert maxblocksize == 2048 or lplonly_flag if lplonly_flag: BLOCK_SIZE = 116 else: @@ -1005,9 +994,9 @@ def module_fw_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin data = f.read(count) progress = (imagesize - remaining) * 100.0 / imagesize if lplonly_flag: - fw_download_status = self.cdb.cmd0103h(address, data) + fw_download_status = self.cdb.block_write_lpl(address, data) else: - fw_download_status = self.cdb.cmd0104h(address, data, autopaging_flag, writelength) + fw_download_status = self.cdb.block_write_epl(address, data, autopaging_flag, writelength) if fw_download_status != 1: logger.info('CDB download failed. CDB Status: %d' %fw_download_status) exit(1) @@ -1020,7 +1009,7 @@ def module_fw_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin time.sleep(2) # complete FW download (CMD 0107h) - fw_complete_status = self.cdb.cmd0107h() + fw_complete_status = self.cdb.validate_fw_image() if fw_complete_status == 1: logger.info('Module FW download complete: Success') else: @@ -1059,6 +1048,466 @@ def module_fw_switch(self): self.get_module_fw_info() else: logger.info('Not both images are valid.') + + def get_transceiver_info(self): + """ + Retrieves transceiver info of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_INFO|ifname ; information for module on port + ; field = value + module_media_type = 1*255VCHAR ; module media interface ID + host_electrical_interface = 1*255VCHAR ; host electrical interface ID + media_interface_code = 1*255VCHAR ; media interface code + host_lane_count = INTEGER ; host lane count + media_lane_count = INTEGER ; media lane count + host_lane_assignment_option = INTEGER ; permissible first host lane number for application + media_lane_assignment_option = INTEGER ; permissible first media lane number for application + active_apsel_hostlane1 = INTEGER ; active application selected code assigned to host lane 1 + active_apsel_hostlane2 = INTEGER ; active application selected code assigned to host lane 2 + active_apsel_hostlane3 = INTEGER ; active application selected code assigned to host lane 3 + active_apsel_hostlane4 = INTEGER ; active application selected code assigned to host lane 4 + active_apsel_hostlane5 = INTEGER ; active application selected code assigned to host lane 5 + active_apsel_hostlane6 = INTEGER ; active application selected code assigned to host lane 6 + active_apsel_hostlane7 = INTEGER ; active application selected code assigned to host lane 7 + active_apsel_hostlane8 = INTEGER ; active application selected code assigned to host lane 8 + media_interface_technology = 1*255VCHAR ; media interface technology + hardwarerev = 1*255VCHAR ; module hardware revision + serialnum = 1*255VCHAR ; module serial number + manufacturename = 1*255VCHAR ; module venndor name + modelname = 1*255VCHAR ; module model name + vendor_rev = 1*255VCHAR ; module vendor revision + vendor_oui = 1*255VCHAR ; vendor organizationally unique identifier + vendor_date = 1*255VCHAR ; module manufacture date + connector_type = 1*255VCHAR ; connector type + specification_compliance = 1*255VCHAR ; electronic or optical interfaces that supported + active_firmware = 1*255VCHAR ; active firmware + inactive_firmware = 1*255VCHAR ; inactive firmware + ================================================================================ + """ + trans_info = dict() + trans_info['module_media_type'] = self.get_module_media_type() + trans_info['host_electrical_interface'] = self.get_host_electrical_interface() + trans_info['media_interface_code'] = self.get_module_media_interface() + trans_info['host_lane_count'] = self.get_host_lane_count() + trans_info['media_lane_count'] = self.get_media_lane_count() + trans_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option() + trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() + apsel_dict = self.get_active_apsel_hostlane() + trans_info['active_apsel_hostlane1'] = apsel_dict['hostlane1'] + trans_info['active_apsel_hostlane2'] = apsel_dict['hostlane2'] + trans_info['active_apsel_hostlane3'] = apsel_dict['hostlane3'] + trans_info['active_apsel_hostlane4'] = apsel_dict['hostlane4'] + trans_info['active_apsel_hostlane5'] = apsel_dict['hostlane5'] + trans_info['active_apsel_hostlane6'] = apsel_dict['hostlane6'] + trans_info['active_apsel_hostlane7'] = apsel_dict['hostlane7'] + trans_info['active_apsel_hostlane8'] = apsel_dict['hostlane8'] + trans_info['media_interface_technology'] = self.get_media_interface_technology() + trans_info['hardwarerev'] = self.get_module_hardware_revision() + trans_info['serialnum'] = self.get_vendor_serial() + trans_info['manufacturename'] = self.get_vendor_name() + trans_info['vendor_rev'] = self.get_vendor_rev() + trans_info['vendor_oui'] = self.get_vendor_OUI() + trans_info['vendor_date'] = self.get_vendor_date() + trans_info['connector_type'] = self.get_connector_type() + trans_info['specification_compliance'] = self.get_cmis_rev() + trans_info['active_firmware'] = self.get_module_active_firmware() + trans_info['inactive_firmware'] = self.get_module_inactive_firmware() + return trans_info + + def get_transceiver_bulk_status(self): + """ + Retrieves bulk status info for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_DOM_SENSOR|ifname ; information module DOM sensors on port + ; field = value + temperature = FLOAT ; temperature value in Celsius + voltage = FLOAT ; voltage value + txpower = FLOAT ; tx power in mW + rxpower = FLOAT ; rx power in mW + txbias = FLOAT ; tx bias in mA + laser_temperature = FLOAT ; laser temperature value in Celsius + prefec_ber = FLOAT ; prefec ber + postfec_ber = FLOAT ; postfec ber + ======================================================================== + """ + trans_dom = dict() + case_temp_dict = self.get_module_temperature() + trans_dom['temperature'] = case_temp_dict['monitor value'] + voltage_dict = self.get_module_voltage() + trans_dom['voltage'] = voltage_dict['monitor value'] + tx_power_dict = self.get_txpower() + trans_dom['txpower'] = tx_power_dict['monitor value lane1'] + rx_power_dict = self.get_rxpower() + trans_dom['rxpower'] = rx_power_dict['monitor value lane1'] + tx_bias_current_dict = self.get_txbias() + trans_dom['txbias'] = tx_bias_current_dict['monitor value lane1'] + laser_temp_dict = self.get_laser_temperature() + trans_dom['laser_temperature'] = laser_temp_dict['monitor value'] + self.vdm_dict = self.get_vdm() + trans_dom['prefec_ber'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][0] + trans_dom['postfec_ber'] = self.vdm_dict['Errored Frames Average Media Input'][1][0] + return trans_dom + + def get_transceiver_threshold_info(self): + """ + Retrieves threshold info for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_STATUS|ifname ; DOM threshold information for module on port + ; field = value + temphighalarm = FLOAT ; temperature high alarm threshold in Celsius + temphighwarning = FLOAT ; temperature high warning threshold in Celsius + templowalarm = FLOAT ; temperature low alarm threshold in Celsius + templowwarning = FLOAT ; temperature low warning threshold in Celsius + vcchighalarm = FLOAT ; vcc high alarm threshold in V + vcchighwarning = FLOAT ; vcc high warning threshold in V + vcclowalarm = FLOAT ; vcc low alarm threshold in V + vcclowwarning = FLOAT ; vcc low warning threshold in V + txpowerhighalarm = FLOAT ; tx power high alarm threshold in mW + txpowerlowalarm = FLOAT ; tx power low alarm threshold in mW + txpowerhighwarning = FLOAT ; tx power high warning threshold in mW + txpowerlowwarning = FLOAT ; tx power low alarm threshold in mW + rxpowerhighalarm = FLOAT ; rx power high alarm threshold in mW + rxpowerlowalarm = FLOAT ; rx power low alarm threshold in mW + rxpowerhighwarning = FLOAT ; rx power high warning threshold in mW + rxpowerlowwarning = FLOAT ; rx power low warning threshold in mW + txbiashighalarm = FLOAT ; tx bias high alarm threshold in mA + txbiaslowalarm = FLOAT ; tx bias low alarm threshold in mA + txbiashighwarning = FLOAT ; tx bias high warning threshold in mA + txbiaslowwarning = FLOAT ; tx bias low warning threshold in mA + lasertemphighalarm = FLOAT ; laser temperature high alarm threshold in Celsius + lasertemplowalarm = FLOAT ; laser temperature low alarm threshold in Celsius + lasertemphighwarning = FLOAT ; laser temperature high warning threshold in Celsius + lasertemplowwarning = FLOAT ; laser temperature low warning threshold in Celsius + prefecberhighalarm = FLOAT ; prefec ber high alarm threshold + prefecberlowalarm = FLOAT ; prefec ber low alarm threshold + prefecberhighwarning = FLOAT ; prefec ber high warning threshold + prefecberlowwarning = FLOAT ; prefec ber low warning threshold + postfecberhighalarm = FLOAT ; postfec ber high alarm threshold + postfecberlowalarm = FLOAT ; postfec ber low alarm threshold + postfecberhighwarning = FLOAT ; postfec ber high warning threshold + postfecberlowwarning = FLOAT ; postfec ber low warning threshold + ======================================================================== + """ + trans_dom_th = dict() + case_temp_dict = self.get_module_temperature() + trans_dom_th['temphighalarm'] = case_temp_dict['high alarm'] + trans_dom_th['templowalarm'] = case_temp_dict['low alarm'] + trans_dom_th['temphighwarning'] = case_temp_dict['high warn'] + trans_dom_th['templowwarning'] = case_temp_dict['low warn'] + voltage_dict = self.get_module_voltage() + trans_dom_th['vcchighalarm'] = voltage_dict['high alarm'] + trans_dom_th['vcclowalarm'] = voltage_dict['low alarm'] + trans_dom_th['vcchighwarning'] = voltage_dict['high warn'] + trans_dom_th['vcclowwarning'] = voltage_dict['low warn'] + tx_power_dict = self.get_txpower() + trans_dom_th['txpowerhighalarm'] = tx_power_dict['high alarm'] + trans_dom_th['txpowerlowalarm'] = tx_power_dict['low alarm'] + trans_dom_th['txpowerhighwarning'] = tx_power_dict['high warn'] + trans_dom_th['txpowerlowwarning'] = tx_power_dict['low warn'] + rx_power_dict = self.get_rxpower() + trans_dom_th['rxpowerhighalarm'] = rx_power_dict['high alarm'] + trans_dom_th['rxpowerlowalarm'] = rx_power_dict['low alarm'] + trans_dom_th['rxpowerhighwarning'] = rx_power_dict['high warn'] + trans_dom_th['rxpowerlowwarning'] = rx_power_dict['low warn'] + tx_bias_current_dict = self.get_txbias() + trans_dom_th['txbiashighalarm'] = tx_bias_current_dict['high alarm'] + trans_dom_th['txbiaslowalarm'] = tx_bias_current_dict['low alarm'] + trans_dom_th['txbiashighwarning'] = tx_bias_current_dict['high warn'] + trans_dom_th['txbiaslowwarning'] = tx_bias_current_dict['low warn'] + laser_temp_dict = self.get_laser_temperature() + trans_dom_th['lasertemphighalarm'] = laser_temp_dict['high alarm'] + trans_dom_th['lasertemplowalarm'] = laser_temp_dict['low alarm'] + trans_dom_th['lasertemphighwarning'] = laser_temp_dict['high warn'] + trans_dom_th['lasertemplowwarning'] = laser_temp_dict['low warn'] + self.vdm_dict = self.get_vdm() + trans_dom_th['prefecberhighalarm'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][1] + trans_dom_th['prefecberlowalarm'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][2] + trans_dom_th['prefecberhighwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][3] + trans_dom_th['prefecberlowwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][4] + trans_dom_th['postfecberhighalarm'] = self.vdm_dict['Errored Frames Average Media Input'][1][1] + trans_dom_th['postfecberlowalarm'] = self.vdm_dict['Errored Frames Average Media Input'][1][2] + trans_dom_th['postfecberhighwarning'] = self.vdm_dict['Errored Frames Average Media Input'][1][3] + trans_dom_th['postfecberlowwarning'] = self.vdm_dict['Errored Frames Average Media Input'][1][4] + return trans_dom_th + + def get_transceiver_status(self): + """ + Retrieves transceiver status of this SFP + + Returns: + A dict which contains following keys/values : + ================================================================================ + key = TRANSCEIVER_STATUS|ifname ; Error information for module on port + ; field = value + status = 1*255VCHAR ; code of the module status (plug in, plug out) + error = 1*255VCHAR ; module error (N/A or a string consisting of error descriptions joined by "|", like "error1 | error2" ) + module_state = 1*255VCHAR ; current module state (ModuleLowPwr, ModulePwrUp, ModuleReady, ModulePwrDn, Fault) + module_fault_cause = 1*255VCHAR ; reason of entering the module fault state + datapath_firmware_fault = BOOLEAN ; datapath (DSP) firmware fault + module_firmware_fault = BOOLEAN ; module firmware fault + module_state_changed = BOOLEAN ; module state changed + datapath_hostlane1 = 1*255VCHAR ; data path state indicator on host lane 1 + datapath_hostlane2 = 1*255VCHAR ; data path state indicator on host lane 2 + datapath_hostlane3 = 1*255VCHAR ; data path state indicator on host lane 3 + datapath_hostlane4 = 1*255VCHAR ; data path state indicator on host lane 4 + datapath_hostlane5 = 1*255VCHAR ; data path state indicator on host lane 5 + datapath_hostlane6 = 1*255VCHAR ; data path state indicator on host lane 6 + datapath_hostlane7 = 1*255VCHAR ; data path state indicator on host lane 7 + datapath_hostlane8 = 1*255VCHAR ; data path state indicator on host lane 8 + txoutput_status = BOOLEAN ; tx output status on media lane + rxoutput_status_hostlane1 = BOOLEAN ; rx output status on host lane 1 + rxoutput_status_hostlane2 = BOOLEAN ; rx output status on host lane 2 + rxoutput_status_hostlane3 = BOOLEAN ; rx output status on host lane 3 + rxoutput_status_hostlane4 = BOOLEAN ; rx output status on host lane 4 + rxoutput_status_hostlane5 = BOOLEAN ; rx output status on host lane 5 + rxoutput_status_hostlane6 = BOOLEAN ; rx output status on host lane 6 + rxoutput_status_hostlane7 = BOOLEAN ; rx output status on host lane 7 + rxoutput_status_hostlane8 = BOOLEAN ; rx output status on host lane 8 + txfault = BOOLEAN ; tx fault flag on media lane + txlos_hostlane1 = BOOLEAN ; tx loss of signal flag on host lane 1 + txlos_hostlane2 = BOOLEAN ; tx loss of signal flag on host lane 2 + txlos_hostlane3 = BOOLEAN ; tx loss of signal flag on host lane 3 + txlos_hostlane4 = BOOLEAN ; tx loss of signal flag on host lane 4 + txlos_hostlane5 = BOOLEAN ; tx loss of signal flag on host lane 5 + txlos_hostlane6 = BOOLEAN ; tx loss of signal flag on host lane 6 + txlos_hostlane7 = BOOLEAN ; tx loss of signal flag on host lane 7 + txlos_hostlane8 = BOOLEAN ; tx loss of signal flag on host lane 8 + txcdrlol_hostlane1 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 1 + txcdrlol_hostlane2 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 2 + txcdrlol_hostlane3 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 3 + txcdrlol_hostlane4 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 4 + txcdrlol_hostlane5 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 5 + txcdrlol_hostlane6 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 6 + txcdrlol_hostlane7 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 7 + txcdrlol_hostlane8 = BOOLEAN ; tx clock and data recovery loss of lock on host lane 8 + rxlos = BOOLEAN ; rx loss of signal flag on media lane + rxcdrlol = BOOLEAN ; rx clock and data recovery loss of lock on media lane + config_state_hostlane1 = 1*255VCHAR ; configuration status for the data path of host line 1 + config_state_hostlane2 = 1*255VCHAR ; configuration status for the data path of host line 2 + config_state_hostlane3 = 1*255VCHAR ; configuration status for the data path of host line 3 + config_state_hostlane4 = 1*255VCHAR ; configuration status for the data path of host line 4 + config_state_hostlane5 = 1*255VCHAR ; configuration status for the data path of host line 5 + config_state_hostlane6 = 1*255VCHAR ; configuration status for the data path of host line 6 + config_state_hostlane7 = 1*255VCHAR ; configuration status for the data path of host line 7 + config_state_hostlane8 = 1*255VCHAR ; configuration status for the data path of host line 8 + dpinit_pending_hostlane1 = BOOLEAN ; data path configuration updated on host lane 1 + dpinit_pending_hostlane2 = BOOLEAN ; data path configuration updated on host lane 2 + dpinit_pending_hostlane3 = BOOLEAN ; data path configuration updated on host lane 3 + dpinit_pending_hostlane4 = BOOLEAN ; data path configuration updated on host lane 4 + dpinit_pending_hostlane5 = BOOLEAN ; data path configuration updated on host lane 5 + dpinit_pending_hostlane6 = BOOLEAN ; data path configuration updated on host lane 6 + dpinit_pending_hostlane7 = BOOLEAN ; data path configuration updated on host lane 7 + dpinit_pending_hostlane8 = BOOLEAN ; data path configuration updated on host lane 8 + temphighalarm_flag = BOOLEAN ; temperature high alarm flag + temphighwarning_flag = BOOLEAN ; temperature high warning flag + templowalarm_flag = BOOLEAN ; temperature low alarm flag + templowwarning_flag = BOOLEAN ; temperature low warning flag + vcchighalarm_flag = BOOLEAN ; vcc high alarm flag + vcchighwarning_flag = BOOLEAN ; vcc high warning flag + vcclowalarm_flag = BOOLEAN ; vcc low alarm flag + vcclowwarning_flag = BOOLEAN ; vcc low warning flag + txpowerhighalarm_flag = BOOLEAN ; tx power high alarm flag + txpowerlowalarm_flag = BOOLEAN ; tx power low alarm flag + txpowerhighwarning_flag = BOOLEAN ; tx power high warning flag + txpowerlowwarning_flag = BOOLEAN ; tx power low alarm flag + rxpowerhighalarm_flag = BOOLEAN ; rx power high alarm flag + rxpowerlowalarm_flag = BOOLEAN ; rx power low alarm flag + rxpowerhighwarning_flag = BOOLEAN ; rx power high warning flag + rxpowerlowwarning_flag = BOOLEAN ; rx power low warning flag + txbiashighalarm_flag = BOOLEAN ; tx bias high alarm flag + txbiaslowalarm_flag = BOOLEAN ; tx bias low alarm flag + txbiashighwarning_flag = BOOLEAN ; tx bias high warning flag + txbiaslowwarning_flag = BOOLEAN ; tx bias low warning flag + lasertemphighalarm_flag = BOOLEAN ; laser temperature high alarm flag + lasertemplowalarm_flag = BOOLEAN ; laser temperature low alarm flag + lasertemphighwarning_flag = BOOLEAN ; laser temperature high warning flag + lasertemplowwarning_flag = BOOLEAN ; laser temperature low warning flag + prefecberhighalarm_flag = BOOLEAN ; prefec ber high alarm flag + prefecberlowalarm_flag = BOOLEAN ; prefec ber low alarm flag + prefecberhighwarning_flag = BOOLEAN ; prefec ber high warning flag + prefecberlowwarning_flag = BOOLEAN ; prefec ber low warning flag + postfecberhighalarm_flag = BOOLEAN ; postfec ber high alarm flag + postfecberlowalarm_flag = BOOLEAN ; postfec ber low alarm flag + postfecberhighwarning_flag = BOOLEAN ; postfec ber high warning flag + postfecberlowwarning_flag = BOOLEAN ; postfec ber low warning flag + ================================================================================ + """ + trans_status = dict() + trans_status['module_state'] = self.get_module_state() + trans_status['module_fault_cause'] = self.get_module_fault_cause() + dp_fw_fault, module_fw_fault, module_state_changed = self.get_module_firmware_fault_state_changed() + trans_status['datapath_firmware_fault'] = dp_fw_fault + trans_status['module_firmware_fault'] = module_fw_fault + trans_status['module_state_changed'] = module_state_changed + dp_state_dict = self.get_datapath_state() + trans_status['datapath_hostlane1'] = dp_state_dict['dp_lane1'] + trans_status['datapath_hostlane2'] = dp_state_dict['dp_lane2'] + trans_status['datapath_hostlane3'] = dp_state_dict['dp_lane3'] + trans_status['datapath_hostlane4'] = dp_state_dict['dp_lane4'] + trans_status['datapath_hostlane5'] = dp_state_dict['dp_lane5'] + trans_status['datapath_hostlane6'] = dp_state_dict['dp_lane6'] + trans_status['datapath_hostlane7'] = dp_state_dict['dp_lane7'] + trans_status['datapath_hostlane8'] = dp_state_dict['dp_lane8'] + tx_output_status_dict = self.get_tx_output_status() + trans_status['txoutput_status'] = tx_output_status_dict['TX_lane1'] + rx_output_status_dict = self.get_rx_output_status() + trans_status['rxoutput_status_hostlane1'] = rx_output_status_dict['RX_lane1'] + trans_status['rxoutput_status_hostlane2'] = rx_output_status_dict['RX_lane2'] + trans_status['rxoutput_status_hostlane3'] = rx_output_status_dict['RX_lane3'] + trans_status['rxoutput_status_hostlane4'] = rx_output_status_dict['RX_lane4'] + trans_status['rxoutput_status_hostlane5'] = rx_output_status_dict['RX_lane5'] + trans_status['rxoutput_status_hostlane6'] = rx_output_status_dict['RX_lane6'] + trans_status['rxoutput_status_hostlane7'] = rx_output_status_dict['RX_lane7'] + trans_status['rxoutput_status_hostlane8'] = rx_output_status_dict['RX_lane8'] + tx_fault_dict = self.get_tx_fault() + trans_status['txfault'] = tx_fault_dict['TX_lane1'] + tx_los_dict = self.get_tx_los() + trans_status['txlos_hostlane1'] = tx_los_dict['TX_lane1'] + trans_status['txlos_hostlane2'] = tx_los_dict['TX_lane2'] + trans_status['txlos_hostlane3'] = tx_los_dict['TX_lane3'] + trans_status['txlos_hostlane4'] = tx_los_dict['TX_lane4'] + trans_status['txlos_hostlane5'] = tx_los_dict['TX_lane5'] + trans_status['txlos_hostlane6'] = tx_los_dict['TX_lane6'] + trans_status['txlos_hostlane7'] = tx_los_dict['TX_lane7'] + trans_status['txlos_hostlane8'] = tx_los_dict['TX_lane8'] + tx_lol_dict = self.get_tx_cdr_lol() + trans_status['txcdrlol_hostlane1'] = tx_lol_dict['TX_lane1'] + trans_status['txcdrlol_hostlane2'] = tx_lol_dict['TX_lane2'] + trans_status['txcdrlol_hostlane3'] = tx_lol_dict['TX_lane3'] + trans_status['txcdrlol_hostlane4'] = tx_lol_dict['TX_lane4'] + trans_status['txcdrlol_hostlane5'] = tx_lol_dict['TX_lane5'] + trans_status['txcdrlol_hostlane6'] = tx_lol_dict['TX_lane6'] + trans_status['txcdrlol_hostlane7'] = tx_lol_dict['TX_lane7'] + trans_status['txcdrlol_hostlane8'] = tx_lol_dict['TX_lane8'] + rx_los_dict = self.get_rx_los() + trans_status['rxlos'] = rx_los_dict['RX_lane1'] + rx_lol_dict = self.get_rx_cdr_lol() + trans_status['rxcdrlol'] = rx_lol_dict['RX_lane1'] + config_status_dict = self.get_config_datapath_hostlane_status() + trans_status['config_state_hostlane1'] = config_status_dict['config_DP_status_hostlane1'] + trans_status['config_state_hostlane2'] = config_status_dict['config_DP_status_hostlane2'] + trans_status['config_state_hostlane3'] = config_status_dict['config_DP_status_hostlane3'] + trans_status['config_state_hostlane4'] = config_status_dict['config_DP_status_hostlane4'] + trans_status['config_state_hostlane5'] = config_status_dict['config_DP_status_hostlane5'] + trans_status['config_state_hostlane6'] = config_status_dict['config_DP_status_hostlane6'] + trans_status['config_state_hostlane7'] = config_status_dict['config_DP_status_hostlane7'] + trans_status['config_state_hostlane8'] = config_status_dict['config_DP_status_hostlane8'] + dpinit_pending_dict = self.get_dpinit_pending() + trans_status['dpinit_pending_hostlane1'] = dpinit_pending_dict['hostlane1'] + trans_status['dpinit_pending_hostlane2'] = dpinit_pending_dict['hostlane2'] + trans_status['dpinit_pending_hostlane3'] = dpinit_pending_dict['hostlane3'] + trans_status['dpinit_pending_hostlane4'] = dpinit_pending_dict['hostlane4'] + trans_status['dpinit_pending_hostlane5'] = dpinit_pending_dict['hostlane5'] + trans_status['dpinit_pending_hostlane6'] = dpinit_pending_dict['hostlane6'] + trans_status['dpinit_pending_hostlane7'] = dpinit_pending_dict['hostlane7'] + trans_status['dpinit_pending_hostlane8'] = dpinit_pending_dict['hostlane8'] + module_flag = self.get_module_level_flag() + trans_status['temphighalarm_flag'] = module_flag['case_temp_flags']['case_temp_high_alarm_flag'] + trans_status['templowalarm_flag'] = module_flag['case_temp_flags']['case_temp_low_alarm_flag'] + trans_status['temphighwarning_flag'] = module_flag['case_temp_flags']['case_temp_high_warn_flag'] + trans_status['templowwarning_flag'] = module_flag['case_temp_flags']['case_temp_low_warn_flag'] + trans_status['vcchighalarm_flag'] = module_flag['voltage_flags']['voltage_high_alarm_flag'] + trans_status['vcclowalarm_flag'] = module_flag['voltage_flags']['voltage_low_alarm_flag'] + trans_status['vcchighwarning_flag'] = module_flag['voltage_flags']['voltage_high_warn_flag'] + trans_status['vcclowwarning_flag'] = module_flag['voltage_flags']['voltage_low_warn_flag'] + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + if aux2_mon_type == 0: + trans_status['lasertemphighalarm_flag'] = module_flag['aux2_flags']['aux2_high_alarm_flag'] + trans_status['lasertemplowalarm_flag'] = module_flag['aux2_flags']['aux2_low_alarm_flag'] + trans_status['lasertemphighwarning_flag'] = module_flag['aux2_flags']['aux2_high_warn_flag'] + trans_status['lasertemplowwarning_flag'] = module_flag['aux2_flags']['aux2_low_warn_flag'] + elif aux2_mon_type == 1 and aux3_mon_type == 0: + trans_status['lasertemphighalarm_flag'] = module_flag['aux3_flags']['aux3_high_alarm_flag'] + trans_status['lasertemplowalarm_flag'] = module_flag['aux3_flags']['aux3_low_alarm_flag'] + trans_status['lasertemphighwarning_flag'] = module_flag['aux3_flags']['aux3_high_warn_flag'] + trans_status['lasertemplowwarning_flag'] = module_flag['aux3_flags']['aux3_low_warn_flag'] + + tx_power_flag_dict = self.get_tx_power_flag() + trans_status['txpowerhighalarm_flag'] = tx_power_flag_dict['tx_power_high_alarm']['TX_lane1'] + trans_status['txpowerlowalarm_flag'] = tx_power_flag_dict['tx_power_low_alarm']['TX_lane1'] + trans_status['txpowerhighwarning_flag'] = tx_power_flag_dict['tx_power_high_warn']['TX_lane1'] + trans_status['txpowerlowwarning_flag'] = tx_power_flag_dict['tx_power_low_warn']['TX_lane1'] + rx_power_flag_dict = self.get_rx_power_flag() + trans_status['rxpowerhighalarm_flag'] = rx_power_flag_dict['rx_power_high_alarm']['RX_lane1'] + trans_status['rxpowerlowalarm_flag'] = rx_power_flag_dict['rx_power_low_alarm']['RX_lane1'] + trans_status['rxpowerhighwarning_flag'] = rx_power_flag_dict['rx_power_high_warn']['RX_lane1'] + trans_status['rxpowerlowwarning_flag'] = rx_power_flag_dict['rx_power_low_warn']['RX_lane1'] + tx_bias_flag_dict = self.get_tx_bias_flag() + trans_status['txbiashighalarm_flag'] = tx_bias_flag_dict['tx_bias_high_alarm']['TX_lane1'] + trans_status['txbiaslowalarm_flag'] = tx_bias_flag_dict['tx_bias_low_alarm']['TX_lane1'] + trans_status['txbiashighwarning_flag'] = tx_bias_flag_dict['tx_bias_high_warn']['TX_lane1'] + trans_status['txbiaslowwarning_flag'] = tx_bias_flag_dict['tx_bias_low_warn']['TX_lane1'] + self.vdm_dict = self.get_vdm() + trans_status['prefecberhighalarm_flag'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][5] + trans_status['prefecberlowalarm_flag'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][6] + trans_status['prefecberhighwarning_flag'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][7] + trans_status['prefecberlowwarning_flag'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][8] + trans_status['postfecberhighalarm_flag'] = self.vdm_dict['Errored Frames Average Media Input'][1][5] + trans_status['postfecberlowalarm_flag'] = self.vdm_dict['Errored Frames Average Media Input'][1][6] + trans_status['postfecberhighwarning_flag'] = self.vdm_dict['Errored Frames Average Media Input'][1][7] + trans_status['postfecberlowwarning_flag'] = self.vdm_dict['Errored Frames Average Media Input'][1][8] + return trans_status + + def get_transceiver_loopback(self): + """ + Retrieves loopback mode for this xcvr + + Returns: + A dict containing the following keys/values : + ======================================================================== + key = TRANSCEIVER_PM|ifname ; information of loopback on port + ; field = value + media_output_loopback = BOOLEAN ; media side output loopback enable + media_input_loopback = BOOLEAN ; media side input loopback enable + host_output_loopback_lane1 = BOOLEAN ; host side output loopback enable lane1 + host_output_loopback_lane2 = BOOLEAN ; host side output loopback enable lane2 + host_output_loopback_lane3 = BOOLEAN ; host side output loopback enable lane3 + host_output_loopback_lane4 = BOOLEAN ; host side output loopback enable lane4 + host_output_loopback_lane5 = BOOLEAN ; host side output loopback enable lane5 + host_output_loopback_lane6 = BOOLEAN ; host side output loopback enable lane6 + host_output_loopback_lane7 = BOOLEAN ; host side output loopback enable lane7 + host_output_loopback_lane8 = BOOLEAN ; host side output loopback enable lane8 + host_input_loopback_lane1 = BOOLEAN ; host side input loopback enable lane1 + host_input_loopback_lane2 = BOOLEAN ; host side input loopback enable lane2 + host_input_loopback_lane3 = BOOLEAN ; host side input loopback enable lane3 + host_input_loopback_lane4 = BOOLEAN ; host side input loopback enable lane4 + host_input_loopback_lane5 = BOOLEAN ; host side input loopback enable lane5 + host_input_loopback_lane6 = BOOLEAN ; host side input loopback enable lane6 + host_input_loopback_lane7 = BOOLEAN ; host side input loopback enable lane7 + host_input_loopback_lane8 = BOOLEAN ; host side input loopback enable lane8 + ======================================================================== + """ + trans_loopback = dict() + trans_loopback['media_output_loopback'] = self.get_media_output_loopback() + trans_loopback['media_input_loopback'] = self.get_media_input_loopback() + host_output_loopback_status = self.get_host_output_loopback() + trans_loopback['host_output_loopback_lane1'] = host_output_loopback_status[0] + trans_loopback['host_output_loopback_lane2'] = host_output_loopback_status[1] + trans_loopback['host_output_loopback_lane3'] = host_output_loopback_status[2] + trans_loopback['host_output_loopback_lane4'] = host_output_loopback_status[3] + trans_loopback['host_output_loopback_lane5'] = host_output_loopback_status[4] + trans_loopback['host_output_loopback_lane6'] = host_output_loopback_status[5] + trans_loopback['host_output_loopback_lane7'] = host_output_loopback_status[6] + trans_loopback['host_output_loopback_lane8'] = host_output_loopback_status[7] + host_input_loopback_status = self.get_host_input_loopback() + trans_loopback['host_input_loopback_lane1'] = host_input_loopback_status[0] + trans_loopback['host_input_loopback_lane2'] = host_input_loopback_status[1] + trans_loopback['host_input_loopback_lane3'] = host_input_loopback_status[2] + trans_loopback['host_input_loopback_lane4'] = host_input_loopback_status[3] + trans_loopback['host_input_loopback_lane5'] = host_input_loopback_status[4] + trans_loopback['host_input_loopback_lane6'] = host_input_loopback_status[5] + trans_loopback['host_input_loopback_lane7'] = host_input_loopback_status[6] + trans_loopback['host_input_loopback_lane8'] = host_input_loopback_status[7] + return trans_loopback # TODO: other XcvrApi methods diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py index 3928330f0..1605eed62 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py @@ -24,6 +24,8 @@ class CmisCdbApi(XcvrApi): def __init__(self, xcvr_eeprom): super(CmisCdbApi, self).__init__(xcvr_eeprom) + self.cdb_instance_supported = self.xcvr_eeprom.read(consts.CDB_SUPPORT) >> 6 + assert self.cdb_instance_supported == 0 def cdb1_chkflags(self): ''' @@ -144,6 +146,10 @@ def read_cdb(self): # Query status def cmd0000h(self): + ''' + This QUERY Status command may be used to retrieve the password acceptance + status and to perform a test of the CDB interface + ''' cmd = bytearray(b'\x00\x00\x00\x00\x02\x00\x00\x00\x00\x10') cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): @@ -159,6 +165,9 @@ def cmd0000h(self): # Enter password def cmd0001h(self): + ''' + The Enter Password command allows the host to enter a host password + ''' cmd = bytearray(b'\x00\x01\x00\x00\x04\x00\x00\x00\x00\x00\x10\x11') cmd[133-INIT_OFFSET] = self.cdb_chkcode(cmd) for attemp in range(MAX_TRY): @@ -190,7 +199,7 @@ def cmd0040h(self): return self.read_cdb() # Firmware Update Features Supported - def cmd0041h(self): + def get_fw_management_features(self): ''' This command is used to query supported firmware update features ''' @@ -208,7 +217,7 @@ def cmd0041h(self): return self.read_cdb() # Get FW info - def cmd0100h(self): + def get_fw_info(self): ''' This command returns the firmware versions and firmware default running images that reside in the module @@ -227,7 +236,7 @@ def cmd0100h(self): return self.read_cdb() # Start FW download - def cmd0101h(self, startLPLsize, header, imagesize): + def start_fw_download(self, startLPLsize, header, imagesize): ''' This command starts the firmware download ''' @@ -252,7 +261,7 @@ def cmd0101h(self, startLPLsize, header, imagesize): return status # Abort FW download - def cmd0102h(self): + def abort_fw_download(self): ''' This command aborts the firmware download ''' @@ -270,7 +279,7 @@ def cmd0102h(self): return status # Download FW with LPL - def cmd0103h(self, addr, data): + def block_write_lpl(self, addr, data): ''' This command writes one block of the firmware image into the LPL ''' @@ -298,11 +307,11 @@ def cmd0103h(self, addr, data): return status # Download FW with EPL - def cmd0104h(self, addr, data, autopaging_flag, writelength): + def block_write_epl(self, addr, data, autopaging_flag, writelength): ''' This command writes one block of the firmware image into the EPL ''' - epl_len = 2048 + epl_len = len(data) subtime = time.time() if not autopaging_flag: pages = epl_len // PAGE_LENGTH @@ -330,7 +339,7 @@ def cmd0104h(self, addr, data, autopaging_flag, writelength): datachunk = data[offset : ] self.xcvr_eeprom.write_raw(0xA0*PAGE_LENGTH+offset+INIT_OFFSET, len(datachunk), datachunk) subtimeint = time.time()-subtime - logger.info('2048B write time: %.2fs' %subtimeint) + logger.info('%dB write time: %.2fs' %(epl_len, subtimeint)) cmd = bytearray(b'\x01\x04\x08\x00\x04\x00\x00\x00') addr_byte = struct.pack('>L',addr) cmd += addr_byte @@ -347,7 +356,7 @@ def cmd0104h(self, addr, data, autopaging_flag, writelength): return status # FW download complete - def cmd0107h(self): + def validate_fw_image(self): ''' When this command is issued, the module shall validate the complete image and then return success or failure @@ -371,7 +380,7 @@ def cmd0107h(self): # 01h = Attempt Hitless Reset to Inactive Image # 02h = Traffic affecting Reset to Running Image. # 03h = Attempt Hitless Reset to Running Image - def cmd0109h(self, mode = 0x01): + def run_fw_image(self, mode = 0x01): ''' The host uses this command to run a selected image from module internal firmware banks ''' @@ -393,7 +402,7 @@ def cmd0109h(self, mode = 0x01): return status # Commit FW image - def cmd010Ah(self): + def commit_fw_image(self): ''' A Commit is the process where the running image is set to be the image to be used on exit from module reset. In other words, a committed image is the image that will run and is expected to be a 'good' firmware diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py index 8a0b189cf..eaae6d6a1 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisVDM.py @@ -1,3 +1,9 @@ +""" + cmisCDB.py + + Implementation of APIs related to VDMs +""" + from ...fields import consts from ..xcvr_api import XcvrApi import struct @@ -14,12 +20,31 @@ def __init__(self, xcvr_eeprom): super(CmisVdmApi, self).__init__(xcvr_eeprom) def get_F16(self, value): + ''' + This function converts raw data to "F16" format defined in cmis. + ''' scale_exponent = (value >> 11) & 0x1f mantissa = value & 0x7ff result = mantissa*10**(scale_exponent-24) return result def get_vdm_page(self, page, VDM_flag_page): + ''' + This function returns VDM items from a specific VDM page. + Output format is a dictionary. Key is observable type; value is a dictionary. + In the inside dictionary, key is lane; value is a list + [ + vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn, + vdm_high_alarm_flag, + vdm_low_alarm_flag, + vdm_high_warn_flag, + vdm_low_warn_flag + ] + ''' if page not in [0x20, 0x21, 0x22, 0x23]: raise ValueError('Page not in VDM Descriptor range!') vdm_descriptor = self.xcvr_eeprom.read_raw(page * PAGE_SIZE + PAGE_OFFSET, PAGE_SIZE) @@ -117,6 +142,22 @@ def get_vdm_page(self, page, VDM_flag_page): return vdm_Page_data def get_vdm_allpage(self): + ''' + This function returns VDM items from all advertised VDM pages. + Output format is a dictionary. Key is observable type; value is a dictionary. + In the inside dictionary, key is lane; value is a list + [ + vdm_value, + vdm_thrsh_high_alarm, + vdm_thrsh_low_alarm, + vdm_thrsh_high_warn, + vdm_thrsh_low_warn, + vdm_high_alarm_flag, + vdm_low_alarm_flag, + vdm_high_warn_flag, + vdm_low_warn_flag + ] + ''' vdm_page_supported_raw = self.xcvr_eeprom.read(consts.VDM_SUPPORTED_PAGE) & 0x3 VDM_START_PAGE = 0x20 vdm = dict() diff --git a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py index 06e3f42e1..6afd538b0 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py @@ -109,8 +109,8 @@ class Sff8024(XcvrCodes): # 4-6 differ between 8472 and 8436/8636 7: "256B/257B (transcoded FEC-enabled data)", 8: "PAM4" - } - + } + EXT_SPEC_COMPLIANCE = { 0: 'Unspecified', 1: '100G AOC (Active Optical Cable) or 25GAUI C2M AOC', diff --git a/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py b/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py index 1306017da..80e96a2f6 100644 --- a/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py +++ b/sonic_platform_base/sonic_xcvr/xcvr_api_factory.py @@ -75,4 +75,4 @@ def create_xcvr_api(self): api = Sff8436Api(xcvr_eeprom) else: api = None - return api + return api diff --git a/tests/sonic_xcvr/test_ccmis.py b/tests/sonic_xcvr/test_ccmis.py index 9009c2070..3b12b4f58 100644 --- a/tests/sonic_xcvr/test_ccmis.py +++ b/tests/sonic_xcvr/test_ccmis.py @@ -1,5 +1,7 @@ from mock import MagicMock +from unittest.mock import patch import pytest +from sonic_platform_base.sonic_xcvr.api.public.cmis import CmisApi from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi from sonic_platform_base.sonic_xcvr.mem_maps.public.cmis import CmisMemMap from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom @@ -110,6 +112,16 @@ def test_set_laser_freq(self, input_param, mock_response): ccmis.get_supported_freq_config.return_value = mock_response ccmis.set_laser_freq(input_param) + @pytest.mark.parametrize("input_param, mock_response",[ + (-10, (-14, -9)), + (-8, (-12, -8)), + ]) + def test_set_tx_power(self, input_param, mock_response): + ccmis = self.mock_ccmis_api() + ccmis.get_supported_power_config = MagicMock() + ccmis.get_supported_power_config.return_value = mock_response + ccmis.set_tx_power(input_param) + @pytest.mark.parametrize("mock_response, expected", [ ( [ @@ -155,27 +167,36 @@ def test_get_pm_all(self, mock_response, expected): result = ccmis.get_pm_all() assert result == expected - @pytest.mark.parametrize("mock_response, expected",[ ( - [ - 'Single Mode Fiber (SMF)', - '400GAUI-8 C2M (Annex 120E)', - '400ZR, DWDM, amplified', - 8, 1, 1, 1, - {'hostlane1': 1, 'hostlane2': 1, 'hostlane3': 1, 'hostlane4': 1, - 'hostlane5': 1, 'hostlane6': 1, 'hostlane7': 1, 'hostlane8': 1}, - '1550 nm DFB', - '0.0', - '00000000', - 'VENDOR_NAME', - '0.0', - 'xx-xx-xx', - '21010100', - 'LC', - '5.0', - '0.1', - '0.0', + [ { + 'active_firmware': '0.1', + 'media_lane_count': 1, + 'inactive_firmware': '0.0', + 'vendor_rev': '0.0', + 'host_electrical_interface': '400GAUI-8 C2M (Annex 120E)', + 'vendor_oui': 'xx-xx-xx', + 'manufacturename': 'VENDOR_NAME', + 'media_interface_technology': '1550 nm DFB', + 'media_interface_code': '400ZR, DWDM, amplified', + 'serialnum': '00000000', + 'module_media_type': 'Single Mode Fiber (SMF)', + 'host_lane_count': 8, + 'active_apsel_hostlane1': 1, + 'active_apsel_hostlane3': 1, + 'active_apsel_hostlane2': 1, + 'active_apsel_hostlane5': 1, + 'active_apsel_hostlane4': 1, + 'active_apsel_hostlane7': 1, + 'active_apsel_hostlane6': 1, + 'active_apsel_hostlane8': 1, + 'hardwarerev': '0.0', + 'specification_compliance': '5.0', + 'media_lane_assignment_option': 1, + 'connector_type': 'LC', + 'host_lane_assignment_option': 1, + 'vendor_date': '21010100' + }, (-20, 0), (0xff, -72, 120, 191300, 196100) ], @@ -213,62 +234,30 @@ def test_get_pm_all(self, mock_response, expected): } ) ]) - def test_get_transceiver_info(self, mock_response, expected): + @patch("sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_info") + def test_get_transceiver_info(self, get_transceiver_info_func, mock_response, expected): ccmis = self.mock_ccmis_api() - ccmis.get_module_media_type = MagicMock() - ccmis.get_module_media_type.return_value = mock_response[0] - ccmis.get_host_electrical_interface = MagicMock() - ccmis.get_host_electrical_interface.return_value = mock_response[1] - ccmis.get_module_media_interface = MagicMock() - ccmis.get_module_media_interface.return_value = mock_response[2] - ccmis.get_host_lane_count = MagicMock() - ccmis.get_host_lane_count.return_value = mock_response[3] - ccmis.get_media_lane_count = MagicMock() - ccmis.get_media_lane_count.return_value = mock_response[4] - ccmis.get_host_lane_assignment_option = MagicMock() - ccmis.get_host_lane_assignment_option.return_value = mock_response[5] - ccmis.get_media_lane_assignment_option = MagicMock() - ccmis.get_media_lane_assignment_option.return_value = mock_response[6] - ccmis.get_active_apsel_hostlane = MagicMock() - ccmis.get_active_apsel_hostlane.return_value = mock_response[7] - ccmis.get_media_interface_technology = MagicMock() - ccmis.get_media_interface_technology.return_value = mock_response[8] - ccmis.get_module_hardware_revision = MagicMock() - ccmis.get_module_hardware_revision.return_value = mock_response[9] - ccmis.get_vendor_serial = MagicMock() - ccmis.get_vendor_serial.return_value = mock_response[10] - ccmis.get_vendor_name = MagicMock() - ccmis.get_vendor_name.return_value = mock_response[11] - ccmis.get_vendor_rev = MagicMock() - ccmis.get_vendor_rev.return_value = mock_response[12] - ccmis.get_vendor_OUI = MagicMock() - ccmis.get_vendor_OUI.return_value = mock_response[13] - ccmis.get_vendor_date = MagicMock() - ccmis.get_vendor_date.return_value = mock_response[14] - ccmis.get_connector_type = MagicMock() - ccmis.get_connector_type.return_value = mock_response[15] - ccmis.get_cmis_rev = MagicMock() - ccmis.get_cmis_rev.return_value = mock_response[16] - ccmis.get_module_active_firmware = MagicMock() - ccmis.get_module_active_firmware.return_value = mock_response[17] - ccmis.get_module_inactive_firmware = MagicMock() - ccmis.get_module_inactive_firmware.return_value = mock_response[18] + get_transceiver_info_func.return_value = mock_response[0] ccmis.get_supported_power_config = MagicMock() - ccmis.get_supported_power_config.return_value = mock_response[19] + ccmis.get_supported_power_config.return_value = mock_response[1] ccmis.get_supported_freq_config = MagicMock() - ccmis.get_supported_freq_config.return_value = mock_response[20] + ccmis.get_supported_freq_config.return_value = mock_response[2] result = ccmis.get_transceiver_info() assert result == expected @pytest.mark.parametrize("mock_response, expected",[ ( [ - {'monitor value': 50}, - {'monitor value': 3.3}, - {'monitor value lane1': 0.1}, - {'monitor value lane1': 0.09}, - {'monitor value lane1': 70}, - {'monitor value': 40}, + { + 'temperature': 50, + 'voltage': 3.3, + 'txpower': 0.1, + 'rxpower': 0.09, + 'txbias': 70, + 'laser_temperature': 40, + 'prefec_ber': 0.001, + 'postfec_ber': 0, + }, { 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, @@ -324,28 +313,17 @@ def test_get_transceiver_info(self, mock_response, expected): } ) ]) - def test_get_transceiver_bulk_status(self, mock_response, expected): + @patch("sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_bulk_status") + def test_get_transceiver_bulk_status(self, get_transceiver_bulk_status_func, mock_response, expected): ccmis = self.mock_ccmis_api() - ccmis.get_module_temperature = MagicMock() - ccmis.get_module_temperature.return_value = mock_response[0] - ccmis.get_module_voltage = MagicMock() - ccmis.get_module_voltage.return_value = mock_response[1] - ccmis.get_txpower = MagicMock() - ccmis.get_txpower.return_value = mock_response[2] - ccmis.get_rxpower = MagicMock() - ccmis.get_rxpower.return_value = mock_response[3] - ccmis.get_txbias = MagicMock() - ccmis.get_txbias.return_value = mock_response[4] - ccmis.get_laser_temperature = MagicMock() - ccmis.get_laser_temperature.return_value = mock_response[5] - ccmis.get_vdm = MagicMock() - ccmis.get_vdm.return_value = mock_response[6] + get_transceiver_bulk_status_func.return_value = mock_response[0] + ccmis.vdm_dict = mock_response[1] ccmis.get_laser_config_freq = MagicMock() - ccmis.get_laser_config_freq.return_value = mock_response[7] + ccmis.get_laser_config_freq.return_value = mock_response[2] ccmis.get_current_laser_freq = MagicMock() - ccmis.get_current_laser_freq.return_value = mock_response[8] + ccmis.get_current_laser_freq.return_value = mock_response[3] ccmis.get_tx_config_power = MagicMock() - ccmis.get_tx_config_power.return_value = mock_response[9] + ccmis.get_tx_config_power.return_value = mock_response[4] result = ccmis.get_transceiver_bulk_status() assert result == expected @@ -353,12 +331,16 @@ def test_get_transceiver_bulk_status(self, mock_response, expected): @pytest.mark.parametrize("mock_response, expected",[ ( [ - {'high alarm': 80, 'low alarm': 0, 'high warn': 75, 'low warn': 10}, - {'high alarm': 3.5, 'low alarm': 3.1, 'high warn': 3.45, 'low warn': 3.15}, - {'high alarm': 1.0, 'low alarm': 0.01, 'high warn': 0.7, 'low warn': 0.02}, - {'high alarm': 2.0, 'low alarm': 0.01, 'high warn': 1.0, 'low warn': 0.02}, - {'high alarm': 90, 'low alarm': 10, 'high warn': 80, 'low warn': 20}, - {'high alarm': 80, 'low alarm': 10, 'high warn': 75, 'low warn': 20}, + { + 'temphighalarm': 80, 'templowalarm': 0, 'temphighwarning': 75, 'templowwarning': 10, + 'vcchighalarm': 3.5, 'vcclowalarm': 3.1, 'vcchighwarning': 3.45, 'vcclowwarning': 3.15, + 'txpowerhighalarm': 1.0, 'txpowerlowalarm': 0.01, 'txpowerhighwarning': 0.7, 'txpowerlowwarning': 0.02, + 'rxpowerhighalarm': 2.0, 'rxpowerlowalarm': 0.01, 'rxpowerhighwarning': 1.0, 'rxpowerlowwarning': 0.02, + 'txbiashighalarm': 90, 'txbiaslowalarm': 10, 'txbiashighwarning': 80, 'txbiaslowwarning': 20, + 'lasertemphighalarm': 80, 'lasertemplowalarm': 10, 'lasertemphighwarning': 75, 'lasertemplowwarning': 20, + 'prefecberhighalarm': 0.0125, 'prefecberlowalarm': 0, 'prefecberhighwarning': 0.01, 'prefecberlowwarning': 0, + 'postfecberhighalarm': 1, 'postfecberlowalarm': 0, 'postfecberhighwarning': 1, 'postfecberlowwarning': 0, + }, { 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, @@ -410,115 +392,93 @@ def test_get_transceiver_bulk_status(self, mock_response, expected): } ) ]) - def test_get_transceiver_threshold_info(self, mock_response, expected): + @patch("sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_threshold_info") + def test_get_transceiver_threshold_info(self, get_transceiver_threshold_info_func, mock_response, expected): ccmis = self.mock_ccmis_api() - ccmis.get_module_temperature = MagicMock() - ccmis.get_module_temperature.return_value = mock_response[0] - ccmis.get_module_voltage = MagicMock() - ccmis.get_module_voltage.return_value = mock_response[1] - ccmis.get_txpower = MagicMock() - ccmis.get_txpower.return_value = mock_response[2] - ccmis.get_rxpower = MagicMock() - ccmis.get_rxpower.return_value = mock_response[3] - ccmis.get_txbias = MagicMock() - ccmis.get_txbias.return_value = mock_response[4] - ccmis.get_laser_temperature = MagicMock() - ccmis.get_laser_temperature.return_value = mock_response[5] - ccmis.get_vdm = MagicMock() - ccmis.get_vdm.return_value = mock_response[6] + get_transceiver_threshold_info_func.return_value = mock_response[0] + ccmis.vdm_dict = mock_response[1] result = ccmis.get_transceiver_threshold_info() assert result == expected @pytest.mark.parametrize("mock_response, expected",[ ( [ - 'ModuleReady', 'No Fault detected', (False, False, True), - { - 'dp_lane1': 'DataPathActivated', 'dp_lane2': 'DataPathActivated', - 'dp_lane3': 'DataPathActivated', 'dp_lane4': 'DataPathActivated', - 'dp_lane5': 'DataPathActivated', 'dp_lane6': 'DataPathActivated', - 'dp_lane7': 'DataPathActivated', 'dp_lane8': 'DataPathActivated' - }, - {'TX_lane1': True}, - { - 'RX_lane1': True, 'RX_lane2': True, 'RX_lane3': True, 'RX_lane4': True, - 'RX_lane5': True, 'RX_lane6': True, 'RX_lane7': True, 'RX_lane8': True - }, - {'TX_lane1': False}, { - 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, - 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False - }, - { - 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, - 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False - }, - {'RX_lane1': False}, - {'RX_lane1': False}, - { - 'config_DP_status_hostlane1': 'ConfigSuccess', 'config_DP_status_hostlane2': 'ConfigSuccess', - 'config_DP_status_hostlane3': 'ConfigSuccess', 'config_DP_status_hostlane4': 'ConfigSuccess', - 'config_DP_status_hostlane5': 'ConfigSuccess', 'config_DP_status_hostlane6': 'ConfigSuccess', - 'config_DP_status_hostlane7': 'ConfigSuccess', 'config_DP_status_hostlane8': 'ConfigSuccess' - }, - { - 'hostlane1': False, 'hostlane2': False, - 'hostlane3': False, 'hostlane4': False, - 'hostlane5': False, 'hostlane6': False, - 'hostlane7': False, 'hostlane8': False + 'module_state': 'ModuleReady', + 'module_fault_cause': 'No Fault detected', + 'datapath_firmware_fault': False, + 'module_firmware_fault': False, + 'module_state_changed': True, + 'datapath_hostlane1': 'DataPathActivated', + 'datapath_hostlane2': 'DataPathActivated', + 'datapath_hostlane3': 'DataPathActivated', + 'datapath_hostlane4': 'DataPathActivated', + 'datapath_hostlane5': 'DataPathActivated', + 'datapath_hostlane6': 'DataPathActivated', + 'datapath_hostlane7': 'DataPathActivated', + 'datapath_hostlane8': 'DataPathActivated', + 'txoutput_status': True, + 'rxoutput_status_hostlane1': True, + 'rxoutput_status_hostlane2': True, + 'rxoutput_status_hostlane3': True, + 'rxoutput_status_hostlane4': True, + 'rxoutput_status_hostlane5': True, + 'rxoutput_status_hostlane6': True, + 'rxoutput_status_hostlane7': True, + 'rxoutput_status_hostlane8': True, + 'txfault': False, + 'txlos_hostlane1': False, + 'txlos_hostlane2': False, + 'txlos_hostlane3': False, + 'txlos_hostlane4': False, + 'txlos_hostlane5': False, + 'txlos_hostlane6': False, + 'txlos_hostlane7': False, + 'txlos_hostlane8': False, + 'txcdrlol_hostlane1': False, + 'txcdrlol_hostlane2': False, + 'txcdrlol_hostlane3': False, + 'txcdrlol_hostlane4': False, + 'txcdrlol_hostlane5': False, + 'txcdrlol_hostlane6': False, + 'txcdrlol_hostlane7': False, + 'txcdrlol_hostlane8': False, + 'rxlos': False, + 'rxcdrlol': False, + 'config_state_hostlane1': 'ConfigSuccess', + 'config_state_hostlane2': 'ConfigSuccess', + 'config_state_hostlane3': 'ConfigSuccess', + 'config_state_hostlane4': 'ConfigSuccess', + 'config_state_hostlane5': 'ConfigSuccess', + 'config_state_hostlane6': 'ConfigSuccess', + 'config_state_hostlane7': 'ConfigSuccess', + 'config_state_hostlane8': 'ConfigSuccess', + 'dpinit_pending_hostlane1': False, + 'dpinit_pending_hostlane2': False, + 'dpinit_pending_hostlane3': False, + 'dpinit_pending_hostlane4': False, + 'dpinit_pending_hostlane5': False, + 'dpinit_pending_hostlane6': False, + 'dpinit_pending_hostlane7': False, + 'dpinit_pending_hostlane8': False, + 'temphighalarm_flag': False, 'templowalarm_flag': False, + 'temphighwarning_flag': False, 'templowwarning_flag': False, + 'vcchighalarm_flag': False, 'vcclowalarm_flag': False, + 'vcchighwarning_flag': False, 'vcclowwarning_flag': False, + 'lasertemphighalarm_flag': False, 'lasertemplowalarm_flag': False, + 'lasertemphighwarning_flag': False, 'lasertemplowwarning_flag': False, + 'txpowerhighalarm_flag': False, 'txpowerlowalarm_flag': False, + 'txpowerhighwarning_flag': False, 'txpowerlowwarning_flag': False, + 'rxpowerhighalarm_flag': False, 'rxpowerlowalarm_flag': False, + 'rxpowerhighwarning_flag': False, 'rxpowerlowwarning_flag': False, + 'txbiashighalarm_flag': False, 'txbiaslowalarm_flag': False, + 'txbiashighwarning_flag': False, 'txbiaslowwarning_flag': False, + 'prefecberhighalarm_flag': False, 'prefecberlowalarm_flag': False, + 'prefecberhighwarning_flag': False, 'prefecberlowwarning_flag': False, + 'postfecberhighalarm_flag': False, 'postfecberlowalarm_flag': False, + 'postfecberhighwarning_flag': False, 'postfecberlowwarning_flag': False, }, False, False, ['TuningComplete'], - { - 'case_temp_flags': { - 'case_temp_high_alarm_flag': False, - 'case_temp_low_alarm_flag': False, - 'case_temp_high_warn_flag': False, - 'case_temp_low_warn_flag': False, - }, - 'voltage_flags': { - 'voltage_high_alarm_flag': False, - 'voltage_low_alarm_flag': False, - 'voltage_high_warn_flag': False, - 'voltage_low_warn_flag': False, - }, - 'aux1_flags': { - 'aux1_high_alarm_flag': False, - 'aux1_low_alarm_flag': False, - 'aux1_high_warn_flag': False, - 'aux1_low_warn_flag': False, - }, - 'aux2_flags': { - 'aux2_high_alarm_flag': False, - 'aux2_low_alarm_flag': False, - 'aux2_high_warn_flag': False, - 'aux2_low_warn_flag': False, - }, - 'aux3_flags': { - 'aux3_high_alarm_flag': False, - 'aux3_low_alarm_flag': False, - 'aux3_high_warn_flag': False, - 'aux3_low_warn_flag': False, - } - }, - (0, 0, 0), - { - 'tx_power_high_alarm': {'TX_lane1': False}, - 'tx_power_low_alarm': {'TX_lane1': False}, - 'tx_power_high_warn': {'TX_lane1': False}, - 'tx_power_low_warn': {'TX_lane1': False}, - }, - { - 'rx_power_high_alarm': {'RX_lane1': False}, - 'rx_power_low_alarm': {'RX_lane1': False}, - 'rx_power_high_warn': {'RX_lane1': False}, - 'rx_power_low_warn': {'RX_lane1': False}, - }, - { - 'tx_bias_high_alarm': {'TX_lane1': False}, - 'tx_bias_low_alarm': {'TX_lane1': False}, - 'tx_bias_high_warn': {'TX_lane1': False}, - 'tx_bias_low_warn': {'TX_lane1': False}, - }, { 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, @@ -660,52 +620,17 @@ def test_get_transceiver_threshold_info(self, mock_response, expected): } ) ]) - def test_get_transceiver_status(self, mock_response, expected): + @patch("sonic_platform_base.sonic_xcvr.api.public.cmis.CmisApi.get_transceiver_status") + def test_get_transceiver_status(self, get_transceiver_status_func, mock_response, expected): ccmis = self.mock_ccmis_api() - ccmis.get_module_state = MagicMock() - ccmis.get_module_state.return_value = mock_response[0] - ccmis.get_module_fault_cause = MagicMock() - ccmis.get_module_fault_cause.return_value = mock_response[1] - ccmis.get_module_firmware_fault_state_changed = MagicMock() - ccmis.get_module_firmware_fault_state_changed.return_value = mock_response[2] - ccmis.get_datapath_state = MagicMock() - ccmis.get_datapath_state.return_value = mock_response[3] - ccmis.get_tx_output_status = MagicMock() - ccmis.get_tx_output_status.return_value = mock_response[4] - ccmis.get_rx_output_status = MagicMock() - ccmis.get_rx_output_status.return_value = mock_response[5] - ccmis.get_tx_fault = MagicMock() - ccmis.get_tx_fault.return_value = mock_response[6] - ccmis.get_tx_los = MagicMock() - ccmis.get_tx_los.return_value = mock_response[7] - ccmis.get_tx_cdr_lol = MagicMock() - ccmis.get_tx_cdr_lol.return_value = mock_response[8] - ccmis.get_rx_los = MagicMock() - ccmis.get_rx_los.return_value = mock_response[9] - ccmis.get_rx_cdr_lol = MagicMock() - ccmis.get_rx_cdr_lol.return_value = mock_response[10] - ccmis.get_config_datapath_hostlane_status = MagicMock() - ccmis.get_config_datapath_hostlane_status.return_value = mock_response[11] - ccmis.get_dpinit_pending = MagicMock() - ccmis.get_dpinit_pending.return_value = mock_response[12] + get_transceiver_status_func.return_value = mock_response[0] ccmis.get_tuning_in_progress = MagicMock() - ccmis.get_tuning_in_progress.return_value = mock_response[13] + ccmis.get_tuning_in_progress.return_value = mock_response[1] ccmis.get_wavelength_unlocked = MagicMock() - ccmis.get_wavelength_unlocked.return_value = mock_response[14] + ccmis.get_wavelength_unlocked.return_value = mock_response[2] ccmis.get_laser_tuning_summary = MagicMock() - ccmis.get_laser_tuning_summary.return_value = mock_response[15] - ccmis.get_module_level_flag = MagicMock() - ccmis.get_module_level_flag.return_value = mock_response[16] - ccmis.get_aux_mon_type = MagicMock() - ccmis.get_aux_mon_type.return_value = mock_response[17] - ccmis.get_tx_power_flag = MagicMock() - ccmis.get_tx_power_flag.return_value = mock_response[18] - ccmis.get_rx_power_flag = MagicMock() - ccmis.get_rx_power_flag.return_value = mock_response[19] - ccmis.get_tx_bias_flag = MagicMock() - ccmis.get_tx_bias_flag.return_value = mock_response[20] - ccmis.get_vdm = MagicMock() - ccmis.get_vdm.return_value = mock_response[21] + ccmis.get_laser_tuning_summary.return_value = mock_response[3] + ccmis.vdm_dict = mock_response[4] result = ccmis.get_transceiver_status() assert result == expected @@ -750,47 +675,4 @@ def test_get_transceiver_pm(self, mock_response, expected): result = ccmis.get_transceiver_pm() assert result == expected - @pytest.mark.parametrize("mock_response, expected",[ - ( - [ - False, - False, - [False, False, False, False, False, False, False, False], - [False, False, False, False, False, False, False, False] - ], - { - 'media_output_loopback': False, - 'media_input_loopback': False, - 'host_output_loopback_lane1': False, - 'host_output_loopback_lane2': False, - 'host_output_loopback_lane3': False, - 'host_output_loopback_lane4': False, - 'host_output_loopback_lane5': False, - 'host_output_loopback_lane6': False, - 'host_output_loopback_lane7': False, - 'host_output_loopback_lane8': False, - 'host_input_loopback_lane1': False, - 'host_input_loopback_lane2': False, - 'host_input_loopback_lane3': False, - 'host_input_loopback_lane4': False, - 'host_input_loopback_lane5': False, - 'host_input_loopback_lane6': False, - 'host_input_loopback_lane7': False, - 'host_input_loopback_lane8': False - } - ) - ]) - def test_get_transceiver_loopback(self, mock_response, expected): - ccmis = self.mock_ccmis_api() - ccmis.get_media_output_loopback = MagicMock() - ccmis.get_media_output_loopback.return_value = mock_response[0] - ccmis.get_media_input_loopback = MagicMock() - ccmis.get_media_input_loopback.return_value = mock_response[1] - ccmis.get_host_output_loopback = MagicMock() - ccmis.get_host_output_loopback.return_value = mock_response[2] - ccmis.get_host_input_loopback = MagicMock() - ccmis.get_host_input_loopback.return_value = mock_response[3] - result = ccmis.get_transceiver_loopback() - assert result == expected - # TODO: call other methods in the api diff --git a/tests/sonic_xcvr/test_cmis.py b/tests/sonic_xcvr/test_cmis.py index 83e658cae..b0fc51c37 100644 --- a/tests/sonic_xcvr/test_cmis.py +++ b/tests/sonic_xcvr/test_cmis.py @@ -901,16 +901,6 @@ def test_set_low_power(self, input_param): api = self.mock_cmis_api() api.set_low_power(input_param) - @pytest.mark.parametrize("input_param, mock_response",[ - (-10, (-14, -9)), - (-8, (-12, -8)), - ]) - def test_set_tx_power(self, input_param, mock_response): - api = self.mock_cmis_api() - api.get_supported_power_config = MagicMock() - api.get_supported_power_config.return_value = mock_response - api.set_tx_power(input_param) - @pytest.mark.parametrize("mock_response, expected", [ (127, { @@ -991,8 +981,8 @@ def test_get_module_fw_upgrade_feature(self, input_param, mock_response1, mock_r api.xcvr_eeprom.read = MagicMock() api.xcvr_eeprom.read.side_effect = mock_response1 api.cdb = MagicMock() - api.cdb.cmd0041h = MagicMock() - api.cdb.cmd0041h.return_value = mock_response2 + api.cdb.get_fw_management_features = MagicMock() + api.cdb.get_fw_management_features.return_value = mock_response2 api.cdb.cdb_chkcode = MagicMock() api.cdb.cdb_chkcode.return_value = mock_response2[1] result = api.get_module_fw_upgrade_feature(input_param) @@ -1011,8 +1001,8 @@ def test_get_module_fw_upgrade_feature(self, input_param, mock_response1, mock_r def test_get_module_fw_info(self, mock_response, expected): api = self.mock_cmis_api() api.cdb = MagicMock() - api.cdb.cmd0100h = MagicMock() - api.cdb.cmd0100h.return_value = mock_response + api.cdb.get_fw_info = MagicMock() + api.cdb.get_fw_info.return_value = mock_response api.cdb.cdb_chkcode = MagicMock() api.cdb.cdb_chkcode.return_value = mock_response[1] result = api.get_module_fw_info() @@ -1025,8 +1015,8 @@ def test_get_module_fw_info(self, mock_response, expected): def test_module_fw_run(self, input_param, mock_response): api = self.mock_cmis_api() api.cdb = MagicMock() - api.cdb.cmd0109h = MagicMock() - api.cdb.cmd0109h.return_value = mock_response + api.cdb.run_fw_image = MagicMock() + api.cdb.run_fw_image.return_value = mock_response api.module_fw_run(input_param) @pytest.mark.parametrize("mock_response", [ @@ -1035,8 +1025,8 @@ def test_module_fw_run(self, input_param, mock_response): def test_module_fw_commit(self, mock_response): api = self.mock_cmis_api() api.cdb = MagicMock() - api.cdb.cmd010Ah = MagicMock() - api.cdb.cmd010Ah.return_value = mock_response + api.cdb.commit_fw_image = MagicMock() + api.cdb.commit_fw_image.return_value = mock_response api.module_fw_commit() # @pytest.mark.parametrize("input_param", [ @@ -1075,4 +1065,443 @@ def test_module_fw_switch(self, mock_response): api.cdb.get_module_fw_info.return_value = mock_response api.cdb.module_fw_switch() + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + False, + False, + [False, False, False, False, False, False, False, False], + [False, False, False, False, False, False, False, False] + ], + { + 'media_output_loopback': False, + 'media_input_loopback': False, + 'host_output_loopback_lane1': False, + 'host_output_loopback_lane2': False, + 'host_output_loopback_lane3': False, + 'host_output_loopback_lane4': False, + 'host_output_loopback_lane5': False, + 'host_output_loopback_lane6': False, + 'host_output_loopback_lane7': False, + 'host_output_loopback_lane8': False, + 'host_input_loopback_lane1': False, + 'host_input_loopback_lane2': False, + 'host_input_loopback_lane3': False, + 'host_input_loopback_lane4': False, + 'host_input_loopback_lane5': False, + 'host_input_loopback_lane6': False, + 'host_input_loopback_lane7': False, + 'host_input_loopback_lane8': False + } + ) + ]) + def test_get_transceiver_loopback(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_media_output_loopback = MagicMock() + api.get_media_output_loopback.return_value = mock_response[0] + api.get_media_input_loopback = MagicMock() + api.get_media_input_loopback.return_value = mock_response[1] + api.get_host_output_loopback = MagicMock() + api.get_host_output_loopback.return_value = mock_response[2] + api.get_host_input_loopback = MagicMock() + api.get_host_input_loopback.return_value = mock_response[3] + result = api.get_transceiver_loopback() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + 'Single Mode Fiber (SMF)', + '400GAUI-8 C2M (Annex 120E)', + '400ZR, DWDM, amplified', + 8, 1, 1, 1, + {'hostlane1': 1, 'hostlane2': 1, 'hostlane3': 1, 'hostlane4': 1, + 'hostlane5': 1, 'hostlane6': 1, 'hostlane7': 1, 'hostlane8': 1}, + '1550 nm DFB', + '0.0', + '00000000', + 'VENDOR_NAME', + '0.0', + 'xx-xx-xx', + '21010100', + 'LC', + '5.0', + '0.1', + '0.0' + ], + { + 'active_firmware': '0.1', + 'media_lane_count': 1, + 'inactive_firmware': '0.0', + 'vendor_rev': '0.0', + 'host_electrical_interface': '400GAUI-8 C2M (Annex 120E)', + 'vendor_oui': 'xx-xx-xx', + 'manufacturename': 'VENDOR_NAME', + 'media_interface_technology': '1550 nm DFB', + 'media_interface_code': '400ZR, DWDM, amplified', + 'serialnum': '00000000', + 'module_media_type': 'Single Mode Fiber (SMF)', + 'host_lane_count': 8, + 'active_apsel_hostlane1': 1, + 'active_apsel_hostlane3': 1, + 'active_apsel_hostlane2': 1, + 'active_apsel_hostlane5': 1, + 'active_apsel_hostlane4': 1, + 'active_apsel_hostlane7': 1, + 'active_apsel_hostlane6': 1, + 'active_apsel_hostlane8': 1, + 'hardwarerev': '0.0', + 'specification_compliance': '5.0', + 'media_lane_assignment_option': 1, + 'connector_type': 'LC', + 'host_lane_assignment_option': 1, + 'vendor_date': '21010100' + } + ) + ]) + def test_get_transceiver_info(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_module_media_type = MagicMock() + api.get_module_media_type.return_value = mock_response[0] + api.get_host_electrical_interface = MagicMock() + api.get_host_electrical_interface.return_value = mock_response[1] + api.get_module_media_interface = MagicMock() + api.get_module_media_interface.return_value = mock_response[2] + api.get_host_lane_count = MagicMock() + api.get_host_lane_count.return_value = mock_response[3] + api.get_media_lane_count = MagicMock() + api.get_media_lane_count.return_value = mock_response[4] + api.get_host_lane_assignment_option = MagicMock() + api.get_host_lane_assignment_option.return_value = mock_response[5] + api.get_media_lane_assignment_option = MagicMock() + api.get_media_lane_assignment_option.return_value = mock_response[6] + api.get_active_apsel_hostlane = MagicMock() + api.get_active_apsel_hostlane.return_value = mock_response[7] + api.get_media_interface_technology = MagicMock() + api.get_media_interface_technology.return_value = mock_response[8] + api.get_module_hardware_revision = MagicMock() + api.get_module_hardware_revision.return_value = mock_response[9] + api.get_vendor_serial = MagicMock() + api.get_vendor_serial.return_value = mock_response[10] + api.get_vendor_name = MagicMock() + api.get_vendor_name.return_value = mock_response[11] + api.get_vendor_rev = MagicMock() + api.get_vendor_rev.return_value = mock_response[12] + api.get_vendor_OUI = MagicMock() + api.get_vendor_OUI.return_value = mock_response[13] + api.get_vendor_date = MagicMock() + api.get_vendor_date.return_value = mock_response[14] + api.get_connector_type = MagicMock() + api.get_connector_type.return_value = mock_response[15] + api.get_cmis_rev = MagicMock() + api.get_cmis_rev.return_value = mock_response[16] + api.get_module_active_firmware = MagicMock() + api.get_module_active_firmware.return_value = mock_response[17] + api.get_module_inactive_firmware = MagicMock() + api.get_module_inactive_firmware.return_value = mock_response[18] + result = api.get_transceiver_info() + assert result == expected + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + {'monitor value': 50}, + {'monitor value': 3.3}, + {'monitor value lane1': 0.1}, + {'monitor value lane1': 0.09}, + {'monitor value lane1': 70}, + {'monitor value': 40}, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + } + ], + { + 'temperature': 50, + 'voltage': 3.3, + 'txpower': 0.1, + 'rxpower': 0.09, + 'txbias': 70, + 'laser_temperature': 40, + 'prefec_ber': 0.001, + 'postfec_ber': 0, + } + ) + ]) + def test_get_transceiver_bulk_status(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_module_temperature = MagicMock() + api.get_module_temperature.return_value = mock_response[0] + api.get_module_voltage = MagicMock() + api.get_module_voltage.return_value = mock_response[1] + api.get_txpower = MagicMock() + api.get_txpower.return_value = mock_response[2] + api.get_rxpower = MagicMock() + api.get_rxpower.return_value = mock_response[3] + api.get_txbias = MagicMock() + api.get_txbias.return_value = mock_response[4] + api.get_laser_temperature = MagicMock() + api.get_laser_temperature.return_value = mock_response[5] + api.get_vdm = MagicMock() + api.get_vdm.return_value = mock_response[6] + result = api.get_transceiver_bulk_status() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + {'high alarm': 80, 'low alarm': 0, 'high warn': 75, 'low warn': 10}, + {'high alarm': 3.5, 'low alarm': 3.1, 'high warn': 3.45, 'low warn': 3.15}, + {'high alarm': 1.0, 'low alarm': 0.01, 'high warn': 0.7, 'low warn': 0.02}, + {'high alarm': 2.0, 'low alarm': 0.01, 'high warn': 1.0, 'low warn': 0.02}, + {'high alarm': 90, 'low alarm': 10, 'high warn': 80, 'low warn': 20}, + {'high alarm': 80, 'low alarm': 10, 'high warn': 75, 'low warn': 20}, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + } + ], + { + 'temphighalarm': 80, 'templowalarm': 0, 'temphighwarning': 75, 'templowwarning': 10, + 'vcchighalarm': 3.5, 'vcclowalarm': 3.1, 'vcchighwarning': 3.45, 'vcclowwarning': 3.15, + 'txpowerhighalarm': 1.0, 'txpowerlowalarm': 0.01, 'txpowerhighwarning': 0.7, 'txpowerlowwarning': 0.02, + 'rxpowerhighalarm': 2.0, 'rxpowerlowalarm': 0.01, 'rxpowerhighwarning': 1.0, 'rxpowerlowwarning': 0.02, + 'txbiashighalarm': 90, 'txbiaslowalarm': 10, 'txbiashighwarning': 80, 'txbiaslowwarning': 20, + 'lasertemphighalarm': 80, 'lasertemplowalarm': 10, 'lasertemphighwarning': 75, 'lasertemplowwarning': 20, + 'prefecberhighalarm': 0.0125, 'prefecberlowalarm': 0, 'prefecberhighwarning': 0.01, 'prefecberlowwarning': 0, + 'postfecberhighalarm': 1, 'postfecberlowalarm': 0, 'postfecberhighwarning': 1, 'postfecberlowwarning': 0, + } + ) + ]) + def test_get_transceiver_threshold_info(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_module_temperature = MagicMock() + api.get_module_temperature.return_value = mock_response[0] + api.get_module_voltage = MagicMock() + api.get_module_voltage.return_value = mock_response[1] + api.get_txpower = MagicMock() + api.get_txpower.return_value = mock_response[2] + api.get_rxpower = MagicMock() + api.get_rxpower.return_value = mock_response[3] + api.get_txbias = MagicMock() + api.get_txbias.return_value = mock_response[4] + api.get_laser_temperature = MagicMock() + api.get_laser_temperature.return_value = mock_response[5] + api.get_vdm = MagicMock() + api.get_vdm.return_value = mock_response[6] + result = api.get_transceiver_threshold_info() + assert result == expected + + @pytest.mark.parametrize("mock_response, expected",[ + ( + [ + 'ModuleReady', 'No Fault detected', (False, False, True), + { + 'dp_lane1': 'DataPathActivated', 'dp_lane2': 'DataPathActivated', + 'dp_lane3': 'DataPathActivated', 'dp_lane4': 'DataPathActivated', + 'dp_lane5': 'DataPathActivated', 'dp_lane6': 'DataPathActivated', + 'dp_lane7': 'DataPathActivated', 'dp_lane8': 'DataPathActivated' + }, + {'TX_lane1': True}, + { + 'RX_lane1': True, 'RX_lane2': True, 'RX_lane3': True, 'RX_lane4': True, + 'RX_lane5': True, 'RX_lane6': True, 'RX_lane7': True, 'RX_lane8': True + }, + {'TX_lane1': False}, + { + 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, + 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False + }, + { + 'TX_lane1': False, 'TX_lane2': False, 'TX_lane3': False, 'TX_lane4': False, + 'TX_lane5': False, 'TX_lane6': False, 'TX_lane7': False, 'TX_lane8': False + }, + {'RX_lane1': False}, + {'RX_lane1': False}, + { + 'config_DP_status_hostlane1': 'ConfigSuccess', 'config_DP_status_hostlane2': 'ConfigSuccess', + 'config_DP_status_hostlane3': 'ConfigSuccess', 'config_DP_status_hostlane4': 'ConfigSuccess', + 'config_DP_status_hostlane5': 'ConfigSuccess', 'config_DP_status_hostlane6': 'ConfigSuccess', + 'config_DP_status_hostlane7': 'ConfigSuccess', 'config_DP_status_hostlane8': 'ConfigSuccess' + }, + { + 'hostlane1': False, 'hostlane2': False, + 'hostlane3': False, 'hostlane4': False, + 'hostlane5': False, 'hostlane6': False, + 'hostlane7': False, 'hostlane8': False + }, + { + 'case_temp_flags': { + 'case_temp_high_alarm_flag': False, + 'case_temp_low_alarm_flag': False, + 'case_temp_high_warn_flag': False, + 'case_temp_low_warn_flag': False, + }, + 'voltage_flags': { + 'voltage_high_alarm_flag': False, + 'voltage_low_alarm_flag': False, + 'voltage_high_warn_flag': False, + 'voltage_low_warn_flag': False, + }, + 'aux1_flags': { + 'aux1_high_alarm_flag': False, + 'aux1_low_alarm_flag': False, + 'aux1_high_warn_flag': False, + 'aux1_low_warn_flag': False, + }, + 'aux2_flags': { + 'aux2_high_alarm_flag': False, + 'aux2_low_alarm_flag': False, + 'aux2_high_warn_flag': False, + 'aux2_low_warn_flag': False, + }, + 'aux3_flags': { + 'aux3_high_alarm_flag': False, + 'aux3_low_alarm_flag': False, + 'aux3_high_warn_flag': False, + 'aux3_low_warn_flag': False, + } + }, + (0, 0, 0), + { + 'tx_power_high_alarm': {'TX_lane1': False}, + 'tx_power_low_alarm': {'TX_lane1': False}, + 'tx_power_high_warn': {'TX_lane1': False}, + 'tx_power_low_warn': {'TX_lane1': False}, + }, + { + 'rx_power_high_alarm': {'RX_lane1': False}, + 'rx_power_low_alarm': {'RX_lane1': False}, + 'rx_power_high_warn': {'RX_lane1': False}, + 'rx_power_low_warn': {'RX_lane1': False}, + }, + { + 'tx_bias_high_alarm': {'TX_lane1': False}, + 'tx_bias_low_alarm': {'TX_lane1': False}, + 'tx_bias_high_warn': {'TX_lane1': False}, + 'tx_bias_low_warn': {'TX_lane1': False}, + }, + { + 'Pre-FEC BER Average Media Input':{1:[0.001, 0.0125, 0, 0.01, 0, False, False, False, False]}, + 'Errored Frames Average Media Input':{1:[0, 1, 0, 1, 0, False, False, False, False]}, + } + ], + { + 'module_state': 'ModuleReady', + 'module_fault_cause': 'No Fault detected', + 'datapath_firmware_fault': False, + 'module_firmware_fault': False, + 'module_state_changed': True, + 'datapath_hostlane1': 'DataPathActivated', + 'datapath_hostlane2': 'DataPathActivated', + 'datapath_hostlane3': 'DataPathActivated', + 'datapath_hostlane4': 'DataPathActivated', + 'datapath_hostlane5': 'DataPathActivated', + 'datapath_hostlane6': 'DataPathActivated', + 'datapath_hostlane7': 'DataPathActivated', + 'datapath_hostlane8': 'DataPathActivated', + 'txoutput_status': True, + 'rxoutput_status_hostlane1': True, + 'rxoutput_status_hostlane2': True, + 'rxoutput_status_hostlane3': True, + 'rxoutput_status_hostlane4': True, + 'rxoutput_status_hostlane5': True, + 'rxoutput_status_hostlane6': True, + 'rxoutput_status_hostlane7': True, + 'rxoutput_status_hostlane8': True, + 'txfault': False, + 'txlos_hostlane1': False, + 'txlos_hostlane2': False, + 'txlos_hostlane3': False, + 'txlos_hostlane4': False, + 'txlos_hostlane5': False, + 'txlos_hostlane6': False, + 'txlos_hostlane7': False, + 'txlos_hostlane8': False, + 'txcdrlol_hostlane1': False, + 'txcdrlol_hostlane2': False, + 'txcdrlol_hostlane3': False, + 'txcdrlol_hostlane4': False, + 'txcdrlol_hostlane5': False, + 'txcdrlol_hostlane6': False, + 'txcdrlol_hostlane7': False, + 'txcdrlol_hostlane8': False, + 'rxlos': False, + 'rxcdrlol': False, + 'config_state_hostlane1': 'ConfigSuccess', + 'config_state_hostlane2': 'ConfigSuccess', + 'config_state_hostlane3': 'ConfigSuccess', + 'config_state_hostlane4': 'ConfigSuccess', + 'config_state_hostlane5': 'ConfigSuccess', + 'config_state_hostlane6': 'ConfigSuccess', + 'config_state_hostlane7': 'ConfigSuccess', + 'config_state_hostlane8': 'ConfigSuccess', + 'dpinit_pending_hostlane1': False, + 'dpinit_pending_hostlane2': False, + 'dpinit_pending_hostlane3': False, + 'dpinit_pending_hostlane4': False, + 'dpinit_pending_hostlane5': False, + 'dpinit_pending_hostlane6': False, + 'dpinit_pending_hostlane7': False, + 'dpinit_pending_hostlane8': False, + 'temphighalarm_flag': False, 'templowalarm_flag': False, + 'temphighwarning_flag': False, 'templowwarning_flag': False, + 'vcchighalarm_flag': False, 'vcclowalarm_flag': False, + 'vcchighwarning_flag': False, 'vcclowwarning_flag': False, + 'lasertemphighalarm_flag': False, 'lasertemplowalarm_flag': False, + 'lasertemphighwarning_flag': False, 'lasertemplowwarning_flag': False, + 'txpowerhighalarm_flag': False, 'txpowerlowalarm_flag': False, + 'txpowerhighwarning_flag': False, 'txpowerlowwarning_flag': False, + 'rxpowerhighalarm_flag': False, 'rxpowerlowalarm_flag': False, + 'rxpowerhighwarning_flag': False, 'rxpowerlowwarning_flag': False, + 'txbiashighalarm_flag': False, 'txbiaslowalarm_flag': False, + 'txbiashighwarning_flag': False, 'txbiaslowwarning_flag': False, + 'prefecberhighalarm_flag': False, 'prefecberlowalarm_flag': False, + 'prefecberhighwarning_flag': False, 'prefecberlowwarning_flag': False, + 'postfecberhighalarm_flag': False, 'postfecberlowalarm_flag': False, + 'postfecberhighwarning_flag': False, 'postfecberlowwarning_flag': False, + } + ) + ]) + def test_get_transceiver_status(self, mock_response, expected): + api = self.mock_cmis_api() + api.get_module_state = MagicMock() + api.get_module_state.return_value = mock_response[0] + api.get_module_fault_cause = MagicMock() + api.get_module_fault_cause.return_value = mock_response[1] + api.get_module_firmware_fault_state_changed = MagicMock() + api.get_module_firmware_fault_state_changed.return_value = mock_response[2] + api.get_datapath_state = MagicMock() + api.get_datapath_state.return_value = mock_response[3] + api.get_tx_output_status = MagicMock() + api.get_tx_output_status.return_value = mock_response[4] + api.get_rx_output_status = MagicMock() + api.get_rx_output_status.return_value = mock_response[5] + api.get_tx_fault = MagicMock() + api.get_tx_fault.return_value = mock_response[6] + api.get_tx_los = MagicMock() + api.get_tx_los.return_value = mock_response[7] + api.get_tx_cdr_lol = MagicMock() + api.get_tx_cdr_lol.return_value = mock_response[8] + api.get_rx_los = MagicMock() + api.get_rx_los.return_value = mock_response[9] + api.get_rx_cdr_lol = MagicMock() + api.get_rx_cdr_lol.return_value = mock_response[10] + api.get_config_datapath_hostlane_status = MagicMock() + api.get_config_datapath_hostlane_status.return_value = mock_response[11] + api.get_dpinit_pending = MagicMock() + api.get_dpinit_pending.return_value = mock_response[12] + api.get_module_level_flag = MagicMock() + api.get_module_level_flag.return_value = mock_response[13] + api.get_aux_mon_type = MagicMock() + api.get_aux_mon_type.return_value = mock_response[14] + api.get_tx_power_flag = MagicMock() + api.get_tx_power_flag.return_value = mock_response[15] + api.get_rx_power_flag = MagicMock() + api.get_rx_power_flag.return_value = mock_response[16] + api.get_tx_bias_flag = MagicMock() + api.get_tx_bias_flag.return_value = mock_response[17] + api.get_vdm = MagicMock() + api.get_vdm.return_value = mock_response[18] + result = api.get_transceiver_status() + assert result == expected \ No newline at end of file diff --git a/tests/sonic_xcvr/test_cmisCDB.py b/tests/sonic_xcvr/test_cmisCDB.py index ce0a88813..ab9500405 100644 --- a/tests/sonic_xcvr/test_cmisCDB.py +++ b/tests/sonic_xcvr/test_cmisCDB.py @@ -101,99 +101,99 @@ def test_cmd0040h(self, mock_response, expected): ([1], (None, None, None)), ([64, 64, 64], (None, None, None)), ]) - def test_cmd0041h(self, mock_response, expected): + def test_get_fw_management_features(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd0041h() + result = cdb.get_fw_management_features() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ ([1], (None, None, None)), ([64, 64, 64], (None, None, None)), ]) - def test_cmd0100h(self, mock_response, expected): + def test_get_fw_info(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd0100h() + result = cdb.get_fw_info() assert result == expected @pytest.mark.parametrize("input_param, mock_response, expected", [ ([3, bytearray(b'\x00\x00\x00'), 1000000], [1], 1), ([3, bytearray(b'\x00\x00\x00'), 1000000], [64, 64, 64], 64) ]) - def test_cmd0101h(self, input_param, mock_response, expected): + def test_start_fw_download(self, input_param, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd0101h(*input_param) + result = cdb.start_fw_download(*input_param) assert result == expected @pytest.mark.parametrize("mock_response, expected", [ ([1], 1), ([64, 64, 64], 64), ]) - def test_cmd0102h(self, mock_response, expected): + def test_abort_fw_download(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd0102h() + result = cdb.abort_fw_download() assert result == expected @pytest.mark.parametrize("input_param, mock_response, expected", [ ([100, bytearray(116)], [1], 1), ([100, bytearray(116)], [64, 64, 64], 64) ]) - def test_cmd0103h(self, input_param, mock_response, expected): + def test_block_write_lpl(self, input_param, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd0103h(*input_param) + result = cdb.block_write_lpl(*input_param) assert result == expected @pytest.mark.parametrize("input_param, mock_response, expected", [ ([100, bytearray(2048), True, 100], [1], 1), ([100, bytearray(2047), False, 100], [64, 64, 64], 64), ]) - def test_cmd0104h(self, input_param, mock_response, expected): + def test_block_write_epl(self, input_param, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd0104h(*input_param) + result = cdb.block_write_epl(*input_param) assert result == expected @pytest.mark.parametrize("mock_response, expected", [ ([1], 1), ([64, 64, 64], 64), ]) - def test_cmd0107h(self, mock_response, expected): + def test_validate_fw_image(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd0107h() + result = cdb.validate_fw_image() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ ([1], 1), ([64, 64, 64], 64), ]) - def test_cmd0109h(self, mock_response, expected): + def test_run_fw_image(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd0109h() + result = cdb.run_fw_image() assert result == expected @pytest.mark.parametrize("mock_response, expected", [ ([1], 1), ([64, 64, 64], 64), ]) - def test_cmd010Ah(self, mock_response, expected): + def test_commit_fw_image(self, mock_response, expected): cdb = self.mock_cdb_api() cdb.cdb1_chkstatus = MagicMock() cdb.cdb1_chkstatus.side_effect = mock_response - result = cdb.cmd010Ah() + result = cdb.commit_fw_image() assert result == expected From 35093d5f9fafaad608f50034530f7a530f724e75 Mon Sep 17 00:00:00 2001 From: qinchuanares Date: Tue, 2 Nov 2021 09:42:09 -0700 Subject: [PATCH 16/16] resolving merge conflicts with master --- .../sonic_xcvr/api/public/c_cmis.py | 2 +- .../sonic_xcvr/api/public/cmis.py | 1384 +++++++-------- .../sonic_xcvr/api/public/cmisCDB.py | 2 +- .../sonic_xcvr/codes/public/cmis.py | 130 ++ .../sonic_xcvr/codes/public/sff8024.py | 2 +- .../sonic_xcvr/fields/consts.py | 26 +- .../sonic_xcvr/mem_maps/public/cmis.py | 445 ++--- .../sonic_xcvr/xcvr_api_factory.py | 31 +- sonic_platform_base/sonic_xcvr/xcvr_eeprom.py | 16 +- tests/sonic_xcvr/test_cmis.py | 1545 +---------------- tests/sonic_xcvr/test_xcvr_field.py | 55 +- 11 files changed, 1158 insertions(+), 2480 deletions(-) create mode 100644 sonic_platform_base/sonic_xcvr/codes/public/cmis.py diff --git a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py index e29d6bfbb..863a79986 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -893,4 +893,4 @@ def get_transceiver_pm(self): trans_pm['rx_sig_power_avg'] = PM_dict['rx_sigpwr_avg'] trans_pm['rx_sig_power_min'] = PM_dict['rx_sigpwr_min'] trans_pm['rx_sig_power_max'] = PM_dict['rx_sigpwr_max'] - return trans_pm + return trans_pm \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index 01cc324ed..914d30c65 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -1,8 +1,12 @@ """ cmis.py - Implementation of XcvrApi that corresponds to CMIS + Implementation of XcvrApi that corresponds to the CMIS specification. """ + +from ...fields import consts +from ..xcvr_api import XcvrApi + import logging from ...fields import consts from ..xcvr_api import XcvrApi @@ -13,147 +17,30 @@ logger = logging.getLogger(__name__) logger.addHandler(logging.NullHandler()) -BYTELENGTH = 8 class CmisApi(XcvrApi): NUM_CHANNELS = 8 def __init__(self, xcvr_eeprom): super(CmisApi, self).__init__(xcvr_eeprom) - # Transceiver Information def get_model(self): - ''' - This function returns the part number of the module - ''' return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD) - def get_vendor_rev(self): - ''' - This function returns the revision level for part number provided by vendor - ''' - return self.xcvr_eeprom.read(consts.VENDOR_REV_FIELD) - def get_vendor_serial(self): - ''' - This function returns the serial number of the module - ''' return self.xcvr_eeprom.read(consts.VENDOR_SERIAL_NO_FIELD) - def get_vendor_name(self): - ''' - This function returns the vendor name of the module - ''' - return self.xcvr_eeprom.read(consts.VENDOR_NAME_FIELD) - def get_module_type(self): ''' This function returns the SFF8024Identifier (module type / form-factor). Table 4-1 in SFF-8024 Rev4.6 ''' return self.xcvr_eeprom.read(consts.ID_FIELD) - def get_vendor_OUI(self): - ''' - This function returns the vendor IEEE company ID - ''' - return self.xcvr_eeprom.read(consts.VENDOR_OUI_FIELD) - - def get_vendor_date(self): - ''' - This function returns the module manufacture date. It returns YYMMDDXX. XX is the lot code. - ''' - return self.xcvr_eeprom.read(consts.VENDOR_DATE_FIELD) - def get_connector_type(self): ''' This function returns module connector. Table 4-3 in SFF-8024 Rev4.6 ''' return self.xcvr_eeprom.read(consts.CONNECTOR_FIELD) - def get_module_media_type(self): - ''' - This function returns module media type: MMF, SMF, Passive Copper Cable, Active Cable Assembly or Base-T. - ''' - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_TYPE) - - def get_host_electrical_interface(self): - ''' - This function returns module host electrical interface. Table 4-5 in SFF-8024 Rev4.6 - ''' - return self.xcvr_eeprom.read(consts.HOST_ELECTRICAL_INTERFACE) - - def get_module_media_interface(self): - ''' - This function returns module media electrical interface. Table 4-6 ~ 4-10 in SFF-8024 Rev4.6 - ''' - media_type = self.get_module_media_type() - if media_type == 'Multimode Fiber (MMF)': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM) - elif media_type == 'Single Mode Fiber (SMF)': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_SM) - elif media_type == 'Passive Copper Cable': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER) - elif media_type == 'Active Cable Assembly': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE) - elif media_type == 'BASE-T': - return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_BASE_T) - else: - return 'Unknown media interface' - - def get_host_lane_count(self): - ''' - This function returns number of host lanes - ''' - lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) - return (lane_count >> 4) & 0xf - - def get_media_lane_count(self): - ''' - This function returns number of media lanes - ''' - lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) - return (lane_count) & 0xf - - def get_host_lane_assignment_option(self): - ''' - This function returns the host lane that the application begins on - ''' - return self.xcvr_eeprom.read(consts.HOST_LANE_ASSIGNMENT_OPTION) - - def get_media_lane_assignment_option(self): - ''' - This function returns the media lane that the application is allowed to begin on - ''' - return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION) - - def get_active_apsel_hostlane(self): - ''' - This function returns the application select code that each host lane has - ''' - apsel_dict = dict() - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_1) - apsel_dict['hostlane1'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_2) - apsel_dict['hostlane2'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_3) - apsel_dict['hostlane3'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_4) - apsel_dict['hostlane4'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_5) - apsel_dict['hostlane5'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_6) - apsel_dict['hostlane6'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_7) - apsel_dict['hostlane7'] = (result >> 4) & 0xf - result = self.xcvr_eeprom.read(consts.ACTIVE_APSEL_HOSTLANE_8) - apsel_dict['hostlane8'] = (result >> 4) & 0xf - return apsel_dict - - def get_media_interface_technology(self): - ''' - This function returns the media lane technology - ''' - return self.xcvr_eeprom.read(consts.MEDIA_INTERFACE_TECH) - def get_module_hardware_revision(self): ''' This function returns the module hardware revision @@ -162,7 +49,7 @@ def get_module_hardware_revision(self): hw_minor_rev = self.xcvr_eeprom.read(consts.HW_MAJOR_REV) hw_rev = [str(num) for num in [hw_major_rev, hw_minor_rev]] return '.'.join(hw_rev) - + def get_cmis_rev(self): ''' This function returns the CMIS version the module complies to @@ -172,7 +59,22 @@ def get_cmis_rev(self): cmis_minor = (cmis) & 0xf cmis_rev = [str(num) for num in [cmis_major, cmis_minor]] return '.'.join(cmis_rev) - + + # Transceiver status + def get_module_state(self): + ''' + This function returns the module state + ''' + result = self.xcvr_eeprom.read(consts.MODULE_STATE) >> 1 + DICT = self.xcvr_eeprom.mem_map.codes.MODULE_STATE + return DICT.get(result, "Unknown") + + def get_module_fault_cause(self): + ''' + This function returns the module fault cause + ''' + return self.xcvr_eeprom.read(consts.MODULE_FAULT_CAUSE) + def get_module_active_firmware(self): ''' This function returns the active firmware version @@ -191,492 +93,576 @@ def get_module_inactive_firmware(self): inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]] return '.'.join(inactive_fw) - # Transceiver DOM + def get_transceiver_info(self): + admin_info = self.xcvr_eeprom.read(consts.ADMIN_INFO_FIELD) + media_type = self.xcvr_eeprom.read(consts.MEDIA_TYPE_FIELD) + if admin_info is None or media_type is None: + return None + + ext_id = admin_info[consts.EXT_ID_FIELD] + power_class = ext_id[consts.POWER_CLASS_FIELD] + max_power = ext_id[consts.MAX_POWER_FIELD] + + xcvr_info = { + "type": admin_info[consts.ID_FIELD], + "type_abbrv_name": admin_info[consts.ID_ABBRV_FIELD], + "hardware_rev": admin_info[consts.VENDOR_REV_FIELD], + "serial": admin_info[consts.VENDOR_SERIAL_NO_FIELD], + "manufacturer": admin_info[consts.VENDOR_NAME_FIELD], + "model": admin_info[consts.VENDOR_PART_NO_FIELD], + "connector": admin_info[consts.CONNECTOR_FIELD], + "encoding": "N/A", # Not supported + "ext_identifier": "%s (%sW Max)" % (power_class, max_power), + "ext_rateselect_compliance": "N/A", # Not supported + "cable_type": "Length cable Assembly(m)", + "cable_length": float(admin_info[consts.LENGTH_ASSEMBLY_FIELD]), + "nominal_bit_rate": 0, # Not supported + "specification_compliance": media_type, + "vendor_date": admin_info[consts.VENDOR_DATE_FIELD], + "vendor_oui": admin_info[consts.VENDOR_OUI_FIELD], + # TODO + "application_advertisement": "N/A", + } + return xcvr_info + + def get_transceiver_bulk_status(self): + rx_los = self.get_rx_los() + tx_fault = self.get_tx_fault() + tx_disable = self.get_tx_disable() + tx_disabled_channel = self.get_tx_disable_channel() + temp = self.get_module_temperature() + voltage = self.get_voltage() + tx_bias = self.get_tx_bias() + rx_power = self.get_rx_power() + tx_power = self.get_tx_power() + read_failed = rx_los is None or \ + tx_fault is None or \ + tx_disable is None or \ + tx_disabled_channel is None or \ + temp is None or \ + voltage is None or \ + tx_bias is None or \ + rx_power is None or \ + tx_power is None + if read_failed: + return None + + bulk_status = { + "rx_los": all(rx_los) if self.get_rx_los_support() else 'N/A', + "tx_fault": all(tx_fault) if self.get_tx_fault_support() else 'N/A', + "tx_disable": all(tx_disable), + "tx_disabled_channel": tx_disabled_channel, + "temperature": temp, + "voltage": voltage + } + + for i in range(1, self.NUM_CHANNELS + 1): + bulk_status["tx%dbias" % i] = tx_bias[i - 1] + bulk_status["rx%dpower" % i] = rx_power[i - 1] + bulk_status["tx%dpower" % i] = tx_power[i - 1] + + return bulk_status + + def get_transceiver_threshold_info(self): + threshold_info_keys = ['temphighalarm', 'temphighwarning', + 'templowalarm', 'templowwarning', + 'vcchighalarm', 'vcchighwarning', + 'vcclowalarm', 'vcclowwarning', + 'rxpowerhighalarm', 'rxpowerhighwarning', + 'rxpowerlowalarm', 'rxpowerlowwarning', + 'txpowerhighalarm', 'txpowerhighwarning', + 'txpowerlowalarm', 'txpowerlowwarning', + 'txbiashighalarm', 'txbiashighwarning', + 'txbiaslowalarm', 'txbiaslowwarning' + ] + threshold_info_dict = dict.fromkeys(threshold_info_keys, 'N/A') + + thresh_support = self.get_transceiver_thresholds_support() + if thresh_support is None: + return None + if not thresh_support: + return threshold_info_dict + thresh = self.xcvr_eeprom.read(consts.THRESHOLDS_FIELD) + if thresh is None: + return None + + return { + "temphighalarm": float("{:.3f}".format(thresh[consts.TEMP_HIGH_ALARM_FIELD])), + "templowalarm": float("{:.3f}".format(thresh[consts.TEMP_LOW_ALARM_FIELD])), + "temphighwarning": float("{:.3f}".format(thresh[consts.TEMP_HIGH_WARNING_FIELD])), + "templowwarning": float("{:.3f}".format(thresh[consts.TEMP_LOW_WARNING_FIELD])), + "vcchighalarm": float("{:.3f}".format(thresh[consts.VOLTAGE_HIGH_ALARM_FIELD])), + "vcclowalarm": float("{:.3f}".format(thresh[consts.VOLTAGE_LOW_ALARM_FIELD])), + "vcchighwarning": float("{:.3f}".format(thresh[consts.VOLTAGE_HIGH_WARNING_FIELD])), + "vcclowwarning": float("{:.3f}".format(thresh[consts.VOLTAGE_LOW_WARNING_FIELD])), + "rxpowerhighalarm": float("{:.3f}".format(thresh[consts.RX_POWER_HIGH_ALARM_FIELD])), + "rxpowerlowalarm": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.RX_POWER_LOW_ALARM_FIELD]))), + "rxpowerhighwarning": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.RX_POWER_HIGH_WARNING_FIELD]))), + "rxpowerlowwarning": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.RX_POWER_LOW_WARNING_FIELD]))), + "txpowerhighalarm": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.TX_POWER_HIGH_ALARM_FIELD]))), + "txpowerlowalarm": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.TX_POWER_LOW_ALARM_FIELD]))), + "txpowerhighwarning": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.TX_POWER_HIGH_WARNING_FIELD]))), + "txpowerlowwarning": float("{:.3f}".format(self.mw_to_dbm(thresh[consts.TX_POWER_LOW_WARNING_FIELD]))), + "txbiashighalarm": float("{:.3f}".format(thresh[consts.TX_BIAS_HIGH_ALARM_FIELD])), + "txbiaslowalarm": float("{:.3f}".format(thresh[consts.TX_BIAS_LOW_ALARM_FIELD])), + "txbiashighwarning": float("{:.3f}".format(thresh[consts.TX_BIAS_HIGH_WARNING_FIELD])), + "txbiaslowwarning": float("{:.3f}".format(thresh[consts.TX_BIAS_LOW_WARNING_FIELD])) + } + def get_module_temperature(self): - ''' - This function returns the module case temperature and its thresholds. Unit in deg C - ''' - case_temp = self.xcvr_eeprom.read(consts.CASE_TEMP) - case_temp_high_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_ALARM) - case_temp_low_alarm = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_ALARM) - case_temp_high_warn = self.xcvr_eeprom.read(consts.CASE_TEMP_HIGH_WARN) - case_temp_low_warn = self.xcvr_eeprom.read(consts.CASE_TEMP_LOW_WARN) - case_temp_dict = {'monitor value': case_temp, - 'high alarm': case_temp_high_alarm, - 'low alarm': case_temp_low_alarm, - 'high warn': case_temp_high_warn, - 'low warn': case_temp_low_warn} - return case_temp_dict - - def get_module_voltage(self): - ''' - This function returns the monitored value of the 3.3-V supply voltage and its thresholds. - Unit in V - ''' - voltage = self.xcvr_eeprom.read(consts.VOLTAGE) - voltage_high_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_ALARM) - voltage_low_alarm = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_ALARM) - voltage_high_warn = self.xcvr_eeprom.read(consts.VOLTAGE_HIGH_WARN) - voltage_low_warn = self.xcvr_eeprom.read(consts.VOLTAGE_LOW_WARN) - voltage_dict = {'monitor value': voltage, - 'high alarm': voltage_high_alarm, - 'low alarm': voltage_low_alarm, - 'high warn': voltage_high_warn, - 'low warn': voltage_low_warn} - return voltage_dict - - def get_txpower(self): - ''' - This function returns the TX output power. Unit in mW - ''' - tx_power = self.xcvr_eeprom.read(consts.TX_POW) - tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM) - tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM) - tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN) - tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN) - tx_power_dict = {'monitor value lane1': tx_power, - 'high alarm': tx_power_high_alarm, - 'low alarm': tx_power_low_alarm, - 'high warn': tx_power_high_warn, - 'low warn': tx_power_low_warn} - return tx_power_dict - - def get_rxpower(self): - ''' - This function returns the RX input power. Unit in mW - ''' - rx_power = self.xcvr_eeprom.read(consts.RX_POW) - rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM) - rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM) - rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN) - rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN) - rx_power_dict = {'monitor value lane1': rx_power, - 'high alarm': rx_power_high_alarm, - 'low alarm': rx_power_low_alarm, - 'high warn': rx_power_high_warn, - 'low warn': rx_power_low_warn} - return rx_power_dict - - def get_txbias(self): - ''' - This function returns the TX laser bias current. Unit in mA - ''' - tx_bias_current = self.xcvr_eeprom.read(consts.TX_BIAS) - tx_bias_current_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_ALARM) - tx_bias_current_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_ALARM) - tx_bias_current_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_HIGH_WARN) - tx_bias_current_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_CURR_LOW_WARN) - tx_bias_current_dict = {'monitor value lane1': tx_bias_current, - 'high alarm': tx_bias_current_high_alarm, - 'low alarm': tx_bias_current_low_alarm, - 'high warn': tx_bias_current_high_warn, - 'low warn': tx_bias_current_low_warn} - return tx_bias_current_dict + if not self.get_temperature_support(): + return 'N/A' + temp = self.xcvr_eeprom.read(consts.TEMPERATURE_FIELD) + if temp is None: + return None + return float("{:.3f}".format(temp)) - def get_tx_config_power(self): + def get_voltage(self): + if not self.get_voltage_support(): + return 'N/A' + voltage = self.xcvr_eeprom.read(consts.VOLTAGE_FIELD) + if voltage is None: + return None + return float("{:.3f}".format(voltage)) + + def is_flat_memory(self): + return self.xcvr_eeprom.read(consts.FLAT_MEM_FIELD) + + def get_temperature_support(self): + return not self.is_flat_memory() + + def get_voltage_support(self): + return not self.is_flat_memory() + + def get_rx_los_support(self): + return not self.is_flat_memory() + + def get_tx_cdr_lol(self): ''' - This function returns the configured TX output power. Unit in dBm + This function returns TX CDR LOL flag on TX host lane ''' - return self.xcvr_eeprom.read(consts.TX_CONFIG_POWER) + result = self.xcvr_eeprom.read(consts.TX_CDR_LOL) + tx_lol_dict = dict() + for bitpos in range(self.NUM_CHANNELS): + tx_lol_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - def get_media_output_loopback(self): + def get_rx_los(self): + rx_los_support = self.get_rx_los_support() + if rx_los_support is None: + return None + if not rx_los_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + rx_los = self.xcvr_eeprom.read(consts.RX_LOS_FIELD) + if rx_los is None: + return None + return [bool(rx_los & (1 << i)) for i in range(self.NUM_CHANNELS)] + + def get_rx_cdr_lol(self): ''' - This function returns the media output loopback status + This function returns RX CDR LOL flag on RX media lane ''' - result = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) - return result == 1 + result = self.xcvr_eeprom.read(consts.RX_CDR_LOL) + rx_lol_dict = dict() + for bitpos in range(self.NUM_CHANNELS): + rx_lol_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return rx_lol_dict - def get_media_input_loopback(self): + def get_tx_power_flag(self): ''' - This function returns the media input loopback status + This function returns TX power out of range flag on TX media lane ''' - result = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) - return result == 1 + tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM_FLAG) + tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM_FLAG) + tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN_FLAG) + tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN_FLAG) + tx_power_high_alarm_dict = dict() + tx_power_low_alarm_dict = dict() + tx_power_high_warn_dict = dict() + tx_power_low_warn_dict = dict() + for bitpos in range(self.NUM_CHANNELS): + tx_power_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_alarm >> bitpos) & 0x1) + tx_power_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_alarm >> bitpos) & 0x1) + tx_power_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_warn >> bitpos) & 0x1) + tx_power_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_warn >> bitpos) & 0x1) - def get_host_output_loopback(self): + tx_power_flag_dict = {'tx_power_high_alarm': tx_power_high_alarm_dict, + 'tx_power_low_alarm': tx_power_low_alarm_dict, + 'tx_power_high_warn': tx_power_high_warn_dict, + 'tx_power_low_warn': tx_power_low_warn_dict,} + return tx_power_flag_dict + + def get_tx_bias_flag(self): ''' - This function returns the host output loopback status + This function returns TX bias out of range flag on TX media lane ''' - result = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) - loopback_status = [] - for bitpos in range(BYTELENGTH): - loopback_status.append(bool((result >> bitpos) & 0x1)) - return loopback_status + tx_bias_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_ALARM_FLAG) + tx_bias_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_ALARM_FLAG) + tx_bias_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_WARN_FLAG) + tx_bias_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_WARN_FLAG) + tx_bias_high_alarm_dict = dict() + tx_bias_low_alarm_dict = dict() + tx_bias_high_warn_dict = dict() + tx_bias_low_warn_dict = dict() + for bitpos in range(self.NUM_CHANNELS): + tx_bias_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_alarm >> bitpos) & 0x1) + tx_bias_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_alarm >> bitpos) & 0x1) + tx_bias_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_warn >> bitpos) & 0x1) + tx_bias_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_warn >> bitpos) & 0x1) - def get_host_input_loopback(self): + tx_bias_flag_dict = {'tx_bias_high_alarm': tx_bias_high_alarm_dict, + 'tx_bias_low_alarm': tx_bias_low_alarm_dict, + 'tx_bias_high_warn': tx_bias_high_warn_dict, + 'tx_bias_low_warn': tx_bias_low_warn_dict,} + return tx_bias_flag_dict + + def get_rx_power_flag(self): ''' - This function returns the host input loopback status + This function returns RX power out of range flag on RX media lane ''' - result = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) - loopback_status = [] - for bitpos in range(BYTELENGTH): - loopback_status.append(bool((result >> bitpos) & 0x1)) - return loopback_status + rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM_FLAG) + rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM_FLAG) + rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN_FLAG) + rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN_FLAG) + rx_power_high_alarm_dict = dict() + rx_power_low_alarm_dict = dict() + rx_power_high_warn_dict = dict() + rx_power_low_warn_dict = dict() + for bitpos in range(self.NUM_CHANNELS): + rx_power_high_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_alarm >> bitpos) & 0x1) + rx_power_low_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_alarm >> bitpos) & 0x1) + rx_power_high_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_warn >> bitpos) & 0x1) + rx_power_low_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_warn >> bitpos) & 0x1) - def get_aux_mon_type(self): + rx_power_flag_dict = {'rx_power_high_alarm': rx_power_high_alarm_dict, + 'rx_power_low_alarm': rx_power_low_alarm_dict, + 'rx_power_high_warn': rx_power_high_warn_dict, + 'rx_power_low_warn': rx_power_low_warn_dict,} + return rx_power_flag_dict + + def get_tx_output_status(self): ''' - This function returns the aux monitor types + This function returns whether TX output signals are valid on TX media lane ''' - result = self.xcvr_eeprom.read(consts.AUX_MON_TYPE) - aux1_mon_type = result & 0x1 - aux2_mon_type = (result >> 1) & 0x1 - aux3_mon_type = (result >> 2) & 0x1 - return aux1_mon_type, aux2_mon_type, aux3_mon_type + result = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) + tx_output_status_dict = dict() + for bitpos in range(self.NUM_CHANNELS): + tx_output_status_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_output_status_dict - def get_laser_temperature(self): + def get_rx_output_status(self): ''' - This function returns the laser temperature monitor value + This function returns whether RX output signals are valid on RX host lane ''' - aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() - LASER_TEMP_SCALE = 256.0 - if aux2_mon_type == 0: - laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE - laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEMP_SCALE - laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEMP_SCALE - laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEMP_SCALE - laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEMP_SCALE - elif aux2_mon_type == 1 and aux3_mon_type == 0: - laser_temp = self.xcvr_eeprom.read(consts.AUX3_MON)/LASER_TEMP_SCALE - laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX3_HIGH_ALARM)/LASER_TEMP_SCALE - laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX3_LOW_ALARM)/LASER_TEMP_SCALE - laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX3_HIGH_WARN)/LASER_TEMP_SCALE - laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX3_LOW_WARN)/LASER_TEMP_SCALE - else: + result = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) + rx_output_status_dict = dict() + for bitpos in range(self.NUM_CHANNELS): + rx_output_status_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return rx_output_status_dict + + def get_tx_bias_support(self): + return not self.is_flat_memory() + + def get_tx_bias(self): + tx_bias_support = self.get_tx_bias_support() + if tx_bias_support is None: return None - laser_temp_dict = {'monitor value': laser_temp, - 'high alarm': laser_temp_high_alarm, - 'low alarm': laser_temp_low_alarm, - 'high warn': laser_temp_high_warn, - 'low warn': laser_temp_low_warn} - return laser_temp_dict - - def get_laser_TEC_current(self): - ''' - This function returns the laser TEC current monitor value - ''' - aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() - LASER_TEC_CURRENT_SCALE = 32767.0 - if aux1_mon_type == 1: - laser_tec_current = self.xcvr_eeprom.read(consts.AUX1_MON)/LASER_TEC_CURRENT_SCALE - laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX1_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE - laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX1_LOW_ALARM)/LASER_TEC_CURRENT_SCALE - laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX1_HIGH_WARN)/LASER_TEC_CURRENT_SCALE - laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX1_LOW_WARN)/LASER_TEC_CURRENT_SCALE - elif aux1_mon_type == 0 and aux2_mon_type == 1: - laser_tec_current = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEC_CURRENT_SCALE - laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE - laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEC_CURRENT_SCALE - laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEC_CURRENT_SCALE - laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEC_CURRENT_SCALE - else: + if not tx_bias_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + tx_bias = self.xcvr_eeprom.read(consts.TX_BIAS_FIELD) + if tx_bias is None: return None - laser_tec_current_dict = {'monitor value': laser_tec_current, - 'high alarm': laser_tec_current_high_alarm, - 'low alarm': laser_tec_current_low_alarm, - 'high warn': laser_tec_current_high_warn, - 'low warn': laser_tec_current_low_warn} - return laser_tec_current_dict + return [channel_bias for channel_bias in tx_bias.values()] + + def get_tx_power(self): + tx_power_support = self.get_tx_power_support() + if tx_power_support is None: + return None + if not tx_power_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + tx_power = self.xcvr_eeprom.read(consts.TX_POWER_FIELD) + if tx_power is None: + return None + return [float("{:.3f}".format(channel_power)) for channel_power in tx_power.values()] + + def get_tx_power_support(self): + return not self.is_flat_memory() + + def get_rx_power(self): + rx_power_support = self.get_rx_power_support() + if rx_power_support is None: + return None + if not rx_power_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + rx_power = self.xcvr_eeprom.read(consts.RX_POWER_FIELD) + if rx_power is None: + return None + return [float("{:.3f}".format(channel_power)) for channel_power in rx_power.values()] + + def get_rx_power_support(self): + return not self.is_flat_memory() + + def get_tx_fault_support(self): + return not self.is_flat_memory() and self.xcvr_eeprom.read(consts.TX_FAULT_SUPPORT_FIELD) + + def get_tx_fault(self): + tx_fault_support = self.get_tx_fault_support() + if tx_fault_support is None: + return None + if not tx_fault_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + tx_fault = self.xcvr_eeprom.read(consts.TX_FAULT_FIELD) + if tx_fault is None: + return None + return [bool(tx_fault & (1 << i)) for i in range(self.NUM_CHANNELS)] - def get_custom_field(self, signed = False, scale = 1.0): + def get_tx_los(self): ''' - This function returns the custom monitor field + This function returns TX LOS flag on TX host lane ''' - result = self.xcvr_eeprom.read(consts.CUSTOM_MON) - if signed: - result -= 2**15 - result /= scale - return result + result = self.xcvr_eeprom.read(consts.TX_LOS_FLAG) + tx_los_dict = dict() + for bitpos in range(self.NUM_CHANNELS): + tx_los_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) + return tx_los_dict + def get_tx_disable_support(self): + return not self.is_flat_memory() and self.xcvr_eeprom.read(consts.TX_DISABLE_SUPPORT_FIELD) - def get_vdm_api(self): - self.vdm = CmisVdmApi(self.xcvr_eeprom) - return self.vdm + def get_tx_disable(self): + tx_disable_support = self.get_tx_disable_support() + if tx_disable_support is None: + return None + if not tx_disable_support: + return ["N/A" for _ in range(self.NUM_CHANNELS)] + tx_disable = self.xcvr_eeprom.read(consts.TX_DISABLE_FIELD) + if tx_disable is None: + return None + return [bool(tx_disable & (1 << i)) for i in range(self.NUM_CHANNELS)] - def get_vdm(self): + def tx_disable(self, tx_disable): + val = 0xFF if tx_disable else 0x0 + return self.xcvr_eeprom.write(consts.TX_DISABLE_FIELD, val) + + def get_tx_disable_channel(self): + tx_disable_support = self.get_tx_disable_support() + if tx_disable_support is None: + return None + if not tx_disable_support: + return 'N/A' + return self.xcvr_eeprom.read(consts.TX_DISABLE_FIELD) + + def tx_disable_channel(self, channel, disable): + channel_state = self.get_tx_disable_channel() + if channel_state is None or channel_state == 'N/A': + return False + + for i in range(self.NUM_CHANNELS): + mask = (1 << i) + if not (channel & mask): + continue + if disable: + channel_state |= mask + else: + channel_state &= ~mask + + return self.xcvr_eeprom.write(consts.TX_DISABLE_FIELD, channel_state) + + def get_transceiver_thresholds_support(self): + return not self.is_flat_memory() + + def get_lpmode_support(self): + power_class = self.xcvr_eeprom.read(consts.POWER_CLASS_FIELD) + if power_class is None: + return False + return "Power Class 1" not in power_class + + def get_power_override_support(self): + return False + + def get_module_media_type(self): ''' - This function returns all the VDM items, including real time monitor value, threholds and flags + This function returns module media type: MMF, SMF, Passive Copper Cable, Active Cable Assembly or Base-T. ''' - try: - self.vdm - except AttributeError: - self.get_vdm_api() - vdm = self.vdm.get_vdm_allpage() - return vdm + return self.xcvr_eeprom.read(consts.MEDIA_TYPE_FIELD) - # Transceiver status - def get_module_state(self): + def get_host_electrical_interface(self): ''' - This function returns the module state + This function returns module host electrical interface. Table 4-5 in SFF-8024 Rev4.6 ''' - result = self.xcvr_eeprom.read(consts.MODULE_STATE) >> 1 - DICT = self.xcvr_eeprom.mem_map.codes.MODULE_STATE - return DICT.get(result, "Unknown") + return self.xcvr_eeprom.read(consts.HOST_ELECTRICAL_INTERFACE) - def get_module_fault_cause(self): + def get_module_media_interface(self): ''' - This function returns the module fault cause + This function returns module media electrical interface. Table 4-6 ~ 4-10 in SFF-8024 Rev4.6 ''' - return self.xcvr_eeprom.read(consts.MODULE_FAULT_CAUSE) + media_type = self.get_module_media_type() + if media_type == 'Multimode Fiber (MMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_850NM) + elif media_type == 'Single Mode Fiber (SMF)': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_SM) + elif media_type == 'Passive Copper Cable': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER) + elif media_type == 'Active Cable Assembly': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE) + elif media_type == 'BASE-T': + return self.xcvr_eeprom.read(consts.MODULE_MEDIA_INTERFACE_BASE_T) + else: + return 'Unknown media interface' - def get_module_firmware_fault_state_changed(self): + def is_coherent_module(self): ''' - This function returns datapath firmware fault state, module firmware fault state - and whether module state changed + Returns True if the module follow C-CMIS spec, False otherwise ''' - result = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) - datapath_firmware_fault = bool((result >> 2) & 0x1) - module_firmware_fault = bool((result >> 1) & 0x1) - module_state_changed = bool(result & 0x1) - return datapath_firmware_fault, module_firmware_fault, module_state_changed + mintf = self.get_module_media_interface() + return False if 'ZR' not in mintf else True - def get_module_level_flag(self): + def get_host_lane_count(self): ''' - This function returns teh module level flags, including - - 3.3 V voltage supply flags - - Case temperature flags - - Aux 1 flags - - Aux 2 flags - - Aux 3 flags - - Custom field flags + This function returns number of host lanes ''' - module_flag_byte1 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE1) - module_flag_byte2 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE2) - module_flag_byte3 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE3) - - voltage_high_alarm_flag = bool((module_flag_byte1 >> 4) & 0x1) - voltage_low_alarm_flag = bool((module_flag_byte1 >> 5) & 0x1) - voltage_high_warn_flag = bool((module_flag_byte1 >> 6) & 0x1) - voltage_low_warn_flag = bool((module_flag_byte1 >> 7) & 0x1) - voltage_flags = {'voltage_high_alarm_flag': voltage_high_alarm_flag, - 'voltage_low_alarm_flag': voltage_low_alarm_flag, - 'voltage_high_warn_flag': voltage_high_warn_flag, - 'voltage_low_warn_flag': voltage_low_warn_flag} - - case_temp_high_alarm_flag = bool((module_flag_byte1 >> 0) & 0x1) - case_temp_low_alarm_flag = bool((module_flag_byte1 >> 1) & 0x1) - case_temp_high_warn_flag = bool((module_flag_byte1 >> 2) & 0x1) - case_temp_low_warn_flag = bool((module_flag_byte1 >> 3) & 0x1) - case_temp_flags = {'case_temp_high_alarm_flag': case_temp_high_alarm_flag, - 'case_temp_low_alarm_flag': case_temp_low_alarm_flag, - 'case_temp_high_warn_flag': case_temp_high_warn_flag, - 'case_temp_low_warn_flag': case_temp_low_warn_flag} - - aux2_high_alarm_flag = bool((module_flag_byte2 >> 4) & 0x1) - aux2_low_alarm_flag = bool((module_flag_byte2 >> 5) & 0x1) - aux2_high_warn_flag = bool((module_flag_byte2 >> 6) & 0x1) - aux2_low_warn_flag = bool((module_flag_byte2 >> 7) & 0x1) - aux2_flags = {'aux2_high_alarm_flag': aux2_high_alarm_flag, - 'aux2_low_alarm_flag': aux2_low_alarm_flag, - 'aux2_high_warn_flag': aux2_high_warn_flag, - 'aux2_low_warn_flag': aux2_low_warn_flag} - - aux1_high_alarm_flag = bool((module_flag_byte2 >> 0) & 0x1) - aux1_low_alarm_flag = bool((module_flag_byte2 >> 1) & 0x1) - aux1_high_warn_flag = bool((module_flag_byte2 >> 2) & 0x1) - aux1_low_warn_flag = bool((module_flag_byte2 >> 3) & 0x1) - aux1_flags = {'aux1_high_alarm_flag': aux1_high_alarm_flag, - 'aux1_low_alarm_flag': aux1_low_alarm_flag, - 'aux1_high_warn_flag': aux1_high_warn_flag, - 'aux1_low_warn_flag': aux1_low_warn_flag} - - custom_mon_high_alarm_flag = bool((module_flag_byte3 >> 4) & 0x1) - custom_mon_low_alarm_flag = bool((module_flag_byte3 >> 5) & 0x1) - custom_mon_high_warn_flag = bool((module_flag_byte3 >> 6) & 0x1) - custom_mon_low_warn_flag = bool((module_flag_byte3 >> 7) & 0x1) - custom_mon_flags = {'custom_mon_high_alarm_flag': custom_mon_high_alarm_flag, - 'custom_mon_low_alarm_flag': custom_mon_low_alarm_flag, - 'custom_mon_high_warn_flag': custom_mon_high_warn_flag, - 'custom_mon_low_warn_flag': custom_mon_low_warn_flag} - - aux3_high_alarm_flag = bool((module_flag_byte3 >> 0) & 0x1) - aux3_low_alarm_flag = bool((module_flag_byte3 >> 1) & 0x1) - aux3_high_warn_flag = bool((module_flag_byte3 >> 2) & 0x1) - aux3_low_warn_flag = bool((module_flag_byte3 >> 3) & 0x1) - aux3_flags = {'aux3_high_alarm_flag': aux3_high_alarm_flag, - 'aux3_low_alarm_flag': aux3_low_alarm_flag, - 'aux3_high_warn_flag': aux3_high_warn_flag, - 'aux3_low_warn_flag': aux3_low_warn_flag} - - module_flag = {'voltage_flags': voltage_flags, - 'case_temp_flags': case_temp_flags, - 'aux1_flags': aux1_flags, - 'aux2_flags': aux2_flags, - 'aux3_flags': aux3_flags, - 'custom_mon_flags': custom_mon_flags} - return module_flag + lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) + return (lane_count >> 4) & 0xf - def get_datapath_state(self): + def get_media_lane_count(self): ''' - This function returns the eight datapath states + This function returns number of media lanes ''' - result = self.xcvr_eeprom.read(consts.DATAPATH_STATE) - dp_lane7 = (result >> 0) & 0xf - dp_lane8 = (result >> 4) & 0xf - dp_lane5 = (result >> 8) & 0xf - dp_lane6 = (result >> 12) & 0xf - dp_lane3 = (result >> 16) & 0xf - dp_lane4 = (result >> 20) & 0xf - dp_lane1 = (result >> 24) & 0xf - dp_lane2 = (result >> 28) & 0xf - DICT = self.xcvr_eeprom.mem_map.codes.DATAPATH_STATE - dp_state_dict = {'dp_lane1': DICT.get(dp_lane1, "Unknown"), - 'dp_lane2': DICT.get(dp_lane2, "Unknown"), - 'dp_lane3': DICT.get(dp_lane3, "Unknown"), - 'dp_lane4': DICT.get(dp_lane4, "Unknown"), - 'dp_lane5': DICT.get(dp_lane5, "Unknown"), - 'dp_lane6': DICT.get(dp_lane6, "Unknown"), - 'dp_lane7': DICT.get(dp_lane7, "Unknown"), - 'dp_lane8': DICT.get(dp_lane8, "Unknown") - } - return dp_state_dict + lane_count = self.xcvr_eeprom.read(consts.LANE_COUNT) + return (lane_count) & 0xf - def get_tx_output_status(self): + def get_media_interface_technology(self): ''' - This function returns whether TX output signals are valid on TX media lane + This function returns the media lane technology ''' - result = self.xcvr_eeprom.read(consts.TX_OUTPUT_STATUS) - tx_output_status_dict = dict() - for bitpos in range(BYTELENGTH): - tx_output_status_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return tx_output_status_dict + return self.xcvr_eeprom.read(consts.MEDIA_INTERFACE_TECH) - def get_rx_output_status(self): + def get_host_lane_assignment_option(self): ''' - This function returns whether RX output signals are valid on RX host lane + This function returns the host lane that the application begins on ''' - result = self.xcvr_eeprom.read(consts.RX_OUTPUT_STATUS) - rx_output_status_dict = dict() - for bitpos in range(BYTELENGTH): - rx_output_status_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return rx_output_status_dict + return self.xcvr_eeprom.read(consts.HOST_LANE_ASSIGNMENT_OPTION) - def get_tx_fault(self): + def get_media_lane_assignment_option(self): ''' - This function returns TX failure flag on TX media lane + This function returns the media lane that the application is allowed to begin on ''' - result = self.xcvr_eeprom.read(consts.TX_FAULT_FLAG) - tx_fault_dict = dict() - for bitpos in range(BYTELENGTH): - tx_fault_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return tx_fault_dict + return self.xcvr_eeprom.read(consts.MEDIA_LANE_ASSIGNMENT_OPTION) - def get_tx_los(self): + def get_active_apsel_hostlane(self): ''' - This function returns TX LOS flag on TX host lane + This function returns the application select code that each host lane has ''' - result = self.xcvr_eeprom.read(consts.TX_LOS_FLAG) - tx_los_dict = dict() - for bitpos in range(BYTELENGTH): - tx_los_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return tx_los_dict + return self.xcvr_eeprom.read(consts.ACTIVE_APSEL_CODE) - def get_tx_cdr_lol(self): + def get_tx_config_power(self): ''' - This function returns TX CDR LOL flag on TX host lane + This function returns the configured TX output power. Unit in dBm ''' - result = self.xcvr_eeprom.read(consts.TX_CDR_LOL) - tx_lol_dict = dict() - for bitpos in range(BYTELENGTH): - tx_lol_dict['TX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return tx_lol_dict + return self.xcvr_eeprom.read(consts.TX_CONFIG_POWER) - def get_tx_power_flag(self): + def get_media_output_loopback(self): ''' - This function returns TX power out of range flag on TX media lane + This function returns the media output loopback status ''' - tx_power_high_alarm = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM_FLAG) - tx_power_low_alarm = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM_FLAG) - tx_power_high_warn = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN_FLAG) - tx_power_low_warn = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN_FLAG) - tx_power_high_alarm_dict = dict() - tx_power_low_alarm_dict = dict() - tx_power_high_warn_dict = dict() - tx_power_low_warn_dict = dict() - for bitpos in range(BYTELENGTH): - tx_power_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_alarm >> bitpos) & 0x1) - tx_power_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_alarm >> bitpos) & 0x1) - tx_power_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_high_warn >> bitpos) & 0x1) - tx_power_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_power_low_warn >> bitpos) & 0x1) + result = self.xcvr_eeprom.read(consts.MEDIA_OUTPUT_LOOPBACK) + return result == 1 - tx_power_flag_dict = {'tx_power_high_alarm': tx_power_high_alarm_dict, - 'tx_power_low_alarm': tx_power_low_alarm_dict, - 'tx_power_high_warn': tx_power_high_warn_dict, - 'tx_power_low_warn': tx_power_low_warn_dict,} - return tx_power_flag_dict + def get_media_input_loopback(self): + ''' + This function returns the media input loopback status + ''' + result = self.xcvr_eeprom.read(consts.MEDIA_INPUT_LOOPBACK) + return result == 1 - def get_tx_bias_flag(self): + def get_host_output_loopback(self): ''' - This function returns TX bias out of range flag on TX media lane + This function returns the host output loopback status ''' - tx_bias_high_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_ALARM_FLAG) - tx_bias_low_alarm = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_ALARM_FLAG) - tx_bias_high_warn = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_WARN_FLAG) - tx_bias_low_warn = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_WARN_FLAG) - tx_bias_high_alarm_dict = dict() - tx_bias_low_alarm_dict = dict() - tx_bias_high_warn_dict = dict() - tx_bias_low_warn_dict = dict() - for bitpos in range(BYTELENGTH): - tx_bias_high_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_alarm >> bitpos) & 0x1) - tx_bias_low_alarm_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_alarm >> bitpos) & 0x1) - tx_bias_high_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_high_warn >> bitpos) & 0x1) - tx_bias_low_warn_dict['TX_lane%d' %(bitpos+1)] = bool((tx_bias_low_warn >> bitpos) & 0x1) - - tx_bias_flag_dict = {'tx_bias_high_alarm': tx_bias_high_alarm_dict, - 'tx_bias_low_alarm': tx_bias_low_alarm_dict, - 'tx_bias_high_warn': tx_bias_high_warn_dict, - 'tx_bias_low_warn': tx_bias_low_warn_dict,} - return tx_bias_flag_dict + result = self.xcvr_eeprom.read(consts.HOST_OUTPUT_LOOPBACK) + loopback_status = [] + for bitpos in range(self.NUM_CHANNELS): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status - def get_rx_power_flag(self): + def get_host_input_loopback(self): ''' - This function returns RX power out of range flag on RX media lane + This function returns the host input loopback status ''' - rx_power_high_alarm = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM_FLAG) - rx_power_low_alarm = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM_FLAG) - rx_power_high_warn = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN_FLAG) - rx_power_low_warn = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN_FLAG) - rx_power_high_alarm_dict = dict() - rx_power_low_alarm_dict = dict() - rx_power_high_warn_dict = dict() - rx_power_low_warn_dict = dict() - for bitpos in range(BYTELENGTH): - rx_power_high_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_alarm >> bitpos) & 0x1) - rx_power_low_alarm_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_alarm >> bitpos) & 0x1) - rx_power_high_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_high_warn >> bitpos) & 0x1) - rx_power_low_warn_dict['RX_lane%d' %(bitpos+1)] = bool((rx_power_low_warn >> bitpos) & 0x1) + result = self.xcvr_eeprom.read(consts.HOST_INPUT_LOOPBACK) + loopback_status = [] + for bitpos in range(self.NUM_CHANNELS): + loopback_status.append(bool((result >> bitpos) & 0x1)) + return loopback_status - rx_power_flag_dict = {'rx_power_high_alarm': rx_power_high_alarm_dict, - 'rx_power_low_alarm': rx_power_low_alarm_dict, - 'rx_power_high_warn': rx_power_high_warn_dict, - 'rx_power_low_warn': rx_power_low_warn_dict,} - return rx_power_flag_dict + def get_aux_mon_type(self): + ''' + This function returns the aux monitor types + ''' + result = self.xcvr_eeprom.read(consts.AUX_MON_TYPE) + aux1_mon_type = result & 0x1 + aux2_mon_type = (result >> 1) & 0x1 + aux3_mon_type = (result >> 2) & 0x1 + return aux1_mon_type, aux2_mon_type, aux3_mon_type - def get_rx_los(self): + def get_laser_temperature(self): ''' - This function returns RX LOS flag on RX media lane + This function returns the laser temperature monitor value ''' - result = self.xcvr_eeprom.read(consts.RX_LOS_FLAG) - rx_los_dict = dict() - for bitpos in range(BYTELENGTH): - rx_los_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return rx_los_dict + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + LASER_TEMP_SCALE = 256.0 + if aux2_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEMP_SCALE + laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEMP_SCALE + laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEMP_SCALE + laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEMP_SCALE + laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEMP_SCALE + elif aux2_mon_type == 1 and aux3_mon_type == 0: + laser_temp = self.xcvr_eeprom.read(consts.AUX3_MON)/LASER_TEMP_SCALE + laser_temp_high_alarm = self.xcvr_eeprom.read(consts.AUX3_HIGH_ALARM)/LASER_TEMP_SCALE + laser_temp_low_alarm = self.xcvr_eeprom.read(consts.AUX3_LOW_ALARM)/LASER_TEMP_SCALE + laser_temp_high_warn = self.xcvr_eeprom.read(consts.AUX3_HIGH_WARN)/LASER_TEMP_SCALE + laser_temp_low_warn = self.xcvr_eeprom.read(consts.AUX3_LOW_WARN)/LASER_TEMP_SCALE + else: + return None + laser_temp_dict = {'monitor value': laser_temp, + 'high alarm': laser_temp_high_alarm, + 'low alarm': laser_temp_low_alarm, + 'high warn': laser_temp_high_warn, + 'low warn': laser_temp_low_warn} + return laser_temp_dict - def get_rx_cdr_lol(self): + def get_laser_TEC_current(self): ''' - This function returns RX CDR LOL flag on RX media lane + This function returns the laser TEC current monitor value ''' - result = self.xcvr_eeprom.read(consts.RX_CDR_LOL) - rx_lol_dict = dict() - for bitpos in range(BYTELENGTH): - rx_lol_dict['RX_lane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) - return rx_lol_dict + aux1_mon_type, aux2_mon_type, aux3_mon_type = self.get_aux_mon_type() + LASER_TEC_CURRENT_SCALE = 32767.0 + if aux1_mon_type == 1: + laser_tec_current = self.xcvr_eeprom.read(consts.AUX1_MON)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX1_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX1_LOW_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX1_HIGH_WARN)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX1_LOW_WARN)/LASER_TEC_CURRENT_SCALE + elif aux1_mon_type == 0 and aux2_mon_type == 1: + laser_tec_current = self.xcvr_eeprom.read(consts.AUX2_MON)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_alarm = self.xcvr_eeprom.read(consts.AUX2_HIGH_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_alarm = self.xcvr_eeprom.read(consts.AUX2_LOW_ALARM)/LASER_TEC_CURRENT_SCALE + laser_tec_current_high_warn = self.xcvr_eeprom.read(consts.AUX2_HIGH_WARN)/LASER_TEC_CURRENT_SCALE + laser_tec_current_low_warn = self.xcvr_eeprom.read(consts.AUX2_LOW_WARN)/LASER_TEC_CURRENT_SCALE + else: + return None + laser_tec_current_dict = {'monitor value': laser_tec_current, + 'high alarm': laser_tec_current_high_alarm, + 'low alarm': laser_tec_current_low_alarm, + 'high warn': laser_tec_current_high_warn, + 'low warn': laser_tec_current_low_warn} + return laser_tec_current_dict def get_config_datapath_hostlane_status(self): ''' - This function returns configuration command execution + This function returns configuration command execution / result status for the datapath of each host lane - ''' + ''' result = self.xcvr_eeprom.read(consts.CONFIG_LANE_STATUS) config_status_lane7 = (result >> 0) & 0xf config_status_lane8 = (result >> 4) & 0xf @@ -698,6 +684,16 @@ def get_config_datapath_hostlane_status(self): } return config_status_dict + def get_datapath_state(self): + ''' + This function returns the eight datapath states + ''' + result = self.xcvr_eeprom.read(consts.LANE_DATAPATH_STATUS_FIELD) + if result is None: + return {} + dp_state_dict = result[consts.DATA_PATH_STATE] + return dp_state_dict + def get_dpinit_pending(self): ''' This function returns datapath init pending status. @@ -707,7 +703,7 @@ def get_dpinit_pending(self): ''' result = self.xcvr_eeprom.read(consts.DPINIT_PENDING) dpinit_pending_dict = dict() - for bitpos in range(BYTELENGTH): + for bitpos in range(self.NUM_CHANNELS): dpinit_pending_dict['hostlane%d' %(bitpos+1)] = bool((result >> bitpos) & 0x1) return dpinit_pending_dict @@ -729,7 +725,7 @@ def reset_module(self, reset = False): def set_low_power(self, AssertLowPower): ''' - This function sets the module to low power state. + This function sets the module to low power state. AssertLowPower being 0 means "set to high power" AssertLowPower being 1 means "set to low power" ''' @@ -785,7 +781,109 @@ def set_loopback_mode(self, loopback_mode): def get_cdb_api(self): self.cdb = CmisCdbApi(self.xcvr_eeprom) return self.cdb - + + def get_vdm_api(self): + self.vdm = CmisVdmApi(self.xcvr_eeprom) + return self.vdm + + def get_vdm(self): + ''' + This function returns all the VDM items, including real time monitor value, threholds and flags + ''' + try: + self.vdm + except AttributeError: + self.get_vdm_api() + vdm = self.vdm.get_vdm_allpage() + return vdm + + def get_module_firmware_fault_state_changed(self): + ''' + This function returns datapath firmware fault state, module firmware fault state + and whether module state changed + ''' + result = self.xcvr_eeprom.read(consts.MODULE_FIRMWARE_FAULT_INFO) + datapath_firmware_fault = bool((result >> 2) & 0x1) + module_firmware_fault = bool((result >> 1) & 0x1) + module_state_changed = bool(result & 0x1) + return datapath_firmware_fault, module_firmware_fault, module_state_changed + + def get_module_level_flag(self): + ''' + This function returns teh module level flags, including + - 3.3 V voltage supply flags + - Case temperature flags + - Aux 1 flags + - Aux 2 flags + - Aux 3 flags + - Custom field flags + ''' + module_flag_byte1 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE1) + module_flag_byte2 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE2) + module_flag_byte3 = self.xcvr_eeprom.read(consts.MODULE_FLAG_BYTE3) + + voltage_high_alarm_flag = bool((module_flag_byte1 >> 4) & 0x1) + voltage_low_alarm_flag = bool((module_flag_byte1 >> 5) & 0x1) + voltage_high_warn_flag = bool((module_flag_byte1 >> 6) & 0x1) + voltage_low_warn_flag = bool((module_flag_byte1 >> 7) & 0x1) + voltage_flags = {'voltage_high_alarm_flag': voltage_high_alarm_flag, + 'voltage_low_alarm_flag': voltage_low_alarm_flag, + 'voltage_high_warn_flag': voltage_high_warn_flag, + 'voltage_low_warn_flag': voltage_low_warn_flag} + + case_temp_high_alarm_flag = bool((module_flag_byte1 >> 0) & 0x1) + case_temp_low_alarm_flag = bool((module_flag_byte1 >> 1) & 0x1) + case_temp_high_warn_flag = bool((module_flag_byte1 >> 2) & 0x1) + case_temp_low_warn_flag = bool((module_flag_byte1 >> 3) & 0x1) + case_temp_flags = {'case_temp_high_alarm_flag': case_temp_high_alarm_flag, + 'case_temp_low_alarm_flag': case_temp_low_alarm_flag, + 'case_temp_high_warn_flag': case_temp_high_warn_flag, + 'case_temp_low_warn_flag': case_temp_low_warn_flag} + + aux2_high_alarm_flag = bool((module_flag_byte2 >> 4) & 0x1) + aux2_low_alarm_flag = bool((module_flag_byte2 >> 5) & 0x1) + aux2_high_warn_flag = bool((module_flag_byte2 >> 6) & 0x1) + aux2_low_warn_flag = bool((module_flag_byte2 >> 7) & 0x1) + aux2_flags = {'aux2_high_alarm_flag': aux2_high_alarm_flag, + 'aux2_low_alarm_flag': aux2_low_alarm_flag, + 'aux2_high_warn_flag': aux2_high_warn_flag, + 'aux2_low_warn_flag': aux2_low_warn_flag} + + aux1_high_alarm_flag = bool((module_flag_byte2 >> 0) & 0x1) + aux1_low_alarm_flag = bool((module_flag_byte2 >> 1) & 0x1) + aux1_high_warn_flag = bool((module_flag_byte2 >> 2) & 0x1) + aux1_low_warn_flag = bool((module_flag_byte2 >> 3) & 0x1) + aux1_flags = {'aux1_high_alarm_flag': aux1_high_alarm_flag, + 'aux1_low_alarm_flag': aux1_low_alarm_flag, + 'aux1_high_warn_flag': aux1_high_warn_flag, + 'aux1_low_warn_flag': aux1_low_warn_flag} + + custom_mon_high_alarm_flag = bool((module_flag_byte3 >> 4) & 0x1) + custom_mon_low_alarm_flag = bool((module_flag_byte3 >> 5) & 0x1) + custom_mon_high_warn_flag = bool((module_flag_byte3 >> 6) & 0x1) + custom_mon_low_warn_flag = bool((module_flag_byte3 >> 7) & 0x1) + custom_mon_flags = {'custom_mon_high_alarm_flag': custom_mon_high_alarm_flag, + 'custom_mon_low_alarm_flag': custom_mon_low_alarm_flag, + 'custom_mon_high_warn_flag': custom_mon_high_warn_flag, + 'custom_mon_low_warn_flag': custom_mon_low_warn_flag} + + aux3_high_alarm_flag = bool((module_flag_byte3 >> 0) & 0x1) + aux3_low_alarm_flag = bool((module_flag_byte3 >> 1) & 0x1) + aux3_high_warn_flag = bool((module_flag_byte3 >> 2) & 0x1) + aux3_low_warn_flag = bool((module_flag_byte3 >> 3) & 0x1) + aux3_flags = {'aux3_high_alarm_flag': aux3_high_alarm_flag, + 'aux3_low_alarm_flag': aux3_low_alarm_flag, + 'aux3_high_warn_flag': aux3_high_warn_flag, + 'aux3_low_warn_flag': aux3_low_warn_flag} + + module_flag = {'voltage_flags': voltage_flags, + 'case_temp_flags': case_temp_flags, + 'aux1_flags': aux1_flags, + 'aux2_flags': aux2_flags, + 'aux3_flags': aux3_flags, + 'custom_mon_flags': custom_mon_flags} + return module_flag + def get_module_fw_upgrade_feature(self, verbose = False): """ This function obtains CDB features supported by the module from CDB command 0041h, @@ -873,7 +971,7 @@ def get_module_fw_info(self): ImageBCommitted = ((fwStatus >> 5) & 0x01) # bit 5 - image B is committed ImageBValid = ((fwStatus >> 6) & 0x01) # bit 6 - image B is valid - if ImageARunning == 1: + if ImageARunning == 1: RunningImage = 'A' elif ImageBRunning == 1: RunningImage = 'B' @@ -890,10 +988,10 @@ def get_module_fw_info(self): def module_fw_run(self, mode = 0x01): """ - This command is used to start and run a selected image. - This command transfers control from the currently - running firmware to a selected firmware that is started. It - can be used to switch between firmware versions, or to + This command is used to start and run a selected image. + This command transfers control from the currently + running firmware to a selected firmware that is started. It + can be used to switch between firmware versions, or to perform a restart of the currently running firmware. mode: 00h = Traffic affecting Reset to Inactive Image. @@ -918,7 +1016,7 @@ def module_fw_run(self, mode = 0x01): def module_fw_commit(self): """ - The host uses this command to commit the running image + The host uses this command to commit the running image so that the module will boot from it on future boots. """ try: @@ -1019,8 +1117,8 @@ def module_fw_download(self, startLPLsize, maxblocksize, lplonly_flag, autopagin def module_fw_upgrade(self, imagepath): """ - This function performs firmware upgrade. - 1. show FW version in the beginning + This function performs firmware upgrade. + 1. show FW version in the beginning 2. check module advertised FW download capability 3. configure download 4. show download progress @@ -1049,196 +1147,6 @@ def module_fw_switch(self): else: logger.info('Not both images are valid.') - def get_transceiver_info(self): - """ - Retrieves transceiver info of this SFP - - Returns: - A dict which contains following keys/values : - ================================================================================ - key = TRANSCEIVER_INFO|ifname ; information for module on port - ; field = value - module_media_type = 1*255VCHAR ; module media interface ID - host_electrical_interface = 1*255VCHAR ; host electrical interface ID - media_interface_code = 1*255VCHAR ; media interface code - host_lane_count = INTEGER ; host lane count - media_lane_count = INTEGER ; media lane count - host_lane_assignment_option = INTEGER ; permissible first host lane number for application - media_lane_assignment_option = INTEGER ; permissible first media lane number for application - active_apsel_hostlane1 = INTEGER ; active application selected code assigned to host lane 1 - active_apsel_hostlane2 = INTEGER ; active application selected code assigned to host lane 2 - active_apsel_hostlane3 = INTEGER ; active application selected code assigned to host lane 3 - active_apsel_hostlane4 = INTEGER ; active application selected code assigned to host lane 4 - active_apsel_hostlane5 = INTEGER ; active application selected code assigned to host lane 5 - active_apsel_hostlane6 = INTEGER ; active application selected code assigned to host lane 6 - active_apsel_hostlane7 = INTEGER ; active application selected code assigned to host lane 7 - active_apsel_hostlane8 = INTEGER ; active application selected code assigned to host lane 8 - media_interface_technology = 1*255VCHAR ; media interface technology - hardwarerev = 1*255VCHAR ; module hardware revision - serialnum = 1*255VCHAR ; module serial number - manufacturename = 1*255VCHAR ; module venndor name - modelname = 1*255VCHAR ; module model name - vendor_rev = 1*255VCHAR ; module vendor revision - vendor_oui = 1*255VCHAR ; vendor organizationally unique identifier - vendor_date = 1*255VCHAR ; module manufacture date - connector_type = 1*255VCHAR ; connector type - specification_compliance = 1*255VCHAR ; electronic or optical interfaces that supported - active_firmware = 1*255VCHAR ; active firmware - inactive_firmware = 1*255VCHAR ; inactive firmware - ================================================================================ - """ - trans_info = dict() - trans_info['module_media_type'] = self.get_module_media_type() - trans_info['host_electrical_interface'] = self.get_host_electrical_interface() - trans_info['media_interface_code'] = self.get_module_media_interface() - trans_info['host_lane_count'] = self.get_host_lane_count() - trans_info['media_lane_count'] = self.get_media_lane_count() - trans_info['host_lane_assignment_option'] = self.get_host_lane_assignment_option() - trans_info['media_lane_assignment_option'] = self.get_media_lane_assignment_option() - apsel_dict = self.get_active_apsel_hostlane() - trans_info['active_apsel_hostlane1'] = apsel_dict['hostlane1'] - trans_info['active_apsel_hostlane2'] = apsel_dict['hostlane2'] - trans_info['active_apsel_hostlane3'] = apsel_dict['hostlane3'] - trans_info['active_apsel_hostlane4'] = apsel_dict['hostlane4'] - trans_info['active_apsel_hostlane5'] = apsel_dict['hostlane5'] - trans_info['active_apsel_hostlane6'] = apsel_dict['hostlane6'] - trans_info['active_apsel_hostlane7'] = apsel_dict['hostlane7'] - trans_info['active_apsel_hostlane8'] = apsel_dict['hostlane8'] - trans_info['media_interface_technology'] = self.get_media_interface_technology() - trans_info['hardwarerev'] = self.get_module_hardware_revision() - trans_info['serialnum'] = self.get_vendor_serial() - trans_info['manufacturename'] = self.get_vendor_name() - trans_info['vendor_rev'] = self.get_vendor_rev() - trans_info['vendor_oui'] = self.get_vendor_OUI() - trans_info['vendor_date'] = self.get_vendor_date() - trans_info['connector_type'] = self.get_connector_type() - trans_info['specification_compliance'] = self.get_cmis_rev() - trans_info['active_firmware'] = self.get_module_active_firmware() - trans_info['inactive_firmware'] = self.get_module_inactive_firmware() - return trans_info - - def get_transceiver_bulk_status(self): - """ - Retrieves bulk status info for this xcvr - - Returns: - A dict containing the following keys/values : - ======================================================================== - key = TRANSCEIVER_DOM_SENSOR|ifname ; information module DOM sensors on port - ; field = value - temperature = FLOAT ; temperature value in Celsius - voltage = FLOAT ; voltage value - txpower = FLOAT ; tx power in mW - rxpower = FLOAT ; rx power in mW - txbias = FLOAT ; tx bias in mA - laser_temperature = FLOAT ; laser temperature value in Celsius - prefec_ber = FLOAT ; prefec ber - postfec_ber = FLOAT ; postfec ber - ======================================================================== - """ - trans_dom = dict() - case_temp_dict = self.get_module_temperature() - trans_dom['temperature'] = case_temp_dict['monitor value'] - voltage_dict = self.get_module_voltage() - trans_dom['voltage'] = voltage_dict['monitor value'] - tx_power_dict = self.get_txpower() - trans_dom['txpower'] = tx_power_dict['monitor value lane1'] - rx_power_dict = self.get_rxpower() - trans_dom['rxpower'] = rx_power_dict['monitor value lane1'] - tx_bias_current_dict = self.get_txbias() - trans_dom['txbias'] = tx_bias_current_dict['monitor value lane1'] - laser_temp_dict = self.get_laser_temperature() - trans_dom['laser_temperature'] = laser_temp_dict['monitor value'] - self.vdm_dict = self.get_vdm() - trans_dom['prefec_ber'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][0] - trans_dom['postfec_ber'] = self.vdm_dict['Errored Frames Average Media Input'][1][0] - return trans_dom - - def get_transceiver_threshold_info(self): - """ - Retrieves threshold info for this xcvr - - Returns: - A dict containing the following keys/values : - ======================================================================== - key = TRANSCEIVER_STATUS|ifname ; DOM threshold information for module on port - ; field = value - temphighalarm = FLOAT ; temperature high alarm threshold in Celsius - temphighwarning = FLOAT ; temperature high warning threshold in Celsius - templowalarm = FLOAT ; temperature low alarm threshold in Celsius - templowwarning = FLOAT ; temperature low warning threshold in Celsius - vcchighalarm = FLOAT ; vcc high alarm threshold in V - vcchighwarning = FLOAT ; vcc high warning threshold in V - vcclowalarm = FLOAT ; vcc low alarm threshold in V - vcclowwarning = FLOAT ; vcc low warning threshold in V - txpowerhighalarm = FLOAT ; tx power high alarm threshold in mW - txpowerlowalarm = FLOAT ; tx power low alarm threshold in mW - txpowerhighwarning = FLOAT ; tx power high warning threshold in mW - txpowerlowwarning = FLOAT ; tx power low alarm threshold in mW - rxpowerhighalarm = FLOAT ; rx power high alarm threshold in mW - rxpowerlowalarm = FLOAT ; rx power low alarm threshold in mW - rxpowerhighwarning = FLOAT ; rx power high warning threshold in mW - rxpowerlowwarning = FLOAT ; rx power low warning threshold in mW - txbiashighalarm = FLOAT ; tx bias high alarm threshold in mA - txbiaslowalarm = FLOAT ; tx bias low alarm threshold in mA - txbiashighwarning = FLOAT ; tx bias high warning threshold in mA - txbiaslowwarning = FLOAT ; tx bias low warning threshold in mA - lasertemphighalarm = FLOAT ; laser temperature high alarm threshold in Celsius - lasertemplowalarm = FLOAT ; laser temperature low alarm threshold in Celsius - lasertemphighwarning = FLOAT ; laser temperature high warning threshold in Celsius - lasertemplowwarning = FLOAT ; laser temperature low warning threshold in Celsius - prefecberhighalarm = FLOAT ; prefec ber high alarm threshold - prefecberlowalarm = FLOAT ; prefec ber low alarm threshold - prefecberhighwarning = FLOAT ; prefec ber high warning threshold - prefecberlowwarning = FLOAT ; prefec ber low warning threshold - postfecberhighalarm = FLOAT ; postfec ber high alarm threshold - postfecberlowalarm = FLOAT ; postfec ber low alarm threshold - postfecberhighwarning = FLOAT ; postfec ber high warning threshold - postfecberlowwarning = FLOAT ; postfec ber low warning threshold - ======================================================================== - """ - trans_dom_th = dict() - case_temp_dict = self.get_module_temperature() - trans_dom_th['temphighalarm'] = case_temp_dict['high alarm'] - trans_dom_th['templowalarm'] = case_temp_dict['low alarm'] - trans_dom_th['temphighwarning'] = case_temp_dict['high warn'] - trans_dom_th['templowwarning'] = case_temp_dict['low warn'] - voltage_dict = self.get_module_voltage() - trans_dom_th['vcchighalarm'] = voltage_dict['high alarm'] - trans_dom_th['vcclowalarm'] = voltage_dict['low alarm'] - trans_dom_th['vcchighwarning'] = voltage_dict['high warn'] - trans_dom_th['vcclowwarning'] = voltage_dict['low warn'] - tx_power_dict = self.get_txpower() - trans_dom_th['txpowerhighalarm'] = tx_power_dict['high alarm'] - trans_dom_th['txpowerlowalarm'] = tx_power_dict['low alarm'] - trans_dom_th['txpowerhighwarning'] = tx_power_dict['high warn'] - trans_dom_th['txpowerlowwarning'] = tx_power_dict['low warn'] - rx_power_dict = self.get_rxpower() - trans_dom_th['rxpowerhighalarm'] = rx_power_dict['high alarm'] - trans_dom_th['rxpowerlowalarm'] = rx_power_dict['low alarm'] - trans_dom_th['rxpowerhighwarning'] = rx_power_dict['high warn'] - trans_dom_th['rxpowerlowwarning'] = rx_power_dict['low warn'] - tx_bias_current_dict = self.get_txbias() - trans_dom_th['txbiashighalarm'] = tx_bias_current_dict['high alarm'] - trans_dom_th['txbiaslowalarm'] = tx_bias_current_dict['low alarm'] - trans_dom_th['txbiashighwarning'] = tx_bias_current_dict['high warn'] - trans_dom_th['txbiaslowwarning'] = tx_bias_current_dict['low warn'] - laser_temp_dict = self.get_laser_temperature() - trans_dom_th['lasertemphighalarm'] = laser_temp_dict['high alarm'] - trans_dom_th['lasertemplowalarm'] = laser_temp_dict['low alarm'] - trans_dom_th['lasertemphighwarning'] = laser_temp_dict['high warn'] - trans_dom_th['lasertemplowwarning'] = laser_temp_dict['low warn'] - self.vdm_dict = self.get_vdm() - trans_dom_th['prefecberhighalarm'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][1] - trans_dom_th['prefecberlowalarm'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][2] - trans_dom_th['prefecberhighwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][3] - trans_dom_th['prefecberlowwarning'] = self.vdm_dict['Pre-FEC BER Average Media Input'][1][4] - trans_dom_th['postfecberhighalarm'] = self.vdm_dict['Errored Frames Average Media Input'][1][1] - trans_dom_th['postfecberlowalarm'] = self.vdm_dict['Errored Frames Average Media Input'][1][2] - trans_dom_th['postfecberhighwarning'] = self.vdm_dict['Errored Frames Average Media Input'][1][3] - trans_dom_th['postfecberlowwarning'] = self.vdm_dict['Errored Frames Average Media Input'][1][4] - return trans_dom_th - def get_transceiver_status(self): """ Retrieves transceiver status of this SFP @@ -1299,7 +1207,7 @@ def get_transceiver_status(self): config_state_hostlane6 = 1*255VCHAR ; configuration status for the data path of host line 6 config_state_hostlane7 = 1*255VCHAR ; configuration status for the data path of host line 7 config_state_hostlane8 = 1*255VCHAR ; configuration status for the data path of host line 8 - dpinit_pending_hostlane1 = BOOLEAN ; data path configuration updated on host lane 1 + dpinit_pending_hostlane1 = BOOLEAN ; data path configuration updated on host lane 1 dpinit_pending_hostlane2 = BOOLEAN ; data path configuration updated on host lane 2 dpinit_pending_hostlane3 = BOOLEAN ; data path configuration updated on host lane 3 dpinit_pending_hostlane4 = BOOLEAN ; data path configuration updated on host lane 4 @@ -1307,7 +1215,7 @@ def get_transceiver_status(self): dpinit_pending_hostlane6 = BOOLEAN ; data path configuration updated on host lane 6 dpinit_pending_hostlane7 = BOOLEAN ; data path configuration updated on host lane 7 dpinit_pending_hostlane8 = BOOLEAN ; data path configuration updated on host lane 8 - temphighalarm_flag = BOOLEAN ; temperature high alarm flag + temphighalarm_flag = BOOLEAN ; temperature high alarm flag temphighwarning_flag = BOOLEAN ; temperature high warning flag templowalarm_flag = BOOLEAN ; temperature low alarm flag templowwarning_flag = BOOLEAN ; temperature low warning flag @@ -1349,14 +1257,14 @@ def get_transceiver_status(self): trans_status['module_firmware_fault'] = module_fw_fault trans_status['module_state_changed'] = module_state_changed dp_state_dict = self.get_datapath_state() - trans_status['datapath_hostlane1'] = dp_state_dict['dp_lane1'] - trans_status['datapath_hostlane2'] = dp_state_dict['dp_lane2'] - trans_status['datapath_hostlane3'] = dp_state_dict['dp_lane3'] - trans_status['datapath_hostlane4'] = dp_state_dict['dp_lane4'] - trans_status['datapath_hostlane5'] = dp_state_dict['dp_lane5'] - trans_status['datapath_hostlane6'] = dp_state_dict['dp_lane6'] - trans_status['datapath_hostlane7'] = dp_state_dict['dp_lane7'] - trans_status['datapath_hostlane8'] = dp_state_dict['dp_lane8'] + trans_status['DP1State'] = dp_state_dict['dp_lane1'] + trans_status['DP2State'] = dp_state_dict['dp_lane2'] + trans_status['DP3State'] = dp_state_dict['dp_lane3'] + trans_status['DP4State'] = dp_state_dict['dp_lane4'] + trans_status['DP5State'] = dp_state_dict['dp_lane5'] + trans_status['DP6State'] = dp_state_dict['dp_lane6'] + trans_status['DP7State'] = dp_state_dict['dp_lane7'] + trans_status['DP8State'] = dp_state_dict['dp_lane8'] tx_output_status_dict = self.get_tx_output_status() trans_status['txoutput_status'] = tx_output_status_dict['TX_lane1'] rx_output_status_dict = self.get_rx_output_status() @@ -1465,7 +1373,7 @@ def get_transceiver_loopback(self): A dict containing the following keys/values : ======================================================================== key = TRANSCEIVER_PM|ifname ; information of loopback on port - ; field = value + ; field = value media_output_loopback = BOOLEAN ; media side output loopback enable media_input_loopback = BOOLEAN ; media side input loopback enable host_output_loopback_lane1 = BOOLEAN ; host side output loopback enable lane1 @@ -1483,7 +1391,7 @@ def get_transceiver_loopback(self): host_input_loopback_lane5 = BOOLEAN ; host side input loopback enable lane5 host_input_loopback_lane6 = BOOLEAN ; host side input loopback enable lane6 host_input_loopback_lane7 = BOOLEAN ; host side input loopback enable lane7 - host_input_loopback_lane8 = BOOLEAN ; host side input loopback enable lane8 + host_input_loopback_lane8 = BOOLEAN ; host side input loopback enable lane8 ======================================================================== """ trans_loopback = dict() @@ -1508,6 +1416,4 @@ def get_transceiver_loopback(self): trans_loopback['host_input_loopback_lane7'] = host_input_loopback_status[6] trans_loopback['host_input_loopback_lane8'] = host_input_loopback_status[7] return trans_loopback - # TODO: other XcvrApi methods - - + # TODO: other XcvrApi methods \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py index 1605eed62..9b408dd74 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmisCDB.py @@ -427,4 +427,4 @@ def commit_fw_image(self): continue else: break - return status + return status \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/codes/public/cmis.py b/sonic_platform_base/sonic_xcvr/codes/public/cmis.py new file mode 100644 index 000000000..8eaf9c523 --- /dev/null +++ b/sonic_platform_base/sonic_xcvr/codes/public/cmis.py @@ -0,0 +1,130 @@ +from .sff8024 import Sff8024 + +class CmisCodes(Sff8024): + POWER_CLASSES = { + 0: "Power Class 1", + 1: "Power Class 2", + 2: "Power Class 3", + 3: "Power Class 4", + 4: "Power Class 5", + 5: "Power Class 6", + 6: "Power Class 7", + 7: "Power Class 8" + } + + MEDIA_TYPES = { + 0: "Undefined", + 1: "nm_850_media_interface", + 2: "sm_media_interface", + 3: "passive_copper_media_interface", + 4: "active_cable_media_interface", + 5: "base_t_media_interface", + } + + MEDIA_INTERFACE_TECH = { + 0: '850 nm VCSEL', + 1: '1310 nm VCSEL', + 2: '1550 nm VCSEL', + 3: '1310 nm FP', + 4: '1310 nm DFB', + 5: '1550 nm DFB', + 6: '1310 nm EML', + 7: '1550 nm EML', + 8: 'Others', + 9: '1490 nm DFB', + 10: 'Copper cable unequalized', + 11: 'Copper cable passive equalized', + 12: 'Copper cable, near and far end limiting active equalizers', + 13: 'Copper cable, far end limiting active equalizers', + 14: 'Copper cable, near end limiting active equalizers', + 15: 'Copper cable, linear active equalizers', + 16: 'C-band tunable laser', + 17: 'L-band tunable laser', + } + + MODULE_STATE = { + 1: 'ModuleLowPwr', + 2: 'ModulePwrUp', + 3: 'ModuleReady', + 4: 'ModulePwrDn', + 5: 'ModuleFault', + } + + MODULE_FAULT_CAUSE = { + 0: 'No Fault detected', + 1: 'TEC runawawy', + 2: 'Data memory corrupted', + 3: 'Program memory corrupted', + } + + DATAPATH_STATE = { + 1: 'DataPathDeactivated', + 2: 'DataPathInit', + 3: 'DataPathDeinit', + 4: 'DataPathActivated', + 5: 'DataPathTxTurnOn', + 6: 'DataPathTxTurnOff', + 7: 'DataPathInitialized', + } + + CONFIG_STATUS = { + 0: 'ConfigUndefined', + 1: 'ConfigSuccess', + 2: 'ConfigRejected', + 3: 'ConfigRejectedInvalidAppSel', + 4: 'ConfigRejectedInvalidDataPath', + 5: 'ConfigRejectedInvalidSI', + 6: 'ConfigRejectedLaneInUse', + 7: 'ConfigRejectedPartialDataPath', + 12: 'ConfigInProgress', + } + + VDM_TYPE = { + # VDM_ID: [VDM_NAME, DATA_TYPE, SCALE] + 1: ['Laser Age [%]', 'U16', 1], + 2: ['TEC Current [%]', 'S16', 100.0/32767], + 3: ['Laser Frequency Error [MHz]', 'S16', 10], + 4: ['Laser Temperature [C]', 'S16', 1.0/256], + 5: ['eSNR Media Input [dB]', 'U16', 1.0/256], + 6: ['eSNR Host Input [dB]', 'U16', 1.0/256], + 7: ['PAM4 Level Transition Parameter Media Input [dB]', 'U16', 1.0/256], + 8: ['PAM4 Level Transition Parameter Host Input [dB]', 'U16', 1.0/256], + 9: ['Pre-FEC BER Minimum Media Input', 'F16', 1], + 10: ['Pre-FEC BER Minimum Host Input', 'F16', 1], + 11: ['Pre-FEC BER Maximum Media Input', 'F16', 1], + 12: ['Pre-FEC BER Maximum Host Input', 'F16', 1], + 13: ['Pre-FEC BER Average Media Input', 'F16', 1], + 14: ['Pre-FEC BER Average Host Input', 'F16', 1], + 15: ['Pre-FEC BER Current Value Media Input', 'F16', 1], + 16: ['Pre-FEC BER Current Value Host Input', 'F16', 1], + 17: ['Errored Frames Minimum Media Input', 'F16', 1], + 18: ['Errored Frames Minimum Host Input', 'F16', 1], + 19: ['Errored Frames Maximum Media Input', 'F16', 1], + 20: ['Errored Frames Maximum Host Input', 'F16', 1], + 21: ['Errored Frames Average Media Input', 'F16', 1], + 22: ['Errored Frames Average Host Input', 'F16', 1], + 23: ['Errored Frames Current Value Media Input', 'F16', 1], + 24: ['Errored Frames Current Value Host Input', 'F16', 1], + 128: ['Modulator Bias X/I [%]', 'U16', 100.0/65535], + 129: ['Modulator Bias X/Q [%]', 'U16', 100.0/65535], + 130: ['Modulator Bias Y/I [%]', 'U16', 100.0/65535], + 131: ['Modulator Bias Y/Q [%]', 'U16', 100.0/65535], + 132: ['Modulator Bias X_Phase [%]', 'U16', 100.0/65535], + 133: ['Modulator Bias Y_Phase [%]', 'U16', 100.0/65535], + 134: ['CD high granularity, short link [ps/nm]', 'S16', 1], + 135: ['CD low granularity, long link [ps/nm]', 'S16', 20], + 136: ['DGD [ps]', 'U16', 0.01], + 137: ['SOPMD [ps^2]', 'U16', 0.01], + 138: ['PDL [dB]', 'U16', 0.1], + 139: ['OSNR [dB]', 'U16', 0.1], + 140: ['eSNR [dB]', 'U16', 0.1], + 141: ['CFO [MHz]', 'S16', 1], + 142: ['EVM_modem [%]', 'U16', 100.0/65535], + 143: ['Tx Power [dBm]', 'S16', 0.01], + 144: ['Rx Total Power [dBm]', 'S16', 0.01], + 145: ['Rx Signal Power [dBm]', 'S16', 0.01], + 146: ['SOP ROC [krad/s]', 'U16', 1], + 147: ['MER [dB]', 'U16', 0.1] + } + + # TODO: Add other codes \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py index 6afd538b0..a78922b80 100644 --- a/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py +++ b/sonic_platform_base/sonic_xcvr/codes/public/sff8024.py @@ -367,4 +367,4 @@ class Sff8024(XcvrCodes): '04': '10GBASE-T (Clause 55)' } - # TODO: Add other codes + # TODO: Add other codes \ No newline at end of file diff --git a/sonic_platform_base/sonic_xcvr/fields/consts.py b/sonic_platform_base/sonic_xcvr/fields/consts.py index 8db6c8304..9fa5502b7 100644 --- a/sonic_platform_base/sonic_xcvr/fields/consts.py +++ b/sonic_platform_base/sonic_xcvr/fields/consts.py @@ -108,7 +108,7 @@ # CMIS ADMIN_INFO_FIELD = "AdminInfo" -MODULE_MEDIA_TYPE = "ModuleMediaType" +MEDIA_TYPE_FIELD = "ModuleMediaType" HOST_ELECTRICAL_INTERFACE = "HostElectricalInterfaceID" MODULE_MEDIA_INTERFACE_850NM = "ModuleMediaInterface850nm" MODULE_MEDIA_INTERFACE_SM = "ModuleMediaInterfaceSM" @@ -118,14 +118,8 @@ LANE_COUNT = "LaneCount" HOST_LANE_ASSIGNMENT_OPTION = "HostLaneAssignmentOptions" MEDIA_LANE_ASSIGNMENT_OPTION = "MediaLaneAssignmentOptions" -ACTIVE_APSEL_HOSTLANE_1 = "ActiveSetLane1" -ACTIVE_APSEL_HOSTLANE_2 = "ActiveSetLane2" -ACTIVE_APSEL_HOSTLANE_3 = "ActiveSetLane3" -ACTIVE_APSEL_HOSTLANE_4 = "ActiveSetLane4" -ACTIVE_APSEL_HOSTLANE_5 = "ActiveSetLane5" -ACTIVE_APSEL_HOSTLANE_6 = "ActiveSetLane6" -ACTIVE_APSEL_HOSTLANE_7 = "ActiveSetLane7" -ACTIVE_APSEL_HOSTLANE_8 = "ActiveSetLane8" +ACTIVE_APSEL_CODE = "ActiveAppSelCode" +ACTIVE_APSEL_HOSTLANE = "ActiveAppSelLane" MEDIA_INTERFACE_TECH = "MediaInterfaceTechnology" HW_MAJOR_REV = "ModuleHardwareMajorRevision" HW_MINOR_REV = "ModuleHardwareMinorRevision" @@ -210,7 +204,7 @@ MODULE_FLAG_BYTE3 = "ModuleFlagByte3" CDB1_STATUS = "Cdb1Status" MODULE_FAULT_CAUSE = "ModuleFaultCause" -DATAPATH_STATE= "DataPathStateHostLane" +DATA_PATH_STATE= "DataPathState" TX_OUTPUT_STATUS = "TxOutputStatus" RX_OUTPUT_STATUS = "RxOutputStatus" TX_FAULT_FLAG = "TxFault" @@ -241,6 +235,17 @@ TRANS_CONFIG_FIELD = "TransceriverConfig" MODULE_LEVEL_CONTROL = "ModuleControl" +CTRLS_ADVT_FIELD = "Supported Controls Advertisement" +FLAGS_ADVT_FIELD = "Supported Flags Advertisement" + +LANE_DATAPATH_CTRL_FIELD = "Lane Control and Data Path Control" +LANE_DATAPATH_STATUS_FIELD = "Lane Status and Data Path Status" +LEN_MULT_FIELD = "LengthMultiplier" +MAX_POWER_FIELD = "MaxPower" +MGMT_CHAR_FIELD = "Management Characteristics" +MGMT_CHAR_MISC_FIELD = "Management Characteristics (Misc)" + +MODULE_CHAR_ADVT_FIELD = "Module Characteristics Advertising" # C-CMIS @@ -314,4 +319,3 @@ CDB_CMD = "CdbCommand" CDB_WRITE_MSG = "CdbWriteMessage" - 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 6f95d5bc0..eb9612f26 100644 --- a/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py @@ -1,245 +1,296 @@ """ cmis.py - Implementation of XcvrMemMap for CMIS Rev 4.0 + Implementation of XcvrMemMap for CMIS Rev 5.0 """ from ..xcvr_mem_map import XcvrMemMap from ...fields.xcvr_field import ( CodeRegField, + DateField, HexRegField, NumberRegField, - ListRegField, + RegBitField, RegGroupField, StringRegField, - RegBitField, ) from ...fields import consts - -PAGE_SIZE = 128 - -def get_addr(page, offset): - return PAGE_SIZE * page + offset +from ...fields.public.cmis import CableLenField class CmisMemMap(XcvrMemMap): def __init__(self, codes): super(CmisMemMap, self).__init__(codes) + self.MGMT_CHARACTERISTICS = RegGroupField(consts.MGMT_CHAR_FIELD, + NumberRegField(consts.MGMT_CHAR_MISC_FIELD, self.getaddr(0x0, 2), + RegBitField(consts.FLAT_MEM_FIELD, 7) + ) + ) + self.ADMIN_INFO = RegGroupField(consts.ADMIN_INFO_FIELD, - CodeRegField(consts.ID_FIELD, get_addr(0x0, 128), self.codes.XCVR_IDENTIFIERS), - StringRegField(consts.VENDOR_NAME_FIELD, get_addr(0x0, 129), size=16), - HexRegField(consts.VENDOR_OUI_FIELD, get_addr(0x0, 145), size=3), - StringRegField(consts.VENDOR_PART_NO_FIELD, get_addr(0x0, 148), size=16), - StringRegField(consts.VENDOR_REV_FIELD, get_addr(0x0, 164), size=2), - StringRegField(consts.VENDOR_SERIAL_NO_FIELD, get_addr(0x0, 166), size=16), - StringRegField(consts.VENDOR_DATE_FIELD,get_addr(0x0,182), size = 8), - CodeRegField(consts.CONNECTOR_FIELD, get_addr(0x0, 203), self.codes.CONNECTORS), - CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, get_addr(0x0, 86), self.codes.HOST_ELECTRICAL_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_TYPE, get_addr(0x0, 85), self.codes.MODULE_MEDIA_TYPE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, get_addr(0x0, 87), self.codes.NM_850_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_SM, get_addr(0x0, 87), self.codes.SM_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, get_addr(0x0, 87), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, get_addr(0x0, 87), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), - CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, get_addr(0x0, 87), self.codes.BASE_T_MEDIA_INTERFACE), - NumberRegField(consts.LANE_COUNT, get_addr(0x0, 88), format="B", size=1), - NumberRegField(consts.HOST_LANE_ASSIGNMENT_OPTION, get_addr(0x0, 89), format="B", size=1), - NumberRegField(consts.MEDIA_LANE_ASSIGNMENT_OPTION, get_addr(0x1, 176), format="B", size=1), - NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_1, get_addr(0x11, 206), format="B", size=1), - NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_2, get_addr(0x11, 207), format="B", size=1), - NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_3, get_addr(0x11, 208), format="B", size=1), - NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_4, get_addr(0x11, 209), format="B", size=1), - NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_5, get_addr(0x11, 210), format="B", size=1), - NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_6, get_addr(0x11, 211), format="B", size=1), - NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_7, get_addr(0x11, 212), format="B", size=1), - NumberRegField(consts.ACTIVE_APSEL_HOSTLANE_8, get_addr(0x11, 213), format="B", size=1), - CodeRegField(consts.MEDIA_INTERFACE_TECH, get_addr(0x0, 212), self.codes.MEDIA_INTERFACE_TECH), - NumberRegField(consts.HW_MAJOR_REV, get_addr(0x1, 130), size=1), - NumberRegField(consts.HW_MINOR_REV, get_addr(0x1, 131), size=1), - NumberRegField(consts.CMIS_REVISION, get_addr(0x0, 1), format="B", size=1), - NumberRegField(consts.ACTIVE_FW_MAJOR_REV, get_addr(0x0, 39), format="B", size=1), - NumberRegField(consts.ACTIVE_FW_MINOR_REV, get_addr(0x0, 40), format="B", size=1), - NumberRegField(consts.INACTIVE_FW_MAJOR_REV, get_addr(0x1, 128), format="B", size=1), - NumberRegField(consts.INACTIVE_FW_MINOR_REV, get_addr(0x1, 129), format="B", size=1), - # TODO: add remaining admin fields + CodeRegField(consts.ID_FIELD, self.getaddr(0x0, 128), self.codes.XCVR_IDENTIFIERS), + StringRegField(consts.VENDOR_NAME_FIELD, self.getaddr(0x0, 129), size=16), + HexRegField(consts.VENDOR_OUI_FIELD, self.getaddr(0x0, 145), size=3), + StringRegField(consts.VENDOR_PART_NO_FIELD, self.getaddr(0x0, 148), size=16), + StringRegField(consts.VENDOR_REV_FIELD, self.getaddr(0x0, 164), size=2), + StringRegField(consts.VENDOR_SERIAL_NO_FIELD, self.getaddr(0x0, 166), size=16), + DateField(consts.VENDOR_DATE_FIELD, self.getaddr(0x0, 182), size=8), + RegGroupField(consts.EXT_ID_FIELD, + CodeRegField(consts.POWER_CLASS_FIELD, self.getaddr(0x0, 200), self.codes.POWER_CLASSES, + *(RegBitField("%s_%d" % (consts.POWER_CLASS_FIELD, bit), bit) for bit in range(5, 8)) + ), + NumberRegField(consts.MAX_POWER_FIELD, self.getaddr(0x0, 201), scale=4), + ), + NumberRegField(consts.LEN_MULT_FIELD, self.getaddr(0x0, 202), + *(RegBitField("%s_%d" % (consts.LEN_MULT_FIELD, bit), bit) for bit in range (6, 8)) + ), + CableLenField(consts.LENGTH_ASSEMBLY_FIELD, self.getaddr(0x0, 202), + *(RegBitField("%s_%d" % (consts.LENGTH_ASSEMBLY_FIELD, bit), bit) for bit in range(0, 6)) + ), + + CodeRegField(consts.CONNECTOR_FIELD, self.getaddr(0x0, 203), self.codes.CONNECTORS, + deps=[consts.LEN_MULT_FIELD] + ), + CodeRegField(consts.HOST_ELECTRICAL_INTERFACE, self.getaddr(0x0, 86), self.codes.HOST_ELECTRICAL_INTERFACE), + CodeRegField(consts.MEDIA_TYPE_FIELD, self.getaddr(0x0, 85), self.codes.MODULE_MEDIA_TYPE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_850NM, self.getaddr(0x0, 87), self.codes.NM_850_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_SM, self.getaddr(0x0, 87), self.codes.SM_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_PASSIVE_COPPER, self.getaddr(0x0, 87), self.codes.PASSIVE_COPPER_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_ACTIVE_CABLE, self.getaddr(0x0, 87), self.codes.ACTIVE_CABLE_MEDIA_INTERFACE), + CodeRegField(consts.MODULE_MEDIA_INTERFACE_BASE_T, self.getaddr(0x0, 87), self.codes.BASE_T_MEDIA_INTERFACE), + NumberRegField(consts.LANE_COUNT, self.getaddr(0x0, 88), format="B", size=1), + NumberRegField(consts.HOST_LANE_ASSIGNMENT_OPTION, self.getaddr(0x0, 89), format="B", size=1), + NumberRegField(consts.MEDIA_LANE_ASSIGNMENT_OPTION, self.getaddr(0x1, 176), format="B", size=1), + CodeRegField(consts.MEDIA_INTERFACE_TECH, self.getaddr(0x0, 212), self.codes.MEDIA_INTERFACE_TECH), + NumberRegField(consts.HW_MAJOR_REV, self.getaddr(0x1, 130), size=1), + NumberRegField(consts.HW_MINOR_REV, self.getaddr(0x1, 131), size=1), + NumberRegField(consts.CMIS_REVISION, self.getaddr(0x0, 1), format="B", size=1), + NumberRegField(consts.ACTIVE_FW_MAJOR_REV, self.getaddr(0x0, 39), format="B", size=1), + NumberRegField(consts.ACTIVE_FW_MINOR_REV, self.getaddr(0x0, 40), format="B", size=1), + NumberRegField(consts.INACTIVE_FW_MAJOR_REV, self.getaddr(0x1, 128), format="B", size=1), + NumberRegField(consts.INACTIVE_FW_MINOR_REV, self.getaddr(0x1, 129), format="B", size=1), + + RegGroupField(consts.ACTIVE_APSEL_CODE, + *(NumberRegField("%s%d" % (consts.ACTIVE_APSEL_HOSTLANE, lane) , self.getaddr(0x11, offset), + *(RegBitField("Bit%d" % bit, bit) for bit in range(0, 4))) + for lane, offset in zip(range(1, 9), range(206, 214))) + ) ) - self.TRANS_DOM = RegGroupField(consts.TRANS_DOM_FIELD, - NumberRegField(consts.CASE_TEMP, get_addr(0x0, 14), format=">h", size=2, scale=256.0), - NumberRegField(consts.VOLTAGE, get_addr(0x0, 16), format=">H", size=2, scale=10000.0), - NumberRegField(consts.TX_POW, get_addr(0x11, 154), format=">H", size=2, scale=10000.0), - NumberRegField(consts.RX_POW, get_addr(0x11, 186), format=">H", size=2, scale=10000.0), - NumberRegField(consts.TX_BIAS, get_addr(0x11, 170), format=">H", size=2, scale=500.0), - NumberRegField(consts.GRID_SPACING, get_addr(0x12, 128), size=1, ro=False), - NumberRegField(consts.LASER_CONFIG_CHANNEL, get_addr(0x12, 136), format=">h", size=2, ro=False), - NumberRegField(consts.LASER_CURRENT_FREQ, get_addr(0x12, 168), format=">L", size=4), - NumberRegField(consts.TX_CONFIG_POWER, get_addr(0x12, 200), format=">h", size=2, scale=100.0, ro=False), - NumberRegField(consts.AUX_MON_TYPE, get_addr(0x1, 145), size=1), - NumberRegField(consts.AUX1_MON, get_addr(0x0, 18), format=">h", size=2), - NumberRegField(consts.AUX2_MON, get_addr(0x0, 20), format=">h", size=2), - NumberRegField(consts.AUX3_MON, get_addr(0x0, 22), format=">h", size=2), - NumberRegField(consts.CUSTOM_MON, get_addr(0x0, 24), format=">H", size=2), + self.MODULE_LEVEL_MONITORS = RegGroupField(consts.MODULE_MONITORS_FIELD, + NumberRegField(consts.TEMPERATURE_FIELD, self.getaddr(0x0, 14), size=2, format=">h", scale=256), + NumberRegField(consts.VOLTAGE_FIELD, self.getaddr(0x0, 16), size=2, format=">H", scale=10000), + NumberRegField(consts.TX_POW, self.getaddr(0x11, 154), format=">H", size=2, scale=10000.0), + NumberRegField(consts.RX_POW, self.getaddr(0x11, 186), format=">H", size=2, scale=10000.0), + NumberRegField(consts.TX_BIAS, self.getaddr(0x11, 170), format=">H", size=2, scale=500.0), + NumberRegField(consts.GRID_SPACING, self.getaddr(0x12, 128), size=1, ro=False), + NumberRegField(consts.LASER_CONFIG_CHANNEL, self.getaddr(0x12, 136), format=">h", size=2, ro=False), + NumberRegField(consts.LASER_CURRENT_FREQ, self.getaddr(0x12, 168), format=">L", size=4), + NumberRegField(consts.TX_CONFIG_POWER, self.getaddr(0x12, 200), format=">h", size=2, scale=100.0, ro=False), + NumberRegField(consts.AUX_MON_TYPE, self.getaddr(0x1, 145), size=1), + NumberRegField(consts.AUX1_MON, self.getaddr(0x0, 18), format=">h", size=2), + NumberRegField(consts.AUX2_MON, self.getaddr(0x0, 20), format=">h", size=2), + NumberRegField(consts.AUX3_MON, self.getaddr(0x0, 22), format=">h", size=2), + NumberRegField(consts.CUSTOM_MON, self.getaddr(0x0, 24), format=">H", size=2), +) + + self.MODULE_CHAR_ADVT = RegGroupField(consts.MODULE_CHAR_ADVT_FIELD, + NumberRegField(consts.CTRLS_ADVT_FIELD, self.getaddr(0x1, 155), + RegBitField(consts.TX_DISABLE_SUPPORT_FIELD, 1), + size=2, format="