Skip to content

Commit

Permalink
More changes
Browse files Browse the repository at this point in the history
  • Loading branch information
vvolam committed Feb 28, 2025
1 parent d2b2509 commit c6fa955
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 31 deletions.
35 changes: 21 additions & 14 deletions sonic_platform_base/sonic_xcvr/api/public/c_cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""
from sonic_py_common import logger
from ...fields import consts
from .cmis import CmisApi, CMIS_VDM_KEY_TO_DB_PREFIX_KEY_MAP
from .cmis import CmisApi, CMIS_VDM_KEY_TO_DB_PREFIX_KEY_MAP, CMIS_XCVR_INFO_DEFAULT_DICT
import time
import copy
BYTELENGTH = 8
Expand Down Expand Up @@ -46,16 +46,15 @@

helper_logger = logger.Logger(SYSLOG_IDENTIFIER)

class CCmisApi(CmisApi):
C_CMIS_XCVR_INFO_DEFAULT_DICT = copy.deepcopy(CmisApi.cmis_xcvr_info_dict)
C_CMIS_XCVR_INFO_DEFAULT_DICT.update({
"supported_max_tx_power": "N/A",
"supported_min_tx_power": "N/A",
"supported_max_laser_freq": "N/A",
"supported_min_laser_freq": "N/A"
})

C_CMIS_XCVR_INFO_DEFAULT_DICT = copy.deepcopy(CMIS_XCVR_INFO_DEFAULT_DICT)
C_CMIS_XCVR_INFO_DEFAULT_DICT.update({
"supported_max_tx_power": "N/A",
"supported_min_tx_power": "N/A",
"supported_max_laser_freq": "N/A",
"supported_min_laser_freq": "N/A"
})

class CCmisApi(CmisApi):
def __init__(self, xcvr_eeprom):
super(CCmisApi, self).__init__(xcvr_eeprom)

Expand Down Expand Up @@ -322,6 +321,9 @@ def get_pm_all(self):
PM_dict['rx_mer_max'] = self.xcvr_eeprom.read(consts.RX_MAX_MER_PM)
return PM_dict

def _get_xcvr_info_default_dict(self):
return C_CMIS_XCVR_INFO_DEFAULT_DICT

def get_transceiver_info(self):
"""
Retrieves transceiver info of this SFP
Expand Down Expand Up @@ -364,17 +366,22 @@ def get_transceiver_info(self):
supported_min_laser_freq = FLOAT ; support minimum laser frequency
================================================================================
"""
self.xcvr_info = copy.deepcopy(self.C_CMIS_XCVR_INFO_DEFAULT_DICT)
self.xcvr_info = super(CCmisApi, self).get_transceiver_info()
xcvr_info = super(CCmisApi, self).get_transceiver_info()

# Return None if CmisApi class returns None, this indicates to XCVRD that retry is
# needed.
if xcvr_info is None:
return None

