From 8f2dffb9d7708d05823462e9e643965103989d0d Mon Sep 17 00:00:00 2001 From: longhuan-cisco <84595962+longhuan-cisco@users.noreply.github.com> Date: Tue, 6 Dec 2022 09:27:07 -0800 Subject: [PATCH] Add get_transceiver_status and get_transceiver_pm to API interface (#315) * Add get_transceiver_status to API interface * Add test_ccmis support * Add get_transceiver_pm API interface * Add debug log and more description for interface * Remove unnecessary pass --- .../sonic_xcvr/api/public/c_cmis.py | 19 ++- .../sonic_xcvr/api/public/cmis.py | 2 - .../sonic_xcvr/api/xcvr_api.py | 157 ++++++++++++++++++ tests/sonic_xcvr/test_ccmis.py | 11 +- 4 files changed, 179 insertions(+), 10 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 ab8fa893db30..4b5fc8ce6b98 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/c_cmis.py @@ -3,12 +3,16 @@ Implementation of XcvrApi that corresponds to C-CMIS """ +from sonic_py_common import logger from ...fields import consts from .cmis import CmisApi import time BYTELENGTH = 8 VDM_FREEZE = 128 VDM_UNFREEZE = 0 +SYSLOG_IDENTIFIER = "CCmisApi" + +helper_logger = logger.Logger(SYSLOG_IDENTIFIER) class CCmisApi(CmisApi): def __init__(self, xcvr_eeprom): @@ -191,7 +195,7 @@ def get_pm_all(self): 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) + rx_max_frames_uncorr_err_subint_pm = self.xcvr_eeprom.read(consts.RX_MAX_FRAMES_UNCORR_ERR_SUB_INTERVAL_PM) if (rx_frames_subint_pm != 0) and (rx_frames_pm != 0): PM_dict['preFEC_uncorr_frame_ratio_avg'] = rx_frames_uncorr_err_pm*1.0/rx_frames_subint_pm @@ -579,8 +583,6 @@ def get_transceiver_status(self): ================================================================================ 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 @@ -826,10 +828,13 @@ def get_transceiver_status(self): 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] + try: + 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] + except KeyError: + helper_logger.log_debug('Rx Signal Power [dBm] not present in VDM') return trans_status def get_transceiver_pm(self): diff --git a/sonic_platform_base/sonic_xcvr/api/public/cmis.py b/sonic_platform_base/sonic_xcvr/api/public/cmis.py index b9f3f672375d..e4edd38c00a6 100644 --- a/sonic_platform_base/sonic_xcvr/api/public/cmis.py +++ b/sonic_platform_base/sonic_xcvr/api/public/cmis.py @@ -1557,8 +1557,6 @@ def get_transceiver_status(self): ================================================================================ 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 diff --git a/sonic_platform_base/sonic_xcvr/api/xcvr_api.py b/sonic_platform_base/sonic_xcvr/api/xcvr_api.py index 9756dbf9f7a3..e759f794e74c 100644 --- a/sonic_platform_base/sonic_xcvr/api/xcvr_api.py +++ b/sonic_platform_base/sonic_xcvr/api/xcvr_api.py @@ -133,6 +133,163 @@ def get_transceiver_threshold_info(self): """ raise NotImplementedError + def get_transceiver_status(self): + """ + Retrieves transceiver status of this SFP (applicable for CMIS/C-CMIS) + + Returns: + A dict which may contain following keys/values (there could be more for C-CMIS) : + ================================================================================ + key = TRANSCEIVER_STATUS|ifname ; Error information for module on port + ; field = value + 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 + ================================================================================ + + If there is an issue with reading the xcvr, None should be returned. + """ + raise NotImplementedError + + def get_transceiver_pm(self): + """ + Retrieves PM (Performance Monitoring) info for this xcvr (applicable for C-CMIS) + + 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 + + If there is an issue with reading the xcvr, None should be returned. + """ + raise NotImplementedError + def get_rx_los(self): """ Retrieves the RX LOS (loss-of-signal) status of this xcvr diff --git a/tests/sonic_xcvr/test_ccmis.py b/tests/sonic_xcvr/test_ccmis.py index 815f850e1eb1..8896ddfbc6d6 100644 --- a/tests/sonic_xcvr/test_ccmis.py +++ b/tests/sonic_xcvr/test_ccmis.py @@ -561,7 +561,7 @@ def test_get_transceiver_threshold_info(self, get_transceiver_threshold_info_fun ]) @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): - get_transceiver_status_func.return_value = mock_response[0] + get_transceiver_status_func.return_value = dict(mock_response[0]) self.api.get_tuning_in_progress = MagicMock() self.api.get_tuning_in_progress.return_value = mock_response[1] self.api.get_wavelength_unlocked = MagicMock() @@ -572,6 +572,15 @@ def test_get_transceiver_status(self, get_transceiver_status_func, mock_response result = self.api.get_transceiver_status() assert result == expected + # For the case of 'Rx Signal Power [dBm]' not present: + get_transceiver_status_func.return_value = dict(mock_response[0]) + del self.api.vdm_dict['Rx Signal Power [dBm]'] + for k in ['rxsigpowerhighalarm_flag', 'rxsigpowerlowalarm_flag', + 'rxsigpowerhighwarning_flag', 'rxsigpowerlowwarning_flag']: + del expected[k] + result = self.api.get_transceiver_status() + assert result == expected + @pytest.mark.parametrize("mock_response, expected", [ ( {