Skip to content

Commit 596a19b

Browse files
authored
[cmis] combine cmis eeprom i2c read (#84)
Change multiple eeprom i2c reads into a single i2c read across multiple addresses, as addresses are continuous in register group. <!-- Provide a general summary of your changes in the Title above --> #### Description <!-- Describe your changes in detail --> 1. Update functions get_tx_power_flag, get_tx_bias_flag and get_rx_power_flag. 2. Add dedicated groups: TX_POWER_ALARM_FLAGS_FIELD, TX_BIAS_ALARM_FLAGS_FIELD, RX_POWER_ALARM_FLAGS_FIELD. 3. Move the MEDIA_TYPE_FIELD read and prefix lookup out of the loop. #### Motivation and Context CMIS API methods were issuing several separate i2c transactions per call, resulting in high bus overhead, increased latency, and poor scalability. By introducing dedicated RegGroupField groups for TX/RX power and bias alarm flags (e.g. TX_POWER_ALARM_FLAGS, TX_BIAS_ALARM_FLAGS, RX_POWER_ALARM_FLAGS) and refactoring the related methods (get_tx_power_flag, get_tx_bias_flag, get_rx_power_flag, etc.) to use a single block read per group, it resolves API call latency. Also moved constant prefix lookups (media‐type prefix) outside of loops to save time. #### How Has This Been Tested? Test with performance cases for one port, if there are 64 physical ports, then it can save 1.3s. Before: ```bash Running performance tests (3000 iterations each)... get_tx_power_flag: total 32.120s, avg 10.707ms per call get_tx_bias_flag: total 26.635s, avg 8.878ms per call get_rx_power_flag: total 32.306s, avg 10.769ms per call ``` After: ```bash Running performance tests (3000 iterations each)... get_tx_power_flag: total 8.213s, avg 2.738ms per call get_tx_bias_flag: total 7.831s, avg 2.610ms per call get_rx_power_flag: total 9.632s, avg 3.211ms per call ``` Test with config reload, works fine.
1 parent 8129483 commit 596a19b

4 files changed

Lines changed: 142 additions & 102 deletions

File tree

sonic_platform_base/sonic_xcvr/api/public/cmis.py

Lines changed: 25 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -636,77 +636,45 @@ def get_rx_cdr_lol(self):
636636
rx_cdr_lol_final.append(bool(rx_cdr_lol[key]))
637637
return rx_cdr_lol_final
638638

639+
def get_alarm_flags(self, alarm_flag):
640+
'''Generic helper to return alarm and warning flags for given type: TX_POWER, TX_BIAS, RX_POWER.'''
641+
flags = self.xcvr_eeprom.read(getattr(consts, f"{alarm_flag}_ALARM_FLAGS_FIELD"))
642+
if flags is None:
643+
return None
644+
high_alarm = flags.get(getattr(consts, f"{alarm_flag}_HIGH_ALARM_FLAG"))
645+
low_alarm = flags.get(getattr(consts, f"{alarm_flag}_LOW_ALARM_FLAG"))
646+
high_warn = flags.get(getattr(consts, f"{alarm_flag}_HIGH_WARN_FLAG"))
647+
low_warn = flags.get(getattr(consts, f"{alarm_flag}_LOW_WARN_FLAG"))
648+
if high_alarm is None or low_alarm is None or high_warn is None or low_warn is None:
649+
return None
650+
for d in (high_alarm, low_alarm, high_warn, low_warn):
651+
for key, value in d.items():
652+
d[key] = bool(value)
653+
prefix = alarm_flag.lower()
654+
return {
655+
f"{prefix}_high_alarm": high_alarm,
656+
f"{prefix}_low_alarm": low_alarm,
657+
f"{prefix}_high_warn": high_warn,
658+
f"{prefix}_low_warn": low_warn,
659+
}
660+
639661
def get_tx_power_flag(self):
640662
'''
641663
This function returns TX power out of range flag on TX media lane
642664
'''
643-
tx_power_high_alarm_dict = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_ALARM_FLAG)
644-
tx_power_low_alarm_dict = self.xcvr_eeprom.read(consts.TX_POWER_LOW_ALARM_FLAG)
645-
tx_power_high_warn_dict = self.xcvr_eeprom.read(consts.TX_POWER_HIGH_WARN_FLAG)
646-
tx_power_low_warn_dict = self.xcvr_eeprom.read(consts.TX_POWER_LOW_WARN_FLAG)
647-
if tx_power_high_alarm_dict is None or tx_power_low_alarm_dict is None or tx_power_high_warn_dict is None or tx_power_low_warn_dict is None:
648-
return None
649-
for key, value in tx_power_high_alarm_dict.items():
650-
tx_power_high_alarm_dict[key] = bool(value)
651-
for key, value in tx_power_low_alarm_dict.items():
652-
tx_power_low_alarm_dict[key] = bool(value)
653-
for key, value in tx_power_high_warn_dict.items():
654-
tx_power_high_warn_dict[key] = bool(value)
655-
for key, value in tx_power_low_warn_dict.items():
656-
tx_power_low_warn_dict[key] = bool(value)
657-
tx_power_flag_dict = {'tx_power_high_alarm': tx_power_high_alarm_dict,
658-
'tx_power_low_alarm': tx_power_low_alarm_dict,
659-
'tx_power_high_warn': tx_power_high_warn_dict,
660-
'tx_power_low_warn': tx_power_low_warn_dict,}
661-
return tx_power_flag_dict
665+
return self.get_alarm_flags("TX_POWER")
662666

