diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py
index 750870433ac..00c183d7f96 100644
--- a/src/sonic-config-engine/minigraph.py
+++ b/src/sonic-config-engine/minigraph.py
@@ -39,7 +39,7 @@
BACKEND_ASIC_SUB_ROLE = 'BackEnd'
BACKEND_ASIC_INTERFACE_NAME_PREFIX = 'Ethernet-BP'
-# Default Virtual Network Index (VNI)
+# Default Virtual Network Index (VNI)
vni_default = 8000
###############################################################################
@@ -554,6 +554,39 @@ def parse_meta(meta, hname):
region = value
return syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region
+
+def parse_linkmeta(meta, hname):
+ link = meta.find(str(QName(ns, "Link")))
+ linkmetas = {}
+ for linkmeta in link.findall(str(QName(ns1, "LinkMetadata"))):
+ port = None
+ fec_disabled = None
+
+ # Sample: ARISTA05T1:Ethernet1/33;switch-t0:fortyGigE0/4
+ key = linkmeta.find(str(QName(ns1, "Key"))).text
+ endpoints = key.split(';')
+ for endpoint in endpoints:
+ t = endpoint.split(':')
+ if len(t) == 2 and t[0].lower() == hname.lower():
+ port = t[1]
+ break
+ else:
+ # Cannot find a matching hname, something went wrong
+ continue
+
+ properties = linkmeta.find(str(QName(ns1, "Properties")))
+ for device_property in properties.findall(str(QName(ns1, "DeviceProperty"))):
+ name = device_property.find(str(QName(ns1, "Name"))).text
+ value = device_property.find(str(QName(ns1, "Value"))).text
+ if name == "FECDisabled":
+ fec_disabled = value
+
+ linkmetas[port] = {}
+ if fec_disabled:
+ linkmetas[port]["FECDisabled"] = fec_disabled
+ return linkmetas
+
+
def parse_asic_meta(meta, hname):
sub_role = None
device_metas = meta.find(str(QName(ns, "Devices")))
@@ -732,7 +765,6 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
generate asic specific configuration.
"""
root = ET.parse(filename).getroot()
- mini_graph_path = filename
u_neighbors = None
u_devices = None
@@ -766,8 +798,9 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
deployment_id = None
region = None
hostname = None
+ linkmetas = {}
- #hostname is the asic_name, get the asic_id from the asic_name
+ # hostname is the asic_name, get the asic_id from the asic_name
if asic_name is not None:
asic_id = get_npu_id_from_name(asic_name)
else:
@@ -800,6 +833,8 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
(u_neighbors, u_devices, _, _, _, _, _, _) = parse_png(child, hostname)
elif child.tag == str(QName(ns, "MetadataDeclaration")):
(syslog_servers, dhcp_servers, ntp_servers, tacacs_servers, mgmt_routes, erspan_dst, deployment_id, region) = parse_meta(child, hostname)
+ elif child.tag == str(QName(ns, "LinkMetadataDeclaration")):
+ linkmetas = parse_linkmeta(child, hostname)
elif child.tag == str(QName(ns, "DeviceInfos")):
(port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku)
else:
@@ -811,6 +846,8 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
(neighbors, devices, port_speed_png) = parse_asic_png(child, asic_name, hostname)
elif child.tag == str(QName(ns, "MetadataDeclaration")):
(sub_role) = parse_asic_meta(child, asic_name)
+ elif child.tag == str(QName(ns, "LinkMetadataDeclaration")):
+ linkmetas = parse_linkmeta(child, hostname)
elif child.tag == str(QName(ns, "DeviceInfos")):
(port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku)
@@ -896,7 +933,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
for port_name in port_speed_png:
# not consider port not in port_config.ini
- #If no port_config_file is found ports is empty so ignore this error
+ # If no port_config_file is found ports is empty so ignore this error
if port_config_file is not None:
if port_name not in ports:
print >> sys.stderr, "Warning: ignore interface '%s' as it is not in the port_config.ini" % port_name
@@ -905,7 +942,14 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None):
ports.setdefault(port_name, {})['speed'] = port_speed_png[port_name]
for port_name, port in ports.items():
- if port.get('speed') == '100000':
+ # get port alias from port_config.ini
+ if port_config_file:
+ alias = port.get('alias')
+ else:
+ alias = port_name
+ # generate default 100G FEC
+ # Note: FECDisabled only be effective on 100G port right now
+ if port.get('speed') == '100000' and linkmetas.get(alias, {}).get('FECDisabled', '').lower() != 'true':
port['fec'] = 'rs'
# set port description if parsed from deviceinfo
diff --git a/src/sonic-config-engine/tests/t0-sample-graph.xml b/src/sonic-config-engine/tests/t0-sample-graph.xml
index ce12435b403..5e4a68db0e8 100644
--- a/src/sonic-config-engine/tests/t0-sample-graph.xml
+++ b/src/sonic-config-engine/tests/t0-sample-graph.xml
@@ -381,13 +381,14 @@
Ethernet1/1
switch-t0
fortyGigE0/124
+ 100000
DeviceInterfaceLink
true
- 10000
+ 100000
switch-t0
- fortyGigE0/2
+ fortyGigE0/4
true
ARISTA05T1
Ethernet1/33
@@ -439,6 +440,32 @@
+
+
+
+
+
+
+ FECDisabled
+
+ True
+
+
+ ARISTA05T1:Ethernet1/33;switch-t0:fortyGigE0/4
+
+
+
+
+
+ FECDisabled
+
+ True
+
+
+ ARISTA06T1:Ethernet1/34;switch-t0:fortyGigE0/8
+
+
+
switch-t0
Force10-S6000
diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py
index 2570aa7386b..816575f8417 100644
--- a/src/sonic-config-engine/tests/test_cfggen.py
+++ b/src/sonic-config-engine/tests/test_cfggen.py
@@ -107,8 +107,6 @@ def test_minigraph_acl(self):
argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v ACL_TABLE'
output = self.run_script(argument, True)
self.assertEqual(output.strip(), "Warning: Ignoring Control Plane ACL NTP_ACL without type\n"
- "Warning: ignore interface 'fortyGigE0/2' as it is not in the port_config.ini\n"
- "Warning: ignore interface 'fortyGigE0/2' in DEVICE_NEIGHBOR as it is not in the port_config.ini\n"
"{'NTP_ACL': {'services': ['NTP'], 'type': 'CTRLPLANE', 'policy_desc': 'NTP_ACL', 'stage': 'ingress'}, "
"'EVERFLOW': {'stage': 'ingress', 'type': 'MIRROR', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04', 'Ethernet4'], 'policy_desc': 'EVERFLOW'}, "
"'EVERFLOW_EGRESS': {'stage': 'egress', 'type': 'MIRROR', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04', 'Ethernet4'], 'policy_desc': 'EVERFLOW_EGRESS'}, "
@@ -191,7 +189,18 @@ def test_minigraph_extra_neighbors(self):
def test_minigraph_port_description(self):
argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet124\']"'
output = self.run_script(argument)
- self.assertEqual(output.strip(), "{'lanes': '101,102,103,104', 'description': 'ARISTA04T1:Ethernet1/1', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/124', 'admin_status': 'up'}")
+ self.assertEqual(output.strip(), "{'lanes': '101,102,103,104', 'fec': 'rs', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/124', 'admin_status': 'up', 'speed': '100000', 'description': 'ARISTA04T1:Ethernet1/1'}")
+
+ def test_minigraph_port_fec_disabled(self):
+ # Test for FECDisabled
+ argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet4\']"'
+ output = self.run_script(argument)
+ self.assertEqual(output.strip(), "{'lanes': '25,26,27,28', 'description': 'Servers0:eth0', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/4', 'admin_status': 'up', 'speed': '100000'}")
+
+ def test_minigraph_port_rs(self):
+ argument = '-m "' + self.sample_graph_t0 + '" -p "' + self.port_config + '" -v "PORT[\'Ethernet124\']"'
+ output = self.run_script(argument)
+ self.assertEqual(output.strip(), "{'lanes': '101,102,103,104', 'fec': 'rs', 'pfc_asym': 'off', 'mtu': '9100', 'alias': 'fortyGigE0/124', 'admin_status': 'up', 'speed': '100000', 'description': 'ARISTA04T1:Ethernet1/1'}")
def test_minigraph_bgp(self):
argument = '-m "' + self.sample_graph_bgp_speaker + '" -p "' + self.port_config + '" -v "BGP_NEIGHBOR[\'10.0.0.59\']"'