Skip to content

Commit cbac167

Browse files
committed
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.
1 parent 17e77fe commit cbac167

File tree

5 files changed

+165
-10
lines changed

5 files changed

+165
-10
lines changed

scripts/mmuconfig

+32-10
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import argparse
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
2527

2628
BUFFER_POOL_TABLE_NAME = "BUFFER_POOL"
2729
BUFFER_PROFILE_TABLE_NAME = "BUFFER_PROFILE"
@@ -42,38 +44,47 @@ try:
4244
sys.path.insert(0, modules_path)
4345
sys.path.insert(0, tests_path)
4446
import mock_tables.dbconnector
45-
47+
if os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] == "multi_asic":
48+
import mock_tables.mock_multi_asic
49+
mock_tables.dbconnector.load_namespace_config()
4650
except KeyError:
4751
pass
4852

4953
from swsscommon.swsscommon import SonicV2Connector, ConfigDBConnector
5054

5155
class MmuConfig(object):
52-
def __init__(self, verbose, config, filename):
56+
def __init__(self, verbose, config, filename, namespace):
5357
self.verbose = verbose
5458
self.config = config
5559
self.filename = filename
60+
self.namespace = namespace
61+
62+
self.use_unix_socket_path = self.namespace != None
5663

5764
# Set up db connections
5865
if self.config:
59-
self.db = ConfigDBConnector()
66+
self.db = ConfigDBConnector(namespace=namespace, use_unix_socket_path=self.use_unix_socket_path)
6067
self.db.connect()
6168
else:
62-
self.db = SonicV2Connector(use_unix_socket_path=False)
69+
self.db = SonicV2Connector(namespace=namespace, use_unix_socket_path=self.use_unix_socket_path)
6370
self.db.connect(self.db.STATE_DB, False)
6471

6572
def get_table(self, tablename):
6673
if self.config:
6774
return self.db.get_table(tablename)
6875

6976
entries = {}
70-
keys = self.db.keys(self.db.STATE_DB, tablename + '*')
77+
for ns in multi_asic.get_namespace_list(self.namespace):
78+
db = SonicV2Connector(namespace=ns, use_unix_socket_path=True)
79+
db.connect(db.STATE_DB, False)
80+
keys = db.keys(db.STATE_DB, tablename + '*')
7181

72-
if not keys:
73-
return None
82+
if keys:
83+
for key in keys:
84+
entries[key.split('|')[1]] = db.get_all(db.STATE_DB, key)
7485

75-
for key in keys:
76-
entries[key.split('|')[1]] = self.db.get_all(self.db.STATE_DB, key)
86+
if not entries:
87+
return None
7788

7889
return entries
7990

@@ -120,6 +131,9 @@ class MmuConfig(object):
120131
if os.geteuid() != 0 and os.environ.get("UTILITIES_UNIT_TESTING", "0") != "2":
121132
sys.exit("Root privileges required for this operation")
122133

134+
if not self.namespace and multi_asic.is_multi_asic():
135+
sys.exit("Namespace must be specified for this operation")
136+
123137
field = BUFFER_PROFILE_FIELDS[field_alias]
124138
buf_profs = self.db.get_table(BUFFER_PROFILE_TABLE_NAME)
125139
v = int(value)
@@ -164,6 +178,7 @@ def main(config):
164178
parser.add_argument('-l', '--list', action='store_true', help='show buffer state')
165179
parser.add_argument('-v', '--version', action='version', version='%(prog)s 1.0')
166180

181+
parser.add_argument('-n', '--namespace', type=str, help='Namespace name', default=None)
167182
parser.add_argument('-vv', '--verbose', action='store_true', help='verbose output', default=False)
168183
parser.add_argument('-f', '--filename', help='file used by mock tests', type=str, default=None)
169184

@@ -174,7 +189,14 @@ def main(config):
174189
args = parser.parse_args()
175190

176191
try:
177-
mmu_cfg = MmuConfig(args.verbose, config, args.filename)
192+
load_db_config()
193+
namespaces = multi_asic.get_namespace_list()
194+
195+
if args.namespace and args.namespace not in namespaces:
196+
print("Invalid namespace: Namespace must be one of", *namespaces)
197+
sys.exit(1)
198+
199+
mmu_cfg = MmuConfig(args.verbose, config, args.filename, args.namespace)
178200
if args.list:
179201
mmu_cfg.list()
180202
elif config and args.profile:

tests/mmuconfig_input/mmuconfig_test_vectors.py

