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

Fix issue: copper cable should not display DOM information #318

Merged
merged 2 commits into from
Nov 3, 2022
Merged
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
32 changes: 20 additions & 12 deletions sonic_platform_base/sonic_xcvr/api/public/sff8436.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Sff8436Api(XcvrApi):

def __init__(self, xcvr_eeprom):
super(Sff8436Api, self).__init__(xcvr_eeprom)
self._is_copper = None

def get_model(self):
return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD)
Expand Down Expand Up @@ -42,7 +43,7 @@ def get_transceiver_info(self):
cable_type = "Unknown"
for len, type in zip([smf_len, om3_len, om2_len, om1_len, cable_assembly_len], len_types):
if len > 0:
cable_len = len
cable_len = len
cable_type = type

xcvr_info = {
Expand Down Expand Up @@ -119,8 +120,6 @@ def get_transceiver_threshold_info(self):
]
threshold_info_dict = dict.fromkeys(threshold_info_keys, 'N/A')
thresh_support = self.get_transceiver_thresholds_support()
if thresh_support is None:
return None
if not thresh_support:
return threshold_info_dict

Expand Down Expand Up @@ -198,12 +197,16 @@ def get_tx_disable_channel(self):
return self.xcvr_eeprom.read(consts.TX_DISABLE_FIELD)

def get_module_temperature(self):
if not self.get_temperature_support():
return 'N/A'
temp = self.xcvr_eeprom.read(consts.TEMPERATURE_FIELD)
if temp is None:
return None
return float("{:.3f}".format(temp))

def get_voltage(self):
if not self.get_voltage_support():
return 'N/A'
voltage = self.xcvr_eeprom.read(consts.VOLTAGE_FIELD)
if voltage is None:
return None
Expand All @@ -216,6 +219,8 @@ def get_tx_bias(self):
return [channel_bias for channel_bias in tx_bias.values()]

def get_rx_power(self):
if not self.get_rx_power_support():
return ["N/A" for _ in range(self.NUM_CHANNELS)]
rx_power = self.xcvr_eeprom.read(consts.RX_POWER_FIELD)
if rx_power is None:
return None
Expand Down Expand Up @@ -255,27 +260,30 @@ def set_power_override(self, power_override, power_set):
if power_override:
ret &= self.xcvr_eeprom.write(consts.POWER_SET_FIELD, power_set)
return ret

def is_flat_memory(self):
return self.xcvr_eeprom.read(consts.FLAT_MEM_FIELD)

def get_tx_power_support(self):
return False

def get_rx_power_support(self):
return True
return not self.is_copper()

def is_copper(self):
eth_compliance = self.xcvr_eeprom.read(consts.ETHERNET_10_40G_COMPLIANCE_FIELD)
if eth_compliance is None:
return None
return eth_compliance == "40GBASE-CR4"
if self._is_copper is None:
eth_compliance = self.xcvr_eeprom.read(consts.ETHERNET_10_40G_COMPLIANCE_FIELD)
if eth_compliance is None:
return None
else:
self._is_copper = eth_compliance == "40GBASE-CR4"
return self._is_copper

def get_temperature_support(self):
return True
return not self.is_copper()

def get_voltage_support(self):
return True
return not self.is_copper()

def get_rx_los_support(self):
return True
Expand All @@ -290,7 +298,7 @@ def get_tx_disable_support(self):
return self.xcvr_eeprom.read(consts.TX_DISABLE_SUPPORT_FIELD)

def get_transceiver_thresholds_support(self):
return not self.is_flat_memory()
return not self.is_copper() and not self.is_flat_memory()

def get_lpmode_support(self):
power_class = self.xcvr_eeprom.read(consts.POWER_CLASS_FIELD)
Expand Down
38 changes: 24 additions & 14 deletions sonic_platform_base/sonic_xcvr/api/public/sff8636.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def __init__(self, xcvr_eeprom):
super(Sff8636Api, self).__init__(xcvr_eeprom)
self._temp_support = None
self._voltage_support = None
self._is_copper = None

def get_model(self):
return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD)
Expand Down Expand Up @@ -49,7 +50,7 @@ def get_transceiver_info(self):
cable_type = "Unknown"
for len, type in zip([smf_len, om3_len, om2_len, om1_len, cable_assembly_len], len_types):
if len > 0:
cable_len = len
cable_len = len
cable_type = type

xcvr_info = {
Expand Down Expand Up @@ -126,8 +127,6 @@ def get_transceiver_threshold_info(self):
]
threshold_info_dict = dict.fromkeys(threshold_info_keys, 'N/A')
thresh_support = self.get_transceiver_thresholds_support()
if thresh_support is None:
return None
if not thresh_support:
return threshold_info_dict
temp_thresholds = self.xcvr_eeprom.read(consts.TEMP_THRESHOLDS_FIELD)
Expand Down Expand Up @@ -237,6 +236,9 @@ def get_tx_bias(self):
return [channel_bias for channel_bias in tx_bias.values()]

def get_rx_power(self):
rx_power_support = self.get_rx_power_support()
if not rx_power_support:
return ["N/A" for _ in range(self.NUM_CHANNELS)]
rx_power = self.xcvr_eeprom.read(consts.RX_POWER_FIELD)
if rx_power is None:
return None
Expand Down Expand Up @@ -289,23 +291,29 @@ def is_flat_memory(self):
return self.xcvr_eeprom.read(consts.FLAT_MEM_FIELD)

