Skip to content
Open
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
13 changes: 11 additions & 2 deletions sonic-xcvrd/tests/test_xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -1386,7 +1386,11 @@ def mock_get_transceiver_status_flags(physical_port):
'prefec_ber_max': '0.0006833674050752236',
'uncorr_frames_avg': '0.0',
'uncorr_frames_min': '0.0',
'uncorr_frames_max': '0.0', }))
'uncorr_frames_max': '0.0',
'rx_bits_pm': '1000000',
'rx_corr_bits_pm': '1000',
'tx_bits_pm': '2000000',
'tx_frames_pm': '20000', }))
def test_post_port_pm_info_to_db(self):
logical_port_name = "Ethernet0"
port_mapping = PortMapping()
Expand All @@ -1395,9 +1399,14 @@ def test_post_port_pm_info_to_db(self):
mock_cmis_manager = MagicMock()
dom_info_update = DomInfoUpdateTask(DEFAULT_NAMESPACE, port_mapping, mock_sfp_obj_dict, stop_event, mock_cmis_manager)
pm_tbl = Table("STATE_DB", TRANSCEIVER_PM_TABLE)
pm_counters_tbl = Table("STATE_DB", TRANSCEIVER_PM_COUNTERS_TABLE)
assert pm_tbl.get_size() == 0
dom_info_update.post_port_pm_info_to_db(logical_port_name, port_mapping, pm_tbl, stop_event)
assert pm_counters_tbl.get_size() == 0
dom_info_update.post_port_pm_info_to_db(logical_port_name, port_mapping, pm_tbl, pm_counters_tbl, stop_event)
# Non-counter fields (6 preFEC ratios) go to TRANSCEIVER_PM.
Comment on lines +1402 to +1406
assert pm_tbl.get_size_for_key(logical_port_name) == 6
# Raw FEC counters (2 rx + 2 tx) go to TRANSCEIVER_PM_COUNTERS.
assert pm_counters_tbl.get_size_for_key(logical_port_name) == 4

@patch('xcvrd.xcvrd_utilities.port_event_helper.PortMapping.logical_port_name_to_physical_port_list', MagicMock(return_value=[0]))
@patch('xcvrd.xcvrd_utilities.common._wrapper_get_presence', MagicMock(return_value=True))
Expand Down
32 changes: 28 additions & 4 deletions sonic-xcvrd/xcvrd/dom/dom_mgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@
PORT_UPDATE_EVENT_SELECT_TIMEOUT_MSECS = 1000
PORT_UPDATE_EVENT_SELECT_TIMEOUT_FAST_MSECS = 10

# Raw FEC counter fields from get_transceiver_pm() that are published to the
# TRANSCEIVER_PM_COUNTERS table instead of TRANSCEIVER_PM. This is a positive list:
# any field not named here (calculated ratios, optical metrics) stays in TRANSCEIVER_PM.
PM_COUNTER_FIELDS = frozenset({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nkanchi-nexthop there are streaming telemetry applications already using these counters from TRANSCEIVER_PM so this change will break those. To maintain backward compatibility, I would suggest to not remove these fields from old PM table

# media (page 34h) RX FEC counters
'rx_bits_pm', 'rx_bits_subint_pm', 'rx_corr_bits_pm',
'rx_min_corr_bits_subint_pm', 'rx_max_corr_bits_subint_pm',
'rx_frames_pm', 'rx_frames_subint_pm', 'rx_frames_uncorr_err_pm',
'rx_min_frames_uncorr_err_subint_pm', 'rx_max_frames_uncorr_err_subint_pm',
# host (page 3Ah) TX FEC counters
'tx_bits_pm', 'tx_bits_subint_pm', 'tx_corr_bits_pm',
'tx_min_corr_bits_subint_pm', 'tx_max_corr_bits_subint_pm',
'tx_frames_pm', 'tx_frames_subint_pm', 'tx_frames_uncorr_err_pm',
'tx_min_frames_uncorr_err_subint_pm', 'tx_max_frames_uncorr_err_subint_pm',
'tx_corrected_frames_pm', 'tx_corrected_frames_subint_pm',
})

class DomInfoUpdateBase(threading.Thread):