+30
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,36 @@
8383
8484
"""
8585

86+
show_mmu_config_one = """\
87+
Pool: ingress_lossy_pool
88+
---- -------
89+
mode dynamic
90+
type ingress
91+
---- -------
92+
93+
Pool: ingress_lossless_pool_hbm
94+
---- ---------
95+
mode static
96+
size 139458240
97+
type ingress
98+
---- ---------
99+
100+
Profile: ingress_lossy_profile
101+
---------- ------------------
102+
dynamic_th 3
103+
pool ingress_lossy_pool
104+
size 0
105+
---------- ------------------
106+
107+
Profile: ingress_lossless_profile_hbm
108+
--------- -------------------------
109+
static_th 12121212
110+
pool ingress_lossless_pool_hbm
111+
size 0
112+
--------- -------------------------
113+
114+
"""
115+
86116
testData = {
87117
'mmuconfig_list' : {'cmd' : ['show'],
88118
'args' : [],

tests/mock_tables/asic0/config_db.json

+19
Original file line numberDiff line numberDiff line change
@@ -257,5 +257,24 @@
257257
"ports@": "Ethernet124",
258258
"type": "L3",
259259
"stage": "ingress"
260+
},
261+
"BUFFER_POOL|ingress_lossy_pool": {
262+
"mode": "dynamic",
263+
"type": "ingress"
264+
},
265+
"BUFFER_POOL|ingress_lossless_pool_hbm": {
266+
"mode": "static",
267+
"size": "139458240",
268+
"type": "ingress"
269+
},
270+
"BUFFER_PROFILE|ingress_lossy_profile": {
271+
"dynamic_th": "3",
272+
"pool": "ingress_lossy_pool",
273+
"size": "0"
274+
},
275+
"BUFFER_PROFILE|ingress_lossless_profile_hbm": {
276+
"static_th": "12121212",
277+
"pool": "ingress_lossless_pool_hbm",
278+
"size": "0"
260279
}
261280
}

tests/mock_tables/asic1/config_db.json

+35
Original file line numberDiff line numberDiff line change
@@ -197,5 +197,40 @@
197197
"holdtime": "0",
198198
"asn": "65100",
199199
"keepalive": "0"
200+
},
201+
"BUFFER_POOL|ingress_lossless_pool": {
202+
"mode": "dynamic",
203+
"type": "ingress"
204+
},
205+
"BUFFER_PROFILE|alpha_profile": {
206+
"dynamic_th": "0",
207+
"pool": "ingress_lossless_pool",
208+
"headroom_type": "dynamic"
209+
},
210+
"BUFFER_PROFILE|headroom_profile": {
211+
"dynamic_th": "0",
212+
"pool": "ingress_lossless_pool",
213+
"xon": "18432",
214+
"xoff": "32768",
215+
"size": "51200"
216+
},
217+
"BUFFER_POOL|egress_lossless_pool": {
218+
"mode": "dynamic",
219+
"size": "13945824",
220+
"type": "egress"
221+
},
222+
"BUFFER_PROFILE|egress_lossless_profile": {
223+
"dynamic_th": "0",
224+
"pool": "egress_lossless_pool",
225+
"size": "0"
226+
},
227+
"BUFFER_POOL|egress_lossy_pool": {
228+
"mode": "dynamic",
229+
"type": "egress"
230+
},
231+
"BUFFER_PROFILE|egress_lossy_profile": {
232+
"dynamic_th": "0",
233+
"pool": "egress_lossy_pool",
234+
"size": "0"
200235
}
201236
}

tests/multi_asic_mmuconfig_test.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import os
2+
import sys
3+
4+
from utils import get_result_and_return_code
5+
from mmuconfig_input.mmuconfig_test_vectors import *
6+
from json import load
7+
8+
root_path = os.path.dirname(os.path.abspath(__file__))
9+
modules_path = os.path.dirname(root_path)
10+
scripts_path = os.path.join(modules_path, "scripts")
11+
sys.path.insert(0, root_path)
12+
sys.path.insert(0, modules_path)
13+
14+
class TestMmuconfigMultiAsic(object):
15+
@classmethod
16+
def setup_class(cls):
17+
os.environ["PATH"] += os.pathsep + scripts_path
18+
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = "multi_asic"
19+
os.environ['UTILITIES_UNIT_TESTING'] = "2"
20+
print("SETUP")
21+
22+
def executor(self, command, expected_result=None):
23+
return_code, result = get_result_and_return_code(command)
24+
print("return_code: {}".format(return_code))
25+
print("result = {}".format(result))
26+
assert return_code == 0
27+
if expected_result:
28+
assert result == expected_result
29+
30+
def test_mmu_show_config_one_masic(self):
31+
self.executor(['mmuconfig', '-l', '-n', 'asic0'], show_mmu_config_one)
32+
33+
def test_mmu_show_config_all_masic(self):
34+
self.executor(['mmuconfig', '-l'], show_mmu_config)
35+
36+
def test_mmu_alpha_config_masic(self):
37+
self.executor(['mmuconfig', '-p', 'alpha_profile', '-a', '2', '-n', 'asic0'])
38+
fd = open('/tmp/mmuconfig', 'r')
39+
cmp_data = load(fd)
40+
assert cmp_data['alpha_profile']['dynamic_th'] == '2'
41+
42+
@classmethod
43+
def teardown_class(cls):
44+
os.environ['PATH'] = os.pathsep.join(os.environ['PATH'].split(os.pathsep)[:-1])
45+
os.environ['UTILITIES_UNIT_TESTING'] = "0"
46+
os.environ["UTILITIES_UNIT_TESTING_TOPOLOGY"] = ""
47+
if os.path.isfile('/tmp/mmuconfig'):
48+
os.remove('/tmp/mmuconfig')
49+
print("TEARDOWN")

0 commit comments

Comments
 (0)