diff --git a/config/main.py b/config/main.py index 45ae970504..d59502ad25 100644 --- a/config/main.py +++ b/config/main.py @@ -105,6 +105,8 @@ PORT_TPID = "tpid" DEFAULT_TPID = "0x8100" +DOM_CONFIG_SUPPORTED_SUBPORTS = ['0', '1'] + asic_type = None DSCP_RANGE = click.IntRange(min=0, max=63) @@ -5146,6 +5148,43 @@ def reset(ctx, interface_name): cmd = ['sudo', 'sfputil', 'reset', str(interface_name)] clicommon.run_command(cmd) +# +# 'dom' subcommand ('config interface transceiver dom ...') +# This command is supported only for +# 1. non-breakout ports (subport = 0 or subport field is absent in CONFIG_DB) +# 2. first subport of breakout ports (subport = 1) + +@transceiver.command() +@click.argument('interface_name', metavar='', required=True) +@click.argument('desired_config', metavar='(enable|disable)', type=click.Choice(['enable', 'disable'])) +@click.pass_context +def dom(ctx, interface_name, desired_config): + """Enable/disable DOM monitoring for SFP transceiver module""" + log.log_info("interface transceiver dom {} {} executing...".format(interface_name, desired_config)) + # Get the config_db connector + config_db = ctx.obj['config_db'] + + if clicommon.get_interface_naming_mode() == "alias": + interface_name = interface_alias_to_name(config_db, interface_name) + if interface_name is None: + ctx.fail("'interface_name' is None!") + + if interface_name_is_valid(config_db, interface_name) is False: + ctx.fail("Interface name is invalid. Please enter a valid interface name!!") + + port_table_entry = config_db.get_entry("PORT", interface_name) + if not port_table_entry: + ctx.fail("Interface {} does not exist".format(interface_name)) + + # We are handling port configuration only for the below mentioned scenarios + # Port is a non-breakout port (subport = 0 or subport field is absent in CONFIG_DB) + # Port is first subport of breakout ports (subport = 1) + # If the port is not in the above mentioned scenarios, then fail the command + if port_table_entry.get("subport", '0') not in DOM_CONFIG_SUPPORTED_SUBPORTS: + ctx.fail("DOM monitoring config only supported for subports {}".format(DOM_CONFIG_SUPPORTED_SUBPORTS)) + else: + config_db.mod_entry("PORT", interface_name, {"dom_polling": "disabled" if desired_config == "disable" else "enabled"}) + # # 'mpls' subgroup ('config interface mpls ...') # diff --git a/doc/Command-Reference.md b/doc/Command-Reference.md index 84d7fb92db..1744d10fad 100644 --- a/doc/Command-Reference.md +++ b/doc/Command-Reference.md @@ -4997,6 +4997,22 @@ This command is used to reset an SFP transceiver Resetting port Ethernet0... OK ``` +**config interface transceiver dom** + +This command is used to configure the Digital Optical Monitoring (DOM) for an interface. + +- Usage: + ``` + config interface transceiver dom (enable | disable) + ``` + +- Examples: + ``` + user@sonic~$ sudo config interface transceiver dom Ethernet0 enable + + user@sonic~$ sudo config interface transceiver dom Ethernet0 disable + ``` + **config interface mtu (Versions >= 201904)** This command is used to configure the mtu for the Physical interface. Use the value 1500 for setting max transfer unit size to 1500 bytes. diff --git a/tests/config_xcvr_test.py b/tests/config_xcvr_test.py index 5043aa89d5..6e05996db1 100644 --- a/tests/config_xcvr_test.py +++ b/tests/config_xcvr_test.py @@ -1,3 +1,4 @@ +from unittest.mock import patch import click import config.main as config import operator @@ -47,6 +48,25 @@ def test_config_tx_power(self, ctx): result = self.basic_check("tx_power", ["PortChannel0001", "11.3"], ctx, operator.ne) assert 'Invalid port PortChannel0001' in result.output + @patch("config.main.ConfigDBConnector.get_entry") + def test_dom(self, mock_get_entry, ctx): + interface_name = 'Ethernet0' + desired_config = 'enable' + + result = self.basic_check("dom", ["", desired_config], ctx, operator.ne) + assert "Interface name is invalid. Please enter a valid interface name!!" in result.output + + mock_get_entry.return_value = None + result = self.basic_check("dom", [interface_name, desired_config], ctx, operator.ne) + assert "Interface {} does not exist".format(interface_name) in result.output + + mock_get_entry.return_value = {'subport': '2'} + result = self.basic_check("dom", [interface_name, desired_config], ctx, operator.ne) + assert "DOM monitoring config only supported for subports {}".format(config.DOM_CONFIG_SUPPORTED_SUBPORTS) in result.output + + mock_get_entry.return_value = {'subport': '1'} + result = self.basic_check("dom", [interface_name, desired_config], ctx) + def basic_check(self, command_name, para_list, ctx, op=operator.eq, expect_result=0): runner = CliRunner() result = runner.invoke(config.config.commands["interface"].commands["transceiver"].commands[command_name], para_list, obj = ctx)