Skip to content

Commit 2052a63

Browse files
Fix issue: copper cable should not display DOM information (#318)
* Fix issue: copper cable should not display DOM information * Improve unit test coverage
1 parent cf4c6af commit 2052a63

File tree

4 files changed

+89
-30
lines changed

4 files changed

+89
-30
lines changed

sonic_platform_base/sonic_xcvr/api/public/sff8436.py

+20-12
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Sff8436Api(XcvrApi):
1313

1414
def __init__(self, xcvr_eeprom):
1515
super(Sff8436Api, self).__init__(xcvr_eeprom)
16+
self._is_copper = None
1617

1718
def get_model(self):
1819
return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD)
@@ -42,7 +43,7 @@ def get_transceiver_info(self):
4243
cable_type = "Unknown"
4344
for len, type in zip([smf_len, om3_len, om2_len, om1_len, cable_assembly_len], len_types):
4445
if len > 0:
45-
cable_len = len
46+
cable_len = len
4647
cable_type = type
4748

4849
xcvr_info = {
@@ -119,8 +120,6 @@ def get_transceiver_threshold_info(self):
119120
]
120121
threshold_info_dict = dict.fromkeys(threshold_info_keys, 'N/A')
121122
thresh_support = self.get_transceiver_thresholds_support()
122-
if thresh_support is None:
123-
return None
124123
if not thresh_support:
125124
return threshold_info_dict
126125

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

200199
def get_module_temperature(self):
200+
if not self.get_temperature_support():
201+
return 'N/A'
201202
temp = self.xcvr_eeprom.read(consts.TEMPERATURE_FIELD)
202203
if temp is None:
203204
return None
204205
return float("{:.3f}".format(temp))
205206

206207
def get_voltage(self):
208+
if not self.get_voltage_support():
209+
return 'N/A'
207210
voltage = self.xcvr_eeprom.read(consts.VOLTAGE_FIELD)
208211
if voltage is None:
209212
return None
@@ -216,6 +219,8 @@ def get_tx_bias(self):
216219
return [channel_bias for channel_bias in tx_bias.values()]
217220

218221
def get_rx_power(self):
222+
if not self.get_rx_power_support():
223+
return ["N/A" for _ in range(self.NUM_CHANNELS)]
219224
rx_power = self.xcvr_eeprom.read(consts.RX_POWER_FIELD)
220225
if rx_power is None:
221226
return None
@@ -255,27 +260,30 @@ def set_power_override(self, power_override, power_set):
255260
if power_override:
256261
ret &= self.xcvr_eeprom.write(consts.POWER_SET_FIELD, power_set)
257262
return ret
258-
263+
259264
def is_flat_memory(self):
260265
return self.xcvr_eeprom.read(consts.FLAT_MEM_FIELD)
261266

262267
def get_tx_power_support(self):
263268
return False
264269

265270
def get_rx_power_support(self):
266-
return True
271+
return not self.is_copper()
267272

268273
def is_copper(self):
269-
eth_compliance = self.xcvr_eeprom.read(consts.ETHERNET_10_40G_COMPLIANCE_FIELD)
270-
if eth_compliance is None:
271-
return None
272-
return eth_compliance == "40GBASE-CR4"
274+
if self._is_copper is None:
275+
eth_compliance = self.xcvr_eeprom.read(consts.ETHERNET_10_40G_COMPLIANCE_FIELD)
276+
if eth_compliance is None:
277+
return None
278+
else:
279+
self._is_copper = eth_compliance == "40GBASE-CR4"
280+
return self._is_copper
273281

274282
def get_temperature_support(self):
275-
return True
283+
return not self.is_copper()
276284

277285
def get_voltage_support(self):
278-
return True
286+
return not self.is_copper()
279287

280288
def get_rx_los_support(self):
281289
return True
@@ -290,7 +298,7 @@ def get_tx_disable_support(self):
290298
return self.xcvr_eeprom.read(consts.TX_DISABLE_SUPPORT_FIELD)
291299

