From 00b9f3ec815b583d5cd27a549164ddede2400300 Mon Sep 17 00:00:00 2001 From: Yaqiang Zhu Date: Wed, 31 Aug 2022 23:16:47 +0800 Subject: [PATCH] [topo_m0] Add new topo for mgmt tor router (#6208) What is the motivation for this PR? For mgmt tor router, both testing methodology and physical wiring pattern are quite different with existing T0/T1/ topo. Adding this topo can let us filter unrelated test cases from mgmt network. How did you do it? Add a new topo (inherit from t0-52) Enhance topo config and topo_facts for including interfaces Enhance minigraph templates to support generate minigraph for this new topo How did you verify/test it? Generate minigraph and deploy to DUT. Use ./testbed-cli.sh deploy-mg to gen&deploy minigraph with new topo m0 successfully, All the related configuration are correct pushed to DUT after deploy. --- ansible/library/announce_routes.py | 4 +- ansible/roles/eos/templates/m0-leaf.j2 | 1 + ansible/roles/eos/templates/m0-mx.j2 | 134 ++++++++++++++ ansible/templates/minigraph_png.j2 | 4 + ansible/vars/topo_m0.yml | 235 +++++++++++++++++++++++++ ansible/veos | 1 + tests/common/testbed.py | 2 +- 7 files changed, 378 insertions(+), 3 deletions(-) create mode 120000 ansible/roles/eos/templates/m0-leaf.j2 create mode 100644 ansible/roles/eos/templates/m0-mx.j2 create mode 100644 ansible/vars/topo_m0.yml diff --git a/ansible/library/announce_routes.py b/ansible/library/announce_routes.py index 2afd85888ad..2b34b8a2aeb 100644 --- a/ansible/library/announce_routes.py +++ b/ansible/library/announce_routes.py @@ -73,7 +73,7 @@ def wait_for_http(host_ip, http_port, timeout=10): def get_topo_type(topo_name): - pattern = re.compile(r'^(t0-mclag|t0|t1|ptf|fullmesh|dualtor|t2|mgmttor)') + pattern = re.compile(r'^(t0-mclag|t0|t1|ptf|fullmesh|dualtor|t2|mgmttor|m0)') match = pattern.match(topo_name) if not match: return "unsupported" @@ -506,7 +506,7 @@ def main(): topo_type = get_topo_type(topo_name) try: - if topo_type == "t0": + if topo_type == "t0" or topo_type == "m0": fib_t0(topo, ptf_ip, no_default_route=is_storage_backend, action=action) module.exit_json(changed=True) elif topo_type == "t1": diff --git a/ansible/roles/eos/templates/m0-leaf.j2 b/ansible/roles/eos/templates/m0-leaf.j2 new file mode 120000 index 00000000000..8430cb1debd --- /dev/null +++ b/ansible/roles/eos/templates/m0-leaf.j2 @@ -0,0 +1 @@ +t0-leaf.j2 \ No newline at end of file diff --git a/ansible/roles/eos/templates/m0-mx.j2 b/ansible/roles/eos/templates/m0-mx.j2 new file mode 100644 index 00000000000..641059da5d7 --- /dev/null +++ b/ansible/roles/eos/templates/m0-mx.j2 @@ -0,0 +1,134 @@ +{% set host = configuration[hostname] %} +{% set mgmt_ip = ansible_host %} +{% if vm_type is defined and vm_type == "ceos" %} +{% set mgmt_if_index = 0 %} +{% else %} +{% set mgmt_if_index = 1 %} +{% endif %} +no schedule tech-support +! +{% if vm_type is defined and vm_type == "ceos" %} +agent LicenseManager shutdown +agent PowerFuse shutdown +agent PowerManager shutdown +agent Thermostat shutdown +agent LedPolicy shutdown +agent StandbyCpld shutdown +agent Bfd shutdown +{% endif %} +! +hostname {{ hostname }} +! +vrf definition MGMT + rd 1:1 +! +spanning-tree mode mstp +! +aaa root secret 0 123456 +! +username admin privilege 15 role network-admin secret 0 123456 +! +clock timezone UTC +! +lldp run +lldp management-address Management{{ mgmt_if_index }} +lldp management-address vrf MGMT +! +snmp-server community {{ snmp_rocommunity }} ro +snmp-server vrf MGMT +! +ip routing +ip routing vrf MGMT +ipv6 unicast-routing +! +{% if vm_mgmt_gw is defined %} +ip route vrf MGMT 0.0.0.0/0 {{ vm_mgmt_gw }} +{% else %} +ip route vrf MGMT 0.0.0.0/0 {{ mgmt_gw }} +{% endif %} +! +interface Management {{ mgmt_if_index }} + description TO LAB MGMT SWITCH +{% if vm_type is defined and vm_type == "ceos" %} + vrf MGMT +{% else %} + vrf forwarding MGMT +{% endif %} + ip address {{ mgmt_ip }}/{{ mgmt_prefixlen }} + no shutdown +! +{% for name, iface in host['interfaces'].items() %} +interface {{ name }} +{% if name.startswith('Loopback') %} + description LOOPBACK +{% else %} + mtu 9214 + no switchport + no shutdown +{% endif %} +{% if iface['ipv4'] is defined %} + ip address {{ iface['ipv4'] }} +{% endif %} +{% if iface['ipv6'] is defined %} + ipv6 enable + ipv6 address {{ iface['ipv6'] }} + ipv6 nd ra suppress +{% endif %} + no shutdown +! +{% endfor %} +! +interface {{ bp_ifname }} + description backplane + no switchport + no shutdown +{% if host['bp_interface']['ipv4'] is defined %} + ip address {{ host['bp_interface']['ipv4'] }} +{% endif %} +{% if host['bp_interface']['ipv6'] is defined %} + ipv6 enable + ipv6 address {{ host['bp_interface']['ipv6'] }} + ipv6 nd ra suppress +{% endif %} + no shutdown +! +router bgp {{ host['bgp']['asn'] }} + router-id {{ host['interfaces']['Loopback0']['ipv4'] | ipaddr('address') }} + ! + graceful-restart restart-time {{ bgp_gr_timer }} + graceful-restart + ! +{% for asn, remote_ips in host['bgp']['peers'].items() %} +{% for remote_ip in remote_ips %} + neighbor {{ remote_ip }} remote-as {{ asn }} + neighbor {{ remote_ip }} description {{ asn }} +{% if remote_ip | ipv6 %} + address-family ipv6 + neighbor {{ remote_ip }} activate + exit +{% endif %} +{% endfor %} +{% endfor %} + neighbor {{ props.nhipv4 }} remote-as {{ host['bgp']['asn'] }} + neighbor {{ props.nhipv4 }} description exabgp_v4 + neighbor {{ props.nhipv6 }} remote-as {{ host['bgp']['asn'] }} + neighbor {{ props.nhipv6 }} description exabgp_v6 + address-family ipv6 + neighbor {{ props.nhipv6 }} activate + exit + ! +{% for name, iface in host['interfaces'].items() if name.startswith('Loopback') %} +{% if iface['ipv4'] is defined %} + network {{ iface['ipv4'] }} +{% endif %} +{% if iface['ipv6'] is defined %} + network {{ iface['ipv6'] }} +{% endif %} +{% endfor %} +! +management api http-commands + no protocol https + protocol http + no shutdown +! +end diff --git a/ansible/templates/minigraph_png.j2 b/ansible/templates/minigraph_png.j2 index 44610a7ad99..acbd310cca1 100644 --- a/ansible/templates/minigraph_png.j2 +++ b/ansible/templates/minigraph_png.j2 @@ -187,6 +187,10 @@ {% set dev_type = 'CoreRouter' %} {% elif 'T0' in dev %} {% set dev_type = 'ToRRouter' %} +{% elif 'M1' in dev %} +{% set dev_type = 'MgmtLeafRouter' %} +{% elif 'MX' in dev %} +{% set dev_type = 'BmcMgmtToRRouter' %} {% else %} {% set dev_type = 'Unknown' %} {% endif %} diff --git a/ansible/vars/topo_m0.yml b/ansible/vars/topo_m0.yml new file mode 100644 index 00000000000..03cd4a3ce8c --- /dev/null +++ b/ansible/vars/topo_m0.yml @@ -0,0 +1,235 @@ +topology: + host_interfaces: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + - 16 + - 17 + - 18 + - 19 + - 20 + - 21 + - 22 + - 23 + - 24 + - 25 + - 26 + - 27 + - 28 + - 29 + - 30 + - 31 + - 32 + - 33 + - 34 + - 35 + - 36 + - 37 + - 38 + - 39 + - 40 + - 41 + - 42 + - 43 + - 44 + - 45 + VMs: + ARISTA01MX: + vlans: + - 46 + vm_offset: 0 + ARISTA02MX: + vlans: + - 47 + vm_offset: 1 + ARISTA01M1: + vlans: + - 48 + vm_offset: 2 + ARISTA02M1: + vlans: + - 49 + vm_offset: 3 + ARISTA03M1: + vlans: + - 50 + vm_offset: 4 + ARISTA04M1: + vlans: + - 51 + vm_offset: 5 + DUT: + vlan_configs: + default_vlan_config: one_vlan_a + one_vlan_a: + Vlan1000: + id: 1000 + intfs: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45] + prefix: 192.168.0.1/21 + prefix_v6: fc02:1000::1/64 + tag: 1000 + +configuration_properties: + common: + dut_asn: 65100 + dut_type: MgmtToRRouter + podset_number: 30 + tor_number: 16 + tor_subnet_number: 2 + max_tor_subnet_number: 16 + tor_subnet_size: 128 + failure_rate: 0 + nhipv4: 10.10.246.254 + nhipv6: FC0A::FF + mx: + swrole: mx + leaf: + swrole: leaf + +configuration: + ARISTA01MX: + properties: + - common + - mx + bgp: + asn: 64001 + peers: + 65100: + - 10.0.0.64 + - FC00::81 + interfaces: + Loopback0: + ipv4: 100.1.0.33/32 + ipv6: 2064:100::21/128 + Ethernet1: + ipv4: 10.0.0.65/31 + ipv6: fc00::82/126 + bp_interface: + ipv4: 10.10.246.33/24 + ipv6: fc0a::44/64 + + ARISTA02MX: + properties: + - common + - mx + bgp: + asn: 64002 + peers: + 65100: + - 10.0.0.66 + - FC00::85 + interfaces: + Loopback0: + ipv4: 100.1.0.34/32 + ipv6: 2064:100::22/128 + Ethernet1: + ipv4: 10.0.0.67/31 + ipv6: fc00::86/126 + bp_interface: + ipv4: 10.10.246.34/24 + ipv6: fc0a::47/64 + + ARISTA01M1: + properties: + - common + - leaf + bgp: + asn: 65200 + peers: + 65100: + - 10.0.0.56 + - FC00::71 + interfaces: + Loopback0: + ipv4: 100.1.0.29/32 + ipv6: 2064:100::1d/128 + Ethernet1: + lacp: 1 + Port-Channel1: + ipv4: 10.0.0.57/31 + ipv6: fc00::72/126 + bp_interface: + ipv4: 10.10.246.29/24 + ipv6: fc0a::3a/64 + + ARISTA02M1: + properties: + - common + - leaf + bgp: + asn: 65200 + peers: + 65100: + - 10.0.0.58 + - FC00::75 + interfaces: + Loopback0: + ipv4: 100.1.0.30/32 + ipv6: 2064:100::1e/128 + Ethernet1: + lacp: 1 + Port-Channel1: + ipv4: 10.0.0.59/31 + ipv6: fc00::76/126 + bp_interface: + ipv4: 10.10.246.30/24 + ipv6: fc0a::3d/64 + + ARISTA03M1: + properties: + - common + - leaf + bgp: + asn: 65200 + peers: + 65100: + - 10.0.0.60 + - FC00::79 + interfaces: + Loopback0: + ipv4: 100.1.0.31/32 + ipv6: 2064:100::1f/128 + Ethernet1: + lacp: 1 + Port-Channel1: + ipv4: 10.0.0.61/31 + ipv6: fc00::7a/126 + bp_interface: + ipv4: 10.10.246.31/24 + ipv6: fc0a::3e/64 + + ARISTA04M1: + properties: + - common + - leaf + bgp: + asn: 65200 + peers: + 65100: + - 10.0.0.62 + - FC00::7D + interfaces: + Loopback0: + ipv4: 100.1.0.32/32 + ipv6: 2064:100::20/128 + Ethernet1: + lacp: 1 + Port-Channel1: + ipv4: 10.0.0.63/31 + ipv6: fc00::7e/126 + bp_interface: + ipv4: 10.10.246.32/24 + ipv6: fc0a::41/64 diff --git a/ansible/veos b/ansible/veos index 24ac9b3b643..311dfa6ce67 100644 --- a/ansible/veos +++ b/ansible/veos @@ -38,6 +38,7 @@ all: - dualtor-mixed - dualtor-mixed-56 - dualtor-mixed-120 + - m0 children: server_1: server_2: diff --git a/tests/common/testbed.py b/tests/common/testbed.py index cba4fe12275..2de8fcd31f9 100644 --- a/tests/common/testbed.py +++ b/tests/common/testbed.py @@ -260,7 +260,7 @@ def _generate_sai_ptf_topo(self, tb_dict): def get_testbed_type(self, topo_name): - pattern = re.compile(r'^(wan|t0|t1|ptf|fullmesh|dualtor|t2|tgen|mgmttor)') + pattern = re.compile(r'^(wan|t0|t1|ptf|fullmesh|dualtor|t2|tgen|mgmttor|m0)') match = pattern.match(topo_name) if match == None: logger.warning("Unsupported testbed type - {}".format(topo_name))