663667
def get_tx_bias_flag(self):
664668
'''
665669
This function returns TX bias out of range flag on TX media lane
666670
'''
667-
tx_bias_high_alarm_dict = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_ALARM_FLAG)
668-
tx_bias_low_alarm_dict = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_ALARM_FLAG)
669-
tx_bias_high_warn_dict = self.xcvr_eeprom.read(consts.TX_BIAS_HIGH_WARN_FLAG)
670-
tx_bias_low_warn_dict = self.xcvr_eeprom.read(consts.TX_BIAS_LOW_WARN_FLAG)
671-
if tx_bias_high_alarm_dict is None or tx_bias_low_alarm_dict is None or tx_bias_high_warn_dict is None or tx_bias_low_warn_dict is None:
672-
return None
673-
for key, value in tx_bias_high_alarm_dict.items():
674-
tx_bias_high_alarm_dict[key] = bool(value)
675-
for key, value in tx_bias_low_alarm_dict.items():
676-
tx_bias_low_alarm_dict[key] = bool(value)
677-
for key, value in tx_bias_high_warn_dict.items():
678-
tx_bias_high_warn_dict[key] = bool(value)
679-
for key, value in tx_bias_low_warn_dict.items():
680-
tx_bias_low_warn_dict[key] = bool(value)
681-
tx_bias_flag_dict = {'tx_bias_high_alarm': tx_bias_high_alarm_dict,
682-
'tx_bias_low_alarm': tx_bias_low_alarm_dict,
683-
'tx_bias_high_warn': tx_bias_high_warn_dict,
684-
'tx_bias_low_warn': tx_bias_low_warn_dict,}
685-
return tx_bias_flag_dict
671+
return self.get_alarm_flags("TX_BIAS")
686672

687673
def get_rx_power_flag(self):
688674
'''
689675
This function returns RX power out of range flag on RX media lane
690676
'''
691-
rx_power_high_alarm_dict = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_ALARM_FLAG)
692-
rx_power_low_alarm_dict = self.xcvr_eeprom.read(consts.RX_POWER_LOW_ALARM_FLAG)
693-
rx_power_high_warn_dict = self.xcvr_eeprom.read(consts.RX_POWER_HIGH_WARN_FLAG)
694-
rx_power_low_warn_dict = self.xcvr_eeprom.read(consts.RX_POWER_LOW_WARN_FLAG)
695-
if rx_power_high_alarm_dict is None or rx_power_low_alarm_dict is None or rx_power_high_warn_dict is None or rx_power_low_warn_dict is None:
696-
return None
697-
for key, value in rx_power_high_alarm_dict.items():
698-
rx_power_high_alarm_dict[key] = bool(value)
699-
for key, value in rx_power_low_alarm_dict.items():
700-
rx_power_low_alarm_dict[key] = bool(value)
701-
for key, value in rx_power_high_warn_dict.items():
702-
rx_power_high_warn_dict[key] = bool(value)
703-
for key, value in rx_power_low_warn_dict.items():
704-
rx_power_low_warn_dict[key] = bool(value)
705-
rx_power_flag_dict = {'rx_power_high_alarm': rx_power_high_alarm_dict,
706-
'rx_power_low_alarm': rx_power_low_alarm_dict,
707-
'rx_power_high_warn': rx_power_high_warn_dict,
708-
'rx_power_low_warn': rx_power_low_warn_dict,}
709-
return rx_power_flag_dict
677+
return self.get_alarm_flags("RX_POWER")
710678

