From df98b92c12066db2130bfed489762d99892aff86 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Thu, 16 Jul 2020 14:09:03 -0700 Subject: [PATCH] topotests: initial set of tests for evpn multihoming The base topology is a two level CLOS with two racks. There are two PEs/TORs in each rack that provide active-active redundancy to two dual-attached servers in the rack. And EVPN-PIM is used for flooded traffic. Reference: evpn-mh-topo-tests.pdf Tests have been added for the following functionality - 1. ES management 2. EAD/Type-1 route handling 3. Type-2 route with non-zero ESI 4. MAC sync and remote MAC (with remote-ES destination) handling Signed-off-by: Anuradha Karuppiah --- .../bgp-evpn-mh/evpn-mh-topo-tests.pdf | Bin 0 -> 90963 bytes tests/topotests/bgp-evpn-mh/hostd11/evpn.conf | 0 tests/topotests/bgp-evpn-mh/hostd11/pim.conf | 0 .../topotests/bgp-evpn-mh/hostd11/zebra.conf | 0 tests/topotests/bgp-evpn-mh/hostd12/evpn.conf | 0 tests/topotests/bgp-evpn-mh/hostd12/pim.conf | 0 .../topotests/bgp-evpn-mh/hostd12/zebra.conf | 0 tests/topotests/bgp-evpn-mh/hostd21/evpn.conf | 0 tests/topotests/bgp-evpn-mh/hostd21/pim.conf | 0 .../topotests/bgp-evpn-mh/hostd21/zebra.conf | 0 tests/topotests/bgp-evpn-mh/hostd22/evpn.conf | 0 tests/topotests/bgp-evpn-mh/hostd22/pim.conf | 0 .../topotests/bgp-evpn-mh/hostd22/zebra.conf | 0 tests/topotests/bgp-evpn-mh/spine1/evpn.conf | 17 + tests/topotests/bgp-evpn-mh/spine1/pim.conf | 18 + tests/topotests/bgp-evpn-mh/spine1/zebra.conf | 15 + tests/topotests/bgp-evpn-mh/spine2/evpn.conf | 17 + tests/topotests/bgp-evpn-mh/spine2/pim.conf | 18 + tests/topotests/bgp-evpn-mh/spine2/zebra.conf | 15 + tests/topotests/bgp-evpn-mh/test_evpn_mh.py | 651 ++++++++++++++++++ tests/topotests/bgp-evpn-mh/torm11/evpn.conf | 21 + tests/topotests/bgp-evpn-mh/torm11/pim.conf | 13 + tests/topotests/bgp-evpn-mh/torm11/zebra.conf | 23 + tests/topotests/bgp-evpn-mh/torm12/evpn.conf | 21 + tests/topotests/bgp-evpn-mh/torm12/pim.conf | 13 + tests/topotests/bgp-evpn-mh/torm12/zebra.conf | 23 + tests/topotests/bgp-evpn-mh/torm21/evpn.conf | 21 + tests/topotests/bgp-evpn-mh/torm21/pim.conf | 13 + tests/topotests/bgp-evpn-mh/torm21/zebra.conf | 23 + tests/topotests/bgp-evpn-mh/torm22/evpn.conf | 21 + tests/topotests/bgp-evpn-mh/torm22/pim.conf | 13 + tests/topotests/bgp-evpn-mh/torm22/zebra.conf | 23 + 32 files changed, 979 insertions(+) create mode 100644 tests/topotests/bgp-evpn-mh/evpn-mh-topo-tests.pdf create mode 100644 tests/topotests/bgp-evpn-mh/hostd11/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd11/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd11/zebra.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd12/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd12/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd12/zebra.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd21/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd21/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd21/zebra.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd22/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd22/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/hostd22/zebra.conf create mode 100644 tests/topotests/bgp-evpn-mh/spine1/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/spine1/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/spine1/zebra.conf create mode 100644 tests/topotests/bgp-evpn-mh/spine2/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/spine2/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/spine2/zebra.conf create mode 100755 tests/topotests/bgp-evpn-mh/test_evpn_mh.py create mode 100644 tests/topotests/bgp-evpn-mh/torm11/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm11/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm11/zebra.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm12/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm12/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm12/zebra.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm21/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm21/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm21/zebra.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm22/evpn.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm22/pim.conf create mode 100644 tests/topotests/bgp-evpn-mh/torm22/zebra.conf diff --git a/tests/topotests/bgp-evpn-mh/evpn-mh-topo-tests.pdf b/tests/topotests/bgp-evpn-mh/evpn-mh-topo-tests.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8858e21496c7a76b2271e9793b7a7d8065330249 GIT binary patch literal 90963 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 Xq~qxV-Gc`0FTED#78K(Bd$0c=l|Wux literal 0 HcmV?d00001 diff --git a/tests/topotests/bgp-evpn-mh/hostd11/evpn.conf b/tests/topotests/bgp-evpn-mh/hostd11/evpn.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd11/pim.conf b/tests/topotests/bgp-evpn-mh/hostd11/pim.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd11/zebra.conf b/tests/topotests/bgp-evpn-mh/hostd11/zebra.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd12/evpn.conf b/tests/topotests/bgp-evpn-mh/hostd12/evpn.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd12/pim.conf b/tests/topotests/bgp-evpn-mh/hostd12/pim.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd12/zebra.conf b/tests/topotests/bgp-evpn-mh/hostd12/zebra.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd21/evpn.conf b/tests/topotests/bgp-evpn-mh/hostd21/evpn.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd21/pim.conf b/tests/topotests/bgp-evpn-mh/hostd21/pim.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd21/zebra.conf b/tests/topotests/bgp-evpn-mh/hostd21/zebra.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd22/evpn.conf b/tests/topotests/bgp-evpn-mh/hostd22/evpn.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd22/pim.conf b/tests/topotests/bgp-evpn-mh/hostd22/pim.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/hostd22/zebra.conf b/tests/topotests/bgp-evpn-mh/hostd22/zebra.conf new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/topotests/bgp-evpn-mh/spine1/evpn.conf b/tests/topotests/bgp-evpn-mh/spine1/evpn.conf new file mode 100644 index 0000000000..2e26f60f44 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/spine1/evpn.conf @@ -0,0 +1,17 @@ +frr defaults datacenter +! +router bgp 65001 + bgp router-id 192.168.100.13 + no bgp ebgp-requires-policy + neighbor 192.168.1.2 remote-as external + neighbor 192.168.2.2 remote-as external + neighbor 192.168.3.2 remote-as external + neighbor 192.168.4.2 remote-as external + redistribute connected + address-family l2vpn evpn + neighbor 192.168.1.2 activate + neighbor 192.168.2.2 activate + neighbor 192.168.3.2 activate + neighbor 192.168.4.2 activate + exit-address-family +! diff --git a/tests/topotests/bgp-evpn-mh/spine1/pim.conf b/tests/topotests/bgp-evpn-mh/spine1/pim.conf new file mode 100644 index 0000000000..68e686e8c7 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/spine1/pim.conf @@ -0,0 +1,18 @@ +ip pim rp 192.168.100.13 +ip pim spt-switchover infinity-and-beyond +! +int lo + ip pim +! +int spine1-eth0 + ip pim +! +int spine1-eth1 + ip pim +! +int spine1-eth2 + ip pim +! +int spine1-eth3 + ip pim +! diff --git a/tests/topotests/bgp-evpn-mh/spine1/zebra.conf b/tests/topotests/bgp-evpn-mh/spine1/zebra.conf new file mode 100644 index 0000000000..80e9e5a263 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/spine1/zebra.conf @@ -0,0 +1,15 @@ +int spine1-eth0 + ip addr 192.168.1.1/24 +! +int spine1-eth1 + ip addr 192.168.2.1/24 +! +int spine1-eth2 + ip addr 192.168.3.1/24 +! +int spine1-eth3 + ip addr 192.168.4.1/24 +! +int lo + ip addr 192.168.100.13/32 + ip addr 192.168.100.100/32 diff --git a/tests/topotests/bgp-evpn-mh/spine2/evpn.conf b/tests/topotests/bgp-evpn-mh/spine2/evpn.conf new file mode 100644 index 0000000000..ec2e789276 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/spine2/evpn.conf @@ -0,0 +1,17 @@ +frr defaults datacenter +! +router bgp 65001 + bgp router-id 192.168.100.14 + no bgp ebgp-requires-policy + neighbor 192.168.5.2 remote-as external + neighbor 192.168.6.2 remote-as external + neighbor 192.168.7.2 remote-as external + neighbor 192.168.8.2 remote-as external + redistribute connected + address-family l2vpn evpn + neighbor 192.168.5.2 activate + neighbor 192.168.6.2 activate + neighbor 192.168.7.2 activate + neighbor 192.168.8.2 activate + exit-address-family +! diff --git a/tests/topotests/bgp-evpn-mh/spine2/pim.conf b/tests/topotests/bgp-evpn-mh/spine2/pim.conf new file mode 100644 index 0000000000..c1566240e6 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/spine2/pim.conf @@ -0,0 +1,18 @@ +ip pim rp 192.168.100.13 +ip pim spt-switchover infinity-and-beyond +! +int lo + ip pim +! +int spine2-eth0 + ip pim +! +int spine2-eth1 + ip pim +! +int spine2-eth2 + ip pim +! +int spine2-eth3 + ip pim +! diff --git a/tests/topotests/bgp-evpn-mh/spine2/zebra.conf b/tests/topotests/bgp-evpn-mh/spine2/zebra.conf new file mode 100644 index 0000000000..1cd1df8c81 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/spine2/zebra.conf @@ -0,0 +1,15 @@ +int spine2-eth0 + ip addr 192.168.5.1/24 +! +int spine2-eth1 + ip addr 192.168.6.1/24 +! +int spine2-eth2 + ip addr 192.168.7.1/24 +! +int spine2-eth3 + ip addr 192.168.8.1/24 +! +int lo + ip addr 192.168.100.14/32 + ip addr 192.168.100.100/32 diff --git a/tests/topotests/bgp-evpn-mh/test_evpn_mh.py b/tests/topotests/bgp-evpn-mh/test_evpn_mh.py new file mode 100755 index 0000000000..fe28f79bd4 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/test_evpn_mh.py @@ -0,0 +1,651 @@ +#!/usr/bin/env python + +# +# test_evpn_mh.py +# +# Copyright (c) 2020 by +# Cumulus Networks, Inc. +# Anuradha Karuppiah +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_evpn_mh.py: Testing EVPN multihoming + +""" + +import os +import re +import sys +import pytest +import json +import platform +from functools import partial + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. +from mininet.topo import Topo + +##################################################### +## +## Network Topology Definition +## +## See topology picture at evpn-mh-topo-tests.pdf +##################################################### + + +class NetworkTopo(Topo): + ''' + EVPN Multihoming Topology - + 1. Two level CLOS + 2. Two spine switches - spine1, spine2 + 3. Two racks with Top-of-Rack switches per rack - tormx1, tormx2 + 4. Two dual attached hosts per-rack - hostdx1, hostdx2 + ''' + + def build(self, **_opts): + "Build function" + + tgen = get_topogen(self) + + tgen.add_router("spine1") + tgen.add_router("spine2") + tgen.add_router("torm11") + tgen.add_router("torm12") + tgen.add_router("torm21") + tgen.add_router("torm22") + tgen.add_router("hostd11") + tgen.add_router("hostd12") + tgen.add_router("hostd21") + tgen.add_router("hostd22") + + # On main router + # First switch is for a dummy interface (for local network) + + + ##################### spine1 ######################## + # spine1-eth0 is connected to torm11-eth0 + switch = tgen.add_switch("sw1") + switch.add_link(tgen.gears["spine1"]) + switch.add_link(tgen.gears["torm11"]) + + # spine1-eth1 is connected to torm12-eth0 + switch = tgen.add_switch("sw2") + switch.add_link(tgen.gears["spine1"]) + switch.add_link(tgen.gears["torm12"]) + + # spine1-eth2 is connected to torm21-eth0 + switch = tgen.add_switch("sw3") + switch.add_link(tgen.gears["spine1"]) + switch.add_link(tgen.gears["torm21"]) + + # spine1-eth3 is connected to torm22-eth0 + switch = tgen.add_switch("sw4") + switch.add_link(tgen.gears["spine1"]) + switch.add_link(tgen.gears["torm22"]) + + ##################### spine2 ######################## + # spine2-eth0 is connected to torm11-eth1 + switch = tgen.add_switch("sw5") + switch.add_link(tgen.gears["spine2"]) + switch.add_link(tgen.gears["torm11"]) + + # spine2-eth1 is connected to torm12-eth1 + switch = tgen.add_switch("sw6") + switch.add_link(tgen.gears["spine2"]) + switch.add_link(tgen.gears["torm12"]) + + # spine2-eth2 is connected to torm21-eth1 + switch = tgen.add_switch("sw7") + switch.add_link(tgen.gears["spine2"]) + switch.add_link(tgen.gears["torm21"]) + + # spine2-eth3 is connected to torm22-eth1 + switch = tgen.add_switch("sw8") + switch.add_link(tgen.gears["spine2"]) + switch.add_link(tgen.gears["torm22"]) + + ##################### torm11 ######################## + # torm11-eth2 is connected to hostd11-eth0 + switch = tgen.add_switch("sw9") + switch.add_link(tgen.gears["torm11"]) + switch.add_link(tgen.gears["hostd11"]) + + # torm11-eth3 is connected to hostd12-eth0 + switch = tgen.add_switch("sw10") + switch.add_link(tgen.gears["torm11"]) + switch.add_link(tgen.gears["hostd12"]) + + ##################### torm12 ######################## + # torm12-eth2 is connected to hostd11-eth1 + switch = tgen.add_switch("sw11") + switch.add_link(tgen.gears["torm12"]) + switch.add_link(tgen.gears["hostd11"]) + + # torm12-eth3 is connected to hostd12-eth1 + switch = tgen.add_switch("sw12") + switch.add_link(tgen.gears["torm12"]) + switch.add_link(tgen.gears["hostd12"]) + + ##################### torm21 ######################## + # torm21-eth2 is connected to hostd21-eth0 + switch = tgen.add_switch("sw13") + switch.add_link(tgen.gears["torm21"]) + switch.add_link(tgen.gears["hostd21"]) + + # torm21-eth3 is connected to hostd22-eth0 + switch = tgen.add_switch("sw14") + switch.add_link(tgen.gears["torm21"]) + switch.add_link(tgen.gears["hostd22"]) + + ##################### torm22 ######################## + # torm22-eth2 is connected to hostd21-eth1 + switch = tgen.add_switch("sw15") + switch.add_link(tgen.gears["torm22"]) + switch.add_link(tgen.gears["hostd21"]) + + # torm22-eth3 is connected to hostd22-eth1 + switch = tgen.add_switch("sw16") + switch.add_link(tgen.gears["torm22"]) + switch.add_link(tgen.gears["hostd22"]) + + +##################################################### +## +## Tests starting +## +##################################################### + +tor_ips = {"torm11" : "192.168.100.15", \ + "torm12" : "192.168.100.16", \ + "torm21" : "192.168.100.17", \ + "torm22" : "192.168.100.18"} + +svi_ips = {"torm11" : "45.0.0.2", \ + "torm12" : "45.0.0.3", \ + "torm21" : "45.0.0.4", \ + "torm22" : "45.0.0.5"} + +tor_ips_rack_1 = {"torm11" : "192.168.100.15", \ + "torm12" : "192.168.100.16"} + +tor_ips_rack_2 = {"torm21" : "192.168.100.17", \ + "torm22" : "192.168.100.18"} + +host_es_map = {"hostd11" : "03:44:38:39:ff:ff:01:00:00:01", + "hostd12" : "03:44:38:39:ff:ff:01:00:00:02", + "hostd21" : "03:44:38:39:ff:ff:02:00:00:01", + "hostd22" : "03:44:38:39:ff:ff:02:00:00:02"} + +def config_bond(node, bond_name, bond_members, bond_ad_sys_mac, br): + ''' + Used to setup bonds on the TORs and hosts for MH + ''' + node.run("ip link add dev %s type bond mode 802.3ad" % bond_name) + node.run("ip link set dev %s type bond lacp_rate 1" % bond_name) + node.run("ip link set dev %s type bond miimon 100" % bond_name) + node.run("ip link set dev %s type bond xmit_hash_policy layer3+4" % bond_name) + node.run("ip link set dev %s type bond min_links 1" % bond_name) + node.run("ip link set dev %s type bond ad_actor_system %s" %\ + (bond_name, bond_ad_sys_mac)) + + for bond_member in bond_members: + node.run("ip link set dev %s down" % bond_member) + node.run("ip link set dev %s master %s" % (bond_member, bond_name)) + node.run("ip link set dev %s up" % bond_member) + + node.run("ip link set dev %s up" % bond_name) + + # if bridge is specified add the bond as a bridge member + if br: + node.run(" ip link set dev %s master bridge" % bond_name) + node.run("/sbin/bridge link set dev %s priority 8" % bond_name) + node.run("/sbin/bridge vlan del vid 1 dev %s" % bond_name) + node.run("/sbin/bridge vlan del vid 1 untagged pvid dev %s" % bond_name) + node.run("/sbin/bridge vlan add vid 1000 dev %s" % bond_name) + node.run("/sbin/bridge vlan add vid 1000 untagged pvid dev %s"\ + % bond_name) + + +def config_mcast_tunnel_termination_device(node): + ''' + The kernel requires a device to terminate VxLAN multicast tunnels + when EVPN-PIM is used for flooded traffic + ''' + node.run("ip link add dev ipmr-lo type dummy") + node.run("ip link set dev ipmr-lo mtu 16000") + node.run("ip link set dev ipmr-lo mode dormant") + node.run("ip link set dev ipmr-lo up") + + +def config_bridge(node): + ''' + Create a VLAN aware bridge + ''' + node.run("ip link add dev bridge type bridge stp_state 0") + node.run("ip link set dev bridge type bridge vlan_filtering 1") + node.run("ip link set dev bridge mtu 9216") + node.run("ip link set dev bridge type bridge ageing_time 1800") + node.run("ip link set dev bridge type bridge mcast_snooping 0") + node.run("ip link set dev bridge type bridge vlan_stats_enabled 1") + node.run("ip link set dev bridge up") + node.run("/sbin/bridge vlan add vid 1000 dev bridge") + + +def config_vxlan(node, node_ip): + ''' + Create a VxLAN device for VNI 1000 and add it to the bridge. + VLAN-1000 is mapped to VNI-1000. + ''' + node.run("ip link add dev vx-1000 type vxlan id 1000 dstport 4789") + node.run("ip link set dev vx-1000 type vxlan nolearning") + node.run("ip link set dev vx-1000 type vxlan local %s" % node_ip) + node.run("ip link set dev vx-1000 type vxlan ttl 64") + node.run("ip link set dev vx-1000 mtu 9152") + node.run("ip link set dev vx-1000 type vxlan dev ipmr-lo group 239.1.1.100") + node.run("ip link set dev vx-1000 up") + + # bridge attrs + node.run("ip link set dev vx-1000 master bridge") + node.run("/sbin/bridge link set dev vx-1000 neigh_suppress on") + node.run("/sbin/bridge link set dev vx-1000 learning off") + node.run("/sbin/bridge link set dev vx-1000 priority 8") + node.run("/sbin/bridge vlan del vid 1 dev vx-1000") + node.run("/sbin/bridge vlan del vid 1 untagged pvid dev vx-1000") + node.run("/sbin/bridge vlan add vid 1000 dev vx-1000") + node.run("/sbin/bridge vlan add vid 1000 untagged pvid dev vx-1000") + + +def config_svi(node, svi_pip): + ''' + Create an SVI for VLAN 1000 + ''' + node.run("ip link add link bridge name vlan1000 type vlan id 1000 protocol 802.1q") + node.run("ip addr add %s/24 dev vlan1000" % svi_pip) + node.run("ip link set dev vlan1000 up") + node.run("/sbin/sysctl net.ipv4.conf.vlan1000.arp_accept=1") + node.run("ip link add link vlan1000 name vlan1000-v0 type macvlan mode private") + node.run("/sbin/sysctl net.ipv6.conf.vlan1000-v0.accept_dad=0") + node.run("/sbin/sysctl net.ipv6.conf.vlan1000-v0.dad_transmits") + node.run("/sbin/sysctl net.ipv6.conf.vlan1000-v0.dad_transmits=0") + node.run("ip link set dev vlan1000-v0 address 00:00:5e:00:01:01") + node.run("ip link set dev vlan1000-v0 up") + # metric 1024 is not working + node.run("ip addr add 45.0.0.1/24 dev vlan1000-v0") + + +def config_tor(tor_name, tor, tor_ip, svi_pip): + ''' + Create the bond/vxlan-bridge on the TOR which acts as VTEP and EPN-PE + ''' + # create a device for terminating VxLAN multicast tunnels + config_mcast_tunnel_termination_device(tor) + + # create a vlan aware bridge + config_bridge(tor) + + # create vxlan device and add it to bridge + config_vxlan(tor, tor_ip) + + # create hostbonds and add them to the bridge + if "torm1" in tor_name: + sys_mac = "44:38:39:ff:ff:01" + else: + sys_mac = "44:38:39:ff:ff:02" + bond_member = tor_name + "-eth2" + config_bond(tor, "hostbond1", [bond_member], sys_mac, "bridge") + + bond_member = tor_name + "-eth3" + config_bond(tor, "hostbond2", [bond_member], sys_mac, "bridge") + + # create SVI + config_svi(tor, svi_pip) + + +def config_tors(tgen, tors): + for tor_name in tors: + tor = tgen.gears[tor_name] + config_tor(tor_name, tor, tor_ips.get(tor_name), svi_ips.get(tor_name)) + +def compute_host_ip_mac(host_name): + host_id = host_name.split("hostd")[1] + host_ip = "45.0.0."+ host_id + "/24" + host_mac = "00:00:00:00:00:" + host_id + + return host_ip, host_mac + +def config_host(host_name, host): + ''' + Create the dual-attached bond on host nodes for MH + ''' + bond_members = [] + bond_members.append(host_name + "-eth0") + bond_members.append(host_name + "-eth1") + bond_name = "torbond" + config_bond(host, bond_name, bond_members, "00:00:00:00:00:00", None) + + host_ip, host_mac = compute_host_ip_mac(host_name) + host.run("ip addr add %s dev %s" % (host_ip, bond_name)) + host.run("ip link set dev %s address %s" % (bond_name, host_mac)) + + +def config_hosts(tgen, hosts): + for host_name in hosts: + host = tgen.gears[host_name] + config_host(host_name, host) + + +def setup_module(module): + "Setup topology" + tgen = Topogen(NetworkTopo, module.__name__) + tgen.start_topology() + + krel = platform.release() + if topotest.version_cmp(krel, "4.19") < 0: + tgen.errors = "kernel 4.19 needed for multihoming tests" + pytest.skip(tgen.errors) + + tors = [] + tors.append("torm11") + tors.append("torm12") + tors.append("torm21") + tors.append("torm22") + config_tors(tgen, tors) + + hosts = [] + hosts.append("hostd11") + hosts.append("hostd12") + hosts.append("hostd21") + hosts.append("hostd22") + config_hosts(tgen, hosts) + + # tgen.mininet_cli() + # This is a sample of configuration loading. + router_list = tgen.routers() + for rname, router in router_list.iteritems(): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_PIM, os.path.join(CWD, "{}/pim.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/evpn.conf".format(rname)) + ) + tgen.start_router() + # tgen.mininet_cli() + + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def check_local_es(esi, vtep_ips, dut_name, down_vteps): + ''' + Check if ES peers are setup correctly on local ESs + ''' + peer_ips = [] + if "torm1" in dut_name: + tor_ips_rack = tor_ips_rack_1 + else: + tor_ips_rack = tor_ips_rack_2 + + for tor_name, tor_ip in tor_ips_rack.iteritems(): + if dut_name not in tor_name: + peer_ips.append(tor_ip) + + # remove down VTEPs from the peer check list + peer_set = set(peer_ips) + down_vtep_set = set(down_vteps) + peer_set = peer_set - down_vtep_set + + vtep_set = set(vtep_ips) + diff = peer_set.symmetric_difference(vtep_set) + + return (esi, diff) if diff else None + + +def check_remote_es(esi, vtep_ips, dut_name, down_vteps): + ''' + Verify list of PEs associated with a remote ES + ''' + remote_ips = [] + + if "torm1" in dut_name: + tor_ips_rack = tor_ips_rack_2 + else: + tor_ips_rack = tor_ips_rack_1 + + for tor_name, tor_ip in tor_ips_rack.iteritems(): + remote_ips.append(tor_ip) + + # remove down VTEPs from the remote check list + remote_set = set(remote_ips) + down_vtep_set = set(down_vteps) + remote_set = remote_set - down_vtep_set + + vtep_set = set(vtep_ips) + diff = remote_set.symmetric_difference(vtep_set) + + return (esi, diff) if diff else None + +def check_es(dut): + ''' + Verify list of PEs associated all ESs, local and remote + ''' + bgp_es = dut.vtysh_cmd("show bgp l2vp evpn es json") + bgp_es_json = json.loads(bgp_es) + + result = None + + expected_es_set = set([v for k, v in host_es_map.iteritems()]) + curr_es_set = [] + + # check is ES content is correct + for es in bgp_es_json: + esi = es["esi"] + curr_es_set.append(esi) + types = es["type"] + vtep_ips = [] + for vtep in es["vteps"]: + vtep_ips.append(vtep["vtep_ip"]) + + if "local" in types: + result = check_local_es(esi, vtep_ips, dut.name, []) + else: + result = check_remote_es(esi, vtep_ips, dut.name, []) + + if result: + return result + + # check if all ESs are present + curr_es_set = set(curr_es_set) + result = curr_es_set.symmetric_difference(expected_es_set) + + return result if result else None + +def check_one_es(dut, esi, down_vteps): + ''' + Verify list of PEs associated all ESs, local and remote + ''' + bgp_es = dut.vtysh_cmd("show bgp l2vp evpn es %s json" % esi) + es = json.loads(bgp_es) + + if not es: + return "esi %s not found" % esi + + esi = es["esi"] + types = es["type"] + vtep_ips = [] + for vtep in es["vteps"]: + vtep_ips.append(vtep["vtep_ip"]) + + if "local" in types: + result = check_local_es(esi, vtep_ips, dut.name, down_vteps) + else: + result = check_remote_es(esi, vtep_ips, dut.name, down_vteps) + + return result + +def test_evpn_es(): + ''' + Two ES are setup on each rack. This test checks if - + 1. ES peer has been added to the local ES (via Type-1/EAD route) + 2. The remote ESs are setup with the right list of PEs (via Type-1) + ''' + + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + dut_name = "torm11" + dut = tgen.gears[dut_name] + test_fn = partial(check_es, dut) + _, result = topotest.run_and_expect(test_fn, None, count=20, wait=3) + + assertmsg = '"{}" ES content incorrect'.format(dut_name) + assert result is None, assertmsg + # tgen.mininet_cli() + +def test_evpn_ead_update(): + ''' + Flap a host link one the remote rack and check if the EAD updates + are sent/processed for the corresponding ESI + ''' + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # dut on rack1 and host link flap on rack2 + dut_name = "torm11" + dut = tgen.gears[dut_name] + + remote_tor_name = "torm21" + remote_tor = tgen.gears[remote_tor_name] + + host_name = "hostd21" + host = tgen.gears[host_name] + esi = host_es_map.get(host_name) + + # check if the VTEP list is right to start with + down_vteps = [] + test_fn = partial(check_one_es, dut, esi, down_vteps) + _, result = topotest.run_and_expect(test_fn, None, count=20, wait=3) + assertmsg = '"{}" ES content incorrect'.format(dut_name) + assert result is None, assertmsg + + # down a remote host link and check if the EAD withdraw is rxed + # Note: LACP is not working as expected so I am temporarily shutting + # down the link on the remote TOR instead of the remote host + remote_tor.run("ip link set dev %s-%s down" % (remote_tor_name, "eth2")) + down_vteps.append(tor_ips.get(remote_tor_name)) + _, result = topotest.run_and_expect(test_fn, None, count=20, wait=3) + assertmsg = '"{}" ES incorrect after remote link down'.format(dut_name) + assert result is None, assertmsg + + # bring up remote host link and check if the EAD update is rxed + down_vteps.remove(tor_ips.get(remote_tor_name)) + remote_tor.run("ip link set dev %s-%s up" % (remote_tor_name, "eth2")) + _, result = topotest.run_and_expect(test_fn, None, count=20, wait=3) + assertmsg = '"{}" ES incorrect after remote link flap'.format(dut_name) + assert result is None, assertmsg + + # tgen.mininet_cli() + +def check_mac(dut, vni, mac, m_type, esi, intf): + ''' + checks if mac is present and if desination matches the one provided + ''' + + out = dut.vtysh_cmd("show evpn mac vni %d mac %s json" % (vni, mac)) + + mac_js = json.loads(out) + for mac, info in mac_js.iteritems(): + tmp_esi = info.get("esi", "") + tmp_m_type = info.get("type", "") + tmp_intf = info.get("intf", "") if tmp_m_type == "local" else "" + if tmp_esi == esi and tmp_m_type == m_type and intf == intf: + return None + + return "invalid vni %d mac %s out %s" % (vni, mac, mac_js) + +def test_evpn_mac(): + ''' + 1. Add a MAC on hostd11 and check if the MAC is synced between + torm11 and torm12. And installed as a local MAC. + 2. Add a MAC on hostd21 and check if the MAC is installed as a + remote MAC on torm11 and torm12 + ''' + + tgen = get_topogen() + + local_host = tgen.gears["hostd11"] + remote_host = tgen.gears["hostd21"] + tors = [] + tors.append(tgen.gears["torm11"]) + tors.append(tgen.gears["torm12"]) + + # ping the anycast gw from the local and remote hosts to populate + # the mac address on the PEs + local_host.run("arping -I torbond -c 1 45.0.0.1") + remote_host.run("arping -I torbond -c 1 45.0.0.1") + + vni = 1000 + + # check if the rack-1 host MAC is present on all rack-1 PEs + # and points to local access port + m_type = "local" + _, mac = compute_host_ip_mac(local_host.name) + esi = host_es_map.get(local_host.name) + intf = "hostbond1" + + for tor in tors: + test_fn = partial(check_mac, tor, vni, mac, m_type, esi, intf) + _, result = topotest.run_and_expect(test_fn, None, count=20, wait=3) + assertmsg = '"{}" local MAC content incorrect'.format(tor.name) + assert result is None, assertmsg + + # check if the rack-2 host MAC is present on all rack-1 PEs + # and points to the remote ES destination + m_type = "remote" + _, mac = compute_host_ip_mac(remote_host.name) + esi = host_es_map.get(remote_host.name) + intf = "" + + for tor in tors: + test_fn = partial(check_mac, tor, vni, mac, m_type, esi, intf) + _, result = topotest.run_and_expect(test_fn, None, count=20, wait=3) + assertmsg = '"{}" remote MAC content incorrect'.format(tor.name) + assert result is None, assertmsg + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp-evpn-mh/torm11/evpn.conf b/tests/topotests/bgp-evpn-mh/torm11/evpn.conf new file mode 100644 index 0000000000..01f4b65704 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm11/evpn.conf @@ -0,0 +1,21 @@ +! +frr defaults datacenter +! +debug bgp evpn mh es +debug bgp evpn mh route +debug bgp zebra +! +! +router bgp 65002 + bgp router-id 192.168.100.15 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + neighbor 192.168.5.1 remote-as external + redistribute connected + address-family l2vpn evpn + neighbor 192.168.1.1 activate + neighbor 192.168.5.1 activate + advertise-all-vni + advertise-svi-ip + exit-address-family +! diff --git a/tests/topotests/bgp-evpn-mh/torm11/pim.conf b/tests/topotests/bgp-evpn-mh/torm11/pim.conf new file mode 100644 index 0000000000..fbba735873 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm11/pim.conf @@ -0,0 +1,13 @@ +! +ip pim rp 192.168.100.13 239.1.1.0/24 +ip pim spt-switchover infinity-and-beyond +! +interface lo + ip igmp + ip pim +! +interface torm11-eth0 + ip pim +! +interface torm11-eth1 + ip pim diff --git a/tests/topotests/bgp-evpn-mh/torm11/zebra.conf b/tests/topotests/bgp-evpn-mh/torm11/zebra.conf new file mode 100644 index 0000000000..ee4e87e1c2 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm11/zebra.conf @@ -0,0 +1,23 @@ +debug zebra evpn mh es +debug zebra evpn mh mac +debug zebra evpn mh neigh +debug zebra evpn mh nh +debug zebra vxlan +! +int torm11-eth0 + ip addr 192.168.1.2/24 +! +int torm11-eth1 + ip addr 192.168.5.2/24 +! +int lo + ip addr 192.168.100.15/32 +! +interface hostbond1 + evpn mh es-id 1 + evpn mh es-sys-mac 44:38:39:ff:ff:01 +! +interface hostbond2 + evpn mh es-id 2 + evpn mh es-sys-mac 44:38:39:ff:ff:01 +! diff --git a/tests/topotests/bgp-evpn-mh/torm12/evpn.conf b/tests/topotests/bgp-evpn-mh/torm12/evpn.conf new file mode 100644 index 0000000000..2c13024bbc --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm12/evpn.conf @@ -0,0 +1,21 @@ +! +frr defaults datacenter +! +debug bgp evpn mh es +debug bgp evpn mh route +debug bgp zebra +! +! +router bgp 65003 + bgp router-id 192.168.100.16 + no bgp ebgp-requires-policy + neighbor 192.168.2.1 remote-as external + neighbor 192.168.6.1 remote-as external + redistribute connected + address-family l2vpn evpn + neighbor 192.168.2.1 activate + neighbor 192.168.6.1 activate + advertise-all-vni + advertise-svi-ip + exit-address-family +! diff --git a/tests/topotests/bgp-evpn-mh/torm12/pim.conf b/tests/topotests/bgp-evpn-mh/torm12/pim.conf new file mode 100644 index 0000000000..3dd63b44ca --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm12/pim.conf @@ -0,0 +1,13 @@ +! +ip pim rp 192.168.100.13 239.1.1.0/24 +ip pim spt-switchover infinity-and-beyond +! +interface lo + ip igmp + ip pim +! +interface torm12-eth0 + ip pim +! +interface torm12-eth1 + ip pim diff --git a/tests/topotests/bgp-evpn-mh/torm12/zebra.conf b/tests/topotests/bgp-evpn-mh/torm12/zebra.conf new file mode 100644 index 0000000000..736af4159e --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm12/zebra.conf @@ -0,0 +1,23 @@ +debug zebra evpn mh es +debug zebra evpn mh mac +debug zebra evpn mh neigh +debug zebra evpn mh nh +debug zebra vxlan +! +int torm12-eth0 + ip addr 192.168.2.2/24 +! +int torm12-eth1 + ip addr 192.168.6.2/24 +! +int lo + ip addr 192.168.100.16/32 +! +interface hostbond1 + evpn mh es-id 1 + evpn mh es-sys-mac 44:38:39:ff:ff:01 +! +interface hostbond2 + evpn mh es-id 2 + evpn mh es-sys-mac 44:38:39:ff:ff:01 +! diff --git a/tests/topotests/bgp-evpn-mh/torm21/evpn.conf b/tests/topotests/bgp-evpn-mh/torm21/evpn.conf new file mode 100644 index 0000000000..2a2ba061c6 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm21/evpn.conf @@ -0,0 +1,21 @@ +! +frr defaults datacenter +! +debug bgp evpn mh es +debug bgp evpn mh route +debug bgp zebra +! +! +router bgp 65004 + bgp router-id 192.168.100.17 + no bgp ebgp-requires-policy + neighbor 192.168.3.1 remote-as external + neighbor 192.168.7.1 remote-as external + redistribute connected + address-family l2vpn evpn + neighbor 192.168.3.1 activate + neighbor 192.168.7.1 activate + advertise-all-vni + advertise-svi-ip + exit-address-family +! diff --git a/tests/topotests/bgp-evpn-mh/torm21/pim.conf b/tests/topotests/bgp-evpn-mh/torm21/pim.conf new file mode 100644 index 0000000000..71aa91a06d --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm21/pim.conf @@ -0,0 +1,13 @@ +! +ip pim rp 192.168.100.13 239.1.1.0/24 +ip pim spt-switchover infinity-and-beyond +! +interface lo + ip igmp + ip pim +! +interface torm21-eth0 + ip pim +! +interface torm21-eth1 + ip pim diff --git a/tests/topotests/bgp-evpn-mh/torm21/zebra.conf b/tests/topotests/bgp-evpn-mh/torm21/zebra.conf new file mode 100644 index 0000000000..0ebe6f2d95 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm21/zebra.conf @@ -0,0 +1,23 @@ +debug zebra evpn mh es +debug zebra evpn mh mac +debug zebra evpn mh neigh +debug zebra evpn mh nh +debug zebra vxlan +! +int torm21-eth0 + ip addr 192.168.3.2/24 +! +int torm21-eth1 + ip addr 192.168.7.2/24 +! +int lo + ip addr 192.168.100.17/32 +! +interface hostbond1 + evpn mh es-id 1 + evpn mh es-sys-mac 44:38:39:ff:ff:02 +! +interface hostbond2 + evpn mh es-id 2 + evpn mh es-sys-mac 44:38:39:ff:ff:02 +! diff --git a/tests/topotests/bgp-evpn-mh/torm22/evpn.conf b/tests/topotests/bgp-evpn-mh/torm22/evpn.conf new file mode 100644 index 0000000000..b4f4f1dc25 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm22/evpn.conf @@ -0,0 +1,21 @@ +! +frr defaults datacenter +! +debug bgp evpn mh es +debug bgp evpn mh route +debug bgp zebra +! +! +router bgp 65005 + bgp router-id 192.168.100.18 + no bgp ebgp-requires-policy + neighbor 192.168.4.1 remote-as external + neighbor 192.168.8.1 remote-as external + redistribute connected + address-family l2vpn evpn + neighbor 192.168.4.1 activate + neighbor 192.168.8.1 activate + advertise-all-vni + advertise-svi-ip + exit-address-family +! diff --git a/tests/topotests/bgp-evpn-mh/torm22/pim.conf b/tests/topotests/bgp-evpn-mh/torm22/pim.conf new file mode 100644 index 0000000000..46f330f5cd --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm22/pim.conf @@ -0,0 +1,13 @@ +! +ip pim rp 192.168.100.13 239.1.1.0/24 +ip pim spt-switchover infinity-and-beyond +! +interface lo + ip igmp + ip pim +! +interface torm22-eth0 + ip pim +! +interface torm22-eth1 + ip pim diff --git a/tests/topotests/bgp-evpn-mh/torm22/zebra.conf b/tests/topotests/bgp-evpn-mh/torm22/zebra.conf new file mode 100644 index 0000000000..356d8a43e7 --- /dev/null +++ b/tests/topotests/bgp-evpn-mh/torm22/zebra.conf @@ -0,0 +1,23 @@ +debug zebra evpn mh es +debug zebra evpn mh mac +debug zebra evpn mh neigh +debug zebra evpn mh nh +debug zebra vxlan +! +int torm22-eth0 + ip addr 192.168.4.2/24 +! +int torm22-eth1 + ip addr 192.168.8.2/24 +! +int lo + ip addr 192.168.100.18/32 +! +interface hostbond1 + evpn mh es-id 1 + evpn mh es-sys-mac 44:38:39:ff:ff:02 +! +interface hostbond2 + evpn mh es-id 2 + evpn mh es-sys-mac 44:38:39:ff:ff:02 +! -- 2.39.5