forked from sonic-net/sonic-mgmt
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/sonic-net/sonic-mgmt
- Loading branch information
Showing
136 changed files
with
9,561 additions
and
5,236 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
#!/usr/bin/env python3 | ||
|
||
from typing import Any, Dict, List | ||
import ipaddress | ||
import click | ||
import jinja2 | ||
|
||
# Define the roles for the devices in the topology | ||
roles_cfg = { | ||
"t0": { | ||
"asn": 65100, | ||
"downlink": None, | ||
"uplink": {"role": "t1", "asn": 64600}, | ||
"peer": {"role": "pt0", "asn": 65100}, | ||
}, | ||
"t1": { | ||
"asn": 65100, | ||
"downlink": {"role": "t0", "asn": 64000}, | ||
"uplink": {"role": "t2", "asn": 65200}, | ||
"peer": None, | ||
}, | ||
} | ||
|
||
|
||
# Utility functions to calculate IP addresses | ||
def calc_ipv4_pair(subnet_str, port_id): | ||
subnet = ipaddress.IPv4Network(subnet_str) | ||
return (str(subnet.network_address + 2*port_id), str(subnet.network_address + 2*port_id + 1)) | ||
|
||
|
||
def calc_ipv6_pair(subnet_str, port_id): | ||
subnet = ipaddress.IPv6Network(subnet_str) | ||
return (str(subnet.network_address + 4*port_id+1), str(subnet.network_address + 4*port_id + 2)) | ||
|
||
|
||
def calc_ipv4(subnet_str, port_id): | ||
subnet = ipaddress.IPv4Network(subnet_str) | ||
return str(subnet.network_address + port_id) | ||
|
||
|
||
def calc_ipv6(subnet_str, port_id): | ||
subnet = ipaddress.IPv6Network(subnet_str) | ||
return str(subnet.network_address + port_id) | ||
|
||
|
||
class VM: | ||
""" Class to represent a VM in the topology """ | ||
def __init__(self, | ||
port_id: int, | ||
vm_id: int, | ||
name_id: int, | ||
dut_asn: int, | ||
role_cfg: Dict[str, Any], | ||
ip_offset: int = None): | ||
|
||
self.role = role_cfg["role"] | ||
|
||
# IDs of the VM | ||
self.port_id = port_id | ||
self.vm_offset = vm_id | ||
self.ip_offset = vm_id if ip_offset is None else ip_offset | ||
self.name = f"ARISTA{name_id:02d}{self.role.upper()}" | ||
|
||
# VLAN configuration | ||
self.vlans = [port_id] | ||
|
||
# BGP configuration | ||
self.asn = role_cfg["asn"] | ||
self.peer_asn = dut_asn | ||
|
||
# IP addresses | ||
self.dut_intf_ipv4, self.pc_intf_ipv4 = calc_ipv4_pair("10.0.0.0", self.ip_offset) | ||
self.dut_intf_ipv6, self.pc_intf_ipv6 = calc_ipv6_pair("FC00::", self.ip_offset) | ||
self.loopback_ipv4 = calc_ipv4("100.1.0.0", self.ip_offset+1) | ||
self.loopback_ipv6 = calc_ipv6("2064:100::", self.ip_offset+1) | ||
|
||
# Backplane IPs will go with the VM ID | ||
self.bp_ipv4 = calc_ipv4("10.10.246.1", self.vm_offset+1) | ||
self.bp_ipv6 = calc_ipv6("fc0a::1", (self.vm_offset+1)) | ||
|
||
|
||
class HostInterface: | ||
""" Class to represent a host interface in the topology """ | ||
def __init__(self, port_id: int): | ||
self.port_id = port_id | ||
|
||
|
||
def generate_topo(role: str, port_count: int, uplink_ports: List[int], peer_ports: List[int]): | ||
dut_role_cfg = roles_cfg[role] | ||
|
||
vm_list = [] | ||
hostif_list = [] | ||
per_role_vm_count = {} | ||
for port_id in range(0, port_count): | ||
vm = None | ||
hostif = None | ||
|
||
# Get the VM configuration based on the port ID | ||
vm_role_cfg = None | ||
if port_id in uplink_ports: | ||
if dut_role_cfg["uplink"] is None: | ||
raise ValueError("Uplink port specified for a role that doesn't have an uplink") | ||
|
||
vm_role_cfg = dut_role_cfg["uplink"] | ||
|
||
elif port_id in peer_ports: | ||
if dut_role_cfg["peer"] is None: | ||
raise ValueError("Peer port specified for a role that doesn't have a peer") | ||
|
||
vm_role_cfg = dut_role_cfg["peer"] | ||
|
||
else: | ||
# If downlink is not specified, we consider it is host interface | ||
if dut_role_cfg["downlink"] is not None: | ||
vm_role_cfg = dut_role_cfg["downlink"] | ||
vm_role_cfg["asn"] += 1 | ||
|
||
# Create the VM or host interface based on the configuration | ||
if vm_role_cfg is not None: | ||
if vm_role_cfg["role"] not in per_role_vm_count: | ||
per_role_vm_count[vm_role_cfg["role"]] = 0 | ||
per_role_vm_count[vm_role_cfg["role"]] += 1 | ||
|
||
vm = VM(port_id, len(vm_list), per_role_vm_count[vm_role_cfg["role"]], dut_role_cfg["asn"], vm_role_cfg) | ||
vm_list.append(vm) | ||
|
||
else: | ||
hostif = HostInterface(port_id) | ||
hostif_list.append(hostif) | ||
|
||
return vm_list, hostif_list | ||
|
||
|
||
def generate_topo_file_content(role: str, | ||
template_file: str, | ||
vm_list: List[VM], | ||
hostif_list: List[HostInterface]): | ||
|
||
with open(template_file) as f: | ||
template = jinja2.Template(f.read()) | ||
|
||
output = template.render(role=role, | ||
dut=roles_cfg[role], | ||
vm_list=vm_list, | ||
hostif_list=hostif_list) | ||
|
||
return output | ||
|
||
|
||
def output_topo_file(role: str, | ||
keyword: str, | ||
downlink_port_count: int, | ||
uplink_port_count: int, | ||
peer_port_count: int, | ||
file_content: str): | ||
downlink_keyword = f"d{downlink_port_count}" if downlink_port_count > 0 else "" | ||
uplink_keyword = f"u{uplink_port_count}" if uplink_port_count > 0 else "" | ||
peer_keyword = f"s{peer_port_count}" if peer_port_count > 0 else "" | ||
|
||
file_path = f"vars/topo_{role}-{keyword}-{downlink_keyword}{uplink_keyword}{peer_keyword}.yml" | ||
|
||
with open(file_path, "w") as f: | ||
f.write(file_content) | ||
|
||
print(f"Generated topology file: {file_path}") | ||
|
||
|
||
@click.command() | ||
@click.option("--role", "-r", required=True, type=click.Choice(['t1']), help="Role of the device") | ||
@click.option("--keyword", "-k", required=True, type=str, help="Keyword for the topology file") | ||
@click.option("--template", "-t", required=True, type=str, help="Path to the Jinja template file") | ||
@click.option("--port-count", "-c", required=True, type=int, help="Number of ports on the device") | ||
@click.option("--uplinks", "-u", required=False, type=str, default="", help="Comma-separated list of uplink ports") | ||
@click.option("--peers", "-p", required=False, type=str, default="", help="Comma-separated list of peer ports") | ||
def main(role: str, keyword: str, template: str, port_count: int, uplinks: str, peers: str): | ||
""" | ||
Generate a topology file for a device: | ||
\b | ||
Examples (in the ansible directory): | ||
- ./generate_topo.py -r t1 -k isolated -t t1-isolated -c 128 | ||
- ./generate_topo.py -r t1 -k isolated -t t1-isolated -c 232 -u 48,49,58,59,164,165,174,175 | ||
""" | ||
uplink_ports = [int(port) for port in uplinks.split(",")] if uplinks != "" else [] | ||
peer_ports = [int(port) for port in peers.split(",")] if peers != "" else [] | ||
|
||
vm_list, hostif_list = generate_topo(role, port_count, uplink_ports, peer_ports) | ||
file_content = generate_topo_file_content(role, f"templates/topo_{template}.j2", vm_list, hostif_list) | ||
output_topo_file(role, keyword, port_count - len(uplink_ports) - len(peer_ports), len(uplink_ports), | ||
len(peer_ports), file_content) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
t1-28-lag-spine.j2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
t1-28-lag-tor.j2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
topology: | ||
VMs: | ||
{%- for vm in vm_list %} | ||
{{ vm.name }}: | ||
vlans: | ||
- {{ vm.vlans[0] }} | ||
vm_offset: {{ vm.vm_offset }} | ||
{%- endfor %} | ||
|
||
configuration_properties: | ||
common: | ||
dut_asn: {{ dut.asn }} | ||
dut_type: LeafRouter | ||
nhipv4: 10.10.246.254 | ||
nhipv6: FC0A::FF | ||
podset_number: 200 | ||
tor_number: 16 | ||
tor_subnet_number: 2 | ||
max_tor_subnet_number: 16 | ||
tor_subnet_size: 128 | ||
spine: | ||
swrole: spine | ||
tor: | ||
swrole: tor | ||
|
||
configuration: | ||
{%- for vm in vm_list %} | ||
{{vm.name}}: | ||
properties: | ||
- common | ||
bgp: | ||
asn: {{vm.asn}} | ||
peers: | ||
{{vm.peer_asn}}: | ||
- {{vm.dut_intf_ipv4}} | ||
- {{vm.dut_intf_ipv6}} | ||
interfaces: | ||
Loopback0: | ||
ipv4: {{vm.loopback_ipv4}}/32 | ||
ipv6: {{vm.loopback_ipv6}}/128 | ||
Ethernet1: | ||
ipv4: {{vm.pc_intf_ipv4}}/31 | ||
ipv6: {{vm.pc_intf_ipv6}}/126 | ||
bp_interfaces: | ||
ipv4: {{vm.bp_ipv4}}/24 | ||
ipv6: {{vm.bp_ipv6}}/64 | ||
{%- endfor %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,16 @@ | ||
# conf-name,group-name,topo,ptf_image_name,ptf,ptf_ip,ptf_ipv6,server,vm_base,dut,inv_name,auto_recover,comment | ||
ptf1-m,ptf1,ptf32,docker-ptf,ptf_ptf1,10.255.0.188/24,,server_1,,str-msn2700-01,lab,False,Test ptf Mellanox | ||
ptf2-b,ptf2,ptf64,docker-ptf,ptf_ptf2,10.255.0.189/24,,server_1,,lab-s6100-01,lab,False,Test ptf Broadcom | ||
vms-sn2700-t1,vms1-1,t1,docker-ptf,ptf_vms1-1,10.255.0.178/24,,server_1,VM0100,str-msn2700-01,lab,True,Tests Mellanox SN2700 vms | ||
vms-sn2700-t1-lag,vms1-2,t1-lag,docker-ptf,ptf_vms1-2,10.255.0.178/24,,server_1,VM0100,str-msn2700-01,lab,True,Tests Mellanox SN2700 vms | ||
vms-sn2700-t0,vms1-3,t0,docker-ptf,ptf_vms1-3,10.255.0.178/24,,server_1,VM0100,str-msn2700-01,lab,True,Tests Mellanox SN2700 vms | ||
vms-s6000-t0,vms2-1,t0,docker-ptf,ptf_vms2-1,10.255.0.179/24,,server_1,VM0100,lab-s6000-01,lab,True,Tests Dell S6000 vms | ||
vms-a7260-t0,vms3-1,t0-116,docker-ptf,ptf_vms3-1,10.255.0.180/24,,server_1,VM0100,lab-a7260-01,lab,True,Tests Arista A7260 vms | ||
vms-s6100-t0,vms4-1,t0-64,docker-ptf,ptf_vms4-1,10.255.0.181/24,,server_1,VM0100,lab-s6100-01,lab,True,Tests Dell S6100 vms | ||
vms-s6100-t1,vms4-2,t1-64,docker-ptf,ptf_vms4-2,10.255.0.182/24,,server_1,VM0100,lab-s6100-01,lab,True,Tests Dell S6100 vms | ||
vms-s6100-t1-lag,vms5-1,t1-64-lag,docker-ptf,ptf_vms5-1,10.255.0.183/24,,server_1,VM0100,lab-s6100-01,lab,True,ests Dell S6100 vms | ||
vms-multi-dut,vms1-duts,ptf64,docker-ptf,ptf_vms1-duts,10.255.0.184/24,,server_1,VM0100,[dut-host1;dut-host2],lab,True,Example Multi DUTs testbed | ||
vms-example-ixia-1,vms6-1,t0-64,docker-ptf-ixia,example-ixia-ptf-1,10.0.0.30/32,,server_6,VM0600,example-s6100-dut-1,lab,True,superman | ||
ixanvl-vs-conf,anvl,ptf32,docker-ptf-anvl,ptf_anvl,10.250.0.100/24,,server_1,,vlab-01,lab,True,Test ptf ANVL SONIC VM | ||
vms-snappi-sonic,vms6-1,ptf64,docker-ptf-snappi,snappi-sonic-ptf,10.251.0.232,,Server_6,,sonic-s6100-dut1,snappi-sonic,True,Batman | ||
vms-snappi-sonic-multidut,vms6-1,ptf64,docker-ptf-snappi,snappi-sonic-ptf,10.251.0.232,,Server_6,,[sonic-s6100-dut1;sonic-s6100-dut2],snappi-sonic,True,Batman | ||
# conf-name,group-name,topo,ptf_image_name,ptf,ptf_ip,ptf_ipv6,server,vm_base,dut,inv_name,auto_recover,is_smartswitch,comment | ||
ptf1-m,ptf1,ptf32,docker-ptf,ptf_ptf1,10.255.0.188/24,,server_1,,str-msn2700-01,lab,False,,Test ptf Mellanox | ||
ptf2-b,ptf2,ptf64,docker-ptf,ptf_ptf2,10.255.0.189/24,,server_1,,lab-s6100-01,lab,False,,Test ptf Broadcom | ||
vms-sn2700-t1,vms1-1,t1,docker-ptf,ptf_vms1-1,10.255.0.178/24,,server_1,VM0100,str-msn2700-01,lab,True,,Tests Mellanox SN2700 vms | ||
vms-sn2700-t1-lag,vms1-2,t1-lag,docker-ptf,ptf_vms1-2,10.255.0.178/24,,server_1,VM0100,str-msn2700-01,lab,True,,Tests Mellanox SN2700 vms | ||
vms-sn2700-t0,vms1-3,t0,docker-ptf,ptf_vms1-3,10.255.0.178/24,,server_1,VM0100,str-msn2700-01,lab,True,,Tests Mellanox SN2700 vms | ||
vms-s6000-t0,vms2-1,t0,docker-ptf,ptf_vms2-1,10.255.0.179/24,,server_1,VM0100,lab-s6000-01,lab,True,,Tests Dell S6000 vms | ||
vms-a7260-t0,vms3-1,t0-116,docker-ptf,ptf_vms3-1,10.255.0.180/24,,server_1,VM0100,lab-a7260-01,lab,True,,Tests Arista A7260 vms | ||
vms-s6100-t0,vms4-1,t0-64,docker-ptf,ptf_vms4-1,10.255.0.181/24,,server_1,VM0100,lab-s6100-01,lab,True,,Tests Dell S6100 vms | ||
vms-s6100-t1,vms4-2,t1-64,docker-ptf,ptf_vms4-2,10.255.0.182/24,,server_1,VM0100,lab-s6100-01,lab,True,,Tests Dell S6100 vms | ||
vms-s6100-t1-lag,vms5-1,t1-64-lag,docker-ptf,ptf_vms5-1,10.255.0.183/24,,server_1,VM0100,lab-s6100-01,lab,True,,ests Dell S6100 vms | ||
vms-multi-dut,vms1-duts,ptf64,docker-ptf,ptf_vms1-duts,10.255.0.184/24,,server_1,VM0100,[dut-host1;dut-host2],lab,True,,Example Multi DUTs testbed | ||
vms-example-ixia-1,vms6-1,t0-64,docker-ptf-ixia,example-ixia-ptf-1,10.0.0.30/32,,server_6,VM0600,example-s6100-dut-1,lab,True,,superman | ||
ixanvl-vs-conf,anvl,ptf32,docker-ptf-anvl,ptf_anvl,10.250.0.100/24,,server_1,,vlab-01,lab,True,,Test ptf ANVL SONIC VM | ||
vms-snappi-sonic,vms6-1,ptf64,docker-ptf-snappi,snappi-sonic-ptf,10.251.0.232,,Server_6,,sonic-s6100-dut1,snappi-sonic,True,,Batman | ||
vms-snappi-sonic-multidut,vms6-1,ptf64,docker-ptf-snappi,snappi-sonic-ptf,10.251.0.232,,Server_6,,[sonic-s6100-dut1;sonic-s6100-dut2],snappi-sonic,True,,Batman |
Oops, something went wrong.