711679
def get_tx_output_status(self):
712680
'''

sonic_platform_base/sonic_xcvr/fields/consts.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,9 @@
291291
LANE_MON_ADVT_FIELD = "Supported Lane Monitor Advertisement"
292292
LANE_DATAPATH_CTRL_FIELD = "Lane Control and Data Path Control"
293293
LANE_DATAPATH_STATUS_FIELD = "Lane Status and Data Path Status"
294+
TX_POWER_ALARM_FLAGS_FIELD = "TxPowerAlarmFlags"
295+
TX_BIAS_ALARM_FLAGS_FIELD = "TxBiasAlarmFlags"
296+
RX_POWER_ALARM_FLAGS_FIELD = "RxPowerAlarmFlags"
294297
DATAPATH_DEINIT_FIELD = "Data Path Deinit"
295298
LEN_MULT_FIELD = "LengthMultiplier"
296299
MAX_POWER_FIELD = "MaxPower"

sonic_platform_base/sonic_xcvr/mem_maps/public/cmis.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,78 @@ def __init__(self, codes):
293293
)
294294
)
295295

296+
# Group for TX power alarm and warning flags
297+
self.TX_POWER_ALARM_FLAGS = RegGroupField(consts.TX_POWER_ALARM_FLAGS_FIELD,
298+
RegGroupField(consts.TX_POWER_HIGH_ALARM_FLAG,
299+
*(NumberRegField("%s%d" % (consts.TX_POWER_HIGH_ALARM_FLAG, lane), self.getaddr(0x11, 139),
300+
RegBitField("Bit%d" % (lane-1), (lane-1))
301+
) for lane in range(1, 9))
302+
),
303+
RegGroupField(consts.TX_POWER_LOW_ALARM_FLAG,
304+
*(NumberRegField("%s%d" % (consts.TX_POWER_LOW_ALARM_FLAG, lane), self.getaddr(0x11, 140),
305+
RegBitField("Bit%d" % (lane-1), (lane-1))
306+
) for lane in range(1, 9))
307+
),
308+
RegGroupField(consts.TX_POWER_HIGH_WARN_FLAG,
309+
*(NumberRegField("%s%d" % (consts.TX_POWER_HIGH_WARN_FLAG, lane), self.getaddr(0x11, 141),
310+
RegBitField("Bit%d" % (lane-1), (lane-1))
311+
) for lane in range(1, 9))
312+
),
313+
RegGroupField(consts.TX_POWER_LOW_WARN_FLAG,
314+
*(NumberRegField("%s%d" % (consts.TX_POWER_LOW_WARN_FLAG, lane), self.getaddr(0x11, 142),
315+
RegBitField("Bit%d" % (lane-1), (lane-1))
316+
) for lane in range(1, 9))
317+
)
318+
)
319+
320+
# Group for TX bias alarm and warning flags
321+
self.TX_BIAS_ALARM_FLAGS = RegGroupField(consts.TX_BIAS_ALARM_FLAGS_FIELD,
322+
RegGroupField(consts.TX_BIAS_HIGH_ALARM_FLAG,
323+
*(NumberRegField("%s%d" % (consts.TX_BIAS_HIGH_ALARM_FLAG, lane), self.getaddr(0x11, 143),
324+
RegBitField("Bit%d" % (lane-1), (lane-1))
325+
) for lane in range(1, 9))
326+
),
327+
RegGroupField(consts.TX_BIAS_LOW_ALARM_FLAG,
328+
*(NumberRegField("%s%d" % (consts.TX_BIAS_LOW_ALARM_FLAG, lane), self.getaddr(0x11, 144),
329+
RegBitField("Bit%d" % (lane-1), (lane-1))
330+
) for lane in range(1, 9))
331+
),
332+
RegGroupField(consts.TX_BIAS_HIGH_WARN_FLAG,
333+
*(NumberRegField("%s%d" % (consts.TX_BIAS_HIGH_WARN_FLAG, lane), self.getaddr(0x11, 145),
334+
RegBitField("Bit%d" % (lane-1), (lane-1))
335+
) for lane in range(1, 9))
336+
),
337+
RegGroupField(consts.TX_BIAS_LOW_WARN_FLAG,
338+
*(NumberRegField("%s%d" % (consts.TX_BIAS_LOW_WARN_FLAG, lane), self.getaddr(0x11, 146),
339+
RegBitField("Bit%d" % (lane-1), (lane-1))
340+
) for lane in range(1, 9))
341+
)
342+
)
343+
344+
# Group for RX power alarm and warning flags
345+
self.RX_POWER_ALARM_FLAGS = RegGroupField(consts.RX_POWER_ALARM_FLAGS_FIELD,
346+
RegGroupField(consts.RX_POWER_HIGH_ALARM_FLAG,
347+
*(NumberRegField("%s%d" % (consts.RX_POWER_HIGH_ALARM_FLAG, lane), self.getaddr(0x11, 149),
348+
RegBitField("Bit%d" % (lane-1), (lane-1))
349+
) for lane in range(1, 9))
350+
),
351+
RegGroupField(consts.RX_POWER_LOW_ALARM_FLAG,
352+
*(NumberRegField("%s%d" % (consts.RX_POWER_LOW_ALARM_FLAG, lane), self.getaddr(0x11, 150),
353+
RegBitField("Bit%d" % (lane-1), (lane-1))
354+
) for lane in range(1, 9))
355+
),
356+
RegGroupField(consts.RX_POWER_HIGH_WARN_FLAG,
357+
*(NumberRegField("%s%d" % (consts.RX_POWER_HIGH_WARN_FLAG, lane), self.getaddr(0x11, 151),
358+
RegBitField("Bit%d" % (lane-1), (lane-1))
359+
) for lane in range(1, 9))
360+
),
361+
RegGroupField(consts.RX_POWER_LOW_WARN_FLAG,
362+
*(NumberRegField("%s%d" % (consts.RX_POWER_LOW_WARN_FLAG, lane), self.getaddr(0x11, 152),
363+
RegBitField("Bit%d" % (lane-1), (lane-1))
364+
) for lane in range(1, 9))
365+
)
366+
)
367+
296368
self.LANE_DATAPATH_STATUS = RegGroupField(consts.LANE_DATAPATH_STATUS_FIELD,
297369
RegGroupField(consts.TX_FAULT_FIELD,
298370
*(NumberRegField("%s%d" % (consts.TX_FAULT_FIELD, lane), self.getaddr(0x11, 135),

tests/sonic_xcvr/test_cmis.py

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -273,74 +273,71 @@ def test_get_rx_cdr_lol(self, mock_response, expected):
273273
assert result == expected
274274

275275
@pytest.mark.parametrize("mock_response, expected", [
276-
([{'TxPowerHighAlarmFlag1':0}, {'TxPowerLowAlarmFlag1':0}, {'TxPowerHighWarnFlag1':0}, {'TxPowerLowWarnFlag1':0}],
277-
{
278-
'tx_power_high_alarm':{
279-
'TxPowerHighAlarmFlag1': False
280-
},
281-
'tx_power_low_alarm':{
282-
'TxPowerLowAlarmFlag1': False
283-
},
284-
'tx_power_high_warn':{
285-
'TxPowerHighWarnFlag1': False,
276+
(
277+
{
278+
consts.TX_POWER_HIGH_ALARM_FLAG: {'TxPowerHighAlarmFlag1': 0},
279+
consts.TX_POWER_LOW_ALARM_FLAG: {'TxPowerLowAlarmFlag1': 0},
280+
consts.TX_POWER_HIGH_WARN_FLAG: {'TxPowerHighWarnFlag1': 0},
281+
consts.TX_POWER_LOW_WARN_FLAG: {'TxPowerLowWarnFlag1': 0}
286282
},
287-
'tx_power_low_warn':{
288-
'TxPowerLowWarnFlag1': False
283+
{
284+
'tx_power_high_alarm': {'TxPowerHighAlarmFlag1': False},
285+
'tx_power_low_alarm': {'TxPowerLowAlarmFlag1': False},
286+
'tx_power_high_warn': {'TxPowerHighWarnFlag1': False},
287+
'tx_power_low_warn': {'TxPowerLowWarnFlag1': False}
289288
}
290-
}),
291-
([None, None, None, None], None)
289+
),
290+
(None, None)
292291
])
293292
def test_get_tx_power_flag(self, mock_response, expected):
294293
self.api.xcvr_eeprom.read = MagicMock()
295-
self.api.xcvr_eeprom.read.side_effect = mock_response
294+
self.api.xcvr_eeprom.read.return_value = mock_response
296295
result = self.api.get_tx_power_flag()
297296
assert result == expected
298297

299298
@pytest.mark.parametrize("mock_response, expected", [
300-
([{'TxBiasHighAlarmFlag1':0}, {'TxBiasLowAlarmFlag1':0}, {'TxBiasHighWarnFlag1':0}, {'TxBiasLowWarnFlag1':0}],
301-
{
302-
'tx_bias_high_alarm':{
303-
'TxBiasHighAlarmFlag1': False
304-
},
305-
'tx_bias_low_alarm':{
306-
'TxBiasLowAlarmFlag1': False
307-
},
308-
'tx_bias_high_warn':{
309-
'TxBiasHighWarnFlag1': False,
299+
(
300+
{
301+
consts.TX_BIAS_HIGH_ALARM_FLAG: {'TxBiasHighAlarmFlag1': 0},
302+
consts.TX_BIAS_LOW_ALARM_FLAG: {'TxBiasLowAlarmFlag1': 0},
303+
consts.TX_BIAS_HIGH_WARN_FLAG: {'TxBiasHighWarnFlag1': 0},
304+
consts.TX_BIAS_LOW_WARN_FLAG: {'TxBiasLowWarnFlag1': 0}
310305
},
311-
'tx_bias_low_warn':{
312-
'TxBiasLowWarnFlag1': False
306+
{
307+
'tx_bias_high_alarm': {'TxBiasHighAlarmFlag1': False},
308+
'tx_bias_low_alarm': {'TxBiasLowAlarmFlag1': False},
309+
'tx_bias_high_warn': {'TxBiasHighWarnFlag1': False},
310+
'tx_bias_low_warn': {'TxBiasLowWarnFlag1': False}
313311
}
314-
}),
315-
([None, None, None, None], None)
312+
),
313+
(None, None)
316314
])
317315
def test_get_tx_bias_flag(self, mock_response, expected):
318316
self.api.xcvr_eeprom.read = MagicMock()
319-
self.api.xcvr_eeprom.read.side_effect = mock_response
317+
self.api.xcvr_eeprom.read.return_value = mock_response
320318
result = self.api.get_tx_bias_flag()
321319
assert result == expected
322320

323321
@pytest.mark.parametrize("mock_response, expected", [
324-
([{'RxPowerHighAlarmFlag1':0}, {'RxPowerLowAlarmFlag1':0}, {'RxPowerHighWarnFlag1':0}, {'RxPowerLowWarnFlag1':0}],
325-
{
326-
'rx_power_high_alarm':{
327-
'RxPowerHighAlarmFlag1': False
328-
},
329-
'rx_power_low_alarm':{
330-
'RxPowerLowAlarmFlag1': False
331-
},
332-
'rx_power_high_warn':{
333-
'RxPowerHighWarnFlag1': False,
322+
(
323+
{
324+
consts.RX_POWER_HIGH_ALARM_FLAG: {'RxPowerHighAlarmFlag1': 0},
325+
consts.RX_POWER_LOW_ALARM_FLAG: {'RxPowerLowAlarmFlag1': 0},
326+
consts.RX_POWER_HIGH_WARN_FLAG: {'RxPowerHighWarnFlag1': 0},
327+
consts.RX_POWER_LOW_WARN_FLAG: {'RxPowerLowWarnFlag1': 0}
334328
},
335-
'rx_power_low_warn':{
336-
'RxPowerLowWarnFlag1': False
329+
{
330+
'rx_power_high_alarm': {'RxPowerHighAlarmFlag1': False},
331+
'rx_power_low_alarm': {'RxPowerLowAlarmFlag1': False},
332+
'rx_power_high_warn': {'RxPowerHighWarnFlag1': False},
333+
'rx_power_low_warn': {'RxPowerLowWarnFlag1': False}
337334
}
338-
}),
339-
([None, None, None, None], None)
335+
),
336+
(None, None)
340337
])
341338
def test_get_rx_power_flag(self, mock_response, expected):
342339
self.api.xcvr_eeprom.read = MagicMock()
343-
self.api.xcvr_eeprom.read.side_effect = mock_response
340+
self.api.xcvr_eeprom.read.return_value = mock_response
344341
result = self.api.get_rx_power_flag()
345342
assert result == expected
346343

0 commit comments

Comments
 (0)