Skip to content

Commit 3bf2bf9

Browse files
SuvarnaMeenakshiabdosi
authored andcommitted
[config engine] Parser changes to support parsing of multi-asic device minigraph (#4222)
- Changes to minigraph.py to parse minigraph.xml of a multi asic platform - Changes to portconfig.py to parse additional column "asic_port_name" in port_config.ini - Add a new option -n to sonic-cfggen for multi asic platforms - Add unit tests for config generation for multi asic platforms Signed-off-by: SuvarnaMeenakshi <[email protected]> Signed-off-by: Arvindsrinivasan Lakshmi Narasimhan <[email protected]>
1 parent cb22310 commit 3bf2bf9

File tree

10 files changed

+1753
-47
lines changed

10 files changed

+1753
-47
lines changed

src/sonic-config-engine/minigraph.py

Lines changed: 191 additions & 32 deletions
Large diffs are not rendered by default.

src/sonic-config-engine/portconfig.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import sys
44

55

6-
def get_port_config_file_name(hwsku=None, platform=None):
6+
def get_port_config_file_name(hwsku=None, platform=None, asic=None):
77
port_config_candidates = []
88
port_config_candidates.append('/usr/share/sonic/hwsku/port_config.ini')
99
if hwsku:
1010
if platform:
11+
if asic:
12+
port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, asic,'port_config.ini'))
1113
port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, 'port_config.ini'))
1214
port_config_candidates.append(os.path.join('/usr/share/sonic/platform', hwsku, 'port_config.ini'))
1315
port_config_candidates.append(os.path.join('/usr/share/sonic', hwsku, 'port_config.ini'))
@@ -17,17 +19,19 @@ def get_port_config_file_name(hwsku=None, platform=None):
1719
return None
1820

1921

20-
def get_port_config(hwsku=None, platform=None, port_config_file=None):
22+
23+
def get_port_config(hwsku=None, platform=None, port_config_file=None, asic=None):
2124
if not port_config_file:
22-
port_config_file = get_port_config_file_name(hwsku, platform)
25+
port_config_file = get_port_config_file_name(hwsku, platform, asic)
2326
if not port_config_file:
24-
return ({}, {})
27+
return ({}, {}, {})
2528
return parse_port_config_file(port_config_file)
2629

2730

2831
def parse_port_config_file(port_config_file):
2932
ports = {}
3033
port_alias_map = {}
34+
port_alias_asic_map = {}
3135
# Default column definition
3236
titles = ['name', 'lanes', 'alias', 'index']
3337
with open(port_config_file) as data:
@@ -49,6 +53,14 @@ def parse_port_config_file(port_config_file):
4953
data.setdefault('alias', name)
5054
ports[name] = data
5155
port_alias_map[data['alias']] = name
52-
return (ports, port_alias_map)
56+
# asic_port_name to sonic_name mapping also included in
57+
# port_alias_map
58+
if (('asic_port_name' in data) and
59+
(data['asic_port_name'] != name)):
60+
port_alias_map[data['asic_port_name']] = name
61+
# alias to asic_port_name mapping
62+
if 'asic_port_name' in data:
63+
port_alias_asic_map[data['alias']] = data['asic_port_name'].strip()
64+
return (ports, port_alias_map, port_alias_asic_map)
5365

5466

src/sonic-config-engine/sonic-cfggen

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ from functools import partial
3737
from minigraph import minigraph_encoder
3838
from minigraph import parse_xml
3939
from minigraph import parse_device_desc_xml
40+
from minigraph import parse_asic_sub_role
4041
from portconfig import get_port_config
4142
from sonic_device_util import get_machine_info
4243
from sonic_device_util import get_platform_info
4344
from sonic_device_util import get_system_mac
45+
from sonic_device_util import get_npu_id_from_name
4446
from config_samples import generate_sample_config
4547
from config_samples import get_available_config
4648
from swsssdk import SonicV2Connector, ConfigDBConnector
@@ -195,6 +197,7 @@ def main():
195197
group.add_argument("-m", "--minigraph", help="minigraph xml file", nargs='?', const='/etc/sonic/minigraph.xml')
196198
group.add_argument("-M", "--device-description", help="device description xml file")
197199
group.add_argument("-k", "--hwsku", help="HwSKU")
200+
parser.add_argument("-n", "--namespace", help="namespace name, used with -m or -k", nargs='?', const=None)
198201
parser.add_argument("-p", "--port-config", help="port config file, used with -m or -k", nargs='?', const=None)
199202
parser.add_argument("-y", "--yaml", help="yaml file that contains additional variables", action='append', default=[])
200203
parser.add_argument("-j", "--json", help="json file that contains additional variables", action='append', default=[])
@@ -222,13 +225,18 @@ def main():
222225

223226
data = {}
224227
hwsku = args.hwsku
228+
asic_name = args.namespace
229+
asic_id = None
230+
if asic_name is not None:
231+
asic_id = get_npu_id_from_name(asic_name)
232+
225233

226234
if hwsku is not None:
227235
hardware_data = {'DEVICE_METADATA': {'localhost': {
228236
'hwsku': hwsku
229237
}}}
230238
deep_update(data, hardware_data)
231-
(ports, _) = get_port_config(hwsku, platform, args.port_config)
239+
(ports, _, _) = get_port_config(hwsku, platform, args.port_config, asic_id)
232240
if not ports:
233241
print('Failed to get port config', file=sys.stderr)
234242
sys.exit(1)
@@ -242,11 +250,11 @@ def main():
242250
minigraph = args.minigraph
243251
if platform:
244252
if args.port_config != None:
245-
deep_update(data, parse_xml(minigraph, platform, args.port_config))
253+
deep_update(data, parse_xml(minigraph, platform, args.port_config, asic_name=asic_name))
246254
else:
247-
deep_update(data, parse_xml(minigraph, platform))
255+
deep_update(data, parse_xml(minigraph, platform, asic_name=asic_name))
248256
else:
249-
deep_update(data, parse_xml(minigraph, port_config_file=args.port_config))
257+
deep_update(data, parse_xml(minigraph, port_config_file=args.port_config, asic_name=asic_name))
250258