min_power, max_power = self.get_supported_power_config()
_, _, _, low_freq_supported, high_freq_supported = self.get_supported_freq_config()
self.xcvr_info.update({
xcvr_info.update({
'supported_max_tx_power': max_power,
'supported_min_tx_power': min_power,
'supported_max_laser_freq': high_freq_supported,
'supported_min_laser_freq': low_freq_supported
})
return self.xcvr_info
return xcvr_info

def get_transceiver_bulk_status(self):
"""
Expand Down
27 changes: 15 additions & 12 deletions sonic_platform_base/sonic_xcvr/api/public/cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,7 @@ class VdmSubtypeIndex(Enum):
"Errored Frames Current Value Host Input" : "errored_frames_curr_host_input"
}

class CmisApi(XcvrApi):
NUM_CHANNELS = 8
LowPwrRequestSW = 4
LowPwrAllowRequestHW = 6

cmis_xcvr_info_dict = {
CMIS_XCVR_INFO_DEFAULT_DICT = {
"type": "N/A",
"type_abbrv_name": "N/A",
"hardware_rev": "N/A",
Expand Down Expand Up @@ -114,6 +109,11 @@ class CmisApi(XcvrApi):
"vdm_supported": "N/A"
}

class CmisApi(XcvrApi):
NUM_CHANNELS = 8
LowPwrRequestSW = 4
LowPwrAllowRequestHW = 6

def __init__(self, xcvr_eeprom):
super(CmisApi, self).__init__(xcvr_eeprom)
self.vdm = CmisVdmApi(xcvr_eeprom) if not self.is_flat_memory() else None
Expand Down Expand Up @@ -291,6 +291,9 @@ def get_module_inactive_firmware(self):
inactive_fw = [str(num) for num in [inactive_fw_major, inactive_fw_minor]]
return '.'.join(inactive_fw)

def _get_xcvr_info_default_dict(self):
return CMIS_XCVR_INFO_DEFAULT_DICT

def get_transceiver_info(self):
admin_info = self.xcvr_eeprom.read(consts.ADMIN_INFO_FIELD)
if admin_info is None:
Expand All @@ -299,8 +302,8 @@ def get_transceiver_info(self):
ext_id = admin_info[consts.EXT_ID_FIELD]
power_class = ext_id[consts.POWER_CLASS_FIELD]
max_power = ext_id[consts.MAX_POWER_FIELD]
self.xcvr_info = copy.deepcopy(CmisApi.cmis_xcvr_info_dict)
self.xcvr_info.update({
xcvr_info = copy.deepcopy(self._get_xcvr_info_default_dict())
xcvr_info.update({
"type": admin_info[consts.ID_FIELD],
"type_abbrv_name": admin_info[consts.ID_ABBRV_FIELD],
"hardware_rev": self.get_module_hardware_revision(),
Expand Down Expand Up @@ -328,18 +331,18 @@ def get_transceiver_info(self):
})
apsel_dict = self.get_active_apsel_hostlane()
for lane in range(1, self.NUM_CHANNELS + 1):
self.xcvr_info["%s%d" % ("active_apsel_hostlane", lane)] = \
xcvr_info["%s%d" % ("active_apsel_hostlane", lane)] = \
apsel_dict["%s%d" % (consts.ACTIVE_APSEL_HOSTLANE, lane)]

# In normal case will get a valid value for each of the fields. If get a 'None' value
# means there was a failure while reading the EEPROM, either because the EEPROM was
# not ready yet or experincing some other issues. It shouldn't return a dict with a
# not ready yet or experiencing some other issues. It shouldn't return a dict with a
# wrong field value, instead should return a 'None' to indicate to XCVRD that retry is
# needed.
if None in self.xcvr_info.values():
if None in xcvr_info.values():
return None
else:
return self.xcvr_info
return xcvr_info

def get_transceiver_info_firmware_versions(self):
return_dict = {"active_firmware" : "N/A", "inactive_firmware" : "N/A"}
Expand Down
65 changes: 61 additions & 4 deletions tests/sonic_xcvr/test_ccmis.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from mock import MagicMock
from mock import patch
import pytest
from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi
from sonic_platform_base.sonic_xcvr.api.public.c_cmis import CCmisApi, C_CMIS_XCVR_INFO_DEFAULT_DICT
from sonic_platform_base.sonic_xcvr.mem_maps.public.c_cmis import CCmisMemMap
from sonic_platform_base.sonic_xcvr.xcvr_eeprom import XcvrEeprom
from sonic_platform_base.sonic_xcvr.codes.public.cmis import CmisCodes
Expand Down Expand Up @@ -161,14 +161,68 @@ def test_get_pm_all(self, mock_response, expected):
@pytest.mark.parametrize("mock_response, expected",[
(
(
{
'type': 'QSFP-DD Double Density 8X Pluggable Transceiver'
{ # EEPROM DATA
'type': 'QSFP-DD Double Density 8X Pluggable Transceiver',
'type_abbrv_name': 'QSFP-DD',
'model': 'ABCD',
'encoding': 'N/A',
'ext_identifier': 'Power Class 8 (20.0W Max)',
'ext_rateselect_compliance': 'N/A',
'cable_type': 'Length Cable Assembly(m)',
'cable_length': 0.0,
'nominal_bit_rate': 'N/A',
'specification_compliance': 'sm_media_interface',
'application_advertisement': 'N/A',
'media_lane_count': 1,
'vendor_rev': '0.0',
'host_electrical_interface': '400GAUI-8 C2M (Annex 120E)',
'vendor_oui': 'xx-xx-xx',
'manufacturer': 'VENDOR_NAME',
'media_interface_technology': '1550 nm DFB',
'media_interface_code': '400ZR, DWDM, amplified',
'serial': '00000000',
'host_lane_count': 8,
**{f'active_apsel_hostlane{i}': 1 for i in range(1, 9)},
'hardware_rev': '0.0',
'cmis_rev': '5.0',
'media_lane_assignment_option': 1,
'connector': 'LC',
'host_lane_assignment_option': 1,
'vendor_date': '21010100',
'vdm_supported': True,
},
(-20, 0),
(0xff, -72, 120, 191300, 196100)
),
{
{ # Expected Result
'type': 'QSFP-DD Double Density 8X Pluggable Transceiver',
'type_abbrv_name': 'QSFP-DD',
'model': 'ABCD',
'encoding': 'N/A',
'ext_identifier': 'Power Class 8 (20.0W Max)',
'ext_rateselect_compliance': 'N/A',
'cable_type': 'Length Cable Assembly(m)',
'cable_length': 0.0,
'nominal_bit_rate': 'N/A',
'specification_compliance': 'sm_media_interface',
'application_advertisement': 'N/A',
'media_lane_count': 1,
'vendor_rev': '0.0',
'host_electrical_interface': '400GAUI-8 C2M (Annex 120E)',
'vendor_oui': 'xx-xx-xx',
'manufacturer': 'VENDOR_NAME',
'media_interface_technology': '1550 nm DFB',
'media_interface_code': '400ZR, DWDM, amplified',
'serial': '00000000',
'host_lane_count': 8,
**{f'active_apsel_hostlane{i}': 1 for i in range(1, 9)},
'hardware_rev': '0.0',
'cmis_rev': '5.0',
'media_lane_assignment_option': 1,
'connector': 'LC',
'host_lane_assignment_option': 1,
'vendor_date': '21010100',
'vdm_supported': True,
'supported_min_laser_freq': 191300,
'supported_max_laser_freq': 196100,
'supported_max_tx_power': 0,
Expand All @@ -189,6 +243,9 @@ def test_get_transceiver_info(self, get_transceiver_info_func, mock_response, ex
result = self.api.get_transceiver_info()
assert result == expected

# Test result is same as default dictionary length
assert len(C_CMIS_XCVR_INFO_DEFAULT_DICT) == len(result)


@pytest.mark.parametrize("mock_response, expected",[
(
Expand Down
7 changes: 6 additions & 1 deletion tests/sonic_xcvr/test_cmis.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import pytest
import traceback
import random
from sonic_platform_base.sonic_xcvr.api.public.cmis import CmisApi, CMIS_VDM_KEY_TO_DB_PREFIX_KEY_MAP, THRESHOLD_TYPE_STR_MAP, FLAG_TYPE_STR_MAP
from sonic_platform_base.sonic_xcvr.api.public.cmis import CmisApi, CMIS_VDM_KEY_TO_DB_PREFIX_KEY_MAP, THRESHOLD_TYPE_STR_MAP
from sonic_platform_base.sonic_xcvr.api.public.cmis import FLAG_TYPE_STR_MAP, CMIS_XCVR_INFO_DEFAULT_DICT
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.cmis import CmisCodes
Expand Down Expand Up @@ -1522,6 +1523,10 @@ def test_get_transceiver_info(self, mock_response, expected):
result = self.api.get_transceiver_info()
assert result == expected

if result is not None:
# Test result is same as default dictionary length
assert len(CMIS_XCVR_INFO_DEFAULT_DICT) == len(result)

# Test negative path
self.api.get_cmis_rev.return_value = None
result = self.api.get_transceiver_info()
Expand Down

0 comments on commit c6fa955

Please sign in to comment.