def get_tx_power_support(self):
if self.is_copper():
return False
return self.xcvr_eeprom.read(consts.TX_POWER_SUPPORT_FIELD)

def get_rx_power_support(self):
return True
return not self.is_copper()

def is_copper(self):
eth_compliance = self.xcvr_eeprom.read(consts.ETHERNET_10_40G_COMPLIANCE_FIELD)
ext_spec_compliance = self.xcvr_eeprom.read(consts.EXT_SPEC_COMPLIANCE_FIELD)
if eth_compliance is None or ext_spec_compliance is None:
return None

return eth_compliance == "40GBASE-CR4" or \
"CR" in ext_spec_compliance or \
"ACC" in ext_spec_compliance or \
"Copper" in ext_spec_compliance
if self._is_copper is None:
eth_compliance = self.xcvr_eeprom.read(consts.ETHERNET_10_40G_COMPLIANCE_FIELD)
ext_spec_compliance = self.xcvr_eeprom.read(consts.EXT_SPEC_COMPLIANCE_FIELD)
if eth_compliance is None or ext_spec_compliance is None:
return None
else:
self._is_copper = eth_compliance == "40GBASE-CR4" or \
"CR" in ext_spec_compliance or \
"ACC" in ext_spec_compliance or \
"Copper" in ext_spec_compliance
return self._is_copper

def get_temperature_support(self):
if self.is_copper():
return False
if self._temp_support is None:
rev_compliance = self.xcvr_eeprom.read(consts.REV_COMPLIANCE_FIELD)
# TODO: instead of checking for specific decoded value, should
Expand All @@ -317,6 +325,8 @@ def get_temperature_support(self):
return self._temp_support

def get_voltage_support(self):
if self.is_copper():
return False
if self._voltage_support is None:
rev_compliance = self.xcvr_eeprom.read(consts.REV_COMPLIANCE_FIELD)
# TODO: instead of checking for specific decoded value, should
Expand All @@ -340,7 +350,7 @@ def get_tx_disable_support(self):
return self.xcvr_eeprom.read(consts.TX_DISABLE_SUPPORT_FIELD)

def get_transceiver_thresholds_support(self):
return not self.is_flat_memory()
return not self.is_copper() and not self.is_flat_memory()

def get_lpmode_support(self):
power_class = self.xcvr_eeprom.read(consts.POWER_CLASS_FIELD)
Expand Down
26 changes: 24 additions & 2 deletions tests/sonic_xcvr/test_sff8436.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from mock import MagicMock
from mock import MagicMock, patch

from sonic_platform_base.sonic_xcvr.api.public.sff8436 import Sff8436Api
from sonic_platform_base.sonic_xcvr.codes.public.sff8436 import Sff8436Codes
Expand All @@ -15,7 +15,7 @@ class TestSff8436(object):

def test_api(self):
"""
Verify all api access valid fields
Verify all api access valid fields
"""
self.api.get_model()
self.api.get_serial()
Expand Down Expand Up @@ -51,3 +51,25 @@ def test_api(self):
self.api.get_transceiver_thresholds_support()
self.api.get_lpmode_support()
self.api.get_power_override_support()

def test_is_copper(self):
with patch.object(self.api, 'xcvr_eeprom') as mock_eeprom:
mock_eeprom.read = MagicMock()
mock_eeprom.read.return_value = None
assert self.api.is_copper() is None
mock_eeprom.read.return_value = '40GBASE-CR4'
assert self.api.is_copper()
self.api._is_copper = None
mock_eeprom.read.return_value = 'SR'
assert not self.api.is_copper()

def test_simulate_copper(self):
with patch.object(self.api, 'is_copper', return_value=True):
assert self.api.get_rx_power() == ['N/A'] * self.api.NUM_CHANNELS
assert self.api.get_module_temperature() == 'N/A'
assert self.api.get_voltage() == 'N/A'
assert not self.api.get_tx_power_support()
assert not self.api.get_rx_power_support()
assert not self.api.get_rx_power_support()
assert not self.api.get_temperature_support()
assert not self.api.get_voltage_support()
23 changes: 21 additions & 2 deletions tests/sonic_xcvr/test_sff8636.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from mock import MagicMock
from mock import MagicMock, patch

from sonic_platform_base.sonic_xcvr.api.public.sff8636 import Sff8636Api
from sonic_platform_base.sonic_xcvr.codes.public.sff8636 import Sff8636Codes
Expand All @@ -15,7 +15,7 @@ class TestSff8636(object):

def test_api(self):
"""
Verify all api access valid fields
Verify all api access valid fields
"""
self.api.get_model()
self.api.get_serial()
Expand Down Expand Up @@ -52,3 +52,22 @@ def test_api(self):
self.api.get_lpmode_support()
self.api.get_power_override_support()

def test_is_copper(self):
with patch.object(self.api, 'xcvr_eeprom') as mock_eeprom:
mock_eeprom.read = MagicMock()
mock_eeprom.read.return_value = None
assert self.api.is_copper() is None
mock_eeprom.read.return_value = '40GBASE-CR4'
assert self.api.is_copper()
self.api._is_copper = None
mock_eeprom.read.return_value = 'SR'
assert not self.api.is_copper()

def test_simulate_copper(self):
with patch.object(self.api, 'is_copper', return_value=True):
assert self.api.get_rx_power() == ['N/A'] * self.api.NUM_CHANNELS
assert not self.api.get_tx_power_support()
assert not self.api.get_rx_power_support()
assert not self.api.get_rx_power_support()
assert not self.api.get_temperature_support()
assert not self.api.get_voltage_support()