Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dualtor][minigraph.py] Add soc_ipv4 and cable_type to MUX_CABLE #10776

Merged
merged 3 commits into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions src/sonic-config-engine/minigraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
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

Expand Down Expand Up @@ -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
Expand All @@ -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")):
Expand All @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we rename this d_subtype, is it supposed to be cable_subtype ?

Copy link
Contributor Author

@lolyu lolyu May 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is cable_type if the device is of SmartCable, but I want the attribute name(SubType) to be more generic, and in function get_mux_cable_entries, it will be treated as cable type (LINE#1754)


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 = {}
Expand Down Expand Up @@ -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")):
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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']
Expand All @@ -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': {
Expand Down
41 changes: 39 additions & 2 deletions src/sonic-config-engine/tests/simple-sample-graph-case.xml
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@
<EndDevice>switch-t0</EndDevice>
<EndPort>fortyGigE0/4</EndPort>
<FlowControl>true</FlowControl>
<StartDevice>mux-cable</StartDevice>
<StartDevice>server1-SC</StartDevice>
<StartPort>L</StartPort>
<Validate>true</Validate>
</DeviceLinkBase>
Expand All @@ -269,7 +269,7 @@
<EndDevice>switch-t0</EndDevice>
<EndPort>fortyGigE0/8</EndPort>
<FlowControl>true</FlowControl>
<StartDevice>mux-cable</StartDevice>
<StartDevice>server2-SC</StartDevice>
<StartPort>U</StartPort>
<Validate>true</Validate>
</DeviceLinkBase>
Expand Down Expand Up @@ -317,6 +317,24 @@
</ManagementAddress>
<HwSku>Force10-S6000</HwSku>
</Device>
<Device i:type="SmartCable">
<ElementType>SmartCable</ElementType>
<Address xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
<d5p1:IPPrefix>0.0.0.0/0</d5p1:IPPrefix>
</Address>
<AddressV6 xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
<d5p1:IPPrefix>::/0</d5p1:IPPrefix>
</AddressV6>
<ManagementAddress xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
<d5p1:IPPrefix>0.0.0.0/0</d5p1:IPPrefix>
</ManagementAddress>
<ManagementAddressV6 xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
<d5p1:IPPrefix>::/0</d5p1:IPPrefix>
</ManagementAddressV6>
<SerialNumber i:nil="true" />
<Hostname>server1-SC</Hostname>
<HwSku>smartcable-sku</HwSku>
</Device>
<Device i:type="Server">
<ElementType>Server</ElementType>
<Address xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
Expand All @@ -331,6 +349,25 @@
<Hostname>server1</Hostname>
<HwSku>server-sku</HwSku>
</Device>
<Device i:type="SmartCable">
<ElementType>SmartCable</ElementType>
<SubType>active-active</SubType>
<Address xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
<d5p1:IPPrefix>10.10.10.3/32</d5p1:IPPrefix>
</Address>
<AddressV6 xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
<d5p1:IPPrefix>::/0</d5p1:IPPrefix>
</AddressV6>
<ManagementAddress xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
<d5p1:IPPrefix>0.0.0.0/0</d5p1:IPPrefix>
</ManagementAddress>
<ManagementAddressV6 xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
<d5p1:IPPrefix>::/0</d5p1:IPPrefix>
</ManagementAddressV6>
<SerialNumber i:nil="true" />
<Hostname>server2-SC</Hostname>
<HwSku>smartcable-sku</HwSku>
</Device>
<Device i:type="Server">
<ElementType>Server</ElementType>
<Address xmlns:d5p1="Microsoft.Search.Autopilot.NetMux">
Expand Down
19 changes: 18 additions & 1 deletion src/sonic-config-engine/tests/test_minigraph_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,21 @@ def test_minigraph_neighbor_metadata(self):
'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)
Expand Down Expand Up @@ -365,7 +380,9 @@ def test_minigraph_mux_cable_table(self):
'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'
}
}

Expand Down