292300
def get_transceiver_thresholds_support(self):
293-
return not self.is_flat_memory()
301+
return not self.is_copper() and not self.is_flat_memory()
294302

295303
def get_lpmode_support(self):
296304
power_class = self.xcvr_eeprom.read(consts.POWER_CLASS_FIELD)

sonic_platform_base/sonic_xcvr/api/public/sff8636.py

+24-14
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def __init__(self, xcvr_eeprom):
1717
super(Sff8636Api, self).__init__(xcvr_eeprom)
1818
self._temp_support = None
1919
self._voltage_support = None
20+
self._is_copper = None
2021

2122
def get_model(self):
2223
return self.xcvr_eeprom.read(consts.VENDOR_PART_NO_FIELD)
@@ -49,7 +50,7 @@ def get_transceiver_info(self):
4950
cable_type = "Unknown"
5051
for len, type in zip([smf_len, om3_len, om2_len, om1_len, cable_assembly_len], len_types):
5152
if len > 0:
52-
cable_len = len
53+
cable_len = len
5354
cable_type = type
5455

5556
xcvr_info = {
@@ -126,8 +127,6 @@ def get_transceiver_threshold_info(self):
126127
]
127128
threshold_info_dict = dict.fromkeys(threshold_info_keys, 'N/A')
128129
thresh_support = self.get_transceiver_thresholds_support()
129-
if thresh_support is None:
130-
return None
131130
if not thresh_support:
132131
return threshold_info_dict
133132
temp_thresholds = self.xcvr_eeprom.read(consts.TEMP_THRESHOLDS_FIELD)
@@ -237,6 +236,9 @@ def get_tx_bias(self):
237236
return [channel_bias for channel_bias in tx_bias.values()]
238237

239238
def get_rx_power(self):
239+
rx_power_support = self.get_rx_power_support()
240+
if not rx_power_support:
241+
return ["N/A" for _ in range(self.NUM_CHANNELS)]
240242
rx_power = self.xcvr_eeprom.read(consts.RX_POWER_FIELD)
241243
if rx_power is None:
242244
return None
@@ -289,23 +291,29 @@ def is_flat_memory(self):
289291
return self.xcvr_eeprom.read(consts.FLAT_MEM_FIELD)
290292

291293
def get_tx_power_support(self):
294+
if self.is_copper():
295+
return False
292296
return self.xcvr_eeprom.read(consts.TX_POWER_SUPPORT_FIELD)
293297

294298
def get_rx_power_support(self):
295-
return True
299+
return not self.is_copper()
296300

297301
def is_copper(self):
298-
eth_compliance = self.xcvr_eeprom.read(consts.ETHERNET_10_40G_COMPLIANCE_FIELD)
299-
ext_spec_compliance = self.xcvr_eeprom.read(consts.EXT_SPEC_COMPLIANCE_FIELD)
300-
if eth_compliance is None or ext_spec_compliance is None:
301-
return None
302-
303-
return eth_compliance == "40GBASE-CR4" or \
304-
"CR" in ext_spec_compliance or \
305-
"ACC" in ext_spec_compliance or \
306-
"Copper" in ext_spec_compliance
302+
if self._is_copper is None:
303+
eth_compliance = self.xcvr_eeprom.read(consts.ETHERNET_10_40G_COMPLIANCE_FIELD)
304+
ext_spec_compliance = self.xcvr_eeprom.read(consts.EXT_SPEC_COMPLIANCE_FIELD)
305+
if eth_compliance is None or ext_spec_compliance is None:
306+
return None
307+
else:
308+
self._is_copper = eth_compliance == "40GBASE-CR4" or \
309+
"CR" in ext_spec_compliance or \
310+
"ACC" in ext_spec_compliance or \
311+
"Copper" in ext_spec_compliance
312+
return self._is_copper
307313

308314
def get_temperature_support(self):
315+
if self.is_copper():
316+
return False
309317
if self._temp_support is None:
310318
rev_compliance = self.xcvr_eeprom.read(consts.REV_COMPLIANCE_FIELD)
311319
# TODO: instead of checking for specific decoded value, should
@@ -317,6 +325,8 @@ def get_temperature_support(self):
317325
return self._temp_support
318326

