DellEMC: Z9332f SFP enhancements (#7457)

#### Why I did it
400G media EEPROM and DOM information are not populated properly in DellEMC Z9332f platform.

#### How I did it
Handled QSFP_DD, QSFP28/QSFP+, SFP+ accordingly based on media type detected.
This commit is contained in:
Aravind Mani 2021-05-05 10:03:11 -07:00 committed by GitHub
parent a2d33a2a37
commit 659d078fd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 452 additions and 141 deletions

View File

@ -121,7 +121,7 @@ class Chassis(ChassisBase):
eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom" eeprom_base = "/sys/class/i2c-adapter/i2c-{0}/{0}-0050/eeprom"
for index in range(self.PORT_START, self.PORTS_IN_BLOCK): for index in range(self.PORT_START, self.PORTS_IN_BLOCK):
eeprom_path = eeprom_base.format(self._port_to_i2c_mapping[index]) eeprom_path = eeprom_base.format(self._port_to_i2c_mapping[index])
port_type = 'SFP' if index in _sfp_port else 'QSFP' port_type = 'SFP' if index in _sfp_port else 'QSFP_DD'
sfp_node = Sfp(index, port_type, eeprom_path) sfp_node = Sfp(index, port_type, eeprom_path)
self._sfp_list.append(sfp_node) self._sfp_list.append(sfp_node)

View File

@ -21,23 +21,45 @@ try:
from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId from sonic_platform_base.sonic_sfp.sff8472 import sff8472InterfaceId
from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom from sonic_platform_base.sonic_sfp.sff8472 import sff8472Dom
from sonic_platform_base.sonic_sfp.sff8472 import sffbase from sonic_platform_base.sonic_sfp.sff8472 import sffbase
from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_InterfaceId
from sonic_platform_base.sonic_sfp.sff8024 import type_of_media_interface
from sonic_platform_base.sonic_sfp.qsfp_dd import qsfp_dd_Dom
except ImportError as e: except ImportError as e:
raise ImportError(str(e) + "- required module not found") raise ImportError(str(e) + "- required module not found")
# Enabled when ext_media is available
#ext_media_module = None
#try:
# import ext_media_api as ext_media_module
#except :
# ext_media_module = None
# pass
PAGE_OFFSET = 0 PAGE_OFFSET = 0
KEY_OFFSET = 1 KEY_OFFSET = 1
KEY_WIDTH = 2 KEY_WIDTH = 2
FUNC_NAME = 3 FUNC_NAME = 3
QSFP_DD_PAGE0 = 0
QSFP_DD_PAGE1 = 128
QSFP_DD_PAGE2 = 256
QSFP_DD_PAGE3 = 384
QSFP_DD_DOM_CAPABILITY_OFFSET = 2
QSFP_DD_DOM_CAPABILITY_WIDTH = 1
QSFP_DD_TEMP_OFFSET = 14
QSFP_DD_TEMP_WIDTH = 2
QSFP_DD_VOLT_OFFSET = 16
QSFP_DD_VOLT_WIDTH = 2
QSFP_DD_TXBIAS_OFFSET = 26
QSFP_DD_TXBIAS_WIDTH = 16
QSFP_DD_TXPOWER_OFFSET = 42
QSFP_DD_TXPOWER_WIDTH = 16
QSFP_DD_RXPOWER_WIDTH = 58
QSFP_DD_RXPOWER_OFFSET = 16
QSFP_DD_RXLOS_OFFSET = 19
QSFP_DD_RXLOS_WIDTH = 1
QSFP_DD_TX_DISABLE_OFFSET = 86
QSFP_DD_TX_DISABLE_WIDTH = 1
QSFP_DD_MEDIA_TYPE_OFFSET = 85
QSFP_DD_MEDIA_TYPE_WIDTH = 1
QSFP_DD_APP1_ADV_OFFSET = 86
QSFP_DD_APP1_ADV_WIDTH = 32
QSFP_DD_APP2_ADV_OFFSET = 351
QSFP_DD_APP2_ADV_WIDTH = 28
QSFP_INFO_OFFSET = 128 QSFP_INFO_OFFSET = 128
QSFP_DOM_OFFSET = 0 QSFP_DOM_OFFSET = 0
QSFP_DOM_OFFSET1 = 384 QSFP_DOM_OFFSET1 = 384
@ -83,9 +105,13 @@ dom_dict_keys = ['rx_los', 'tx_fault', 'reset_status',
'power_lpmode', 'tx_disable', 'tx_disable_channel', 'power_lpmode', 'tx_disable', 'tx_disable_channel',
'temperature', 'voltage', 'rx1power', 'temperature', 'voltage', 'rx1power',
'rx2power', 'rx3power', 'rx4power', 'rx2power', 'rx3power', 'rx4power',
'tx1bias', 'tx2bias', 'tx3bias', 'rx5power', 'rx6power', 'rx7power',
'tx4bias', 'tx1power', 'tx2power', 'rx8power', 'tx1bias', 'tx2bias',
'tx3power', 'tx4power'] 'tx3bias', 'tx4bias', 'tx5bias',
'tx6bias', 'tx7bias', 'tx8bias',
'tx1power', 'tx2power', 'tx3power',
'tx4power', 'tx5power', 'tx6power',
'tx7power', 'tx8power']
threshold_dict_keys = ['temphighalarm', 'temphighwarning', threshold_dict_keys = ['temphighalarm', 'temphighwarning',
'templowalarm', 'templowwarning', 'templowalarm', 'templowwarning',
@ -97,6 +123,22 @@ threshold_dict_keys = ['temphighalarm', 'temphighwarning',
'txpowerlowalarm', 'txpowerlowwarning', 'txpowerlowalarm', 'txpowerlowwarning',
'txbiashighalarm', 'txbiashighwarning', 'txbiashighalarm', 'txbiashighwarning',
'txbiaslowalarm', 'txbiaslowwarning'] 'txbiaslowalarm', 'txbiaslowwarning']
qsfp_dd_parser = {
'ChannelThreshold': [QSFP_DD_PAGE3, 0, 72, 'parse_module_threshold_values'],
'cable_length': [QSFP_DD_PAGE1, 74, 1, 'parse_cable_len'],
'connector': [QSFP_DD_PAGE1, 75, 1, 'parse_connector'],
'type': [QSFP_DD_PAGE1, 0, 1, 'parse_sfp_type'],
'ext_identifier': [QSFP_DD_PAGE1, 72, 2, 'parse_ext_iden'],
'type_abbrv_name': [QSFP_DD_PAGE1, 0, 21, 'parse_sfp_type_abbrv_name'],
'manufacturer': [QSFP_DD_PAGE1, 1, 16, 'parse_vendor_name'],
'vendor_oui': [QSFP_DD_PAGE1, 17, 3, 'parse_vendor_oui'],
'model': [QSFP_DD_PAGE1, 20, 16, 'parse_vendor_pn'],
'hardware_rev': [QSFP_DD_PAGE1, 36, 2, 'parse_vendor_rev'],
'serial': [QSFP_DD_PAGE1, 38, 16, 'parse_vendor_sn'],
'vendor_date': [QSFP_DD_PAGE1, 54, 8, 'parse_vendor_date'],
'ModuleThreshold': [QSFP_DD_PAGE3, 0, 72, 'parse_module_threshold_values'],
'dom_capability': [QSFP_DD_PAGE0, 2 , 1, 'parse_dom_capability'],
}
sff8436_parser = { sff8436_parser = {
'reset_status': [QSFP_DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'], 'reset_status': [QSFP_DOM_OFFSET, 2, 1, 'parse_dom_status_indicator'],
@ -108,9 +150,8 @@ sff8436_parser = {
'Temperature': [QSFP_DOM_OFFSET, 22, 2, 'parse_temperature'], 'Temperature': [QSFP_DOM_OFFSET, 22, 2, 'parse_temperature'],
'Voltage': [QSFP_DOM_OFFSET, 26, 2, 'parse_voltage'], 'Voltage': [QSFP_DOM_OFFSET, 26, 2, 'parse_voltage'],
'ChannelMonitor': [QSFP_DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'], 'ChannelMonitor': [QSFP_DOM_OFFSET, 34, 16, 'parse_channel_monitor_params'],
'ChannelMonitor_TxPower': 'ChannelMonitor_TxPower':
[QSFP_DOM_OFFSET, 34, 24, 'parse_channel_monitor_params_with_tx_power'], [QSFP_DOM_OFFSET, 34, 24, 'parse_channel_monitor_params_with_tx_power'],
'cable_type': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], 'cable_type': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'],
'cable_length': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'], 'cable_length': [QSFP_INFO_OFFSET, -1, -1, 'parse_sfp_info_bulk'],
'connector': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'], 'connector': [QSFP_INFO_OFFSET, 0, 20, 'parse_sfp_info_bulk'],
@ -172,7 +213,7 @@ QSFP_TYPE_LIST = [
'11' # QSFP28 or later '11' # QSFP28 or later
] ]
QSFP_DD_TYPE_LIST = [ QSFP_DD_TYPE_LIST = [
'18' #QSFP-DD Type '18' #QSFP_DD Type
] ]
OSFP_TYPE_LIST=[ OSFP_TYPE_LIST=[
'19' # OSFP 8X Type '19' # OSFP 8X Type
@ -226,25 +267,50 @@ class Sfp(SfpBase):
SfpBase.__init__(self) SfpBase.__init__(self)
self.index = index self.index = index
self.eeprom_path = eeprom_path self.eeprom_path = eeprom_path
#sfp_type is the native port type and media_type is the transceiver type #port_type is the native port type and sfp_type is the transceiver type
#media_type will be detected in get_transceiver_info #sfp_type will be detected in get_transceiver_info
self.sfp_type = sfp_type self.port_type = sfp_type
self.media_type = self.sfp_type self.sfp_type = self.port_type
self.qsfpInfo = sff8436InterfaceId() self.qsfpInfo = sff8436InterfaceId()
self.qsfpDomInfo = sff8436Dom() self.qsfpDomInfo = sff8436Dom()
self.sfpInfo = sff8472InterfaceId() self.sfpInfo = sff8472InterfaceId()
self.sfpDomInfo = sff8472Dom(None,1) self.sfpDomInfo = sff8472Dom(None,1)
self.qsfp_dd_Info = qsfp_dd_InterfaceId()
self.qsfp_dd_DomInfo = qsfp_dd_Dom()
def get_eeprom_sysfs_path(self): def get_eeprom_sysfs_path(self):
return self.eeprom_path return self.eeprom_path
def detect_dom_capability(self):
if self.sfp_type == 'QSFP_DD':
offset = 0
qsfp_dom_capability_raw = self._read_eeprom_bytes(
self.eeprom_path, offset + QSFP_DD_DOM_CAPABILITY_OFFSET, QSFP_DD_DOM_CAPABILITY_WIDTH)
if qsfp_dom_capability_raw is not None:
if self.qsfp_dd_Info is None:
return None
dom_capability = self.qsfp_dd_Info.parse_dom_capability(qsfp_dom_capability_raw, 0)
if dom_capability['data']['Flat_MEM']['value'] == 'Off':
self.qsfp_dd_app2_list = True
self.dom_rx_power_supported = True
self.dom_tx_power_supported = True
self.dom_tx_bias_supported = True
else:
self.qsfp_dd_app2_list = False
self.dom_rx_power_supported = False
self.dom_tx_power_supported = False
self.dom_tx_bias_supported = False
else:
self.dom_rx_power_supported = False
self.dom_tx_power_supported = False
self.dom_tx_bias_supported = False
def _strip_unit_from_str(self, value_str): def _strip_unit_from_str(self, value_str):
match = re.match(r'(.*)C$|(.*)Volts$|(.*)mA$|(.*)dBm$', value_str) match = re.match(r'(.*)C$|(.*)Volts$|(.*)mA$|(.*)dBm$', value_str)
if match: if match:
for value in match.groups(): for value in match.groups():
if value is not None: if value is not None:
return float(value) return float(value)
return None return None
def pci_mem_read(self, mm, offset): def pci_mem_read(self, mm, offset):
@ -312,24 +378,46 @@ class Sfp(SfpBase):
eeprom_data = None eeprom_data = None
page_offset = None page_offset = None
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP_DD':
page_offset = qsfp_dd_parser[eeprom_key][PAGE_OFFSET]
eeprom_data_raw = self._read_eeprom_bytes(
self.eeprom_path,
(qsfp_dd_parser[eeprom_key][PAGE_OFFSET] +
qsfp_dd_parser[eeprom_key][KEY_OFFSET]),
qsfp_dd_parser[eeprom_key][KEY_WIDTH])
if eeprom_data_raw is not None:
# Offset 128 is used to retrieve qsfpDD_InterfaceId Info
# Offset 0 is used to retrieve QsfpDD_Dom Info
if page_offset <= 128:
if self.qsfp_dd_Info is None:
return None
eeprom_data = getattr(
self.qsfp_dd_Info, qsfp_dd_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0)
else:
if self.qsfp_dd_DomInfo is None:
return None
eeprom_data = getattr(
self.qsfp_dd_DomInfo, qsfp_dd_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0)
elif self.sfp_type == 'QSFP':
page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET] page_offset = sff8436_parser[eeprom_key][PAGE_OFFSET]
eeprom_data_raw = self._read_eeprom_bytes( eeprom_data_raw = self._read_eeprom_bytes(
self.eeprom_path, self.eeprom_path,
(sff8436_parser[eeprom_key][PAGE_OFFSET] + (sff8436_parser[eeprom_key][PAGE_OFFSET] +
sff8436_parser[eeprom_key][KEY_OFFSET]), sff8436_parser[eeprom_key][KEY_OFFSET]),
sff8436_parser[eeprom_key][KEY_WIDTH]) sff8436_parser[eeprom_key][KEY_WIDTH])
if (eeprom_data_raw is not None): if eeprom_data_raw is not None:
# Offset 128 is used to retrieve sff8436InterfaceId Info # Offset 128 is used to retrieve sff8436InterfaceId Info
# Offset 0 is used to retrieve sff8436Dom Info # Offset 0 is used to retrieve sff8436Dom Info
if (page_offset == 128): if page_offset == 128:
if ( self.qsfpInfo is None): if self.qsfpInfo is None:
return None return None
eeprom_data = getattr( eeprom_data = getattr(
self.qsfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])( self.qsfpInfo, sff8436_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0) eeprom_data_raw, 0)
else: else:
if ( self.qsfpDomInfo is None): if self.qsfpDomInfo is None:
return None return None
eeprom_data = getattr( eeprom_data = getattr(
self.qsfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])( self.qsfpDomInfo, sff8436_parser[eeprom_key][FUNC_NAME])(
@ -341,17 +429,17 @@ class Sfp(SfpBase):
(sff8472_parser[eeprom_key][PAGE_OFFSET] + (sff8472_parser[eeprom_key][PAGE_OFFSET] +
sff8472_parser[eeprom_key][KEY_OFFSET]), sff8472_parser[eeprom_key][KEY_OFFSET]),
sff8472_parser[eeprom_key][KEY_WIDTH]) sff8472_parser[eeprom_key][KEY_WIDTH])
if (eeprom_data_raw is not None): if eeprom_data_raw is not None:
# Offset 0 is used to retrieve sff8472InterfaceId Info # Offset 0 is used to retrieve sff8472InterfaceId Info
# Offset 256 is used to retrieve sff8472Dom Info # Offset 256 is used to retrieve sff8472Dom Info
if (page_offset == 0): if page_offset == 0:
if ( self.sfpInfo is None): if self.sfpInfo is None:
return None return None
eeprom_data = getattr( eeprom_data = getattr(
self.sfpInfo, sff8472_parser[eeprom_key][FUNC_NAME])( self.sfpInfo, sff8472_parser[eeprom_key][FUNC_NAME])(
eeprom_data_raw, 0) eeprom_data_raw, 0)
else: else:
if ( self.sfpDomInfo is None): if self.sfpDomInfo is None:
return None return None
eeprom_data = getattr( eeprom_data = getattr(
self.sfpDomInfo, sff8472_parser[eeprom_key][FUNC_NAME])( self.sfpDomInfo, sff8472_parser[eeprom_key][FUNC_NAME])(
@ -366,12 +454,17 @@ class Sfp(SfpBase):
transceiver_info_dict = {} transceiver_info_dict = {}
compliance_code_dict = {} compliance_code_dict = {}
transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A') transceiver_info_dict = dict.fromkeys(info_dict_keys, 'N/A')
self.media_type = self.set_media_type() if not self.get_presence():
if not self.reinit_sfp_driver():
return transceiver_info_dict return transceiver_info_dict
self.sfp_type = self.set_media_type()
if self.reinit_sfp_driver() is False:
return transceiver_info_dict
self.detect_dom_capability()
# BaseInformation # BaseInformation
try: if self.sfp_type != 'QSFP_DD':
iface_data = self._get_eeprom_data('type') iface_data = self._get_eeprom_data('type')
connector = iface_data['data']['Connector']['value'] connector = iface_data['data']['Connector']['value']
encoding = iface_data['data']['EncodingCodes']['value'] encoding = iface_data['data']['EncodingCodes']['value']
@ -379,9 +472,8 @@ class Sfp(SfpBase):
rate_identifier = iface_data['data']['RateIdentifier']['value'] rate_identifier = iface_data['data']['RateIdentifier']['value']
identifier = iface_data['data']['type']['value'] identifier = iface_data['data']['type']['value']
type_abbrv_name=iface_data['data']['type_abbrv_name']['value'] type_abbrv_name=iface_data['data']['type_abbrv_name']['value']
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP':
bit_rate = str( bit_rate = str(iface_data['data']['Nominal Bit Rate(100Mbs)']['value'])
iface_data['data']['Nominal Bit Rate(100Mbs)']['value'])
for key in qsfp_compliance_code_tup: for key in qsfp_compliance_code_tup:
if key in iface_data['data']['Specification compliance']['value']: if key in iface_data['data']['Specification compliance']['value']:
compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value'] compliance_code_dict[key] = iface_data['data']['Specification compliance']['value'][key]['value']
@ -400,7 +492,7 @@ class Sfp(SfpBase):
cable_type = key cable_type = key
cable_length = str(iface_data['data'][key]['value']) cable_length = str(iface_data['data'][key]['value'])
transceiver_info_dict['type_abbrv_name']=type_abbrv_name transceiver_info_dict['type_abbrv_name'] = type_abbrv_name
transceiver_info_dict['type'] = identifier transceiver_info_dict['type'] = identifier
transceiver_info_dict['connector'] = connector transceiver_info_dict['connector'] = connector
transceiver_info_dict['encoding'] = encoding transceiver_info_dict['encoding'] = encoding
@ -410,58 +502,135 @@ class Sfp(SfpBase):
transceiver_info_dict['cable_length'] = cable_length transceiver_info_dict['cable_length'] = cable_length
transceiver_info_dict['nominal_bit_rate'] = bit_rate transceiver_info_dict['nominal_bit_rate'] = bit_rate
transceiver_info_dict['specification_compliance'] = str(compliance_code_dict) transceiver_info_dict['specification_compliance'] = str(compliance_code_dict)
except (ValueError, TypeError) : pass
# Vendor Date
try:
vendor_date_data = self._get_eeprom_data('vendor_date') vendor_date_data = self._get_eeprom_data('vendor_date')
vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value'] if vendor_date_data is not None:
transceiver_info_dict['vendor_date'] = vendor_date vendor_date = vendor_date_data['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']
except (ValueError, TypeError) : pass transceiver_info_dict['vendor_date'] = vendor_date
# Vendor Name
try:
vendor_name_data = self._get_eeprom_data('manufacturer') vendor_name_data = self._get_eeprom_data('manufacturer')
vendor_name = vendor_name_data['data']['Vendor Name']['value'] if vendor_name_data is not None:
transceiver_info_dict['manufacturer'] = vendor_name vendor_name = vendor_name_data['data']['Vendor Name']['value']
except (ValueError, TypeError) : pass transceiver_info_dict['manufacturer'] = vendor_name
# Vendor OUI
try:
vendor_oui_data = self._get_eeprom_data('vendor_oui') vendor_oui_data = self._get_eeprom_data('vendor_oui')
vendor_oui = vendor_oui_data['data']['Vendor OUI']['value'] if vendor_oui_data is not None:
transceiver_info_dict['vendor_oui'] = vendor_oui vendor_oui = vendor_oui_data['data']['Vendor OUI']['value']
except (ValueError, TypeError) : pass transceiver_info_dict['vendor_oui'] = vendor_oui
# Vendor PN
try:
vendor_pn_data = self._get_eeprom_data('model') vendor_pn_data = self._get_eeprom_data('model')
vendor_pn = vendor_pn_data['data']['Vendor PN']['value'] if vendor_pn_data is not None:
transceiver_info_dict['model'] = vendor_pn vendor_pn = vendor_pn_data['data']['Vendor PN']['value']
except (ValueError, TypeError) : pass transceiver_info_dict['model'] = vendor_pn
# Vendor Revision
try:
vendor_rev_data = self._get_eeprom_data('hardware_rev') vendor_rev_data = self._get_eeprom_data('hardware_rev')
vendor_rev = vendor_rev_data['data']['Vendor Rev']['value'] if vendor_rev_data is not None:
transceiver_info_dict['hardware_rev'] = vendor_rev vendor_rev = vendor_rev_data['data']['Vendor Rev']['value']
except (ValueError, TypeError) : pass transceiver_info_dict['hardware_rev'] = vendor_rev
# Vendor Serial Number
try:
vendor_sn_data = self._get_eeprom_data('serial') vendor_sn_data = self._get_eeprom_data('serial')
vendor_sn = vendor_sn_data['data']['Vendor SN']['value'] if vendor_sn_data is not None:
transceiver_info_dict['serial'] = vendor_sn vendor_sn = vendor_sn_data['data']['Vendor SN']['value']
except (ValueError, TypeError) : pass transceiver_info_dict['serial'] = vendor_sn
# Attempt ext_media read else:
# if ext_media_module is not None: #QSFP_DD
# ext_media_dict = ext_media_module.get_ext_media_info(self) type_abbrv_name = self._get_eeprom_data('type_abbrv_name')
# for key in ext_media_dict: if type_abbrv_name is not None:
# value = ext_media_dict[key] transceiver_info_dict['type_abbrv_name'] = type_abbrv_name['data']['type_abbrv_name']['value']
# if value in [None, 'None', 'none','n/a', '']:
# value = 'N/A' identifier = self._get_eeprom_data('type')
# transceiver_info_dict[key] = str(value) if identifier is not None:
transceiver_info_dict['type'] = identifier['data']['type']['value']
connector = self._get_eeprom_data('connector')
if connector is not None:
transceiver_info_dict['connector'] = connector['data']['Connector']['value']
ext_id = self._get_eeprom_data('ext_identifier')
if ext_id is not None:
transceiver_info_dict['ext_identifier'] = ext_id['data']['Extended Identifier']['value']
cable_length = self._get_eeprom_data('cable_length')
if cable_length is not None:
#Since the cable length field can be returned as decimal and float in M,converting it to float as common type.
#If the currentreturn type persists, cable length has to defined twice for the same length(e.g. 1 and 1.0M)
transceiver_info_dict['cable_length'] = str(float(cable_length['data']['Length Cable Assembly(m)']['value']))
transceiver_info_dict['encoding'] = "Not supported"
transceiver_info_dict['nominal_bit_rate'] = "Not supported"
transceiver_info_dict['ext_rateselect_compliance'] = "Not supported"
eeprom_raw = []
eeprom_raw = self._read_eeprom_bytes(self.eeprom_path, QSFP_DD_MEDIA_TYPE_OFFSET,
QSFP_DD_MEDIA_TYPE_WIDTH)
if eeprom_raw is not None:
transceiver_info_dict['specification_compliance'] = type_of_media_interface[eeprom_raw[0]]
transceiver_info_dict['cable_type'] = "Length Cable Assembly(m)"
vendor_date = self._get_eeprom_data('vendor_date')
if vendor_date is not None:
transceiver_info_dict['vendor_date'] = vendor_date['data']['VendorDataCode(YYYY-MM-DD Lot)']['value']
vendor_name = self._get_eeprom_data('manufacturer')
if vendor_name is not None:
transceiver_info_dict['manufacturer'] = vendor_name['data']['Vendor Name']['value']
vendor_oui = self._get_eeprom_data('vendor_oui')
if vendor_oui is not None:
transceiver_info_dict['vendor_oui'] = vendor_oui['data']['Vendor OUI']['value']
vendor_pn = self._get_eeprom_data('model')
if vendor_pn is not None:
transceiver_info_dict['model'] = vendor_pn['data']['Vendor PN']['value']
vendor_rev = self._get_eeprom_data('hardware_rev')
if vendor_rev is not None:
transceiver_info_dict['hardware_rev'] = vendor_rev['data']['Vendor Rev']['value']
vendor_sn = self._get_eeprom_data('serial')
if vendor_sn is not None:
transceiver_info_dict['serial'] = vendor_sn['data']['Vendor SN']['value']
if self.qsfp_dd_Info is None:
return None
sfp_media_type_raw = self._read_eeprom_bytes(self.eeprom_path, QSFP_DD_MEDIA_TYPE_OFFSET,
QSFP_DD_MEDIA_TYPE_WIDTH)
if sfp_media_type_raw is not None:
sfp_media_type_dict = self.qsfp_dd_Info.parse_media_type(sfp_media_type_raw, 0)
if sfp_media_type_dict is None:
return None
host_media_list = ""
if self.qsfp_dd_Info is None:
return None
qsfp_dd_app1_list = self._read_eeprom_bytes(self.eeprom_path, QSFP_DD_APP1_ADV_OFFSET,
QSFP_DD_APP1_ADV_WIDTH)
if self.qsfp_dd_app2_list:
possible_application_count = 15
#Additional application advertisement
qsfp_dd_app2_list = self._read_eeprom_bytes(self.eeprom_path, QSFP_DD_APP2_ADV_OFFSET,
QSFP_DD_APP2_ADV_WIDTH)
if qsfp_dd_app1_list is not None and qsfp_dd_app2_list is not None:
sfp_application_type_list = qsfp_dd_app1_list + qsfp_dd_app2_list
else:
return None
else:
possible_application_count = 8
if qsfp_dd_app1_list is not None:
sfp_application_type_list = qsfp_dd_app1_list
else:
return None
for i in range(0, possible_application_count):
if sfp_application_type_list[i * 4] == 'ff':
break
host_electrical, media_interface = self.qsfp_dd_Info.parse_application(sfp_media_type_dict,
sfp_application_type_list[i * 4], sfp_application_type_list[i * 4 + 1])
host_media_list = host_media_list + host_electrical + ' - ' + media_interface
transceiver_info_dict['application_advertisement'] = host_media_list
return transceiver_info_dict return transceiver_info_dict
@ -474,9 +643,30 @@ class Sfp(SfpBase):
threshold_dict_keys, 'N/A') threshold_dict_keys, 'N/A')
try: try:
# Module Threshold if self.sfp_type == 'QSFP_DD':
module_threshold_data = self._get_eeprom_data('ModuleThreshold') module_threshold_data = self._get_eeprom_data('ModuleThreshold')
if self.media_type.startswith('QSFP'): transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value']
transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value']
transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value']
transceiver_dom_threshold_dict['templowwarning'] = module_threshold_data['data']['TempLowWarning']['value']
transceiver_dom_threshold_dict['vcchighalarm'] = module_threshold_data['data']['VccHighAlarm']['value']
transceiver_dom_threshold_dict['vcchighwarning'] = module_threshold_data['data']['VccHighWarning']['value']
transceiver_dom_threshold_dict['vcclowalarm'] = module_threshold_data['data']['VccLowAlarm']['value']
transceiver_dom_threshold_dict['vcclowwarning'] = module_threshold_data['data']['VccLowWarning']['value']
transceiver_dom_threshold_dict['rxpowerhighalarm'] = module_threshold_data['data']['RxPowerHighAlarm']['value']
transceiver_dom_threshold_dict['rxpowerhighwarning'] = module_threshold_data['data']['RxPowerHighWarning']['value']
transceiver_dom_threshold_dict['rxpowerlowalarm'] = module_threshold_data['data']['RxPowerLowAlarm']['value']
transceiver_dom_threshold_dict['rxpowerlowwarning'] = module_threshold_data['data']['RxPowerLowWarning']['value']
transceiver_dom_threshold_dict['txbiashighalarm'] = module_threshold_data['data']['TxBiasHighAlarm']['value']
transceiver_dom_threshold_dict['txbiashighwarning'] = module_threshold_data['data']['TxBiasHighWarning']['value']
transceiver_dom_threshold_dict['txbiaslowalarm'] = module_threshold_data['data']['TxBiasLowAlarm']['value']
transceiver_dom_threshold_dict['txbiaslowwarning'] = module_threshold_data['data']['TxBiasLowWarning']['value']
transceiver_dom_threshold_dict['txpowerhighalarm'] = module_threshold_data['data']['TxPowerHighAlarm']['value']
transceiver_dom_threshold_dict['txpowerhighwarning'] = module_threshold_data['data']['TxPowerHighWarning']['value']
transceiver_dom_threshold_dict['txpowerlowalarm'] = module_threshold_data['data']['TxPowerLowAlarm']['value']
transceiver_dom_threshold_dict['txpowerlowwarning'] = module_threshold_data['data']['TxPowerLowWarning']['value']
elif self.sfp_type == 'QSFP':
module_threshold_data = self._get_eeprom_data('ModuleThreshold')
transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value'] transceiver_dom_threshold_dict['temphighalarm'] = module_threshold_data['data']['TempHighAlarm']['value']
transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value'] transceiver_dom_threshold_dict['temphighwarning'] = module_threshold_data['data']['TempHighWarning']['value']
transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value'] transceiver_dom_threshold_dict['templowalarm'] = module_threshold_data['data']['TempLowAlarm']['value']
@ -509,7 +699,7 @@ class Sfp(SfpBase):
except (ValueError, TypeError) : pass except (ValueError, TypeError) : pass
try: try:
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP':
channel_threshold_data = self._get_eeprom_data('ChannelThreshold') channel_threshold_data = self._get_eeprom_data('ChannelThreshold')
transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['data']['RxPowerHighAlarm']['value'] transceiver_dom_threshold_dict['rxpowerhighalarm'] = channel_threshold_data['data']['RxPowerHighAlarm']['value']
transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['data']['RxPowerHighWarning']['value'] transceiver_dom_threshold_dict['rxpowerhighwarning'] = channel_threshold_data['data']['RxPowerHighWarning']['value']
@ -565,23 +755,58 @@ class Sfp(SfpBase):
# rx power # rx power
rx_power_list = self.get_rx_power() rx_power_list = self.get_rx_power()
if tx_bias_list is not None: if self.sfp_type == 'QSFP_DD':
transceiver_dom_dict['tx1bias'] = tx_bias_list[0] if tx_bias_list is not None:
transceiver_dom_dict['tx2bias'] = tx_bias_list[1] transceiver_dom_dict['tx1bias'] = tx_bias_list[0]
transceiver_dom_dict['tx3bias'] = tx_bias_list[2] transceiver_dom_dict['tx2bias'] = tx_bias_list[1]
transceiver_dom_dict['tx4bias'] = tx_bias_list[3] transceiver_dom_dict['tx3bias'] = tx_bias_list[2]
transceiver_dom_dict['tx4bias'] = tx_bias_list[3]
transceiver_dom_dict['tx5bias'] = tx_bias_list[4]
transceiver_dom_dict['tx6bias'] = tx_bias_list[5]
transceiver_dom_dict['tx7bias'] = tx_bias_list[6]
transceiver_dom_dict['tx8bias'] = tx_bias_list[7]
if rx_power_list is not None: else:
transceiver_dom_dict['rx1power'] = rx_power_list[0] if tx_bias_list is not None:
transceiver_dom_dict['rx2power'] = rx_power_list[1] transceiver_dom_dict['tx1bias'] = tx_bias_list[0]
transceiver_dom_dict['rx3power'] = rx_power_list[2] transceiver_dom_dict['tx2bias'] = tx_bias_list[1]
transceiver_dom_dict['rx4power'] = rx_power_list[3] transceiver_dom_dict['tx3bias'] = tx_bias_list[2]
transceiver_dom_dict['tx4bias'] = tx_bias_list[3]
if tx_power_list is not None: if self.sfp_type == 'QSFP_DD':
transceiver_dom_dict['tx1power'] = tx_power_list[0] if rx_power_list is not None:
transceiver_dom_dict['tx2power'] = tx_power_list[1] transceiver_dom_dict['rx1power'] = rx_power_list[0]
transceiver_dom_dict['tx3power'] = tx_power_list[2] transceiver_dom_dict['rx2power'] = rx_power_list[1]
transceiver_dom_dict['tx4power'] = tx_power_list[3] transceiver_dom_dict['rx3power'] = rx_power_list[2]
transceiver_dom_dict['rx4power'] = rx_power_list[3]
transceiver_dom_dict['rx5power'] = rx_power_list[4]
transceiver_dom_dict['rx6power'] = rx_power_list[5]
transceiver_dom_dict['rx7power'] = rx_power_list[6]
transceiver_dom_dict['rx8power'] = rx_power_list[7]
else:
if rx_power_list is not None:
transceiver_dom_dict['rx1power'] = rx_power_list[0]
transceiver_dom_dict['rx2power'] = rx_power_list[1]
transceiver_dom_dict['rx3power'] = rx_power_list[2]
transceiver_dom_dict['rx4power'] = rx_power_list[3]
if self.sfp_type == 'QSFP_DD':
if tx_power_list is not None:
transceiver_dom_dict['tx1power'] = tx_power_list[0]
transceiver_dom_dict['tx2power'] = tx_power_list[1]
transceiver_dom_dict['tx3power'] = tx_power_list[2]
transceiver_dom_dict['tx4power'] = tx_power_list[3]
transceiver_dom_dict['tx5power'] = tx_power_list[4]
transceiver_dom_dict['tx6power'] = tx_power_list[5]
transceiver_dom_dict['tx7power'] = tx_power_list[6]
transceiver_dom_dict['tx8power'] = tx_power_list[7]
else:
if tx_power_list is not None:
transceiver_dom_dict['tx1power'] = tx_power_list[0]
transceiver_dom_dict['tx2power'] = tx_power_list[1]
transceiver_dom_dict['tx3power'] = tx_power_list[2]
transceiver_dom_dict['tx4power'] = tx_power_list[3]
transceiver_dom_dict['rx_los'] = rx_los transceiver_dom_dict['rx_los'] = rx_los
transceiver_dom_dict['tx_fault'] = tx_fault transceiver_dom_dict['tx_fault'] = tx_fault
@ -612,7 +837,7 @@ class Sfp(SfpBase):
Returns : True if sfp is present and false if it is absent Returns : True if sfp is present and false if it is absent
""" """
# Check for invalid port_num # Check for invalid port_num
mask = {'QSFP' : (1 << 4), 'SFP' : (1 << 0)} mask = {'QSFP_DD' : (1 << 4), 'SFP' : (1 << 0)}
# Port offset starts with 0x4004 # Port offset starts with 0x4004
port_offset = 16388 + ((self.index-1) * 16) port_offset = 16388 + ((self.index-1) * 16)
@ -620,7 +845,7 @@ class Sfp(SfpBase):
status = self.pci_get_value(self.BASE_RES_PATH, port_offset) status = self.pci_get_value(self.BASE_RES_PATH, port_offset)
reg_value = int(status) reg_value = int(status)
# ModPrsL is active low # ModPrsL is active low
if reg_value & mask[self.sfp_type] == 0: if reg_value & mask[self.port_type] == 0:
return True return True
except ValueError: pass except ValueError: pass
@ -656,7 +881,7 @@ class Sfp(SfpBase):
""" """
reset_status = False reset_status = False
try: try:
if (self.sfp_type == 'QSFP'): if self.port_type == 'QSFP_DD':
# Port offset starts with 0x4000 # Port offset starts with 0x4000
port_offset = 16384 + ((self.index-1) * 16) port_offset = 16384 + ((self.index-1) * 16)
@ -676,10 +901,20 @@ class Sfp(SfpBase):
""" """
rx_los_list = [] rx_los_list = []
try: try:
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP_DD':
offset = 512
rx_los_mask = [ 0x01, 0x02, 0x04, 0x08 ,0x10, 0x20, 0x40, 0x80 ]
dom_channel_monitor_raw = self._read_eeprom_bytes(self.eeprom_path,
offset + QSFP_DD_RXLOS_OFFSET, QSFP_DD_RXLOS_WIDTH)
if dom_channel_monitor_raw is not None:
rx_los_data = int(dom_channel_monitor_raw[0], 8)
for mask in rx_los_mask:
rx_los_list.append(rx_los_data & mask != 0)
elif self.sfp_type == 'QSFP':
rx_los_data = self._get_eeprom_data('rx_los') rx_los_data = self._get_eeprom_data('rx_los')
# As the function expects a single boolean, if any one channel experience LOS, # As the function expects a single boolean, if any one channel experience LOS,
# is considered LOS for QSFP # is considered LOS for QSFP
for rx_los_id in ('Rx1LOS', 'Rx2LOS', 'Rx3LOS', 'Rx4LOS') : for rx_los_id in ('Rx1LOS', 'Rx2LOS', 'Rx3LOS', 'Rx4LOS') :
rx_los_list.append(rx_los_data['data'][rx_los_id]['value'] == 'On') rx_los_list.append(rx_los_data['data'][rx_los_id]['value'] == 'On')
else: else:
@ -696,7 +931,9 @@ class Sfp(SfpBase):
""" """
tx_fault_list = [] tx_fault_list = []
try: try:
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP_DD':
tx_fault_list = False
elif self.sfp_type == 'QSFP':
tx_fault_data = self._get_eeprom_data('tx_fault') tx_fault_data = self._get_eeprom_data('tx_fault')
for tx_fault_id in ('Tx1Fault', 'Tx2Fault', 'Tx3Fault', 'Tx4Fault') : for tx_fault_id in ('Tx1Fault', 'Tx2Fault', 'Tx3Fault', 'Tx4Fault') :
tx_fault_list.append(tx_fault_data['data'][tx_fault_id]['value'] == 'On') tx_fault_list.append(tx_fault_data['data'][tx_fault_id]['value'] == 'On')
@ -714,7 +951,9 @@ class Sfp(SfpBase):
""" """
tx_disable_list = [] tx_disable_list = []
try: try:
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP_DD':
return False
elif self.sfp_type == 'QSFP':
tx_disable_data = self._get_eeprom_data('tx_disable') tx_disable_data = self._get_eeprom_data('tx_disable')
for tx_disable_id in ('Tx1Disable', 'Tx2Disable', 'Tx3Disable', 'Tx4Disable'): for tx_disable_id in ('Tx1Disable', 'Tx2Disable', 'Tx3Disable', 'Tx4Disable'):
tx_disable_list.append(tx_disable_data['data'][tx_disable_id]['value'] == 'On') tx_disable_list.append(tx_disable_data['data'][tx_disable_id]['value'] == 'On')
@ -734,7 +973,9 @@ class Sfp(SfpBase):
""" """
tx_disable_channel = 0 tx_disable_channel = 0
try: try:
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP_DD':
tx_disable_channel = 0
elif self.sfp_type == 'QSFP':
tx_disable_data = self._get_eeprom_data('tx_disable') tx_disable_data = self._get_eeprom_data('tx_disable')
for tx_disable_id in ('Tx1Disable', 'Tx2Disable', 'Tx3Disable', 'Tx4Disable'): for tx_disable_id in ('Tx1Disable', 'Tx2Disable', 'Tx3Disable', 'Tx4Disable'):
tx_disable_channel <<= 1 tx_disable_channel <<= 1
@ -748,8 +989,8 @@ class Sfp(SfpBase):
Retrieves the lpmode(low power mode) of this SFP Retrieves the lpmode(low power mode) of this SFP
""" """
lpmode_state = False lpmode_state = False
try: try:
if self.media_type.startswith('QSFP'): if self.sfp_type.startswith('QSFP'):
# Port offset starts with 0x4000 # Port offset starts with 0x4000
port_offset = 16384 + ((self.index-1) * 16) port_offset = 16384 + ((self.index-1) * 16)
@ -770,10 +1011,10 @@ class Sfp(SfpBase):
power_override_state = False power_override_state = False
try: try:
if self.media_type.startswith('QSFP'): if self.sfp_type.startswith('QSFP'):
power_override_data = self._get_eeprom_data('power_override') power_override_data = self._get_eeprom_data('power_override')
power_override = power_override_data['data']['PowerOverRide']['value'] power_override = power_override_data['data']['PowerOverRide']['value']
power_override_state = (power_override == 'On') power_override_state = (power_override is 'On')
except (TypeError, ValueError): pass except (TypeError, ValueError): pass
return power_override_state return power_override_state
@ -782,8 +1023,18 @@ class Sfp(SfpBase):
Retrieves the temperature of this SFP Retrieves the temperature of this SFP
""" """
temperature = None temperature = None
try : try:
temperature_data = self._get_eeprom_data('Temperature') if self.sfp_type == 'QSFP_DD':
if self.qsfp_dd_DomInfo is None:
return None
dom_data_raw = self._read_eeprom_bytes(self.eeprom_path, QSFP_DD_TEMP_OFFSET, QSFP_DD_TEMP_WIDTH)
if dom_data_raw is None:
return None
temperature_data = self.qsfp_dd_DomInfo.parse_temperature(dom_data_raw, 0)
elif self.sfp_type == 'QSFP':
temperature_data = self._get_eeprom_data('Temperature')
temperature = self._strip_unit_from_str(temperature_data['data']['Temperature']['value']) temperature = self._strip_unit_from_str(temperature_data['data']['Temperature']['value'])
except (TypeError, ValueError): except (TypeError, ValueError):
return None return None
@ -795,8 +1046,19 @@ class Sfp(SfpBase):
""" """
voltage = None voltage = None
try: try:
voltage_data = self._get_eeprom_data('Voltage') if self.sfp_type == 'QSFP_DD':
if self.qsfp_dd_DomInfo is None:
return None
dom_data_raw = self._read_eeprom_bytes(self.eeprom_path, QSFP_DD_VOLT_OFFSET, QSFP_DD_VOLT_WIDTH)
if dom_data_raw is None:
return None
voltage_data = self.qsfp_dd_DomInfo.parse_voltage(dom_data_raw, 0)
elif self.sfp_type == 'QSFP':
voltage_data = self._get_eeprom_data('Voltage')
voltage = self._strip_unit_from_str(voltage_data['data']['Vcc']['value']) voltage = self._strip_unit_from_str(voltage_data['data']['Vcc']['value'])
except (TypeError, ValueError): except (TypeError, ValueError):
return None return None
return voltage return voltage
@ -807,14 +1069,29 @@ class Sfp(SfpBase):
""" """
tx_bias_list = [] tx_bias_list = []
try: try:
tx_bias_data = self._get_eeprom_data('ChannelMonitor') offset = 128
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP_DD':
for tx_bias_id in ('TX1Bias', 'TX2Bias', 'TX3Bias', 'TX4Bias') : if self.qsfp_dd_DomInfo is None:
return None
if not self.dom_tx_bias_supported:
return None
tx_bias_data_raw = self._read_eeprom_bytes(self.eeprom_path, offset + QSFP_DD_TXBIAS_OFFSET, QSFP_DD_TXBIAS_WIDTH)
tx_bias_data = self.qsfp_dd_DomInfo.parse_dom_tx_bias(tx_bias_data_raw, 0)
for tx_bias_id in ('TX1Bias', 'TX2Bias', 'TX3Bias', 'TX4Bias',
'TX5Bias', 'TX6Bias', 'TX7Bias', 'TX8Bias'):
tx_bias = self._strip_unit_from_str(tx_bias_data['data'][tx_bias_id]['value'])
tx_bias_list.append(tx_bias)
elif self.sfp_type == 'QSFP':
tx_bias_data = self._get_eeprom_data('ChannelMonitor')
for tx_bias_id in ('TX1Bias', 'TX2Bias', 'TX3Bias', 'TX4Bias'):
tx_bias = self._strip_unit_from_str(tx_bias_data['data'][tx_bias_id]['value']) tx_bias = self._strip_unit_from_str(tx_bias_data['data'][tx_bias_id]['value'])
tx_bias_list.append(tx_bias) tx_bias_list.append(tx_bias)
else: else:
tx1_bias = tx_bias_data['data']['TXBias']['value'] tx1_bias = self._strip_unit_from_str(tx_bias_data['data']['TXBias']['value'])
tx_bias_list.append(self._strip_unit_from_str(tx1_bias)) tx_bias_list.append(tx1_bias)
except (TypeError, ValueError): except (TypeError, ValueError):
return None return None
return tx_bias_list return tx_bias_list
@ -824,15 +1101,29 @@ class Sfp(SfpBase):
Retrieves the received optical power for this SFP Retrieves the received optical power for this SFP
""" """
rx_power_list = [] rx_power_list = []
offset = 128
try: try:
rx_power_data = self._get_eeprom_data('ChannelMonitor') if self.sfp_type == 'QSFP_DD':
if self.media_type.startswith('QSFP'): if self.qsfp_dd_DomInfo is None:
for rx_power_id in ('RX1Power', 'RX2Power', 'RX3Power', 'RX4Power'): return None
if not self.dom_rx_power_supported:
return None
rx_power_data_raw = self._read_eeprom_bytes(self.eeprom_path, offset + QSFP_DD_RXPOWER_OFFSET, QSFP_DD_TXPOWER_WIDTH)
rx_power_data = self.qsfp_dd_DomInfo.parse_dom_rx_power(rx_power_data_raw, 0)
for rx_power_id in ('RX1Power', 'RX2Power', 'RX3Power', 'RX4Power',
'RX5Power', 'RX6Power', 'RX7Power', 'RX8Power'):
rx_power = self._strip_unit_from_str(rx_power_data['data'][rx_power_id]['value']) rx_power = self._strip_unit_from_str(rx_power_data['data'][rx_power_id]['value'])
rx_power_list.append(self._strip_unit_from_str(rx_power)) rx_power_list.append(rx_power)
elif self.sfp_type == 'QSFP':
rx_power_data = self._get_eeprom_data('ChannelMonitor')
for rx_power_id in ('RX1Power', 'RX2Power', 'RX3Power', 'RX4Power'):
rx_power = rx_power_data['data'][rx_power_id]['value']
rx_power_list.append(rx_power)
else: else:
rx1_pw = rx_power_data['data']['RXPower']['value'] rx1_pw = self._strip_unit_from_str(rx_power_data['data']['RXPower']['value'])
rx_power_list.append(self._strip_unit_from_str(rx1_pw)) rx_power_list.append(rx1_pw)
except (TypeError, ValueError): except (TypeError, ValueError):
return None return None
return rx_power_list return rx_power_list
@ -842,8 +1133,25 @@ class Sfp(SfpBase):
Retrieves the TX power of this SFP Retrieves the TX power of this SFP
""" """
tx_power_list = [] tx_power_list = []
offset = 128
try: try:
if self.media_type.startswith('QSFP'): if self.sfp_type == 'QSFP_DD':
if self.qsfp_dd_DomInfo is None:
return None
if not self.dom_tx_power_supported:
return None
tx_power_data_raw = self._read_eeprom_bytes(self.eeprom_path, offset + QSFP_DD_TXPOWER_OFFSET,
QSFP_DD_TXPOWER_WIDTH)
tx_power_data = self.qsfp_dd_DomInfo.parse_dom_tx_power(tx_power_data_raw, 0)
for tx_power_id in ('TX1Power', 'TX2Power', 'TX3Power', 'TX4Power',
'TX5Power', 'TX6Power', 'TX7Power', 'TX8Power'):
tx_pw = self._strip_unit_from_str(tx_power_data['data'][tx_power_id]['value'])
tx_power_list.append(tx_pw)
elif self.sfp_type == 'QSFP':
# QSFP capability byte parse, through this byte can know whether it support tx_power or not. # QSFP capability byte parse, through this byte can know whether it support tx_power or not.
# TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436, # TODO: in the future when decided to migrate to support SFF-8636 instead of SFF-8436,
# need to add more code for determining the capability and version compliance # need to add more code for determining the capability and version compliance
@ -859,12 +1167,12 @@ class Sfp(SfpBase):
return None return None
channel_monitor_data = self._get_eeprom_data('ChannelMonitor_TxPower') channel_monitor_data = self._get_eeprom_data('ChannelMonitor_TxPower')
for tx_power_id in ('TX1Power', 'TX2Power', 'TX3Power', 'TX4Power'): for tx_power_id in ('TX1Power', 'TX2Power', 'TX3Power', 'TX4Power'):
tx_pw = channel_monitor_data['data'][tx_power_id]['value'] tx_pw = self._strip_unit_from_str(channel_monitor_data['data'][tx_power_id]['value'])
tx_power_list.append(self._strip_unit_from_str(tx_pw)) tx_power_list.append(tx_pw)
else: else:
channel_monitor_data = self._get_eeprom_data('ChannelMonitor') channel_monitor_data = self._get_eeprom_data('ChannelMonitor')
tx1_pw = channel_monitor_data['data']['TXPower']['value'] tx1_pw = self._strip_unit_from_str(channel_monitor_data['data']['TXPower']['value'])
tx_power_list.append(self._strip_unit_from_str(tx1_pw)) tx_power_list.append(tx1_pw)
except (TypeError, ValueError): except (TypeError, ValueError):
return None return None
return tx_power_list return tx_power_list
@ -874,7 +1182,7 @@ class Sfp(SfpBase):
Reset the SFP and returns all user settings to their default state Reset the SFP and returns all user settings to their default state
""" """
try: try:
if (self.sfp_type == 'QSFP'): if self.port_type == 'QSFP_DD':
# Port offset starts with 0x4000 # Port offset starts with 0x4000
port_offset = 16384 + ((self.index-1) * 16) port_offset = 16384 + ((self.index-1) * 16)
@ -906,7 +1214,7 @@ class Sfp(SfpBase):
Sets the lpmode(low power mode) of this SFP Sets the lpmode(low power mode) of this SFP
""" """
try: try:
if (self.sfp_type == 'QSFP'): if self.port_type == 'QSFP_DD':
# Port offset starts with 0x4000 # Port offset starts with 0x4000
port_offset = 16384 + ((self.index-1) * 16) port_offset = 16384 + ((self.index-1) * 16)
@ -933,8 +1241,8 @@ class Sfp(SfpBase):
Sets the intL (interrupt; active low) pin of this SFP Sets the intL (interrupt; active low) pin of this SFP
""" """
intl_state = True intl_state = True
try: try:
if (self.sfp_type == 'QSFP'): if self.port_type == 'QSFP_DD':
# Port offset starts with 0x4004 # Port offset starts with 0x4004
port_offset = 16388 + ((self.index-1) * 16) port_offset = 16388 + ((self.index-1) * 16)
@ -977,18 +1285,18 @@ class Sfp(SfpBase):
""" """
Retrieves the native port type Retrieves the native port type
""" """
return self.sfp_type return self.port_type
def get_max_port_power(self): def get_max_port_power(self):
""" """
Retrieves the maximum power allowed on the port in watts Retrieves the maximum power allowed on the port in watts
*** ***
This method of fetching power values is not ideal. This method of fetching power values is not ideal.
TODO: enhance by placing power limits in config file TODO: enhance by placing power limits in config file
*** ***
""" """
return (12.0 if self.sfp_type=='QSFP' else 2.5) return 12.0 if self.port_type == 'QSFP_DD' else 2.5
def set_media_type(self): def set_media_type(self):
""" """
@ -998,18 +1306,18 @@ class Sfp(SfpBase):
eeprom_raw = self._read_eeprom_bytes(self.eeprom_path, MEDIA_TYPE_OFFSET, MEDIA_TYPE_WIDTH) eeprom_raw = self._read_eeprom_bytes(self.eeprom_path, MEDIA_TYPE_OFFSET, MEDIA_TYPE_WIDTH)
if eeprom_raw is not None: if eeprom_raw is not None:
if eeprom_raw[0] in SFP_TYPE_LIST: if eeprom_raw[0] in SFP_TYPE_LIST:
self.media_type = 'SFP' self.sfp_type = 'SFP'
elif eeprom_raw[0] in QSFP_TYPE_LIST: elif eeprom_raw[0] in QSFP_TYPE_LIST:
self.media_type = 'QSFP' self.sfp_type = 'QSFP'
elif eeprom_raw[0] in QSFP_DD_TYPE_LIST: elif eeprom_raw[0] in QSFP_DD_TYPE_LIST:
self.media_type = 'QSFP-DD' self.sfp_type = 'QSFP_DD'
else: else:
#Set native port type if EEPROM type is not recognized/readable #Set native port type if EEPROM type is not recognized/readable
self.media_type = self.sfp_type self.sfp_type = self.port_type
else: else:
self.media_type = self.sfp_type self.sfp_type = self.port_type
return self.media_type return self.sfp_type
def reinit_sfp_driver(self): def reinit_sfp_driver(self):
""" """
@ -1031,18 +1339,21 @@ class Sfp(SfpBase):
driver_name = driver_name.lstrip(" ") driver_name = driver_name.lstrip(" ")
#Avoid re-initialization of the QSFP/SFP optic on QSFP/SFP port. #Avoid re-initialization of the QSFP/SFP optic on QSFP/SFP port.
if (self.media_type == 'SFP' and (driver_name == 'optoe1' or driver_name == 'optoe3')): if self.sfp_type == 'SFP' and driver_name in ['optoe1', 'optoe3']:
subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE)
time.sleep(0.2)
new_device = "echo optoe2 0x50 >" + new_sfp_path new_device = "echo optoe2 0x50 >" + new_sfp_path
subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE)
time.sleep(2) time.sleep(2)
elif (self.media_type == 'QSFP' and (driver_name == 'optoe2' or driver_name == 'optoe3')): elif self.sfp_type == 'QSFP' and driver_name in ['optoe2', 'optoe3']:
subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE)
time.sleep(0.2)
new_device = "echo optoe1 0x50 >" + new_sfp_path new_device = "echo optoe1 0x50 >" + new_sfp_path
subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE)
time.sleep(2) time.sleep(2)
elif (self.media_type == 'QSFP-DD' and (driver_name == 'optoe1' or driver_name == 'optoe2')): elif self.sfp_type == 'QSFP_DD' and driver_name in ['optoe1', 'optoe2']:
subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE) subprocess.Popen(delete_device, shell=True, stdout=subprocess.PIPE)
time.sleep(0.2)
new_device = "echo optoe3 0x50 >" + new_sfp_path new_device = "echo optoe3 0x50 >" + new_sfp_path
subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE) subprocess.Popen(new_device, shell=True, stdout=subprocess.PIPE)
time.sleep(2) time.sleep(2)