Skip to content

Commit 867fc54

Browse files
authored
[DASH] Add support for ENI counters (sonic-net#3496)
### What I did Updated counterpoll cli to support configuration for ENI counters ``` root@dpu:/home/admin# counterpoll eni enable root@dpu:/home/admin# counterpoll eni interval 1000 root@dpu:/home/admin# counterpoll show Type Interval (in ms) Status -------------------------- ------------------ -------- QUEUE_STAT default (10000) enable PORT_STAT default (1000) enable PORT_BUFFER_DROP default (60000) enable RIF_STAT default (1000) enable QUEUE_WATERMARK_STAT default (60000) enable PG_WATERMARK_STAT default (60000) enable PG_DROP_STAT default (10000) enable BUFFER_POOL_WATERMARK_STAT default (60000) enable ACL 10000 enable ENI_STAT 1000 enable ```
1 parent b4d27c4 commit 867fc54

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

counterpoll/main.py

+59
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,29 @@
33
from flow_counter_util.route import exit_if_route_flow_counter_not_support
44
from swsscommon.swsscommon import ConfigDBConnector
55
from tabulate import tabulate
6+
from sonic_py_common import device_info
67

78
BUFFER_POOL_WATERMARK = "BUFFER_POOL_WATERMARK"
89
PORT_BUFFER_DROP = "PORT_BUFFER_DROP"
910
PG_DROP = "PG_DROP"
1011
ACL = "ACL"
12+
ENI = "ENI"
1113
DISABLE = "disable"
1214
ENABLE = "enable"
1315
DEFLT_60_SEC= "default (60000)"
1416
DEFLT_10_SEC= "default (10000)"
1517
DEFLT_1_SEC = "default (1000)"
1618

19+
20+
def is_dpu(db):
21+
""" Check if the device is DPU """
22+
platform_info = device_info.get_platform_info(db)
23+
if platform_info.get('switch_type') == 'dpu':
24+
return True
25+
else:
26+
return False
27+
28+
1729
@click.group()
1830
def cli():
1931
""" SONiC Static Counter Poll configurations """
@@ -126,6 +138,7 @@ def disable():
126138
port_info['FLEX_COUNTER_STATUS'] = DISABLE
127139
configdb.mod_entry("FLEX_COUNTER_TABLE", PORT_BUFFER_DROP, port_info)
128140

141+
129142
# Ingress PG drop packet stat
130143
@cli.group()
131144
@click.pass_context
@@ -382,6 +395,47 @@ def disable(ctx):
382395
fc_info['FLEX_COUNTER_STATUS'] = 'disable'
383396
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", "FLOW_CNT_ROUTE", fc_info)
384397

398+
399+
# ENI counter commands
400+
@cli.group()
401+
@click.pass_context
402+
def eni(ctx):
403+
""" ENI counter commands """
404+
ctx.obj = ConfigDBConnector()
405+
ctx.obj.connect()
406+
if not is_dpu(ctx.obj):
407+
click.echo("ENI counters are not supported on non DPU platforms")
408+
exit(1)
409+
410+
411+
@eni.command(name='interval')
412+
@click.argument('poll_interval', type=click.IntRange(1000, 30000))
413+
@click.pass_context
414+
def eni_interval(ctx, poll_interval):
415+
""" Set eni counter query interval """
416+
eni_info = {}
417+
eni_info['POLL_INTERVAL'] = poll_interval
418+
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", ENI, eni_info)
419+
420+
421+
@eni.command(name='enable')
422+
@click.pass_context
423+
def eni_enable(ctx):
424+
""" Enable eni counter query """
425+
eni_info = {}
426+
eni_info['FLEX_COUNTER_STATUS'] = 'enable'
427+
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", ENI, eni_info)
428+
429+
430+
@eni.command(name='disable')
431+
@click.pass_context
432+
def eni_disable(ctx):
433+
""" Disable eni counter query """
434+
eni_info = {}
435+
eni_info['FLEX_COUNTER_STATUS'] = 'disable'
436+
ctx.obj.mod_entry("FLEX_COUNTER_TABLE", ENI, eni_info)
437+
438+
385439
@cli.command()
386440
def show():
387441
""" Show the counter configuration """
@@ -399,6 +453,7 @@ def show():
399453
tunnel_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'TUNNEL')
400454
trap_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'FLOW_CNT_TRAP')
401455
route_info = configdb.get_entry('FLEX_COUNTER_TABLE', 'FLOW_CNT_ROUTE')
456+
eni_info = configdb.get_entry('FLEX_COUNTER_TABLE', ENI)
402457

403458
header = ("Type", "Interval (in ms)", "Status")
404459
data = []
@@ -428,6 +483,10 @@ def show():
428483
data.append(["FLOW_CNT_ROUTE_STAT", route_info.get("POLL_INTERVAL", DEFLT_10_SEC),
429484
route_info.get("FLEX_COUNTER_STATUS", DISABLE)])
430485

