From d2d31c2b2ea7f8ad874e1b54a5b202ea3a5b06cf Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Thu, 5 Dec 2019 15:58:56 -0800 Subject: [PATCH 1/9] [buildImage] Add support of platform.json parsing to portconfig.py file Signed-off-by: Sangita Maity * [sonic-cfggen] Add a unit-test to test platform capability file Signed-off-by: Sangita Maity Adding a new function to create BRKOUT_CFG TABLE in config db (#17) Signed-off-by: Sangita Maity --- src/sonic-config-engine/minigraph.py | 8 +- src/sonic-config-engine/portconfig.py | 265 +++++- src/sonic-config-engine/sonic-cfggen | 13 +- .../tests/sample_hwsku.json | 100 +++ .../tests/sample_output/platform_output.json | 819 ++++++++++++++++++ .../tests/sample_platform.json | 196 +++++ .../tests/test_cfggen_platformJson.py | 76 ++ .../sonic_daemon_base/daemon_base.py | 15 +- 8 files changed, 1473 insertions(+), 19 deletions(-) create mode 100644 src/sonic-config-engine/tests/sample_hwsku.json create mode 100644 src/sonic-config-engine/tests/sample_output/platform_output.json create mode 100644 src/sonic-config-engine/tests/sample_platform.json create mode 100644 src/sonic-config-engine/tests/test_cfggen_platformJson.py diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index b560df3332cd..b2c5100f3f8c 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -772,7 +772,7 @@ def enable_internal_bgp_session(bgp_sessions, filename, asic_name): # Main functions # ############################################################################### -def parse_xml(filename, platform=None, port_config_file=None, asic_name=None): +def parse_xml(filename, platform=None, port_config_file=None, hwsku_config_file=None, asic_name=None): """ Parse minigraph xml file. Keyword arguments: @@ -782,6 +782,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None): asic_name -- asic name; to parse multi-asic device minigraph to generate asic specific configuration. """ + root = ET.parse(filename).getroot() u_neighbors = None @@ -836,7 +837,10 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None): if child.tag == str(docker_routing_config_mode_qn): docker_routing_config_mode = child.text - (ports, alias_map, alias_asic_map) = get_port_config(hwsku=hwsku, platform=platform, port_config_file=port_config_file, asic=asic_id) + if hwsku_config_file: + (ports, alias_map, alias_asic_map) = get_port_config(hwsku=hwsku, platform=platform, port_config_file=port_config_file, hwsku_config_file=hwsku_config_file, asic=asic_id) + else: + (ports, alias_map, alias_asic_map) = get_port_config(hwsku=hwsku, platform=platform, port_config_file=port_config_file, asic=asic_id) port_alias_map.update(alias_map) port_alias_asic_map.update(alias_asic_map) diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index 87e13687ed55..8bf0e98ad86b 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -1,33 +1,138 @@ #!/usr/bin/env python -import os -import sys +try: + import os + import sys + import json + import ast + import re + from collections import OrderedDict + from swsssdk import ConfigDBConnector +except ImportError as e: + raise ImportError("%s - required module not found" % str(e)) +# Global Variable +PLATFORM_ROOT_PATH = '/usr/share/sonic/device' +PLATFORM_ROOT_PATH_DOCKER = '/usr/share/sonic/platform' +SONIC_ROOT_PATH = '/usr/share/sonic' +HWSKU_ROOT_PATH = '/usr/share/sonic/hwsku' + +PLATFORM_JSON = 'platform.json' +PORT_CONFIG_INI = 'port_config.ini' +HWSKU_JSON = 'hwsku.json' + +PORT_STR = "Ethernet" +BRKOUT_MODE = "default_brkout_mode" +CUR_BRKOUT_MODE = "brkout_mode" +INTF_KEY = "interfaces" + +BRKOUT_PATTERN = r'(\d{1,3})x(\d{1,3}G)(\[\d{1,3}G\])?(\((\d{1,3})\))?' + + +# +# Helper Functions +# +def readJson(filename): + # Read 'platform.json' or 'hwsku.json' file + try: + with open(filename) as fp: + try: + data = json.load(fp) + except json.JSONDecodeError: + print("Json file does not exist") + data_dict = ast.literal_eval(json.dumps(data)) + return data_dict + except: + print("error occurred while parsing json:", sys.exc_info()[1]) + return None + +def db_connect_configdb(): + """ + Connect to configdb + """ + config_db = ConfigDBConnector() + if config_db is None: + return None + try: + config_db.connect() + except: + config_db = None + return config_db def get_port_config_file_name(hwsku=None, platform=None, asic=None): + + # check 'platform.json' file presence + port_config_candidates_Json = [] + port_config_candidates_Json.append(os.path.join(PLATFORM_ROOT_PATH_DOCKER, PLATFORM_JSON)) + if platform: + port_config_candidates_Json.append(os.path.join(PLATFORM_ROOT_PATH, platform, PLATFORM_JSON)) + + # check 'portconfig.ini' file presence port_config_candidates = [] - port_config_candidates.append('/usr/share/sonic/hwsku/port_config.ini') + port_config_candidates.append(os.path.join(HWSKU_ROOT_PATH, PORT_CONFIG_INI)) if hwsku: if platform: if asic: - port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, asic,'port_config.ini')) - port_config_candidates.append(os.path.join('/usr/share/sonic/device', platform, hwsku, 'port_config.ini')) - port_config_candidates.append(os.path.join('/usr/share/sonic/platform', hwsku, 'port_config.ini')) - port_config_candidates.append(os.path.join('/usr/share/sonic', hwsku, 'port_config.ini')) - for candidate in port_config_candidates: + port_config_candidates.append(os.path.join(PLATFORM_ROOT_PATH, platform, hwsku, asic, PORT_CONFIG_INI)) + port_config_candidates.append(os.path.join(PLATFORM_ROOT_PATH, platform, hwsku, PORT_CONFIG_INI)) + port_config_candidates.append(os.path.join(PLATFORM_ROOT_PATH_DOCKER, hwsku, PORT_CONFIG_INI)) + port_config_candidates.append(os.path.join(SONIC_ROOT_PATH, hwsku, PORT_CONFIG_INI)) + + elif platform and not hwsku: + port_config_candidates.append(os.path.join(PLATFORM_ROOT_PATH, platform, PORT_CONFIG_INI)) + + for candidate in port_config_candidates_Json + port_config_candidates: + if os.path.isfile(candidate): + return candidate + return None + +def get_hwsku_file_name(hwsku=None, platform=None): + hwsku_candidates_Json = [] + hwsku_candidates_Json.append(os.path.join(HWSKU_ROOT_PATH, HWSKU_JSON)) + if hwsku: + if platform: + hwsku_candidates_Json.append(os.path.join(PLATFORM_ROOT_PATH, platform, hwsku, HWSKU_JSON)) + hwsku_candidates_Json.append(os.path.join(PLATFORM_ROOT_PATH_DOCKER, hwsku, HWSKU_JSON)) + hwsku_candidates_Json.append(os.path.join(SONIC_ROOT_PATH, hwsku, HWSKU_JSON)) + for candidate in hwsku_candidates_Json: if os.path.isfile(candidate): return candidate return None - +def get_port_config(hwsku=None, platform=None, port_config_file=None, hwsku_config_file=None, asic=None): + config_db = db_connect_configdb() + # If available, Read from CONFIG DB first + if config_db is not None and port_config_file is None: + + port_data = config_db.get_table("PORT") + if port_data is not None: + ports = ast.literal_eval(json.dumps(port_data)) + port_alias_map = {} + port_alias_asic_map = {} + for intf_name in ports.keys(): + port_alias_map[ports[intf_name]["alias"]]= intf_name + return (ports, port_alias_map, port_alias_asic_map) -def get_port_config(hwsku=None, platform=None, port_config_file=None, asic=None): if not port_config_file: port_config_file = get_port_config_file_name(hwsku, platform, asic) if not port_config_file: return ({}, {}, {}) - return parse_port_config_file(port_config_file) + # Read from 'platform.json' file + if port_config_file.endswith('.json'): + if not hwsku_config_file: + hwsku_json_file = get_hwsku_file_name(hwsku, platform) + if not hwsku_json_file: + return ({}, {}, {}) + else: + hwsku_json_file = hwsku_config_file + + return parse_platform_json_file(hwsku_json_file, port_config_file) + + # If 'platform.json' file is not available, read from 'port_config.ini' + else: + return parse_port_config_file(port_config_file) + def parse_port_config_file(port_config_file): ports = {} port_alias_map = {} @@ -63,4 +168,142 @@ def parse_port_config_file(port_config_file): port_alias_asic_map[data['alias']] = data['asic_port_name'].strip() return (ports, port_alias_map, port_alias_asic_map) +# Generate configs (i.e. alias, lanes, speed, index) for port +def gen_port_config(ports, parent_intf_id, index, alias_at_lanes, lanes, k, offset): + if k is not None: + num_lane_used, speed, alt_speed, _ , assigned_lane = k[0], k[1], k[2], k[3], k[4] + + # In case of symmetric mode + if assigned_lane is None: + assigned_lane = len(lanes.split(",")) + + parent_intf_id = int(offset)+int(parent_intf_id) + alias_start = 0 + offset + + step = int(assigned_lane)/int(num_lane_used) + for i in range(0,int(assigned_lane), step): + intf_name = PORT_STR + str(parent_intf_id) + ports[intf_name] = {} + ports[intf_name]['alias'] = alias_at_lanes.split(",")[alias_start] + ports[intf_name]['lanes'] = ','.join(lanes.split(",")[alias_start:alias_start+step]) + if speed: + speed_pat = re.search("^((\d+)G|\d+)$", speed.upper()) + if speed_pat is None: + raise Exception('{} speed is not Supported...'.format(speed)) + speed_G, speed_orig = speed_pat.group(2), speed_pat.group(1) + if speed_G: + conv_speed = int(speed_G)*1000 + else: + conv_speed = int(speed_orig) + ports[intf_name]['speed'] = str(conv_speed) + else: + raise Exception('Regex return for speed is None...') + + ports[intf_name]['index'] = index.split(",")[alias_start] + ports[intf_name]['admin_status'] = "up" + + parent_intf_id += step + alias_start += step + + offset = int(assigned_lane) + int(offset) + return offset + else: + raise Exception('Regex return for k is None...') + +""" +Given a port and breakout mode, this method returns +the list of child ports using platform_json file +""" +def get_child_ports(interface, breakout_mode, platform_json_file): + child_ports = {} + + port_dict = readJson(platform_json_file) + + index = port_dict[INTF_KEY][interface]['index'] + alias_at_lanes = port_dict[INTF_KEY][interface]['alias_at_lanes'] + lanes = port_dict[INTF_KEY][interface]['lanes'] + + """ + Example of match_list for some breakout_mode using regex + Breakout Mode -------> Match_list + ----------------------------- + 2x25G(2)+1x50G(2) ---> [('2', '25G', None, '(2)', '2'), ('1', '50G', None, '(2)', '2')] + 1x50G(2)+2x25G(2) ---> [('1', '50G', None, '(2)', '2'), ('2', '25G', None, '(2)', '2')] + 1x100G[40G] ---------> [('1', '100G', '[40G]', None, None)] + 2x50G ---------------> [('2', '50G', None, None, None)] + """ + # Asymmetric breakout mode + if re.search("\+",breakout_mode) is not None: + breakout_parts = breakout_mode.split("+") + match_list = [re.match(BRKOUT_PATTERN, i).groups() for i in breakout_parts] + + # Symmetric breakout mode + else: + match_list = [re.match(BRKOUT_PATTERN, breakout_mode).groups()] + + offset = 0 + parent_intf_id = int(re.search("Ethernet(\d+)", interface).group(1)) + for k in match_list: + offset = gen_port_config(child_ports, parent_intf_id, index, alias_at_lanes, lanes, k, offset) + return child_ports + +def parse_platform_json_file(hwsku_json_file, platform_json_file): + ports = {} + port_alias_map = {} + port_alias_asic_map = {} + + port_dict = readJson(platform_json_file) + hwsku_dict = readJson(hwsku_json_file) + + if not port_dict: + raise Exception("port_dict is none") + if not hwsku_dict: + raise Exception("hwsku_dict is none") + + if INTF_KEY not in port_dict or INTF_KEY not in hwsku_dict: + raise Exception("INTF_KEY is not present in appropriate file") + + for intf in port_dict[INTF_KEY]: + if intf not in hwsku_dict[INTF_KEY]: + raise Exception("{} is not available in hwsku_dict".format(intf)) + + # take default_brkout_mode from hwsku.json + brkout_mode = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE] + + child_ports = get_child_ports(intf, brkout_mode, platform_json_file) + ports.update(child_ports) + + if not ports: + raise Exception("Ports dictionary is empty") + + for i in ports.keys(): + port_alias_map[ports[i]["alias"]]= i + return (ports, port_alias_map, port_alias_asic_map) + + +def get_breakout_mode(hwsku=None, platform=None, port_config_file=None): + if not port_config_file: + port_config_file = get_port_config_file_name(hwsku, platform) + if not port_config_file: + return None + if port_config_file.endswith('.json'): + hwsku_json_file = get_hwsku_file_name(hwsku, platform) + if not hwsku_json_file: + raise Exception("'hwsku_json' file does not exist!!! This file is necessary to proceed forward.") + + return parse_breakout_mode(hwsku_json_file) + else: + return None + +def parse_breakout_mode(hwsku_json_file): + brkout_table = {} + hwsku_dict = readJson(hwsku_json_file) + if not hwsku_dict: + raise Exception("hwsku_dict is empty") + if INTF_KEY not in hwsku_dict: + raise Exception("INTF_KEY is not present in hwsku_dict") + for intf in hwsku_dict[INTF_KEY]: + brkout_table[intf] = {} + brkout_table[intf][CUR_BRKOUT_MODE] = hwsku_dict[INTF_KEY][intf][BRKOUT_MODE] + return brkout_table diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen index c247d85abec3..f463d9b901c5 100755 --- a/src/sonic-config-engine/sonic-cfggen +++ b/src/sonic-config-engine/sonic-cfggen @@ -37,8 +37,12 @@ from functools import partial from minigraph import minigraph_encoder from minigraph import parse_xml from minigraph import parse_device_desc_xml +<<<<<<< HEAD from minigraph import parse_asic_sub_role from portconfig import get_port_config +======= +from portconfig import get_port_config, get_port_config_file_name, get_breakout_mode +>>>>>>> [buildImage] Add support of platform.json parsing to portconfig.py file from sonic_device_util import get_machine_info from sonic_device_util import get_platform_info from sonic_device_util import get_system_mac @@ -199,6 +203,7 @@ def main(): group.add_argument("-k", "--hwsku", help="HwSKU") parser.add_argument("-n", "--namespace", help="namespace name", nargs='?', const=None, default=None) parser.add_argument("-p", "--port-config", help="port config file, used with -m or -k", nargs='?', const=None) + parser.add_argument("-S", "--hwsku-config", help="hwsku config file, used with -p and -m or -k", nargs='?', const=None) parser.add_argument("-y", "--yaml", help="yaml file that contains additional variables", action='append', default=[]) parser.add_argument("-j", "--json", help="json file that contains additional variables", action='append', default=[]) parser.add_argument("-a", "--additional-data", help="addition data, in json string") @@ -240,12 +245,18 @@ def main(): 'hwsku': hwsku }}} deep_update(data, hardware_data) + if args.port_config is None: + args.port_config = get_port_config_file_name(hwsku, platform) (ports, _, _) = get_port_config(hwsku, platform, args.port_config, asic_id) if not ports: print('Failed to get port config', file=sys.stderr) sys.exit(1) deep_update(data, {'PORT': ports}) + brkout_table = get_breakout_mode(hwsku, platform, args.port_config) + if brkout_table is not None: + deep_update(data, {'BREAKOUT_CFG': brkout_table}) + for json_file in args.json: with open(json_file, 'r') as stream: deep_update(data, FormatConverter.to_deserialized(json.load(stream))) @@ -258,7 +269,7 @@ def main(): else: deep_update(data, parse_xml(minigraph, platform, asic_name=asic_name)) else: - deep_update(data, parse_xml(minigraph, port_config_file=args.port_config, asic_name=asic_name)) + deep_update(data, parse_xml(minigraph, port_config_file=args.port_config, hwsku_config_file=args.hwsku_config, asic_name=asic_name)) if args.device_description != None: deep_update(data, parse_device_desc_xml(args.device_description)) diff --git a/src/sonic-config-engine/tests/sample_hwsku.json b/src/sonic-config-engine/tests/sample_hwsku.json new file mode 100644 index 000000000000..5b450932c238 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_hwsku.json @@ -0,0 +1,100 @@ +{ + "interfaces": { + "Ethernet0": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet4": { + "default_brkout_mode": "2x50G" + }, + "Ethernet8": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet12": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet16": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet20": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet24": { + "default_brkout_mode": "2x50G" + }, + "Ethernet28": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet32": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet36": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet40": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet44": { + "default_brkout_mode": "2x50G" + }, + "Ethernet48": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet52": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet56": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet60": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet64": { + "default_brkout_mode": "2x50G" + }, + "Ethernet68": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet72": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet76": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet80": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet84": { + "default_brkout_mode": "2x50G" + }, + "Ethernet88": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet92": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet96": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet100": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet104": { + "default_brkout_mode": "2x50G" + }, + "Ethernet108": { + "default_brkout_mode": "4x25G[10G]" + }, + "Ethernet112": { + "default_brkout_mode": "2x25G(2)+1x50G(2)" + }, + "Ethernet116": { + "default_brkout_mode": "1x50G(2)+2x25G(2)" + }, + "Ethernet120": { + "default_brkout_mode": "1x100G[40G]" + }, + "Ethernet124": { + "default_brkout_mode": "2x50G" + } + } +} diff --git a/src/sonic-config-engine/tests/sample_output/platform_output.json b/src/sonic-config-engine/tests/sample_output/platform_output.json new file mode 100644 index 000000000000..f4e031fbe536 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_output/platform_output.json @@ -0,0 +1,819 @@ +{ + "Ethernet8": { + "index": "3", + "lanes": "8", + "description": "Eth3/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth3/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet9": { + "index": "3", + "lanes": "9", + "description": " Eth3/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth3/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet36": { + "index": "10", + "lanes": "36,37", + "description": "Eth10/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth10/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet98": { + "index": "25", + "lanes": "98", + "description": " Eth25/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth25/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet0": { + "index": "1", + "lanes": "0,1,2,3", + "fec": "rs", + "description": "Eth1/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth1/1", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet6": { + "index": "2", + "lanes": "6,7", + "description": " Eth2/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth2/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet4": { + "index": "2", + "lanes": "4,5", + "description": "Eth2/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth2/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet109": { + "index": "28", + "lanes": "109", + "description": " Eth28/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth28/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet108": { + "index": "28", + "lanes": "108", + "description": "Eth28/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth28/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet18": { + "index": "5", + "lanes": "18", + "description": " Eth5/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth5/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet100": { + "index": "26", + "lanes": "100,101,102,103", + "fec": "rs", + "description": "Eth26/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth26/1", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet34": { + "index": "9", + "lanes": "34,35", + "description": " Eth9/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth9/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet104": { + "index": "27", + "lanes": "104,105", + "description": "Eth27/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth27/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet106": { + "index": "27", + "lanes": "106,107", + "description": " Eth27/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth27/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet94": { + "index": "24", + "lanes": "94,95", + "description": " Eth24/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth24/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet126": { + "index": "32", + "lanes": "126,127", + "description": " Eth32/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth32/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet96": { + "index": "25", + "lanes": "96,97", + "description": "Eth25/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth25/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet124": { + "index": "32", + "lanes": "124,125", + "description": "Eth32/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth32/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet90": { + "index": "23", + "lanes": "90", + "description": " Eth23/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth23/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet91": { + "index": "23", + "lanes": "91", + "description": " Eth23/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth23/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet92": { + "index": "24", + "lanes": "92", + "description": "Eth24/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth24/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet93": { + "index": "24", + "lanes": "93", + "description": " Eth24/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth24/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet50": { + "index": "13", + "lanes": "50", + "description": " Eth13/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth13/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet51": { + "index": "13", + "lanes": "51", + "description": " Eth13/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth13/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet52": { + "index": "14", + "lanes": "52", + "description": "Eth14/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth14/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet53": { + "index": "14", + "lanes": "53", + "description": " Eth14/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth14/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet54": { + "index": "14", + "lanes": "54,55", + "description": " Eth14/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth14/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet99": { + "index": "25", + "lanes": "99", + "description": " Eth25/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth25/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet56": { + "index": "15", + "lanes": "56,57", + "description": "Eth15/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth15/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet113": { + "index": "29", + "lanes": "113", + "description": " Eth29/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth29/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet76": { + "index": "20", + "lanes": "76,77", + "description": "Eth20/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth20/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet74": { + "index": "19", + "lanes": "74,75", + "description": " Eth19/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth19/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet39": { + "index": "10", + "lanes": "39", + "description": " Eth10/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth10/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet72": { + "index": "19", + "lanes": "72", + "description": "Eth19/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth19/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet73": { + "index": "19", + "lanes": "73", + "description": " Eth19/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth19/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet70": { + "index": "18", + "lanes": "70", + "description": " Eth18/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth18/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet71": { + "index": "18", + "lanes": "71", + "description": " Eth18/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth18/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet32": { + "index": "9", + "lanes": "32", + "description": "Eth9/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth9/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet33": { + "index": "9", + "lanes": "33", + "description": " Eth9/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth9/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet16": { + "index": "5", + "lanes": "16,17", + "description": "Eth5/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth5/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet111": { + "index": "28", + "lanes": "111", + "description": " Eth28/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth28/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet10": { + "index": "3", + "lanes": "10", + "description": " Eth3/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth3/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet11": { + "index": "3", + "lanes": "11", + "description": " Eth3/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth3/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet12": { + "index": "4", + "lanes": "12", + "description": "Eth4/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth4/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet13": { + "index": "4", + "lanes": "13", + "description": " Eth4/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth4/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet58": { + "index": "15", + "lanes": "58", + "description": " Eth15/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth15/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet19": { + "index": "5", + "lanes": "19", + "description": " Eth5/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth5/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet59": { + "index": "15", + "lanes": "59", + "description": " Eth15/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth15/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet38": { + "index": "10", + "lanes": "38", + "description": " Eth10/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth10/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet78": { + "index": "20", + "lanes": "78", + "description": " Eth20/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth20/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet68": { + "index": "18", + "lanes": "68", + "description": "Eth18/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth18/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet14": { + "index": "4", + "lanes": "14,15", + "description": " Eth4/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth4/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet89": { + "index": "23", + "lanes": "89", + "description": " Eth23/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth23/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet88": { + "index": "23", + "lanes": "88", + "description": "Eth23/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth23/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet118": { + "index": "30", + "lanes": "118", + "description": " Eth30/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth30/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet119": { + "index": "30", + "lanes": "119", + "description": " Eth30/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth30/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet116": { + "index": "30", + "lanes": "116,117", + "description": "Eth30/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth30/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet114": { + "index": "29", + "lanes": "114,115", + "description": " Eth29/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth29/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet80": { + "index": "21", + "lanes": "80,81,82,83", + "fec": "rs", + "description": "Eth21/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth21/1", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet112": { + "index": "29", + "lanes": "112", + "description": "Eth29/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth29/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet86": { + "index": "22", + "lanes": "86,87", + "description": " Eth22/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth22/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet110": { + "index": "28", + "lanes": "110", + "description": " Eth28/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth28/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet84": { + "index": "22", + "lanes": "84,85", + "description": "Eth22/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth22/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet31": { + "index": "8", + "lanes": "31", + "description": " Eth8/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth8/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet49": { + "index": "13", + "lanes": "49", + "description": " Eth13/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth13/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet48": { + "index": "13", + "lanes": "48", + "description": "Eth13/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth13/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet46": { + "index": "12", + "lanes": "46,47", + "description": " Eth12/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth12/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet30": { + "index": "8", + "lanes": "30", + "description": " Eth8/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth8/3", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet29": { + "index": "8", + "lanes": "29", + "description": " Eth8/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth8/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet40": { + "index": "11", + "lanes": "40,41,42,43", + "fec": "rs", + "description": "Eth11/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth11/1", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet120": { + "index": "31", + "lanes": "120,121,122,123", + "fec": "rs", + "description": "Eth31/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth31/1", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet28": { + "index": "8", + "lanes": "28", + "description": "Eth8/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth8/1", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet66": { + "index": "17", + "lanes": "66,67", + "description": " Eth17/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth17/3", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet60": { + "index": "16", + "lanes": "60,61,62,63", + "fec": "rs", + "description": "Eth16/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth16/1", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet64": { + "index": "17", + "lanes": "64,65", + "description": "Eth17/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth17/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet44": { + "index": "12", + "lanes": "44,45", + "description": "Eth12/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth12/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet20": { + "index": "6", + "lanes": "20,21,22,23", + "fec": "rs", + "description": "Eth6/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth6/1", + "pfc_asym": "off", + "speed": "100000" + }, + "Ethernet79": { + "index": "20", + "lanes": "79", + "description": " Eth20/4", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth20/4", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet69": { + "index": "18", + "lanes": "69", + "description": " Eth18/2", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth18/2", + "pfc_asym": "off", + "speed": "25000" + }, + "Ethernet24": { + "index": "7", + "lanes": "24,25", + "description": "Eth7/1", + "admin_status": "up", + "mtu": "9100", + "alias": "Eth7/1", + "pfc_asym": "off", + "speed": "50000" + }, + "Ethernet26": { + "index": "7", + "lanes": "26,27", + "description": " Eth7/3", + "admin_status": "up", + "mtu": "9100", + "alias": " Eth7/3", + "pfc_asym": "off", + "speed": "50000" + } +} diff --git a/src/sonic-config-engine/tests/sample_platform.json b/src/sonic-config-engine/tests/sample_platform.json new file mode 100644 index 000000000000..fd11a49ed0a0 --- /dev/null +++ b/src/sonic-config-engine/tests/sample_platform.json @@ -0,0 +1,196 @@ +{ + "interfaces": { + "Ethernet0": { + "index": "1,1,1,1", + "lanes": "0,1,2,3", + "alias_at_lanes": "Eth1/1, Eth1/2, Eth1/3, Eth1/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet4": { + "index": "2,2,2,2", + "lanes": "4,5,6,7", + "alias_at_lanes": "Eth2/1, Eth2/2, Eth2/3, Eth2/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G]" + }, + "Ethernet8": { + "index": "3,3,3,3", + "lanes": "8,9,10,11", + "alias_at_lanes": "Eth3/1, Eth3/2, Eth3/3, Eth3/4", + "breakout_modes": "1x100G[40G],2x50G,2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet12": { + "index": "4,4,4,4", + "lanes": "12,13,14,15", + "alias_at_lanes": "Eth4/1, Eth4/2, Eth4/3, Eth4/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet16": { + "index": "5,5,5,5", + "lanes": "16,17,18,19", + "alias_at_lanes": "Eth5/1, Eth5/2, Eth5/3, Eth5/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet20": { + "index": "6,6,6,6", + "lanes": "20,21,22,23", + "alias_at_lanes": "Eth6/1, Eth6/2, Eth6/3, Eth6/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet24": { + "index": "7,7,7,7", + "lanes": "24,25,26,27", + "alias_at_lanes": "Eth7/1, Eth7/2, Eth7/3, Eth7/4", + "breakout_modes": "1x100G[40G],4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet28": { + "index": "8,8,8,8", + "lanes": "28,29,30,31", + "alias_at_lanes": "Eth8/1, Eth8/2, Eth8/3, Eth8/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet32": { + "index": "9,9,9,9", + "lanes": "32,33,34,35", + "alias_at_lanes": "Eth9/1, Eth9/2, Eth9/3, Eth9/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet36": { + "index": "10,10,10,10", + "lanes": "36,37,38,39", + "alias_at_lanes": "Eth10/1, Eth10/2, Eth10/3, Eth10/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet40": { + "index": "11,11,11,11", + "lanes": "40,41,42,43", + "alias_at_lanes": "Eth11/1, Eth11/2, Eth11/3, Eth11/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet44": { + "index": "12,12,12,12", + "lanes": "44,45,46,47", + "alias_at_lanes": "Eth12/1, Eth12/2, Eth12/3, Eth12/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet48": { + "index": "13,13,13,13", + "lanes": "48,49,50,51", + "alias_at_lanes": "Eth13/1, Eth13/2, Eth13/3, Eth13/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet52": { + "index": "14,14,14,14", + "lanes": "52,53,54,55", + "alias_at_lanes": "Eth14/1, Eth14/2, Eth14/3, Eth14/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet56": { + "index": "15,15,15,15", + "lanes": "56,57,58,59", + "alias_at_lanes": "Eth15/1, Eth15/2, Eth15/3, Eth15/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet60": { + "index": "16,16,16,16", + "lanes": "60,61,62,63", + "alias_at_lanes": "Eth16/1, Eth16/2, Eth16/3, Eth16/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet64": { + "index": "17,17,17,17", + "lanes": "64,65,66,67", + "alias_at_lanes": "Eth17/1, Eth17/2, Eth17/3, Eth17/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet68": { + "index": "18,18,18,18", + "lanes": "68,69,70,71", + "alias_at_lanes": "Eth18/1, Eth18/2, Eth18/3, Eth18/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet72": { + "index": "19,19,19,19", + "lanes": "72,73,74,75", + "alias_at_lanes": "Eth19/1, Eth19/2, Eth19/3, Eth19/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet76": { + "index": "20,20,20,20", + "lanes": "76,77,78,79", + "alias_at_lanes": "Eth20/1, Eth20/2, Eth20/3, Eth20/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet80": { + "index": "21,21,21,21", + "lanes": "80,81,82,83", + "alias_at_lanes": "Eth21/1, Eth21/2, Eth21/3, Eth21/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet84": { + "index": "22,22,22,22", + "lanes": "84,85,86,87", + "alias_at_lanes": "Eth22/1, Eth22/2, Eth22/3, Eth22/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet88": { + "index": "23,23,23,23", + "lanes": "88,89,90,91", + "alias_at_lanes": "Eth23/1, Eth23/2, Eth23/3, Eth23/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet92": { + "index": "24,24,24,24", + "lanes": "92,93,94,95", + "alias_at_lanes": "Eth24/1, Eth24/2, Eth24/3, Eth24/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet96": { + "index": "25,25,25,25", + "lanes": "96,97,98,99", + "alias_at_lanes": "Eth25/1, Eth25/2, Eth25/3, Eth25/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet100": { + "index": "26,26,26,26", + "lanes": "100,101,102,103", + "alias_at_lanes": "Eth26/1, Eth26/2, Eth26/3, Eth26/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet104": { + "index": "27,27,27,27", + "lanes": "104,105,106,107", + "alias_at_lanes": "Eth27/1, Eth27/2, Eth27/3, Eth27/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet108": { + "index": "28,28,28,28", + "lanes": "108,109,110,111", + "alias_at_lanes": "Eth28/1, Eth28/2, Eth28/3, Eth28/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet112": { + "index": "29,29,29,29", + "lanes": "112,113,114,115", + "alias_at_lanes": "Eth29/1, Eth29/2, Eth29/3, Eth29/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet116": { + "index": "30,30,30,30", + "lanes": "116,117,118,119", + "alias_at_lanes": "Eth30/1, Eth30/2, Eth30/3, Eth30/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet120": { + "index": "31,31,31,31", + "lanes": "120,121,122,123", + "alias_at_lanes": "Eth31/1, Eth31/2, Eth31/3, Eth31/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + }, + "Ethernet124": { + "index": "32,32,32,32", + "lanes": "124,125,126,127", + "alias_at_lanes": "Eth32/1, Eth32/2, Eth32/3, Eth32/4", + "breakout_modes": "1x100G[40G],2x50G,4x25G[10G],2x25G(2)+1x50G(2),1x50G(2)+2x25G(2)" + } + } +} diff --git a/src/sonic-config-engine/tests/test_cfggen_platformJson.py b/src/sonic-config-engine/tests/test_cfggen_platformJson.py new file mode 100644 index 000000000000..4b099bee62ca --- /dev/null +++ b/src/sonic-config-engine/tests/test_cfggen_platformJson.py @@ -0,0 +1,76 @@ +from unittest import TestCase +import subprocess +import os +import json +import ast + +# Global Variable +PLATFORM_CAP = "platform_output.json" + +class TestCfgGenPlatformJson(TestCase): + + def setUp(self): + self.test_dir = os.path.dirname(os.path.realpath(__file__)) + self.script_file = os.path.join(self.test_dir, '..', 'sonic-cfggen') + self.sample_graph_simple = os.path.join(self.test_dir, 'simple-sample-graph.xml') + self.platform_json = os.path.join(self.test_dir, 'sample_platform.json') + self.hwsku_json = os.path.join(self.test_dir, 'sample_hwsku.json') + + def run_script(self, argument, check_stderr=False): + print '\n Running sonic-cfggen ' + argument + if check_stderr: + output = subprocess.check_output(self.script_file + ' ' + argument, stderr=subprocess.STDOUT, shell=True) + else: + output = subprocess.check_output(self.script_file + ' ' + argument, shell=True) + + linecount = output.strip().count('\n') + if linecount <= 0: + print ' Output: ' + output.strip() + else: + print ' Output: ({0} lines, {1} bytes)'.format(linecount + 1, len(output)) + return output + + def test_dummy_run(self): + argument = '' + output = self.run_script(argument) + self.assertEqual(output, '') + + def test_print_data(self): + argument = '-m "' + self.sample_graph_simple + '" --print-data' + output = self.run_script(argument) + self.assertTrue(len(output.strip()) > 0) + + # Check whether all interfaces present or not as per platform.json + def test_platform_json_interfaces_keys(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT.keys()"' + output = self.run_script(argument) + expected = "['Ethernet8', 'Ethernet9', 'Ethernet36', 'Ethernet98', 'Ethernet0', 'Ethernet6', 'Ethernet4', 'Ethernet109', 'Ethernet108', 'Ethernet18', 'Ethernet100', 'Ethernet34', 'Ethernet104', 'Ethernet106', 'Ethernet94', 'Ethernet126', 'Ethernet96', 'Ethernet124', 'Ethernet90', 'Ethernet91', 'Ethernet92', 'Ethernet93', 'Ethernet50', 'Ethernet51', 'Ethernet52', 'Ethernet53', 'Ethernet54', 'Ethernet99', 'Ethernet56', 'Ethernet113', 'Ethernet76', 'Ethernet74', 'Ethernet39', 'Ethernet72', 'Ethernet73', 'Ethernet70', 'Ethernet71', 'Ethernet32', 'Ethernet33', 'Ethernet16', 'Ethernet111', 'Ethernet10', 'Ethernet11', 'Ethernet12', 'Ethernet13', 'Ethernet58', 'Ethernet19', 'Ethernet59', 'Ethernet38', 'Ethernet78', 'Ethernet68', 'Ethernet14', 'Ethernet89', 'Ethernet88', 'Ethernet118', 'Ethernet119', 'Ethernet116', 'Ethernet114', 'Ethernet80', 'Ethernet112', 'Ethernet86', 'Ethernet110', 'Ethernet84', 'Ethernet31', 'Ethernet49', 'Ethernet48', 'Ethernet46', 'Ethernet30', 'Ethernet29', 'Ethernet40', 'Ethernet120', 'Ethernet28', 'Ethernet66', 'Ethernet60', 'Ethernet64', 'Ethernet44', 'Ethernet20', 'Ethernet79', 'Ethernet69', 'Ethernet24', 'Ethernet26']" + + self.assertEqual(sorted(output.strip()), sorted(expected)) + + # Check specific Interface with it's proper configuration as per platform.json + def test_platform_json_specific_ethernet_interfaces(self): + + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet8\']"' + output = self.run_script(argument) + expected = "{'index': '3', 'lanes': '8', 'description': 'Eth3/1', 'admin_status': 'up', 'mtu': '9100', 'alias': 'Eth3/1', 'pfc_asym': 'off', 'speed': '25000'}" + self.assertEqual(output.strip(), expected) + + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT[\'Ethernet112\']"' + output = self.run_script(argument) + expected = "{'index': '29', 'lanes': '112', 'description': 'Eth29/1', 'admin_status': 'up', 'mtu': '9100', 'alias': 'Eth29/1', 'pfc_asym': 'off', 'speed': '25000'}" + self.assertEqual(output.strip(), expected) + + # Check all Interface with it's proper configuration as per platform.json + def test_platform_json_all_ethernet_interfaces(self): + argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT"' + output = self.run_script(argument) + + sample_file = os.path.join(self.test_dir, 'sample_output', "platform_output.json") + fh = open(sample_file, 'rb') + fh_data = json.load(fh) + fh.close() + + output_dict = ast.literal_eval(output.strip()) + expected = ast.literal_eval(json.dumps(fh_data)) + self.assertDictEqual(output_dict, expected) diff --git a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py index d3807bf91524..8f932b2c9e39 100644 --- a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py +++ b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py @@ -28,6 +28,7 @@ # Port config information PORT_CONFIG = 'port_config.ini' PORTMAP = 'portmap.ini' +PLATFORM_CAP = 'platform.json' EEPROM_MODULE_NAME = 'eeprom' EEPROM_CLASS_NAME = 'board' @@ -151,13 +152,17 @@ def get_path_to_port_config_file(self): # Get platform and hwsku path (platform_path, hwsku_path) = self.get_path_to_platform_and_hwsku() - # First check for the presence of the new 'port_config.ini' file - port_config_file_path = "/".join([hwsku_path, PORT_CONFIG]) + # First check for the presence of the new 'platform.json' file + port_config_file_path = "/".join([platform_path, PLATFORM_CAP]) if not os.path.isfile(port_config_file_path): - # port_config.ini doesn't exist. Try loading the legacy 'portmap.ini' file - port_config_file_path = "/".join([hwsku_path, PORTMAP]) + + # platform.json doesn't exist. Try loading the legacy 'port_config.ini' file + port_config_file_path = "/".join([hwsku_path, PORT_CONFIG]) if not os.path.isfile(port_config_file_path): - raise IOError("Failed to detect port config file: %s" % (port_config_file_path)) + # port_config.ini doesn't exist. Try loading the legacy 'portmap.ini' file + port_config_file_path = "/".join([hwsku_path, PORTMAP]) + if not os.path.isfile(port_config_file_path): + raise IOError("Failed to detect port config file: %s" % (port_config_file_path)) return port_config_file_path From e5066aff9505e46a5d2558c82bd04d807eba7bc1 Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Tue, 2 Jun 2020 20:46:05 +0000 Subject: [PATCH 2/9] Fix merge conflict due to multi-asic support Signed-off-by: Sangita Maity --- src/sonic-config-engine/sonic-cfggen | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen index f463d9b901c5..afaf3b1c2058 100755 --- a/src/sonic-config-engine/sonic-cfggen +++ b/src/sonic-config-engine/sonic-cfggen @@ -37,12 +37,8 @@ from functools import partial from minigraph import minigraph_encoder from minigraph import parse_xml from minigraph import parse_device_desc_xml -<<<<<<< HEAD from minigraph import parse_asic_sub_role -from portconfig import get_port_config -======= from portconfig import get_port_config, get_port_config_file_name, get_breakout_mode ->>>>>>> [buildImage] Add support of platform.json parsing to portconfig.py file from sonic_device_util import get_machine_info from sonic_device_util import get_platform_info from sonic_device_util import get_system_mac From 20c212cee5738cb491bf77b1f6cf3e8aa6bfca17 Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Tue, 2 Jun 2020 23:19:04 +0000 Subject: [PATCH 3/9] Removed legacy 'portmap.ini' and fixed LGTM issue Signed-off-by: Sangita Maity --- src/sonic-config-engine/portconfig.py | 6 +++--- src/sonic-daemon-base/sonic_daemon_base/daemon_base.py | 6 +----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index 8bf0e98ad86b..95ffcc28cacb 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -41,7 +41,7 @@ def readJson(filename): print("Json file does not exist") data_dict = ast.literal_eval(json.dumps(data)) return data_dict - except: + except Exception as e: print("error occurred while parsing json:", sys.exc_info()[1]) return None @@ -54,7 +54,7 @@ def db_connect_configdb(): return None try: config_db.connect() - except: + except Exception as e: config_db = None return config_db @@ -109,7 +109,7 @@ def get_port_config(hwsku=None, platform=None, port_config_file=None, hwsku_conf port_alias_map = {} port_alias_asic_map = {} for intf_name in ports.keys(): - port_alias_map[ports[intf_name]["alias"]]= intf_name + port_alias_map[ports[intf_name]["alias"]] = intf_name return (ports, port_alias_map, port_alias_asic_map) if not port_config_file: diff --git a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py index 8f932b2c9e39..481e1db65b31 100644 --- a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py +++ b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py @@ -27,7 +27,6 @@ # Port config information PORT_CONFIG = 'port_config.ini' -PORTMAP = 'portmap.ini' PLATFORM_CAP = 'platform.json' EEPROM_MODULE_NAME = 'eeprom' @@ -159,10 +158,7 @@ def get_path_to_port_config_file(self): # platform.json doesn't exist. Try loading the legacy 'port_config.ini' file port_config_file_path = "/".join([hwsku_path, PORT_CONFIG]) if not os.path.isfile(port_config_file_path): - # port_config.ini doesn't exist. Try loading the legacy 'portmap.ini' file - port_config_file_path = "/".join([hwsku_path, PORTMAP]) - if not os.path.isfile(port_config_file_path): - raise IOError("Failed to detect port config file: %s" % (port_config_file_path)) + raise IOError("Failed to detect port config file: %s" % (port_config_file_path)) return port_config_file_path From 2f17452f9b1a9f9f6257ca5b17a4d345b0510f5a Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Wed, 3 Jun 2020 02:32:46 +0000 Subject: [PATCH 4/9] changed variable name as per review Signed-off-by: Sangita Maity --- src/sonic-config-engine/tests/test_cfggen_platformJson.py | 4 ++-- src/sonic-daemon-base/sonic_daemon_base/daemon_base.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sonic-config-engine/tests/test_cfggen_platformJson.py b/src/sonic-config-engine/tests/test_cfggen_platformJson.py index 4b099bee62ca..f94fcb4ab89b 100644 --- a/src/sonic-config-engine/tests/test_cfggen_platformJson.py +++ b/src/sonic-config-engine/tests/test_cfggen_platformJson.py @@ -5,7 +5,7 @@ import ast # Global Variable -PLATFORM_CAP = "platform_output.json" +PLATFORM_OUTPUT_FILE = "platform_output.json" class TestCfgGenPlatformJson(TestCase): @@ -66,7 +66,7 @@ def test_platform_json_all_ethernet_interfaces(self): argument = '-m "' + self.sample_graph_simple + '" -p "' + self.platform_json + '" -S "' + self.hwsku_json + '" -v "PORT"' output = self.run_script(argument) - sample_file = os.path.join(self.test_dir, 'sample_output', "platform_output.json") + sample_file = os.path.join(self.test_dir, 'sample_output', PLATFORM_OUTPUT_FILE) fh = open(sample_file, 'rb') fh_data = json.load(fh) fh.close() diff --git a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py index 481e1db65b31..797110422dc9 100644 --- a/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py +++ b/src/sonic-daemon-base/sonic_daemon_base/daemon_base.py @@ -27,7 +27,7 @@ # Port config information PORT_CONFIG = 'port_config.ini' -PLATFORM_CAP = 'platform.json' +PLATFORM_JSON = 'platform.json' EEPROM_MODULE_NAME = 'eeprom' EEPROM_CLASS_NAME = 'board' @@ -152,7 +152,7 @@ def get_path_to_port_config_file(self): (platform_path, hwsku_path) = self.get_path_to_platform_and_hwsku() # First check for the presence of the new 'platform.json' file - port_config_file_path = "/".join([platform_path, PLATFORM_CAP]) + port_config_file_path = "/".join([platform_path, PLATFORM_JSON]) if not os.path.isfile(port_config_file_path): # platform.json doesn't exist. Try loading the legacy 'port_config.ini' file From 9369448df87aeaae6e4e28001706453dceccaa74 Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Wed, 3 Jun 2020 17:26:07 +0000 Subject: [PATCH 5/9] Fix one LGTM alert related integer division Signed-off-by: Sangita Maity --- src/sonic-config-engine/portconfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index 95ffcc28cacb..1884c8889d50 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -180,7 +180,7 @@ def gen_port_config(ports, parent_intf_id, index, alias_at_lanes, lanes, k, off parent_intf_id = int(offset)+int(parent_intf_id) alias_start = 0 + offset - step = int(assigned_lane)/int(num_lane_used) + step = int(assigned_lane)//int(num_lane_used) for i in range(0,int(assigned_lane), step): intf_name = PORT_STR + str(parent_intf_id) ports[intf_name] = {} From abf66c9d8714433cf88bef63f0358c3b3ff989f9 Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Fri, 12 Jun 2020 23:59:32 +0000 Subject: [PATCH 6/9] Temporary verfication for 'config load_minigraph' hang issue. Signed-off-by: Sangita Maity --- src/sonic-config-engine/portconfig.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index 1884c8889d50..00833336f6b0 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -48,7 +48,7 @@ def readJson(filename): def db_connect_configdb(): """ Connect to configdb - """ + config_db = ConfigDBConnector() if config_db is None: return None @@ -57,6 +57,9 @@ def db_connect_configdb(): except Exception as e: config_db = None return config_db + """ + # Temporary verfication for 'config load_minigraph' hang issue. + return None def get_port_config_file_name(hwsku=None, platform=None, asic=None): From 7eb4196d5c5f630b0d8622f4a1c387bfbc0c8968 Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Sat, 13 Jun 2020 20:52:38 +0000 Subject: [PATCH 7/9] Reverted the last commit and changed config db connecto change Signed-off-by: Sangita Maity --- src/sonic-config-engine/portconfig.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index 00833336f6b0..334ad775ee45 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -48,18 +48,15 @@ def readJson(filename): def db_connect_configdb(): """ Connect to configdb - + """ config_db = ConfigDBConnector() if config_db is None: return None try: - config_db.connect() + config_db.db_connect('CONFIG_DB') except Exception as e: config_db = None return config_db - """ - # Temporary verfication for 'config load_minigraph' hang issue. - return None def get_port_config_file_name(hwsku=None, platform=None, asic=None): From a1fe1abcf0361bd77a375a448eba1d00e0ac0850 Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Mon, 15 Jun 2020 21:18:55 -0700 Subject: [PATCH 8/9] remove minlink initial value while fallback is define --- src/sonic-config-engine/minigraph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index b2c5100f3f8c..99d7fa4bf2c8 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -328,7 +328,7 @@ def parse_dpg(dpg, hname): intfs_inpc.append(pcmbr_list[i]) pc_members[(pcintfname, pcmbr_list[i])] = {'NULL': 'NULL'} if pcintf.find(str(QName(ns, "Fallback"))) != None: - pcs[pcintfname] = {'members': pcmbr_list, 'fallback': pcintf.find(str(QName(ns, "Fallback"))).text, 'min_links': str(int(math.ceil(len() * 0.75)))} + pcs[pcintfname] = {'members': pcmbr_list, 'fallback': pcintf.find(str(QName(ns, "Fallback"))).text} else: pcs[pcintfname] = {'members': pcmbr_list, 'min_links': str(int(math.ceil(len(pcmbr_list) * 0.75)))} From 1936c41eaaa6f464254c3a3fadde8ded79b69b97 Mon Sep 17 00:00:00 2001 From: Sangita Maity Date: Wed, 17 Jun 2020 00:04:34 +0000 Subject: [PATCH 9/9] reverted 'remove minlink initial value while fallback is define' commit and addressed review comments Signed-off-by: Sangita Maity --- src/sonic-config-engine/minigraph.py | 9 +++------ src/sonic-config-engine/portconfig.py | 10 ++++++++-- src/sonic-config-engine/sonic-cfggen | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 99d7fa4bf2c8..a61c3a08529a 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -328,7 +328,7 @@ def parse_dpg(dpg, hname): intfs_inpc.append(pcmbr_list[i]) pc_members[(pcintfname, pcmbr_list[i])] = {'NULL': 'NULL'} if pcintf.find(str(QName(ns, "Fallback"))) != None: - pcs[pcintfname] = {'members': pcmbr_list, 'fallback': pcintf.find(str(QName(ns, "Fallback"))).text} + pcs[pcintfname] = {'members': pcmbr_list, 'fallback': pcintf.find(str(QName(ns, "Fallback"))).text, 'min_links': str(int(math.ceil(len() * 0.75)))} else: pcs[pcintfname] = {'members': pcmbr_list, 'min_links': str(int(math.ceil(len(pcmbr_list) * 0.75)))} @@ -772,7 +772,7 @@ def enable_internal_bgp_session(bgp_sessions, filename, asic_name): # Main functions # ############################################################################### -def parse_xml(filename, platform=None, port_config_file=None, hwsku_config_file=None, asic_name=None): +def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hwsku_config_file=None): """ Parse minigraph xml file. Keyword arguments: @@ -837,10 +837,7 @@ def parse_xml(filename, platform=None, port_config_file=None, hwsku_config_file= if child.tag == str(docker_routing_config_mode_qn): docker_routing_config_mode = child.text - if hwsku_config_file: - (ports, alias_map, alias_asic_map) = get_port_config(hwsku=hwsku, platform=platform, port_config_file=port_config_file, hwsku_config_file=hwsku_config_file, asic=asic_id) - else: - (ports, alias_map, alias_asic_map) = get_port_config(hwsku=hwsku, platform=platform, port_config_file=port_config_file, asic=asic_id) + (ports, alias_map, alias_asic_map) = get_port_config(hwsku=hwsku, platform=platform, port_config_file=port_config_file, asic=asic_id, hwsku_config_file=hwsku_config_file) port_alias_map.update(alias_map) port_alias_asic_map.update(alias_asic_map) diff --git a/src/sonic-config-engine/portconfig.py b/src/sonic-config-engine/portconfig.py index 334ad775ee45..9b2d798aef57 100644 --- a/src/sonic-config-engine/portconfig.py +++ b/src/sonic-config-engine/portconfig.py @@ -53,7 +53,13 @@ def db_connect_configdb(): if config_db is None: return None try: - config_db.db_connect('CONFIG_DB') + """ + This could be blocking during the config load_minigraph phase, + as the CONFIG_DB_INITIALIZED is not yet set in the configDB. + We can ignore the check by using config_db.db_connect('CONFIG_DB') instead + """ + # Connect only if available & initialized + config_db.connect(wait_for_init=False) except Exception as e: config_db = None return config_db @@ -104,7 +110,7 @@ def get_port_config(hwsku=None, platform=None, port_config_file=None, hwsku_conf if config_db is not None and port_config_file is None: port_data = config_db.get_table("PORT") - if port_data is not None: + if bool(port_data): ports = ast.literal_eval(json.dumps(port_data)) port_alias_map = {} port_alias_asic_map = {} diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen index afaf3b1c2058..c0f61d8a95f9 100755 --- a/src/sonic-config-engine/sonic-cfggen +++ b/src/sonic-config-engine/sonic-cfggen @@ -261,11 +261,11 @@ def main(): minigraph = args.minigraph if platform: if args.port_config != None: - deep_update(data, parse_xml(minigraph, platform, args.port_config, asic_name=asic_name)) + deep_update(data, parse_xml(minigraph, platform, args.port_config, asic_name=asic_name, hwsku_config_file=args.hwsku_config)) else: deep_update(data, parse_xml(minigraph, platform, asic_name=asic_name)) else: - deep_update(data, parse_xml(minigraph, port_config_file=args.port_config, hwsku_config_file=args.hwsku_config, asic_name=asic_name)) + deep_update(data, parse_xml(minigraph, port_config_file=args.port_config, asic_name=asic_name, hwsku_config_file=args.hwsku_config)) if args.device_description != None: deep_update(data, parse_device_desc_xml(args.device_description))