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

Add high power class support for non-CMIS modules in xcvrd #574

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
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
52 changes: 45 additions & 7 deletions sonic-xcvrd/tests/test_xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class TestXcvrdThreadException(object):
@patch('xcvrd.sff_mgr.PortChangeObserver', MagicMock(side_effect=NotImplementedError))
def test_SffManagerTask_task_run_with_exception(self):
stop_event = threading.Event()
sff_mgr = SffManagerTask(DEFAULT_NAMESPACE, stop_event, MagicMock(), helper_logger)
sff_mgr = SffManagerTask(True, DEFAULT_NAMESPACE, stop_event, MagicMock(), helper_logger)
exception_received = None
trace = None
try:
Expand Down Expand Up @@ -1432,7 +1432,7 @@ def test_DaemonXcvrd_run(self, mock_task_stop1, mock_task_stop2, mock_task_run1,

def test_SffManagerTask_handle_port_change_event(self):
stop_event = threading.Event()
task = SffManagerTask(DEFAULT_NAMESPACE, stop_event, MagicMock(), helper_logger)
task = SffManagerTask(True, DEFAULT_NAMESPACE, stop_event, MagicMock(), helper_logger)

port_change_event = PortChangeEvent('PortConfigDone', -1, 0, PortChangeEvent.PORT_SET)
task.on_port_update_event(port_change_event)
Expand Down Expand Up @@ -1470,7 +1470,7 @@ def test_SffManagerTask_handle_port_change_event(self):
assert len(task.port_dict) == 0

def test_SffManagerTask_get_active_lanes_for_lport(self):
sff_manager_task = SffManagerTask(DEFAULT_NAMESPACE,
sff_manager_task = SffManagerTask(True, DEFAULT_NAMESPACE,
threading.Event(),
MagicMock(),
helper_logger)
Expand Down Expand Up @@ -1524,7 +1524,7 @@ def test_SffManagerTask_get_active_lanes_for_lport(self):
assert result == expected_result

def test_SffManagerTask_get_active_lanes_for_lport_with_invalid_input(self):
sff_manager_task = SffManagerTask(DEFAULT_NAMESPACE,
sff_manager_task = SffManagerTask(True, DEFAULT_NAMESPACE,
threading.Event(),
MagicMock(),
helper_logger)
Expand All @@ -1547,7 +1547,7 @@ def test_SffManagerTask_get_active_lanes_for_lport_with_invalid_input(self):
def test_SffManagerTask_get_host_tx_status(self, mock_get_state_port_tbl):
mock_get_state_port_tbl.return_value.hget.return_value = (True, 'true')

sff_manager_task = SffManagerTask(DEFAULT_NAMESPACE,
sff_manager_task = SffManagerTask(True, DEFAULT_NAMESPACE,
threading.Event(),
MagicMock(),
helper_logger)
Expand All @@ -1561,7 +1561,7 @@ def test_SffManagerTask_get_host_tx_status(self, mock_get_state_port_tbl):
def test_SffManagerTask_get_admin_status(self, mock_get_cfg_port_tbl):
mock_get_cfg_port_tbl.return_value.hget.return_value = (True, 'up')

sff_manager_task = SffManagerTask(DEFAULT_NAMESPACE,
sff_manager_task = SffManagerTask(True, DEFAULT_NAMESPACE,
threading.Event(),
MagicMock(),
helper_logger)
Expand All @@ -1587,7 +1587,7 @@ def test_SffManagerTask_task_worker(self, mock_chassis):
mock_chassis.get_all_sfps = MagicMock(return_value=[mock_sfp])
mock_chassis.get_sfp = MagicMock(return_value=mock_sfp)

task = SffManagerTask(DEFAULT_NAMESPACE,
task = SffManagerTask(True, DEFAULT_NAMESPACE,
threading.Event(),
mock_chassis,
helper_logger)
Expand Down Expand Up @@ -1673,6 +1673,44 @@ def test_SffManagerTask_task_worker(self, mock_chassis):
assert mock_xcvr_api.tx_disable_channel.call_count == 2
mock_sfp.get_presence = MagicMock(return_value=True)

# high power enabling failure case and enable_sff_mgr_controlled_tx is False
mock_xcvr_api.tx_disable_channel.call_count = 0
mock_xcvr_api.set_high_power_class.call_count = 0
task.enable_sff_mgr_controlled_tx = False
task.get_host_tx_status = MagicMock(return_value='true')
task.get_admin_status = MagicMock(return_value='up')
mock_xcvr_api.set_high_power_class = MagicMock(return_value=False)
port_change_event = PortChangeEvent('Ethernet4', 2, 0, PortChangeEvent.PORT_SET, {
'type': 'QSFP28',
'subport': '0',
'lanes': '1,2,3,4',
})
task.on_port_update_event(port_change_event)
assert len(task.port_dict) == 2
task.task_stopping_event.is_set = MagicMock(side_effect=[False] + [False] * len(task.port_dict) + [True])
task.task_worker()
assert mock_xcvr_api.tx_disable_channel.call_count == 0
assert mock_xcvr_api.set_high_power_class.call_count == 1

# high power enabling exception case
mock_xcvr_api.tx_disable_channel.call_count = 0
mock_xcvr_api.set_high_power_class.call_count = 0
task.enable_sff_mgr_controlled_tx = False
task.get_host_tx_status = MagicMock(return_value='true')
task.get_admin_status = MagicMock(return_value='up')
mock_xcvr_api.set_high_power_class = MagicMock(side_effect=AttributeError("Attribute not found"))
port_change_event = PortChangeEvent('Ethernet8', 3, 0, PortChangeEvent.PORT_SET, {
'type': 'QSFP28',
'subport': '0',
'lanes': '1,2,3,4',
})
task.on_port_update_event(port_change_event)
assert len(task.port_dict) == 3
task.task_stopping_event.is_set = MagicMock(side_effect=[False] + [False] * len(task.port_dict) + [True])
task.task_worker()
assert mock_xcvr_api.tx_disable_channel.call_count == 0
assert mock_xcvr_api.set_high_power_class.call_count == 1

def test_CmisManagerTask_update_port_transceiver_status_table_sw_cmis_state(self):
port_mapping = PortMapping()
stop_event = threading.Event()
Expand Down
18 changes: 17 additions & 1 deletion sonic-xcvrd/xcvrd/sff_mgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ class SffManagerTask(threading.Thread):

SFF_LOGGER_PREFIX = "SFF-MAIN: "

def __init__(self, namespaces, main_thread_stop_event, platform_chassis, helper_logger):
def __init__(self, enable_sff_mgr_controlled_tx, namespaces, main_thread_stop_event, platform_chassis, helper_logger):
threading.Thread.__init__(self)
self.name = "SffManagerTask"
self.enable_sff_mgr_controlled_tx = enable_sff_mgr_controlled_tx
self.exc = None
self.task_stopping_event = threading.Event()
self.main_thread_stop_event = main_thread_stop_event
Expand All @@ -96,6 +97,9 @@ def __init__(self, namespaces, main_thread_stop_event, platform_chassis, helper_
self.xcvr_table_helper = XcvrTableHelper(namespaces)
self.namespaces = namespaces

if not self.enable_sff_mgr_controlled_tx:
self.log_notice("enable_sff_mgr_controlled_tx is False, skipping controlling module TX based on host_tx_ready")

def log_notice(self, message):
self.helper_logger.log_notice("{}{}".format(self.SFF_LOGGER_PREFIX, message))

Expand Down Expand Up @@ -435,6 +439,18 @@ def task_worker(self):
# Skip if these essential routines are not available
continue

if xcvr_inserted:
try:
if api.set_high_power_class(True):
self.log_notice("{}: done enabling high power class".format(lport))
else:
self.log_error("{}: failed to enable high power class".format(lport))
except (AttributeError, NotImplementedError):
pass

if not self.enable_sff_mgr_controlled_tx:
continue

if active_lanes is None:
active_lanes = self.get_active_lanes_for_lport(lport, subport_idx,
len(lanes_list),
Expand Down
18 changes: 7 additions & 11 deletions sonic-xcvrd/xcvrd/xcvrd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2052,12 +2052,12 @@ def retry_eeprom_reading(self):


class DaemonXcvrd(daemon_base.DaemonBase):
def __init__(self, log_identifier, skip_cmis_mgr=False, enable_sff_mgr=False):
def __init__(self, log_identifier, skip_cmis_mgr=False, enable_sff_mgr_controlled_tx=False):
super(DaemonXcvrd, self).__init__(log_identifier, enable_runtime_log_config=True)
self.stop_event = threading.Event()
self.sfp_error_event = threading.Event()
self.skip_cmis_mgr = skip_cmis_mgr
self.enable_sff_mgr = enable_sff_mgr
self.enable_sff_mgr_controlled_tx = enable_sff_mgr_controlled_tx
self.namespaces = ['']
self.threads = []

Expand Down Expand Up @@ -2222,13 +2222,9 @@ def run(self):
port_mapping_data = self.init()

# Start the SFF manager
sff_manager = None
if self.enable_sff_mgr:
sff_manager = SffManagerTask(self.namespaces, self.stop_event, platform_chassis, helper_logger)
sff_manager.start()
self.threads.append(sff_manager)
else:
self.log_notice("Skipping SFF Task Manager")
sff_manager = SffManagerTask(self.enable_sff_mgr_controlled_tx, self.namespaces, self.stop_event, platform_chassis, helper_logger)
sff_manager.start()
self.threads.append(sff_manager)

# Start the CMIS manager
cmis_manager = None
Expand Down Expand Up @@ -2308,10 +2304,10 @@ def run(self):
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--skip_cmis_mgr', action='store_true')
parser.add_argument('--enable_sff_mgr', action='store_true')
parser.add_argument('--enable_sff_mgr_controlled_tx', action='store_true')

args = parser.parse_args()
xcvrd = DaemonXcvrd(SYSLOG_IDENTIFIER, args.skip_cmis_mgr, args.enable_sff_mgr)
xcvrd = DaemonXcvrd(SYSLOG_IDENTIFIER, args.skip_cmis_mgr, args.enable_sff_mgr_controlled_tx)
xcvrd.run()


Expand Down
Loading