diff --git a/counterpoll/main.py b/counterpoll/main.py index 55f1aefeba..d0e410369c 100644 --- a/counterpoll/main.py +++ b/counterpoll/main.py @@ -5,7 +5,10 @@ from tabulate import tabulate BUFFER_POOL_WATERMARK = "BUFFER_POOL_WATERMARK" +PORT_BUFFER_DROP = "PORT_BUFFER_DROP" DISABLE = "disable" +ENABLE = "enable" +DEFLT_60_SEC= "default (60000)" DEFLT_10_SEC= "default (10000)" DEFLT_1_SEC = "default (1000)" @@ -81,6 +84,46 @@ def disable(): port_info['FLEX_COUNTER_STATUS'] = 'disable' configdb.mod_entry("FLEX_COUNTER_TABLE", "PORT", port_info) +# Port buffer drop counter commands +@cli.group() +def port_buffer_drop(): + """ Port buffer drop counter commands """ + +@port_buffer_drop.command() +@click.argument('poll_interval', type=click.IntRange(30000, 300000)) +def interval(poll_interval): + """ + Set port_buffer_drop counter query interval + This counter group causes high CPU usage when polled, + hence the allowed interval is between 30s and 300s. + This is a ahort term solution and + should be changed once the performance is enhanced + """ + configdb = swsssdk.ConfigDBConnector() + configdb.connect() + port_info = {} + if poll_interval is not None: + port_info['POLL_INTERVAL'] = poll_interval + configdb.mod_entry("FLEX_COUNTER_TABLE", PORT_BUFFER_DROP, port_info) + +@port_buffer_drop.command() +def enable(): + """ Enable port counter query """ + configdb = swsssdk.ConfigDBConnector() + configdb.connect() + port_info = {} + port_info['FLEX_COUNTER_STATUS'] = ENABLE + configdb.mod_entry("FLEX_COUNTER_TABLE", PORT_BUFFER_DROP, port_info) + +@port_buffer_drop.command() +def disable(): + """ Disable port counter query """ + configdb = swsssdk.ConfigDBConnector() + configdb.connect() + port_info = {} + port_info['FLEX_COUNTER_STATUS'] = DISABLE + configdb.mod_entry("FLEX_COUNTER_TABLE", PORT_BUFFER_DROP, port_info) + # RIF counter commands @cli.group() def rif(): @@ -166,6 +209,7 @@ def show(): configdb.connect() queue_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'QUEUE') port_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'PORT') + port_drop_info = configdb.get_entry('FLEX_COUNTER_TABLE', PORT_BUFFER_DROP) rif_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'RIF') queue_wm_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'QUEUE_WATERMARK') pg_wm_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'PG_WATERMARK') @@ -177,6 +221,8 @@ def show(): data.append(["QUEUE_STAT", queue_info.get("POLL_INTERVAL", DEFLT_10_SEC), queue_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if port_info: data.append(["PORT_STAT", port_info.get("POLL_INTERVAL", DEFLT_1_SEC), port_info.get("FLEX_COUNTER_STATUS", DISABLE)]) + if port_drop_info: + data.append([PORT_BUFFER_DROP, port_drop_info.get("POLL_INTERVAL", DEFLT_60_SEC), port_drop_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if rif_info: data.append(["RIF_STAT", rif_info.get("POLL_INTERVAL", DEFLT_1_SEC), rif_info.get("FLEX_COUNTER_STATUS", DISABLE)]) if queue_wm_info: diff --git a/sonic-utilities-tests/counterpoll_test.py b/sonic-utilities-tests/counterpoll_test.py new file mode 100644 index 0000000000..b2c806b95c --- /dev/null +++ b/sonic-utilities-tests/counterpoll_test.py @@ -0,0 +1,58 @@ +import sys +import os +import time +import pytest +import click +import swsssdk +from click.testing import CliRunner + +test_path = os.path.dirname(os.path.abspath(__file__)) +modules_path = os.path.dirname(test_path) +scripts_path = os.path.join(modules_path, "scripts") +sys.path.insert(0, test_path) +sys.path.insert(0, modules_path) + +import mock_tables.dbconnector +import counterpoll.main as counterpoll + +expected_counterpoll_show = """Type Interval (in ms) Status +-------------------- ------------------ -------- +QUEUE_STAT 10000 enable +PORT_STAT 1000 enable +PORT_BUFFER_DROP 60000 enable +QUEUE_WATERMARK_STAT 10000 enable +PG_WATERMARK_STAT 10000 enable +""" + +class TestCounterpoll(object): + @classmethod + def setup_class(cls): + print("SETUP") + os.environ["PATH"] += os.pathsep + scripts_path + os.environ["UTILITIES_UNIT_TESTING"] = "1" + + def test_show(self): + runner = CliRunner() + result = runner.invoke(counterpoll.cli.commands["show"], []) + print(result.output) + assert result.output == expected_counterpoll_show + + def test_port_buffer_drop_interval(self): + runner = CliRunner() + result = runner.invoke(counterpoll.cli.commands["port-buffer-drop"].commands["interval"], ["30000"]) + print(result.output) + assert result.exit_code == 0 + + def test_port_buffer_drop_interval_too_short(self): + runner = CliRunner() + result = runner.invoke(counterpoll.cli.commands["port-buffer-drop"].commands["interval"], ["1000"]) + print(result.output) + expected = "Invalid value for 'POLL_INTERVAL': 1000 is not in the valid range of 30000 to 300000." + assert result.exit_code == 2 + assert expected in result.output + + @classmethod + def teardown_class(cls): + print("TEARDOWN") + os.environ["PATH"] = os.pathsep.join(os.environ["PATH"].split(os.pathsep)[:-1]) + os.environ["UTILITIES_UNIT_TESTING"] = "0" diff --git a/sonic-utilities-tests/mock_tables/config_db.json b/sonic-utilities-tests/mock_tables/config_db.json index 080da35728..0c1f48b81d 100644 --- a/sonic-utilities-tests/mock_tables/config_db.json +++ b/sonic-utilities-tests/mock_tables/config_db.json @@ -206,5 +206,26 @@ "state": "enabled", "auto_restart": "enabled", "high_mem_alert": "disabled" + }, + "FLEX_COUNTER_TABLE|QUEUE": { + "POLL_INTERVAL": "10000", + "FLEX_COUNTER_STATUS": "enable" + }, + "FLEX_COUNTER_TABLE|PORT": { + "POLL_INTERVAL": "1000", + "FLEX_COUNTER_STATUS": "enable" + }, + "FLEX_COUNTER_TABLE|PORT_BUFFER_DROP": { + "POLL_INTERVAL": "60000", + "FLEX_COUNTER_STATUS": "enable" + }, + "FLEX_COUNTER_TABLE|QUEUE_WATERMARK": { + "POLL_INTERVAL": "10000", + "FLEX_COUNTER_STATUS": "enable" + }, + "FLEX_COUNTER_TABLE|PG_WATERMARK": { + "POLL_INTERVAL": "10000", + "FLEX_COUNTER_STATUS": "enable" } } +