319327
def get_voltage_support(self):
328+
if self.is_copper():
329+
return False
320330
if self._voltage_support is None:
321331
rev_compliance = self.xcvr_eeprom.read(consts.REV_COMPLIANCE_FIELD)
322332
# TODO: instead of checking for specific decoded value, should
@@ -340,7 +350,7 @@ def get_tx_disable_support(self):
340350
return self.xcvr_eeprom.read(consts.TX_DISABLE_SUPPORT_FIELD)
341351

342352
def get_transceiver_thresholds_support(self):
343-
return not self.is_flat_memory()
353+
return not self.is_copper() and not self.is_flat_memory()
344354

345355
def get_lpmode_support(self):
346356
power_class = self.xcvr_eeprom.read(consts.POWER_CLASS_FIELD)

tests/sonic_xcvr/test_sff8436.py

+24-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from mock import MagicMock
1+
from mock import MagicMock, patch
22

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

1616
def test_api(self):
1717
"""
18-
Verify all api access valid fields
18+
Verify all api access valid fields
1919
"""
2020
self.api.get_model()
2121
self.api.get_serial()
@@ -51,3 +51,25 @@ def test_api(self):
5151
self.api.get_transceiver_thresholds_support()
5252
self.api.get_lpmode_support()
5353
self.api.get_power_override_support()
54+
55+
def test_is_copper(self):
56+
with patch.object(self.api, 'xcvr_eeprom') as mock_eeprom:
57+
mock_eeprom.read = MagicMock()
58+
mock_eeprom.read.return_value = None
59+
assert self.api.is_copper() is None
60+
mock_eeprom.read.return_value = '40GBASE-CR4'
61+
assert self.api.is_copper()
62+
self.api._is_copper = None
63+
mock_eeprom.read.return_value = 'SR'
64+
assert not self.api.is_copper()
65+
66+
def test_simulate_copper(self):
67+
with patch.object(self.api, 'is_copper', return_value=True):
68+
assert self.api.get_rx_power() == ['N/A'] * self.api.NUM_CHANNELS
69+
assert self.api.get_module_temperature() == 'N/A'
70+
assert self.api.get_voltage() == 'N/A'
71+
assert not self.api.get_tx_power_support()
72+
assert not self.api.get_rx_power_support()
73+
assert not self.api.get_rx_power_support()
74+
assert not self.api.get_temperature_support()
75+
assert not self.api.get_voltage_support()

tests/sonic_xcvr/test_sff8636.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from mock import MagicMock
1+
from mock import MagicMock, patch
22

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

1616
def test_api(self):
1717
"""
18-
Verify all api access valid fields
18+
Verify all api access valid fields
1919
"""
2020
self.api.get_model()
2121
self.api.get_serial()
@@ -52,3 +52,22 @@ def test_api(self):
5252
self.api.get_lpmode_support()
5353
self.api.get_power_override_support()
5454

55+
def test_is_copper(self):
56+
with patch.object(self.api, 'xcvr_eeprom') as mock_eeprom:
57+
mock_eeprom.read = MagicMock()
58+
mock_eeprom.read.return_value = None
59+
assert self.api.is_copper() is None
60+
mock_eeprom.read.return_value = '40GBASE-CR4'
61+
assert self.api.is_copper()
62+
self.api._is_copper = None
63+
mock_eeprom.read.return_value = 'SR'
64+
assert not self.api.is_copper()
65+
66+
def test_simulate_copper(self):
67+
with patch.object(self.api, 'is_copper', return_value=True):
68+
assert self.api.get_rx_power() == ['N/A'] * self.api.NUM_CHANNELS
69+
assert not self.api.get_tx_power_support()
70+
assert not self.api.get_rx_power_support()
71+
assert not self.api.get_rx_power_support()
72+
assert not self.api.get_temperature_support()
73+
assert not self.api.get_voltage_support()

0 commit comments

Comments
 (0)