Skip to content

Commit 8f5e4b6

Browse files
bktsim-aristardjeric-aristaarista-hpandya
authored
Fix multi-asic behaviour for mmuconfig (#3061)
* Fixes multi-asic behaviour for mmuconfig Previously, mmuconfig did not function correctly on multi-asic devices as it did not traverse through the correct namespaces, as required for multi-asic devices. This change adds multi-asic support to mmuconfig with the use of multi-asic helper libraries, ensuring that mmuconfig searches throuugh the correct namespaces when used on multi-asic devices, and adds the '-n' optional argument for users to specify namespaces on multi-asic devices. * Fixes for linter * More linter fixes * Enhanced multi-asic support for mmuconfig - Resolve pre-commit errors - Remove use_unix_socket_path argument from DB connectors - Support multiple namespace when none specified - Refactor tests to use the testData dict - Delete single_asic_mmuconfig_test.py - Replace argparse with click in mmuconfig - Add support for namespace in show and config - Modified multi-asic tests to use show/config cli --------- Co-authored-by: rdjeric <[email protected]> Co-authored-by: arista-hpandya <[email protected]>
1 parent c019c48 commit 8f5e4b6

File tree

8 files changed

+483
-101
lines changed

8 files changed

+483
-101
lines changed

config/main.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -6470,13 +6470,26 @@ def ecn(profile, rmax, rmin, ymax, ymin, gmax, gmin, rdrop, ydrop, gdrop, verbos
64706470
@config.command()
64716471
@click.option('-p', metavar='<profile_name>', type=str, required=True, help="Profile name")
64726472
@click.option('-a', metavar='<alpha>', type=click.IntRange(-8,8), help="Set alpha for profile type dynamic")
6473-
@click.option('-s', metavar='<staticth>', type=int, help="Set staticth for profile type static")
6474-
def mmu(p, a, s):
6473+
@click.option('-s', metavar='<staticth>', type=click.IntRange(min=0), help="Set staticth for profile type static")
6474+
@click.option('--verbose', '-vv', is_flag=True, help="Enable verbose output")
6475+
@click.option('--namespace',
6476+
'-n',
6477+
'namespace',
6478+
default=None,
6479+
type=str,
6480+
show_default=True,
6481+
help='Namespace name or all',
6482+
callback=multi_asic_util.multi_asic_namespace_validation_callback)
6483+
def mmu(p, a, s, namespace, verbose):
64756484
"""mmuconfig configuration tasks"""
64766485
log.log_info("'mmuconfig -p {}' executing...".format(p))
64776486
command = ['mmuconfig', '-p', str(p)]
64786487
if a is not None: command += ['-a', str(a)]
64796488
if s is not None: command += ['-s', str(s)]
6489+
if namespace is not None:
6490+
command += ['-n', str(namespace)]
6491+
if verbose:
6492+
command += ['-vv']
64806493
clicommon.run_command(command)
64816494

64826495

scripts/mmuconfig

+64-64
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,23 @@ optional arguments:
1818

1919
import os
2020
import sys
21-
import argparse
21+
import click
2222
import tabulate
2323
import traceback
2424
import json
25+
from utilities_common.general import load_db_config
26+
from sonic_py_common import multi_asic
27+
from utilities_common import multi_asic as multi_asic_util
2528

2629
BUFFER_POOL_TABLE_NAME = "BUFFER_POOL"
2730
BUFFER_PROFILE_TABLE_NAME = "BUFFER_PROFILE"
2831
DEFAULT_LOSSLESS_BUFFER_PARAMETER_NAME = "DEFAULT_LOSSLESS_BUFFER_PARAMETER"
2932

3033
DYNAMIC_THRESHOLD = "dynamic_th"
34+
DYNAMIC_THRESHOLD_MIN = -8
35+
DYNAMIC_THRESHOLD_MAX = 8
3136
STATIC_THRESHOLD = "static_th"
37+
STATIC_THRESHOLD_MIN = 0
3238
BUFFER_PROFILE_FIELDS = {
3339
"alpha": DYNAMIC_THRESHOLD,
3440
"staticth" : STATIC_THRESHOLD
@@ -42,29 +48,33 @@ try:
4248
sys.path.insert(0, modules_path)
4349
sys.path.insert(0, tests_path)
4450
import mock_tables.dbconnector
51+
if os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] == "multi_asic":
52+
import mock_tables.mock_multi_asic
53+
mock_tables.dbconnector.load_namespace_config()
54+
else:
55+
mock_tables.dbconnector.load_database_config()
4556

4657
except KeyError:
4758
pass
4859

4960
from swsscommon.swsscommon import SonicV2Connector, ConfigDBConnector
5061

5162
class MmuConfig(object):
52-
def __init__(self, verbose, config, filename):
63+
def __init__(self, verbose, config, filename, namespace):
5364
self.verbose = verbose
5465
self.config = config
5566
self.filename = filename
67+
self.namespace = namespace
68+
self.multi_asic = multi_asic_util.MultiAsic(namespace_option=namespace)
69+
self.config_db = None
70+
self.db = None
5671

57-
# Set up db connections
58-
if self.config:
59-
self.db = ConfigDBConnector()
60-
self.db.connect()
61-
else:
62-
self.db = SonicV2Connector(use_unix_socket_path=False)
63-
self.db.connect(self.db.STATE_DB, False)
72+
# For unit testing
73+
self.updated_profile_table = {}
6474

6575
def get_table(self, tablename):
6676
if self.config:
67-
return self.db.get_table(tablename)
77+
return self.config_db.get_table(tablename)
6878

6979
entries = {}
7080
keys = self.db.keys(self.db.STATE_DB, tablename + '*')
@@ -77,13 +87,15 @@ class MmuConfig(object):
7787

7888
return entries
7989

90+
@multi_asic_util.run_on_multi_asic
8091
def list(self):
92+
namespace_str = f" for namespace {self.multi_asic.current_namespace}" if multi_asic.is_multi_asic() else ''
8193
lossless_traffic_pattern = self.get_table(DEFAULT_LOSSLESS_BUFFER_PARAMETER_NAME)
8294
if lossless_traffic_pattern:
8395
for _, pattern in lossless_traffic_pattern.items():
8496
config = []
8597

86-
print("Lossless traffic pattern:")
98+
print(f"Lossless traffic pattern{namespace_str}:")
8799
for field, value in pattern.items():
88100
config.append([field, value])
89101
print(tabulate.tabulate(config) + "\n")
@@ -93,97 +105,88 @@ class MmuConfig(object):
93105
for pool_name, pool_data in buf_pools.items():
94106
config = []
95107

96-
print("Pool: " + pool_name)
108+
print(f"Pool{namespace_str}: " + pool_name)
97109
for field, value in pool_data.items():
98110
config.append([field, value])
99111
print(tabulate.tabulate(config) + "\n")
100112
if self.verbose:
101113
print("Total pools: %d\n\n" % len(buf_pools))
102114
else:
103-
print("No buffer pool information available")
115+
print(f"No buffer pool information available{namespace_str}")
104116

105117
buf_profs = self.get_table(BUFFER_PROFILE_TABLE_NAME)
106118
if buf_profs:
107119
for prof_name, prof_data in buf_profs.items():
108120
config = []
109121

110-
print("Profile: " + prof_name)
122+
print(f"Profile{namespace_str}: " + prof_name)
111123
for field, value in prof_data.items():
112124
config.append([field, value])
113125
print(tabulate.tabulate(config) + "\n")
114126
if self.verbose:
115127
print("Total profiles: %d" % len(buf_profs))
116128
else:
117-
print("No buffer profile information available")
129+
print(f"No buffer profile information available{namespace_str}")
118130

131+
@multi_asic_util.run_on_multi_asic
119132
def set(self, profile, field_alias, value):
133+
namespace_str = f" for namespace {self.multi_asic.current_namespace}" if multi_asic.is_multi_asic() else ''
120134
if os.geteuid() != 0 and os.environ.get("UTILITIES_UNIT_TESTING", "0") != "2":
121135
sys.exit("Root privileges required for this operation")
122136

123137
field = BUFFER_PROFILE_FIELDS[field_alias]
124-
buf_profs = self.db.get_table(BUFFER_PROFILE_TABLE_NAME)
125-
v = int(value)
138+
buf_profs = self.config_db.get_table(BUFFER_PROFILE_TABLE_NAME)
126139
if field == DYNAMIC_THRESHOLD:
127-
if v < -8 or v > 8:
128-
sys.exit("Invalid alpha value: 2^(%s)" % (value))
129-
130140
if profile in buf_profs and DYNAMIC_THRESHOLD not in buf_profs[profile]:
131141
sys.exit("%s not using dynamic thresholding" % (profile))
132142
elif field == STATIC_THRESHOLD:
133-
if v < 0:
134-
sys.exit("Invalid static threshold value: (%s)" % (value))
135-
136143
if profile in buf_profs and STATIC_THRESHOLD not in buf_profs[profile]:
137144
sys.exit("%s not using static threshold" % (profile))
138145
else:
139146
sys.exit("Set field %s not supported" % (field))
140147

141148
if self.verbose:
142-
print("Setting %s %s value to %s" % (profile, field, value))
143-
self.db.mod_entry(BUFFER_PROFILE_TABLE_NAME, profile, {field: value})
149+
print("Setting %s %s value to %s%s" % (profile, field, value, namespace_str))
150+
self.config_db.mod_entry(BUFFER_PROFILE_TABLE_NAME, profile, {field: value})
144151
if self.filename is not None:
145-
prof_table = self.db.get_table(BUFFER_PROFILE_TABLE_NAME)
152+
self.updated_profile_table[self.multi_asic.current_namespace] = self.config_db.get_table(BUFFER_PROFILE_TABLE_NAME)
146153
with open(self.filename, "w") as fd:
147-
json.dump(prof_table, fd)
148-
149-
150-
def main(config):
151-
if config:
152-
parser = argparse.ArgumentParser(description='Show and change: mmu configuration',
153-
formatter_class=argparse.RawTextHelpFormatter)
154-
155-
parser.add_argument('-l', '--list', action='store_true', help='show mmu configuration')
156-
parser.add_argument('-p', '--profile', type=str, help='specify buffer profile name', default=None)
157-
parser.add_argument('-a', '--alpha', type=str, help='set n for dyanmic threshold alpha 2^(n)', default=None)
158-
parser.add_argument('-s', '--staticth', type=str, help='set static threshold', default=None)
159-
parser.add_argument('-v', '--version', action='version', version='%(prog)s 1.0')
160-
else:
161-
parser = argparse.ArgumentParser(description='Show buffer state',
162-
formatter_class=argparse.RawTextHelpFormatter)
163-
164-
parser.add_argument('-l', '--list', action='store_true', help='show buffer state')
165-
parser.add_argument('-v', '--version', action='version', version='%(prog)s 1.0')
166-
167-
parser.add_argument('-vv', '--verbose', action='store_true', help='verbose output', default=False)
168-
parser.add_argument('-f', '--filename', help='file used by mock tests', type=str, default=None)
169-
154+
json.dump(self.updated_profile_table, fd)
155+
156+
@click.command(help='Show and change: mmu configuration')
157+
@click.option('-l', '--list', 'show_config', is_flag=True, help='show mmu configuration')
158+
@click.option('-p', '--profile', type=str, help='specify buffer profile name', default=None)
159+
@click.option('-a', '--alpha', type=click.IntRange(DYNAMIC_THRESHOLD_MIN, DYNAMIC_THRESHOLD_MAX), help='set n for dyanmic threshold alpha 2^(n)', default=None)
160+
@click.option('-s', '--staticth', type=click.IntRange(min=STATIC_THRESHOLD_MIN), help='set static threshold', default=None)
161+
@click.option('-n', '--namespace', type=click.Choice(multi_asic.get_namespace_list()), help='Namespace name or skip for all', default=None)
162+
@click.option('-vv', '--verbose', is_flag=True, help='verbose output', default=False)
163+
@click.version_option(version='1.0')
164+
def main(show_config, profile, alpha, staticth, namespace, verbose):
165+
# A test file created for unit test purposes
166+
filename=None
170167
if os.environ.get("UTILITIES_UNIT_TESTING", "0") == "2":
171-
sys.argv.extend(['-f', '/tmp/mmuconfig'])
168+
filename = '/tmp/mmuconfig'
172169

173-
174-
args = parser.parse_args()
170+
# Buffershow and mmuconfig cmds share this script
171+
# Buffershow cmd cannot modify configs hence config is set to False
172+
config = True if sys.argv[0].split('/')[-1] == "mmuconfig" else False
175173

176174
try:
177-
mmu_cfg = MmuConfig(args.verbose, config, args.filename)
178-
if args.list:
175+
load_db_config()
176+
mmu_cfg = MmuConfig(verbose, config, filename, namespace)
177+
178+
# Both mmuconfig and buffershow have access to show_config option
179+
if show_config:
179180
mmu_cfg.list()
180-
elif config and args.profile:
181-
if args.alpha:
182-
mmu_cfg.set(args.profile, "alpha", args.alpha)
183-
elif args.staticth:
184-
mmu_cfg.set(args.profile, "staticth", args.staticth)
181+
# Buffershow cannot modify profiles
182+
elif config and profile:
183+
if alpha:
184+
mmu_cfg.set(profile, "alpha", alpha)
185+
elif staticth:
186+
mmu_cfg.set(profile, "staticth", staticth)
185187
else:
186-
parser.print_help()
188+
ctx = click.get_current_context()
189+
click.echo(ctx.get_help())
187190
sys.exit(1)
188191

189192
except Exception as e:
@@ -192,7 +195,4 @@ def main(config):
192195
sys.exit(1)
193196

194197
if __name__ == "__main__":
195-
if sys.argv[0].split('/')[-1] == "mmuconfig":
196-
main(True)
197-
else:
198-
main(False)
198+
main()

show/main.py

+30-3
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,6 @@ def cli(ctx):
291291
load_db_config()
292292
ctx.obj = Db()
293293

294-
295294
# Add groups from other modules
296295
cli.add_command(acl.acl)
297296
cli.add_command(chassis_modules.chassis)
@@ -2033,9 +2032,22 @@ def boot():
20332032
# 'mmu' command ("show mmu")
20342033
#
20352034
@cli.command('mmu')
2036-
def mmu():
2035+
@click.option('--namespace',
2036+
'-n',
2037+
'namespace',
2038+
default=None,
2039+
type=str,
2040+
show_default=True,
2041+
help='Namespace name or all',
2042+
callback=multi_asic_util.multi_asic_namespace_validation_callback)
2043+
@click.option('--verbose', '-vv', is_flag=True, help="Enable verbose output")
2044+
def mmu(namespace, verbose):
20372045
"""Show mmu configuration"""
20382046
cmd = ['mmuconfig', '-l']
2047+
if namespace is not None:
2048+
cmd += ['-n', str(namespace)]
2049+
if verbose:
2050+
cmd += ['-vv']
20392051
run_command(cmd)
20402052

20412053
#
@@ -2049,10 +2061,25 @@ def buffer():
20492061
#
20502062
# 'configuration' command ("show buffer command")
20512063
#
2064+
2065+
20522066
@buffer.command()
2053-
def configuration():
2067+
@click.option('--namespace',
2068+
'-n',
2069+
'namespace',
2070+
default=None,
2071+
type=str,
2072+
show_default=True,
2073+
help='Namespace name or all',
2074+
callback=multi_asic_util.multi_asic_namespace_validation_callback)
2075+
@click.option('--verbose', '-vv', is_flag=True, help="Enable verbose output")
2076+
def configuration(namespace, verbose):
20542077
"""show buffer configuration"""
20552078
cmd = ['mmuconfig', '-l']
2079+
if namespace is not None:
2080+
cmd += ['-n', str(namespace)]
2081+
if verbose:
2082+
cmd += ['-vv']
20562083
run_command(cmd)
20572084

20582085
#

0 commit comments

Comments
 (0)