Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Platform/Seastone2] add optoe based sfp implementation #11756

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"port_num": 33,
"sfp_api": "sfp_optoe",
"eeprom_path": "/sys/bus/i2c/devices/i2c-{0}/{0}-0050/eeprom",
"port_i2c_mapping": [
2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,17 @@ def __initialize_fan(self):

def __initialize_sfp(self):
from sonic_platform.sfp import Sfp
from sonic_platform.sfp_optoe import SfpOptoe

sfp_config_path = self._api_common.get_config_path(self.SFP_CONFIG)
sfp_config = self._api_common.load_json_file(sfp_config_path)

sfp_index = 0
for index in range(0, sfp_config['port_num']):
sfp = Sfp(sfp_index, conf=sfp_config)
if sfp_config['sfp_api'] == "sfp_optoe":
sfp = SfpOptoe(sfp_index, conf=sfp_config)
else:
sfp = Sfp(sfp_index, conf=sfp_config)
self._sfp_list.append(sfp)
sfp_index += 1
self.sfp_module_initialized = True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ def get_transceiver_info(self):
sfp_interface_bulk_raw[start: end], 0)

transceiver_info_dict['type'] = sfp_interface_bulk_data['data']['type']['value']
transceiver_info_dict['type_abbrv_name'] = sfp_interface_bulk_data['data']['type_abbrv_name']['value']
transceiver_info_dict['manufacturer'] = sfp_vendor_name_data['data']['Vendor Name']['value']
transceiver_info_dict['model'] = sfp_vendor_pn_data['data']['Vendor PN']['value']
transceiver_info_dict['vendor_rev'] = sfp_vendor_rev_data['data']['Vendor Rev']['value']
Expand Down Expand Up @@ -2035,3 +2036,6 @@ def set_power_override(self, power_override, power_set):
return True

return False

def read_eeprom(self, offset, num_bytes):
return self._read_eeprom_specific_bytes(offset, num_bytes)
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#!/usr/bin/env python

#############################################################################
# Celestica
#
# Module contains an implementation of SONiC Platform Base API and
# provides the sfp status which are available in the platform
#
#############################################################################

import time

try:
from sonic_platform_base.sonic_xcvr.sfp_optoe_base import SfpOptoeBase
#from sonic_platform_base.sfp_base import SfpBase
from sonic_platform_base.sonic_sfp.sfputilhelper import SfpUtilHelper
from .common import Common
except ImportError as e:
raise ImportError(str(e) + "- required module not found")


class SfpOptoe(SfpOptoeBase):
"""Platform-specific SfpOptoe class"""

def __init__(self, sfp_index=0, conf=None):
SfpOptoeBase.__init__(self)

self._sfp_index = sfp_index
self._config = conf
self._sfp_type = None
self._api_common = Common(self._config)
self._read_porttab_mappings()

@property
def sfp_type(self):
if self._sfp_type is None:
self._sfp_type = self._detect_sfp_type()
return self._sfp_type

def _detect_sfp_type(self):
sfp_type = 'N/A'
info = self.get_transceiver_info()
if info:
sfp_type = info.get("type_abbrv_name")
# XXX: Need this hack until xcvrd is refactored
if sfp_type in ["OSFP-8X", "QSFP-DD"]:
sfp_type = "QSFP_DD"
return sfp_type

def _read_porttab_mappings(self):
self._sfputil_helper = SfpUtilHelper()
self._sfputil_helper.read_porttab_mappings(
self._get_path_to_port_config_file())

def _get_path_to_port_config_file(self):
host_platform_root_path = '/usr/share/sonic/device'
docker_hwsku_path = '/usr/share/sonic/hwsku'

host_platform_path = "/".join([host_platform_root_path,
self._api_common.platform])
hwsku_path = "/".join([host_platform_path, self._api_common.hwsku]
) if self._api_common.is_host() else docker_hwsku_path

return "/".join([hwsku_path, "port_config.ini"])

def get_eeprom_path(self):
eeprom_path = self._config['eeprom_path']
port_to_i2c_mapping = self._config['port_i2c_mapping']
port_eeprom_path = eeprom_path.format(
port_to_i2c_mapping[self._sfp_index])

return port_eeprom_path

def get_name(self):
"""
Retrieves the human-readable name of a sfp by 1-based index

Returns:
:param index: An integer, 1-based index of the sfp of which to query status
:return: String,
A string representing the name of the sfp.
"""
return self._sfputil_helper.physical_to_logical[self._sfp_index + 1] or "Unknown"

def get_presence(self):
"""
Retrieves the presence of the device
Returns:
bool: True if device is present, False if not
"""
return self._api_common.get_output(self._sfp_index, self._config['get_presence'], False)

def get_position_in_parent(self):
return self._sfp_index

def is_replaceable(self):
return True

def get_status(self):
"""
Retrieves the operational status of the device

Returns:
A boolean value, True if device is operating properly, False if not
"""
if not self.get_presence():
return False
reset = self.get_reset_status()
if reset:
status = False
else:
status = True
return status

def get_reset_status(self):
"""
Retrieves the reset status of SFP
Returns:
A Boolean, True if reset enabled, False if disabled
"""
return self._api_common.get_output(self._sfp_index, self._config['get_reset_status'], False)

def get_lpmode(self):
"""
Retrieves the lpmode (low power mode) status of this SFP
Returns:
A Boolean, True if lpmode is enabled, False if disabled
"""
return self._api_common.get_output(self._sfp_index, self._config['get_lpmode'], False)

def reset(self):
"""
Reset SFP and return all user module settings to their default srate.

Returns:
A boolean, True if successful, False if not
"""
config = self._config['reset']
# Convert our register value back to a hex string and write back
output1 = self._api_common.set_output(self._sfp_index, "0x0", config)

# Sleep 1 second to allow it to settle
time.sleep(1)
# Flip the bit back high and write back to the register to take port out of reset
output2 = self._api_common.set_output(self._sfp_index, "0x1", config)

return True if (output1 and output2) else False

def set_lpmode(self, lpmode):
"""
Sets the lpmode (low power mode) of SFP

Args:
lpmode: A Boolean, True to enable lpmode, False to disable it
Note : lpmode can be overridden by set_power_override

Returns:
A boolean, True if lpmode is set successfully, False if not
"""
return self._api_common.set_output(self._sfp_index, str(lpmode), self._config['set_lpmode'])

def get_error_description(self):
"""
Retrives the error descriptions of the SFP module

Returns:
String that represents the current error descriptions of vendor specific errors
In case there are multiple errors, they should be joined by '|',
like: "Bad EEPROM|Unsupported cable"
"""
if not self.get_presence():
return self.SFP_STATUS_UNPLUGGED
return self.SFP_STATUS_OK