diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index 5625b04eab..ea34db9035 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -3106,23 +3106,19 @@ This command is the standard CMIS diagnostic control used for troubleshooting li - Usage: ``` - sfputil debug loopback PORT_NAME LOOPBACK_MODE + sfputil debug loopback PORT_NAME LOOPBACK_MODE Set the loopback mode - host-side-input: enable host side input loopback mode - host-side-output: enable host side output loopback mode - media-side-input: enable media side input loopback mode - media-side-output: enable media side output loopback mode - host-side-input-none: disable host side input loopback mode - host-side-output-none: disable host side output loopback mode - media-side-input-none: disable media side input loopback mode - media-side-output-none: disable media side output loopback mode - none: disable all loopback mode + host-side-input: host side input loopback mode + host-side-output: host side output loopback mode + media-side-input: media side input loopback mode + media-side-output: media side output loopback mode ``` - Example: ``` - admin@sonic:~$ sfputil debug loopback Ethernet88 host-side-input + admin@sonic:~$ sfputil debug loopback Ethernet88 host-side-input enable + admin@sonic:~$ sfputil debug loopback Ethernet88 media-side-output disable ``` ## DHCP Relay diff --git a/sfputil/main.py b/sfputil/main.py index 004a47ea9f..54b3805f1a 100644 --- a/sfputil/main.py +++ b/sfputil/main.py @@ -1968,12 +1968,12 @@ def debug(): # 'loopback' subcommand @debug.command() @click.argument('port_name', required=True, default=None) -@click.argument('loopback_mode', required=True, default="none", - type=click.Choice(["none", "host-side-input", "host-side-output", - "media-side-input", "media-side-output", - "host-side-input-none", "host-side-output-none", - "media-side-input-none", "media-side-output-none"])) -def loopback(port_name, loopback_mode): +@click.argument('loopback_mode', required=True, default=None, + type=click.Choice(["host-side-input", "host-side-output", + "media-side-input", "media-side-output"])) +@click.argument('enable', required=True, default=None, + type=click.Choice(["enable", "disable"])) +def loopback(port_name, loopback_mode, enable): """Set module diagnostic loopback mode """ physical_port = logical_port_to_physical_port_index(port_name) @@ -2040,12 +2040,15 @@ def loopback(port_name, loopback_mode): lane_mask = 0 try: - status = api.set_loopback_mode(loopback_mode, lane_mask=lane_mask) + status = api.set_loopback_mode(loopback_mode, + lane_mask=lane_mask, + enable=enable == 'enable') except AttributeError: click.echo("{}: Set loopback mode is not applicable for this module".format(port_name)) sys.exit(ERROR_NOT_IMPLEMENTED) except TypeError: - status = api.set_loopback_mode(loopback_mode) + click.echo("{}: Set loopback mode failed. Parameter is not supported".format(port_name)) + sys.exit(EXIT_FAIL) if status: click.echo("{}: Set {} loopback".format(port_name, loopback_mode)) diff --git a/tests/sfputil_test.py b/tests/sfputil_test.py index 3d54d5d715..5f1374be12 100644 --- a/tests/sfputil_test.py +++ b/tests/sfputil_test.py @@ -1648,63 +1648,64 @@ def test_debug_loopback(self, mock_sonic_v2_connector, mock_config_db_connector, runner = CliRunner() mock_sfp.get_presence.return_value = False result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "host-side-input"]) + ["Ethernet0", "host-side-input", "enable"]) assert result.output == 'Ethernet0: SFP EEPROM not detected\n' mock_sfp.get_presence.return_value = True mock_sfp.get_xcvr_api = MagicMock(side_effect=NotImplementedError) result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "host-side-input"]) + ["Ethernet0", "host-side-input", "enable"]) assert result.output == 'Ethernet0: This functionality is not implemented\n' assert result.exit_code == ERROR_NOT_IMPLEMENTED mock_sfp.get_xcvr_api = MagicMock(return_value=mock_api) result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "host-side-input"]) + ["Ethernet0", "host-side-input", "enable"]) assert result.output == 'Ethernet0: Set host-side-input loopback\n' assert result.exit_code != ERROR_NOT_IMPLEMENTED mock_sfp.get_xcvr_api = MagicMock(return_value=mock_api) result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "media-side-input"]) + ["Ethernet0", "media-side-input", "enable"]) assert result.output == 'Ethernet0: Set media-side-input loopback\n' assert result.exit_code != ERROR_NOT_IMPLEMENTED mock_api.set_loopback_mode.return_value = False result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "none"]) - assert result.output == 'Ethernet0: Set none loopback failed\n' + ["Ethernet0", "media-side-output", "enable"]) + assert result.output == 'Ethernet0: Set media-side-output loopback failed\n' assert result.exit_code == EXIT_FAIL mock_api.set_loopback_mode.return_value = True mock_api.set_loopback_mode.side_effect = AttributeError result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "none"]) + ["Ethernet0", "host-side-input", "enable"]) assert result.output == 'Ethernet0: Set loopback mode is not applicable for this module\n' assert result.exit_code == ERROR_NOT_IMPLEMENTED mock_api.set_loopback_mode.side_effect = [TypeError, True] result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "none"]) - assert result.output == 'Ethernet0: Set none loopback\n' + ["Ethernet0", "host-side-input", "enable"]) + assert result.output == 'Ethernet0: Set loopback mode failed. Parameter is not supported\n' + assert result.exit_code == EXIT_FAIL mock_config_db = MagicMock() mock_config_db.get.side_effect = TypeError mock_config_db_connector.return_value = mock_config_db result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "none"]) + ["Ethernet0", "media-side-input", "enable"]) assert result.output == 'Ethernet0: subport is not present in CONFIG_DB\n' assert result.exit_code == EXIT_FAIL mock_config_db_connector.return_value = None result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "none"]) + ["Ethernet0", "media-side-input", "enable"]) assert result.output == 'Ethernet0: Failed to connect to CONFIG_DB\n' assert result.exit_code == EXIT_FAIL mock_config_db_connector.return_value = MagicMock() mock_sonic_v2_connector.return_value = None result = runner.invoke(sfputil.cli.commands['debug'].commands['loopback'], - ["Ethernet0", "none"]) + ["Ethernet0", "media-side-input", "enable"]) assert result.output == 'Ethernet0: Failed to connect to STATE_DB\n' assert result.exit_code == EXIT_FAIL