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

[device/celestica]: Add QSFP-DD DOM parser into sfputil of silverstone #89

Merged
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
220 changes: 218 additions & 2 deletions device/celestica/x86_64-cel_silverstone-r0/plugins/sfputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,175 @@

try:
import time
from sonic_sfp.sfputilbase import SfpUtilBase
from sonic_platform_base.sonic_sfp.sfputilbase import SfpUtilBase
from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId, sff8472Dom
from sonic_platform_base.sonic_sfp.sff8436 import sff8436InterfaceId, sff8436Dom
from sonic_platform_base.sonic_sfp.inf8628 import inf8628InterfaceId
from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_InterfaceId, qsfp_dd_Dom
from sonic_platform_base.sonic_sfp.sffbase import sffbase
except ImportError as e:
raise ImportError("%s - required module not found" % str(e))


class QSFPDDDomPaser(qsfp_dd_Dom):

def __init__(self, eeprom_raw_data):

start_pos = 0
dom_offset = 256

dom_module_monitor_values = {
'Temperature':
{'offset': 14,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_temperature}},
'Vcc':
{'offset': 16,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_voltage}}
}

dom_channel_monitor_params = {
'RX8Power':
{'offset': 72 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_rx_power}},
'RX7Power':
{'offset': 70 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_rx_power}},
'RX6Power':
{'offset': 68 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_rx_power}},
'RX5Power':
{'offset': 66 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_rx_power}},
'RX4Power':
{'offset': 64 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_rx_power}},
'RX3Power':
{'offset': 62 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_rx_power}},
'RX2Power':
{'offset': 60 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_rx_power}},
'RX1Power':
{'offset': 58 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_rx_power}},
'TX8Bias':
{'offset': 56 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_bias}},
'TX7Bias':
{'offset': 54 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_bias}},
'TX6Bias':
{'offset': 52 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_bias}},
'TX5Bias':
{'offset': 50 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_bias}},
'TX4Bias':
{'offset': 48 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_bias}},
'TX3Bias':
{'offset': 46 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_bias}},
'TX2Bias':
{'offset': 44 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_bias}},
'TX1Bias':
{'offset': 42 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_bias}},
'TX8Power':
{'offset': 40 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_tx_power}},
'TX7Power':
{'offset': 38 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_tx_power}},
'TX6Power':
{'offset': 36 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_tx_power}},
'TX5Power':
{'offset': 34 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_tx_power}},
'TX4Power':
{'offset': 32 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_tx_power}},
'TX3Power':
{'offset': 30 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_tx_power}},
'TX2Power':
{'offset': 28 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_tx_power}},
'TX1Power':
{'offset': 26 + dom_offset,
'size': 2,
'type': 'func',
'decode': {'func': qsfp_dd_Dom.calc_tx_power}}
}

dom_map = {
'ModuleMonitorValues':
{'type': 'nested',
'decode': dom_module_monitor_values},
'ChannelMonitorValues':
{'type': 'nested',
'decode': dom_channel_monitor_params}
}

self.dom_data = sffbase.parse(
self, dom_map, eeprom_raw_data, start_pos)

def get_data_pretty(self):
return sffbase.get_data_pretty(self, self.dom_data)


class SfpUtil(SfpUtilBase):
"""Platform-specific SfpUtil class"""

Expand All @@ -22,6 +186,7 @@ class SfpUtil(SfpUtilBase):

EEPROM_OFFSET = 9
PORT_INFO_PATH = '/sys/class/silverstone_fpga'
QSFP_DD_DOM_OFFSET = 2304

_port_name = ""
_port_to_eeprom_mapping = {}
Expand Down Expand Up @@ -61,7 +226,7 @@ def get_port_name(self, port_num):
def get_eeprom_dom_raw(self, port_num):
if port_num in self.osfp_ports:
# QSFP DOM EEPROM is also at addr 0x50 and thus also stored in eeprom_ifraw
return None
return self._read_eeprom_devid(port_num, self.IDENTITY_EEPROM_ADDR, self.QSFP_DD_DOM_OFFSET, 128)
else:
# Read dom eeprom at addr 0x51
return self._read_eeprom_devid(port_num, self.DOM_EEPROM_ADDR, 256)
Expand Down Expand Up @@ -184,3 +349,54 @@ def get_transceiver_change_event(self, timeout=0):
TBD
"""
raise NotImplementedError

def get_qsfp_data(self, eeprom_ifraw):
sfp_data = {}
sfpi_obj = sff8436InterfaceId(eeprom_ifraw)
sfpd_obj = sff8436Dom(eeprom_ifraw) if sfpi_obj else {}

sfp_data['interface'] = sfpi_obj.get_data_pretty() if sfpi_obj else {}
sfp_data['dom'] = sfpd_obj.get_data_pretty() if sfpd_obj else {}
return sfp_data

def get_eeprom_dict(self, port_num):
"""Returns dictionary of interface and dom data.
format: {<port_num> : {'interface': {'version' : '1.0', 'data' : {...}},
'dom' : {'version' : '1.0', 'data' : {...}}}}
"""

sfp_data = {}

eeprom_ifraw = self.get_eeprom_raw(port_num)
eeprom_domraw = self.get_eeprom_dom_raw(port_num)

if eeprom_ifraw is None:
return None

if port_num in self.osfp_ports:
sfpi_obj = inf8628InterfaceId(eeprom_ifraw)
if sfpi_obj:
sfp_data['interface'] = sfpi_obj.get_data_pretty()

# check if it is a 100G module
if sfp_data['interface']['data']['Identifier'] == 'QSFP28 or later':
return self.get_qsfp_data(eeprom_ifraw)

sfpd_obj = QSFPDDDomPaser(
eeprom_ifraw + eeprom_domraw) if eeprom_domraw else None
sfp_data['dom'] = sfpd_obj.get_data_pretty() if sfpd_obj else {}

return sfp_data
else:
sfpi_obj = sff8472InterfaceId(eeprom_ifraw)
if sfpi_obj is not None:
sfp_data['interface'] = sfpi_obj.get_data_pretty()
cal_type = sfpi_obj.get_calibration_type()

if eeprom_domraw is not None:
sfpd_obj = sff8472Dom(eeprom_domraw, cal_type)
if sfpd_obj is not None:
sfp_data['dom'] = sfpd_obj.get_data_pretty()

return sfp_data
return