251259
if args.device_description != None:
252260
deep_update(data, parse_device_desc_xml(args.device_description))
@@ -267,11 +275,28 @@ def main():
267275
configdb.connect()
268276
deep_update(data, FormatConverter.db_to_output(configdb.get_config()))
269277

278+
279+
# the minigraph file must be provided to get the mac address for backend asics
270280
if args.platform_info:
281+
asic_role = None
282+
if asic_name is not None:
283+
if args.minigraph is not None:
284+
asic_role = parse_asic_sub_role(args.minigraph, asic_name)
285+
286+
if asic_role is not None and asic_role.lower() == "backend":
287+
mac = get_system_mac(namespace=asic_name)
288+
else:
289+
mac = get_system_mac()
290+
else:
291+
mac = get_system_mac()
292+
271293
hardware_data = {'DEVICE_METADATA': {'localhost': {
272294
'platform': platform,
273-
'mac': get_system_mac()
295+
'mac': mac,
274296
}}}
297+
# The ID needs to be passed to the SAI to identify the asic.
298+
if asic_name is not None:
299+
hardware_data['DEVICE_METADATA']['localhost'].update(asic_id=asic_id)
275300
deep_update(data, hardware_data)
276301

277302
if args.template is not None:

src/sonic-config-engine/sonic_device_util.py

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import yaml
44
import subprocess
55
import re
6-
6+
from natsort import natsorted
7+
import glob
78
DOCUMENTATION = '''
89
---
910
module: sonic_device_util
@@ -17,6 +18,9 @@
1718
TODO: this file shall be renamed and moved to other places in future
1819
to have it shared with multiple applications.
1920
'''
21+
SONIC_DEVICE_PATH = '/usr/share/sonic/device'
22+
NPU_NAME_PREFIX = 'asic'
23+
NAMESPACE_PATH_GLOB = '/run/netns/*'
2024
def get_machine_info():
2125
if not os.path.isfile('/host/machine.conf'):
2226
return None
@@ -27,7 +31,38 @@ def get_machine_info():
2731
if len(tokens) < 2:
2832
continue
2933
machine_vars[tokens[0]] = tokens[1].strip()
30-
return machine_vars
34+
return machine_vars
35+
36+
def get_npu_id_from_name(npu_name):
37+
if npu_name.startswith(NPU_NAME_PREFIX):
38+
return npu_name[len(NPU_NAME_PREFIX):]
39+
else:
40+
return None
41+
42+
def get_num_npus():
43+
platform = get_platform_info(get_machine_info())
44+
asic_conf_file_path = os.path.join(SONIC_DEVICE_PATH, platform, 'asic.conf')
45+
if not os.path.isfile(asic_conf_file_path):
46+
return 1
47+
with open(asic_conf_file_path) as asic_conf_file:
48+
for line in asic_conf_file:
49+
tokens = line.split('=')
50+
if len(tokens) < 2:
51+
continue
52+
if tokens[0].lower() == 'num_asic':
53+
num_npus = tokens[1].strip()
54+
return num_npus
55+
56+
def get_namespaces():
57+
"""
58+
In a multi NPU platform, each NPU is in a Linux Namespace.
59+
This method returns list of all the Namespace present on the device
60+
"""
61+
ns_list = []
62+
for path in glob.glob(NAMESPACE_PATH_GLOB):
63+
ns = os.path.basename(path)
64+
ns_list.append(ns)
65+
return natsorted(ns_list)
3166

3267
def get_platform_info(machine_info):
3368
if machine_info != None:
@@ -51,7 +86,7 @@ def get_sonic_version_info():
5186
def valid_mac_address(mac):
5287
return bool(re.match("^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$", mac))
5388

54-
def get_system_mac():
89+
def get_system_mac(namespace=None):
5590
version_info = get_sonic_version_info()
5691

5792
if (version_info['asic_type'] == 'mellanox'):
@@ -73,10 +108,14 @@ def get_system_mac():
73108
# Try valid mac in eeprom, else fetch it from eth0
74109
platform = get_platform_info(get_machine_info())
75110
hwsku = get_machine_info()['onie_machine']
76-
profile_cmd = 'cat /usr/share/sonic/device/' + platform +'/'+ hwsku +'/profile.ini | cut -f2 -d='
111+
profile_cmd = 'cat' + SONIC_DEVICE_PATH + '/' + platform +'/'+ hwsku +'/profile.ini | cut -f2 -d='
77112
hw_mac_entry_cmds = [ profile_cmd, "sudo decode-syseeprom -m", "ip link show eth0 | grep ether | awk '{print $2}'" ]
78113
else:
79-
hw_mac_entry_cmds = [ "ip link show eth0 | grep ether | awk '{print $2}'" ]
114+
mac_address_cmd = "cat /sys/class/net/eth0/address"
115+
if namespace is not None:
116+
mac_address_cmd = "sudo ip netns exec {} {}".format(namespace, mac_address_cmd)
117+
118+
hw_mac_entry_cmds = [mac_address_cmd]
80119

81120
for get_mac_cmd in hw_mac_entry_cmds:
82121
proc = subprocess.Popen(get_mac_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

0 commit comments

Comments
 (0)