Skip to content
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
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pr:
include:
- '*'

pool: sonic-common
pool: sonictest

resources:
containers:
Expand Down
41 changes: 41 additions & 0 deletions sonic-xcvrd/tests/test_xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2102,6 +2102,47 @@ def test_SffManagerTask_get_admin_status(self, mock_get_cfg_port_tbl):
mock_get_cfg_port_tbl.assert_called_once_with(0)
mock_get_cfg_port_tbl.return_value.hget.assert_called_once_with(lport, 'admin_status')

@patch('xcvrd.xcvrd.helper_logger')
@patch('xcvrd.xcvrd.platform_chassis')
@patch('xcvrd.sff_mgr.PortChangeObserver')
def test_SffManagerTask_xcvr_api_none_in_task_worker(self, mock_observer, mock_chassis, mock_logger):
"""Test the full task_worker flow when xcvr API is None"""
mock_observer_instance = MagicMock()
mock_observer_instance.handle_port_update_event = MagicMock(side_effect=[True, False])
mock_observer.return_value = mock_observer_instance

# Setup mock SFP that returns None for get_xcvr_api
mock_sfp = MagicMock()
mock_sfp.get_presence = MagicMock(return_value=True)
mock_sfp.get_xcvr_api = MagicMock(return_value=None)
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)

sff_manager_task = SffManagerTask(DEFAULT_NAMESPACE,
threading.Event(),
mock_chassis,
mock_logger)

# Setup port_dict with necessary data
sff_manager_task.port_dict['Ethernet0'] = {
'index': 1,
'type': 'QSFP28',
'subport': '0',
'lanes': ['1', '2', '3', '4'],
'host_tx_ready': 'true',
'admin_status': 'up',
'asic_id': 0
}

# Mock task_stopping_event to stop after processing once
sff_manager_task.task_stopping_event.is_set = MagicMock(side_effect=[False, False, True])

# Run task_worker - it should handle the None API gracefully
sff_manager_task.task_worker()

# Verify error was logged
assert any("skipping sff_mgr since no xcvr api!" in str(call)
for call in mock_logger.log_error.call_args_list)

@patch('xcvrd.xcvrd.platform_chassis')
@patch('xcvrd.sff_mgr.PortChangeObserver', MagicMock(handle_port_update_event=MagicMock()))
def test_SffManagerTask_task_worker(self, mock_chassis):
Expand Down
33 changes: 19 additions & 14 deletions sonic-xcvrd/xcvrd/sff_mgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from .xcvrd_utilities.port_event_helper import PortChangeObserver
from .xcvrd_utilities.xcvr_table_helper import XcvrTableHelper
from xcvrd import xcvrd
from sonic_platform_base.sonic_xcvr.api.public.sff8472 import Sff8472Api
except ImportError as e:
raise ImportError(str(e) + " - required module not found")
Expand Down Expand Up @@ -348,8 +349,25 @@ def task_worker(self):
# TRANSCEIVER_INFO table's XCVR_TYPE is not ready, meaning xcvr is not present
continue

# double-check the HW presence before moving forward
sfp = self.platform_chassis.get_sfp(pport)
if not sfp.get_presence():
self.log_error("{}: module not present!".format(lport))
del self.port_dict[lport][self.XCVR_TYPE]
continue
try:
# Skip if XcvrApi is not supported
api = sfp.get_xcvr_api()
if api is None:
self.log_error(
"{}: skipping sff_mgr since no xcvr api!".format(lport))
continue
except (AttributeError, NotImplementedError):
# Skip if these essential routines are not available
continue

# Procced only for QSFP28/QSFP+ transceiver
if not (xcvr_type.startswith('QSFP28') or xcvr_type.startswith('QSFP+')):
if not (xcvr_type.startswith('QSFP28') or xcvr_type.startswith('QSFP+')) or xcvrd.is_cmis_api(api):
continue

# Handle the case that host_tx_ready value in the local cache hasn't
Expand Down Expand Up @@ -403,20 +421,7 @@ def task_worker(self):
data[self.HOST_TX_READY], host_tx_ready_changed,
data[self.ADMIN_STATUS], admin_status_changed))

# double-check the HW presence before moving forward
sfp = self.platform_chassis.get_sfp(pport)
if not sfp.get_presence():
self.log_error("{}: module not present!".format(lport))
del self.port_dict[lport][self.XCVR_TYPE]
continue
try:
# Skip if XcvrApi is not supported
api = sfp.get_xcvr_api()
if api is None:
self.log_error(
"{}: skipping sff_mgr since no xcvr api!".format(lport))
continue

# Skip if it's not a paged memory device
if api.is_flat_memory():
self.log_notice(
Expand Down
Loading