diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index 35a6f56456..e950e79122 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -44,6 +44,8 @@ VLAN_SUB_INTERFACE_VLAN_ID = '10' FRONTEND_ASIC_SUB_ROLE = 'FrontEnd' BACKEND_ASIC_SUB_ROLE = 'BackEnd' +dualtor_cable_types = ["active-active", "active-standby"] + # Default Virtual Network Index (VNI) vni_default = 8000 @@ -76,6 +78,7 @@ def get_peer_switch_info(link_metadata, devices): return peer_switch_table + def parse_device(device): lo_prefix = None lo_prefix_v6 = None @@ -85,6 +88,7 @@ def parse_device(device): name = None deployment_id = None cluster = None + d_subtype = None for node in device: if node.tag == str(QName(ns, "Address")): @@ -103,11 +107,14 @@ def parse_device(device): d_type = node.text elif node.tag == str(QName(ns, "ClusterName")): cluster = node.text + elif node.tag == str(QName(ns, "SubType")): + d_subtype = node.text if d_type is None and str(QName(ns3, "type")) in device.attrib: d_type = device.attrib[str(QName(ns3, "type"))] - return (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) + return (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster, d_subtype) + def calculate_lcm_for_ecmp (nhdevices_bank_map, nhip_bank_map): banks_enumerated = {} @@ -243,14 +250,16 @@ def parse_png(png, hname, dpg_ecmp_content = None): if child.tag == str(QName(ns, "Devices")): for device in child.findall(str(QName(ns, "Device"))): - (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) = parse_device(device) - device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku } + (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster, d_subtype) = parse_device(device) + device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku} if cluster: device_data['cluster'] = cluster if deployment_id: device_data['deployment_id'] = deployment_id if lo_prefix_v6: device_data['lo_addr_v6'] = lo_prefix_v6 + if d_subtype: + device_data['subtype'] = d_subtype devices[name] = device_data if child.tag == str(QName(ns, "DeviceInterfaceLinks")): @@ -275,10 +284,11 @@ def parse_png(png, hname, dpg_ecmp_content = None): for link in child.findall(str(QName(ns, 'DeviceLinkBase'))): if link.find(str(QName(ns, "ElementType"))).text == "LogicalLink": intf_name = link.find(str(QName(ns, "EndPort"))).text + start_device = link.find(str(QName(ns, "StartDevice"))).text if intf_name in port_alias_map: intf_name = port_alias_map[intf_name] - mux_cable_ports[intf_name] = "true" + mux_cable_ports[intf_name] = start_device if dpg_ecmp_content and (len(dpg_ecmp_content)): for version, content in dpg_ecmp_content.items(): # version is ipv4 or ipv6 @@ -373,7 +383,7 @@ def parse_asic_png(png, asic_name, hostname): if child.tag == str(QName(ns, "Devices")): for device in child.findall(str(QName(ns, "Device"))): - (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster) = parse_device(device) + (lo_prefix, lo_prefix_v6, mgmt_prefix, name, hwsku, d_type, deployment_id, cluster, _) = parse_device(device) device_data = {'lo_addr': lo_prefix, 'type': d_type, 'mgmt_addr': mgmt_prefix, 'hwsku': hwsku } if cluster: device_data['cluster'] = cluster @@ -1475,7 +1485,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw # If connected to a smart cable, get the connection position for port_name, port in ports.items(): if port_name in mux_cable_ports: - port['mux_cable'] = mux_cable_ports[port_name] + port['mux_cable'] = "true" # set port description if parsed from deviceinfo for port_name in port_descriptions: @@ -1720,7 +1730,7 @@ def get_tunnel_entries(tunnel_intfs, lo_intfs, hostname): def get_mux_cable_entries(mux_cable_ports, neighbors, devices): mux_cable_table = {} - for intf in mux_cable_ports: + for intf, cable_name in mux_cable_ports.items(): if intf in neighbors: entry = {} neighbor = neighbors[intf]['name'] @@ -1740,11 +1750,26 @@ def get_mux_cable_entries(mux_cable_ports, neighbors, devices): else: print("Warning: no server IPv4 loopback found for {}, skipping mux cable table entry".format(neighbor)) + if cable_name in devices: + cable_type = devices[cable_name].get('subtype') + if cable_type is None: + continue + if cable_type in dualtor_cable_types: + mux_cable_table[intf]['cable_type'] = cable_type + if cable_type == 'active-active': + soc_ipv4 = devices[cable_name]['lo_addr'].split('/')[0] + soc_ipv4_prefix = ipaddress.ip_network(UNICODE_TYPE(soc_ipv4)) + mux_cable_table[intf]['soc_ipv4'] = str(soc_ipv4_prefix) + else: + print("Warning: skip parsing device %s for mux cable entry, cable type %s not supported" % (cable_name, cable_type)) + else: + print("Warning: skip parsing device %s for mux cable entry, device definition not found" % cable_name) + return mux_cable_table def parse_device_desc_xml(filename): root = ET.parse(filename).getroot() - (lo_prefix, lo_prefix_v6, mgmt_prefix, hostname, hwsku, d_type, _, _) = parse_device(root) + (lo_prefix, lo_prefix_v6, mgmt_prefix, hostname, hwsku, d_type, _, _, _) = parse_device(root) results = {} results['DEVICE_METADATA'] = {'localhost': { diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml index d6a8c394f6..7bbef28aaa 100644 --- a/src/sonic-config-engine/tests/simple-sample-graph-case.xml +++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml @@ -258,7 +258,7 @@ switch-t0 fortyGigE0/4 true - mux-cable + server1-SC L true @@ -269,7 +269,7 @@ switch-t0 fortyGigE0/8 true - mux-cable + server2-SC U true @@ -317,6 +317,24 @@ Force10-S6000 + + SmartCable +
+ 0.0.0.0/0 +
+ + ::/0 + + + 0.0.0.0/0 + + + ::/0 + + + server1-SC + smartcable-sku +
Server
@@ -331,6 +349,25 @@ server1 server-sku + + SmartCable + active-active +
+ 10.10.10.3/32 +
+ + ::/0 + + + 0.0.0.0/0 + + + ::/0 + + + server2-SC + smartcable-sku +
Server
diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py index a6db6f37c5..d5fe3aad75 100644 --- a/src/sonic-config-engine/tests/test_minigraph_case.py +++ b/src/sonic-config-engine/tests/test_minigraph_case.py @@ -226,6 +226,21 @@ class TestCfgGenCaseInsensitive(TestCase): 'lo_addr_v6': 'fe80::0002/128', 'mgmt_addr': '10.0.0.2/32', 'type': 'Server' + }, + 'server1-SC': { + 'hwsku': 'smartcable-sku', + 'lo_addr': '0.0.0.0/0', + 'lo_addr_v6': '::/0', + 'mgmt_addr': '0.0.0.0/0', + 'type': 'SmartCable' + }, + 'server2-SC': { + 'hwsku': 'smartcable-sku', + 'lo_addr': '10.10.10.3/32', + 'lo_addr_v6': '::/0', + 'mgmt_addr': '0.0.0.0/0', + 'type': 'SmartCable', + 'subtype': 'active-active' } } output = self.run_script(argument) @@ -365,7 +380,9 @@ class TestCfgGenCaseInsensitive(TestCase): 'Ethernet8': { 'state': 'auto', 'server_ipv4': '10.10.10.2/32', - 'server_ipv6': 'fe80::2/128' + 'server_ipv6': 'fe80::2/128', + 'soc_ipv4': '10.10.10.3/32', + 'cable_type': 'active-active' } }