486+
if is_dpu(config_db) and eni_info:
487+
data.append(["ENI_STAT", eni_info.get("POLL_INTERVAL", DEFLT_10_SEC),
488+
eni_info.get("FLEX_COUNTER_STATUS", DISABLE)])
489+
431490
click.echo(tabulate(data, headers=header, tablefmt="simple", missingval=""))
432491

433492
def _update_config_db_flex_counter_table(status, filename):

tests/counterpoll_test.py

+55
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import json
33
import os
44
import pytest
5+
import mock
56
import sys
67
from click.testing import CliRunner
78
from shutil import copyfile
@@ -31,6 +32,21 @@
3132
FLOW_CNT_ROUTE_STAT 10000 enable
3233
"""
3334

35+
expected_counterpoll_show_dpu = """Type Interval (in ms) Status
36+
-------------------- ------------------ --------
37+
QUEUE_STAT 10000 enable
38+
PORT_STAT 1000 enable
39+
PORT_BUFFER_DROP 60000 enable
40+
QUEUE_WATERMARK_STAT default (60000) enable
41+
PG_WATERMARK_STAT default (60000) enable
42+
PG_DROP_STAT 10000 enable
43+
ACL 5000 enable
44+
TUNNEL_STAT 3000 enable
45+
FLOW_CNT_TRAP_STAT 10000 enable
46+
FLOW_CNT_ROUTE_STAT 10000 enable
47+
ENI_STAT 1000 enable
48+
"""
49+
3450
class TestCounterpoll(object):
3551
@classmethod
3652
def setup_class(cls):
@@ -44,6 +60,13 @@ def test_show(self):
4460
print(result.output)
4561
assert result.output == expected_counterpoll_show
4662

63+
@mock.patch('counterpoll.main.device_info.get_platform_info')
64+
def test_show_dpu(self, mock_get_platform_info):
65+
mock_get_platform_info.return_value = {'switch_type': 'dpu'}
66+
runner = CliRunner()
67+
result = runner.invoke(counterpoll.cli.commands["show"], [])
68+
assert result.output == expected_counterpoll_show_dpu
69+
4770
def test_port_buffer_drop_interval(self):
4871
runner = CliRunner()
4972
result = runner.invoke(counterpoll.cli.commands["port-buffer-drop"].commands["interval"], ["30000"])
@@ -221,6 +244,38 @@ def test_update_route_counter_interval(self):
221244
assert result.exit_code == 2
222245
assert expected in result.output
223246

247+
@pytest.mark.parametrize("status", ["disable", "enable"])
248+
def test_update_eni_status(self, status):
249+
runner = CliRunner()
250+
result = runner.invoke(counterpoll.cli, ["eni", status])
251+
assert result.exit_code == 1
252+
assert result.output == "ENI counters are not supported on non DPU platforms\n"
253+
254+
@pytest.mark.parametrize("status", ["disable", "enable"])
255+
@mock.patch('counterpoll.main.device_info.get_platform_info')
256+
def test_update_eni_status_dpu(self, mock_get_platform_info, status):
257+
mock_get_platform_info.return_value = {'switch_type': 'dpu'}
258+
runner = CliRunner()
259+
db = Db()
260+
261+
result = runner.invoke(counterpoll.cli.commands["eni"].commands[status], [], obj=db.cfgdb)
262+
assert result.exit_code == 0
263+
264+
table = db.cfgdb.get_table('FLEX_COUNTER_TABLE')
265+
assert status == table["ENI"]["FLEX_COUNTER_STATUS"]
266+
267+
@mock.patch('counterpoll.main.device_info.get_platform_info')
268+
def test_update_eni_interval(self, mock_get_platform_info):
269+
mock_get_platform_info.return_value = {'switch_type': 'dpu'}
270+
runner = CliRunner()
271+
db = Db()
272+
test_interval = "2000"
273+
274+
result = runner.invoke(counterpoll.cli.commands["eni"].commands["interval"], [test_interval], obj=db.cfgdb)
275+
assert result.exit_code == 0
276+
277+
table = db.cfgdb.get_table('FLEX_COUNTER_TABLE')
278+
assert test_interval == table["ENI"]["POLL_INTERVAL"]
224279

225280
@classmethod
226281
def teardown_class(cls):

tests/mock_tables/config_db.json

+4
Original file line numberDiff line numberDiff line change
@@ -1785,6 +1785,10 @@
17851785
"POLL_INTERVAL": "10000",
17861786
"FLEX_COUNTER_STATUS": "enable"
17871787
},
1788+
"FLEX_COUNTER_TABLE|ENI": {
1789+
"POLL_INTERVAL": "1000",
1790+
"FLEX_COUNTER_STATUS": "enable"
1791+
},
17881792
"PFC_WD|Ethernet0": {
17891793
"action": "drop",
17901794
"detection_time": "600",

0 commit comments

Comments
 (0)