name = ''
Expand Down Expand Up @@ -235,7 +252,7 @@ def post_port_sfp_firmware_info_to_db(self, logical_port_name, port_mapping, tab
sys.exit(xcvrd.NOT_IMPLEMENTED_ERROR)

# Update port pm info in db
def post_port_pm_info_to_db(self, logical_port_name, port_mapping, table, stop_event=threading.Event(), pm_info_cache=None):
def post_port_pm_info_to_db(self, logical_port_name, port_mapping, pm_table, pm_counters_table, stop_event=threading.Event(), pm_info_cache=None):
for physical_port, physical_port_name in common.get_physical_port_name_dict(logical_port_name, port_mapping).items():
if stop_event.is_set():
break
Comment on lines +255 to 258
Expand All @@ -259,8 +276,14 @@ def post_port_pm_info_to_db(self, logical_port_name, port_mapping, table, stop_e
if not pm_info_dict:
continue
self.db_utils.beautify_info_dict(pm_info_dict)
fvs = swsscommon.FieldValuePairs([(k, v) for k, v in pm_info_dict.items()])
table.set(physical_port_name, fvs)
# Route raw FEC counters to TRANSCEIVER_PM_COUNTERS; everything else
# (calculated ratios, optical metrics) stays in TRANSCEIVER_PM.
pm_dict = {k: v for k, v in pm_info_dict.items() if k not in PM_COUNTER_FIELDS}
pm_counters_dict = {k: v for k, v in pm_info_dict.items() if k in PM_COUNTER_FIELDS}
if pm_dict:
pm_table.set(physical_port_name, swsscommon.FieldValuePairs(list(pm_dict.items())))
if pm_counters_dict:
pm_counters_table.set(physical_port_name, swsscommon.FieldValuePairs(list(pm_counters_dict.items())))
else:
return xcvrd.SFP_EEPROM_NOT_READY

Expand Down Expand Up @@ -395,7 +418,7 @@ def task_worker(self):
except (KeyError, TypeError) as e:
self.log_warning("Got exception {} while processing vdm statistic values for port {}, ignored".format(repr(e), logical_port_name))
try:
self.post_port_pm_info_to_db(logical_port_name, self.port_mapping, self.xcvr_table_helper.get_pm_tbl(asic_index), self.task_stopping_event)
self.post_port_pm_info_to_db(logical_port_name, self.port_mapping, self.xcvr_table_helper.get_pm_tbl(asic_index), self.xcvr_table_helper.get_pm_counters_tbl(asic_index), self.task_stopping_event)
except (KeyError, TypeError) as e:
self.log_warning("Got exception {} while posting pm info to DB for port {}, ignored".format(repr(e), logical_port_name))

Expand Down Expand Up @@ -520,6 +543,7 @@ def on_remove_logical_port(self, port_change_event):
self.xcvr_table_helper.get_status_flag_set_time_tbl(port_change_event.asic_id),
self.xcvr_table_helper.get_status_flag_clear_time_tbl(port_change_event.asic_id),
self.xcvr_table_helper.get_pm_tbl(port_change_event.asic_id),
self.xcvr_table_helper.get_pm_counters_tbl(port_change_event.asic_id),
self.xcvr_table_helper.get_firmware_info_tbl(port_change_event.asic_id)
])

Expand Down
8 changes: 8 additions & 0 deletions sonic-xcvrd/xcvrd/xcvrd_utilities/xcvr_table_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
TRANSCEIVER_VDM_HWARN_FLAG_CLEAR_TIME = 'TRANSCEIVER_VDM_HWARN_FLAG_CLEAR_TIME'
TRANSCEIVER_VDM_LWARN_FLAG_CLEAR_TIME = 'TRANSCEIVER_VDM_LWARN_FLAG_CLEAR_TIME'
TRANSCEIVER_PM_TABLE = 'TRANSCEIVER_PM'
TRANSCEIVER_PM_COUNTERS_TABLE = 'TRANSCEIVER_PM_COUNTERS'
TRANSCEIVER_CMIS_STATE_TIMESTAMPS_TABLE = 'TRANSCEIVER_CMIS_STATE_TIMESTAMPS'

Comment on lines 47 to 50
NPU_SI_SETTINGS_SYNC_STATUS_KEY = 'NPU_SI_SETTINGS_SYNC_STATUS'
NPU_SI_SETTINGS_DEFAULT_VALUE = 'NPU_SI_SETTINGS_DEFAULT'
Expand All @@ -69,6 +71,8 @@ def __init__(self, namespaces):
self.status_flag_set_time_tbl = {}
self.status_flag_clear_time_tbl = {}
self.status_sw_tbl = {}
self.cmis_state_timestamps_tbl = {}
self.pm_counters_tbl = {}
Comment on lines 73 to +75
self.vdm_real_value_tbl = {}
VDM_THRESHOLD_TYPES = ['halarm', 'lalarm', 'hwarn', 'lwarn']
self.vdm_threshold_tbl = {f'vdm_{t}_threshold_tbl': {} for t in VDM_THRESHOLD_TYPES}
Expand All @@ -94,6 +98,7 @@ def __init__(self, namespaces):
self.status_flag_clear_time_tbl[asic_id] = swsscommon.Table(self.state_db[asic_id], TRANSCEIVER_STATUS_FLAG_CLEAR_TIME_TABLE)
self.status_sw_tbl[asic_id] = swsscommon.Table(self.state_db[asic_id], TRANSCEIVER_STATUS_SW_TABLE)
self.pm_tbl[asic_id] = swsscommon.Table(self.state_db[asic_id], TRANSCEIVER_PM_TABLE)
self.pm_counters_tbl[asic_id] = swsscommon.Table(self.state_db[asic_id], TRANSCEIVER_PM_COUNTERS_TABLE)
self.firmware_info_tbl[asic_id] = swsscommon.Table(self.state_db[asic_id], TRANSCEIVER_FIRMWARE_INFO_TABLE)
self.state_port_tbl[asic_id] = swsscommon.Table(self.state_db[asic_id], swsscommon.STATE_PORT_TABLE_NAME)
self.appl_db[asic_id] = daemon_base.db_connect("APPL_DB", namespace)
Expand Down Expand Up @@ -171,6 +176,9 @@ def get_vdm_flag_clear_time_tbl(self, asic_id, threshold_type):
def get_pm_tbl(self, asic_id):
return self.pm_tbl[asic_id]

def get_pm_counters_tbl(self, asic_id):
return self.pm_counters_tbl[asic_id]

def get_firmware_info_tbl(self, asic_id):
return self.firmware_info_tbl[asic_id]

Expand Down
Loading