tests:add topotest for EVPN aggregate prefix route

Toptotest covers to aggregate EVPN prefix routes.

Testing:

tests/topotests/bgp_evpn_vxlan_svd_topo1$ sudo -E python3 -m pytest -s -vv --cli-on-error
PASSED
test_bgp_evpn_vxlan_svd.py::test_pe_advertise_aggr_evpn_route
--------------------- live log call -------------------------------
2024-03-04 19:59:45,340 INFO: P1: checking if daemons are running
2024-03-04 19:59:45,444 INFO: PE1: checking if daemons are running
2024-03-04 19:59:45,578 INFO: PE2: checking if daemons are running
2024-03-04 19:59:45,680 INFO: host1: checking if daemons are running
2024-03-04 19:59:45,798 INFO: host2: checking if daemons are running
2024-03-04 19:59:45,896 INFO: topo: Checking BGP EVPN route contains non-aggregate prefixes
2024-03-04 19:59:45,992 INFO: topo: Configure BGP aggregate-address summary-only under ipv4-unicast
2024-03-04 19:59:46,120 INFO: topo: Checking BGP EVPN route contains aggregated prefix
PASSED

------- generated xml file: /tmp/topotests/topotests.xml -----
======= 10 passed, 1 skipped in 47.95s =====

Signed-off-by: Chirag Shah <chirag@nvidia.com>
This commit is contained in:
Chirag Shah 2024-03-04 20:00:29 -08:00
parent 5cb7712b3e
commit f345460b7e
5 changed files with 91 additions and 2 deletions

View File

@ -0,0 +1 @@
{"27.3.0.85:3":{"rd":"27.3.0.85:3","[5]:[0]:[16]:[10.27.0.0]":{"prefix":"[5]:[0]:[16]:[10.27.0.0]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"external","routeType":5,"ethTag":0,"ipLen":16,"ip":"10.27.0.0","metric":0,"weight":32768,"peerId":"(unspec)","path":"","origin":"incomplete","extendedCommunity":{"string":"ET:8 RT:65000:4000 Rmac:44:00:00:ff:ff:01"},"nexthops":[{"ip":"10.10.10.10","hostname":"PE1","afi":"ipv4","used":true}]}]]}},"30.0.0.3:2":{"rd":"30.0.0.3:2","[5]:[0]:[32]:[4.4.4.1]":{"prefix":"[5]:[0]:[32]:[4.4.4.1]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"internal","routeType":5,"ethTag":0,"ipLen":32,"ip":"4.4.4.1","metric":0,"locPrf":100,"weight":0,"peerId":"10.30.30.30","path":"","origin":"incomplete","extendedCommunity":{"string":"RT:65000:300 ET:8 Rmac:44:20:00:ff:ff:01"},"nexthops":[{"ip":"10.30.30.30","hostname":"PE2","afi":"ipv4","used":true}]}]]}},"numPrefix":2,"numPaths":2}

View File

@ -0,0 +1 @@
{"27.3.0.85:3":{"rd":"27.3.0.85:3","[5]:[0]:[24]:[10.27.7.0]":{"prefix":"[5]:[0]:[24]:[10.27.7.0]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"external","routeType":5,"ethTag":0,"ipLen":24,"ip":"10.27.7.0","metric":0,"weight":32768,"peerId":"(unspec)","path":"","origin":"incomplete","extendedCommunity":{"string":"ET:8 RT:65000:4000 Rmac:44:00:00:ff:ff:01"},"nexthops":[{"ip":"10.10.10.10","hostname":"PE1","afi":"ipv4","used":true}]}]]},"[5]:[0]:[30]:[10.27.7.8]":{"prefix":"[5]:[0]:[30]:[10.27.7.8]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"external","routeType":5,"ethTag":0,"ipLen":30,"ip":"10.27.7.8","metric":0,"weight":32768,"peerId":"(unspec)","path":"","origin":"incomplete","extendedCommunity":{"string":"ET:8 RT:65000:4000 Rmac:44:00:00:ff:ff:01"},"nexthops":[{"ip":"10.10.10.10","hostname":"PE1","afi":"ipv4","used":true}]}]]},"[5]:[0]:[32]:[10.27.7.22]":{"prefix":"[5]:[0]:[32]:[10.27.7.22]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"external","routeType":5,"ethTag":0,"ipLen":32,"ip":"10.27.7.22","metric":0,"weight":32768,"peerId":"(unspec)","path":"","origin":"incomplete","extendedCommunity":{"string":"ET:8 RT:65000:4000 Rmac:44:00:00:ff:ff:01"},"nexthops":[{"ip":"10.10.10.10","hostname":"PE1","afi":"ipv4","used":true}]}]]}},"30.0.0.3:2":{"rd":"30.0.0.3:2","[5]:[0]:[32]:[4.4.4.1]":{"prefix":"[5]:[0]:[32]:[4.4.4.1]","prefixLen":352,"paths":[[{"valid":true,"bestpath":true,"selectionReason":"First path received","pathFrom":"internal","routeType":5,"ethTag":0,"ipLen":32,"ip":"4.4.4.1","metric":0,"locPrf":100,"weight":0,"peerId":"10.30.30.30","path":"","origin":"incomplete","extendedCommunity":{"string":"RT:65000:300 ET:8 Rmac:44:20:00:ff:ff:01"},"nexthops":[{"ip":"10.30.30.30","hostname":"PE2","afi":"ipv4","used":true}]}]]}},"numPrefix":4,"numPaths":4}

View File

@ -11,9 +11,22 @@ router bgp 65000
advertise-svi-ip advertise-svi-ip
! !
router bgp 65000 vrf vrf-red router bgp 65000 vrf vrf-red
address-family ipv4 unicast
redistribute static
exit-address-family
! !
address-family l2vpn evpn address-family l2vpn evpn
route-target import *:300 route-target import *:300
route-target import auto route-target import auto
exit-address-family exit-address-family
! !
router bgp 65000 vrf vrf-purple
address-family ipv4 unicast
redistribute static
exit-address-family
!
address-family l2vpn evpn
advertise ipv4 unicast
exit-address-family
!

View File

@ -5,6 +5,12 @@ vrf vrf-red
vni 100 vni 100
exit-vrf exit-vrf
! !
vrf vrf-purple
vni 4000
ip route 10.27.7.0/24 blackhole
ip route 10.27.7.22/32 blackhole
ip route 10.27.7.10/30 blackhole
exit-vrf
! !
interface lo interface lo
ip address 10.10.10.10/32 ip address 10.10.10.10/32

View File

@ -91,6 +91,10 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
pe.run("ip link add name bridge type bridge stp_state 0") pe.run("ip link add name bridge type bridge stp_state 0")
pe.run("ip link set dev bridge type bridge vlan_filtering 1") pe.run("ip link set dev bridge type bridge vlan_filtering 1")
pe.run("bridge vlan add vid 1 dev bridge self") pe.run("bridge vlan add vid 1 dev bridge self")
if pe_name == "PE1":
pe.run("ip link set dev bridge address 44:00:00:ff:ff:01")
if pe_name == "PE2":
pe.run("ip link set dev bridge address 44:20:00:ff:ff:01")
pe.run("ip link set dev bridge up") pe.run("ip link set dev bridge up")
# setup svi # setup svi
@ -113,6 +117,18 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
pe.run("bridge vlan add dev vxlan0 vid 1 tunnel_info id 101") pe.run("bridge vlan add dev vxlan0 vid 1 tunnel_info id 101")
pe.run("ip link set up dev vxlan0") pe.run("ip link set up dev vxlan0")
# VRF creation
pe.run("ip link add vrf-purple type vrf table 1003")
pe.run("ip link set dev vrf-purple up")
if pe_name == "PE1":
pe.run("ip link add vrf-blue type vrf table 1002")
pe.run("ip link set dev vrf-blue up")
pe.run("ip addr add 27.2.0.85/32 dev vrf-blue")
pe.run("ip addr add 27.3.0.85/32 dev vrf-purple")
if pe_name == "PE2":
pe.run("ip link add vrf-blue type vrf table 2400")
pe.run("ip link set dev vrf-blue up")
# setup PE interface # setup PE interface
pe.run("ip link set dev {0}-{1} master bridge".format(pe_name, intf)) pe.run("ip link set dev {0}-{1} master bridge".format(pe_name, intf))
pe.run("bridge vlan del vid 1 dev {0}-{1}".format(pe_name, intf)) pe.run("bridge vlan del vid 1 dev {0}-{1}".format(pe_name, intf))
@ -120,7 +136,7 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
pe.run("bridge vlan add vid 1 dev {0}-{1}".format(pe_name, intf)) pe.run("bridge vlan add vid 1 dev {0}-{1}".format(pe_name, intf))
pe.run("bridge vlan add vid 1 pvid untagged dev {0}-{1}".format(pe_name, intf)) pe.run("bridge vlan add vid 1 pvid untagged dev {0}-{1}".format(pe_name, intf))
# l3vni 100 # L3VNI 100
pe.run("ip link add vrf-red type vrf table 1400") pe.run("ip link add vrf-red type vrf table 1400")
pe.run("ip link add link bridge name vlan100 type vlan id 100 protocol 802.1q") pe.run("ip link add link bridge name vlan100 type vlan id 100 protocol 802.1q")
pe.run("ip link set dev vlan100 master vrf-blue") pe.run("ip link set dev vlan100 master vrf-blue")
@ -129,9 +145,16 @@ def setup_pe_router(tgen, pe_name, tunnel_local_ip, svi_ip, intf):
pe.run("bridge vlan add dev vxlan0 vid 100") pe.run("bridge vlan add dev vxlan0 vid 100")
pe.run("bridge vlan add dev vxlan0 vid 100 tunnel_info id 100") pe.run("bridge vlan add dev vxlan0 vid 100 tunnel_info id 100")
# L3VNI 4000
pe.run("ip link add link bridge name vlan400 type vlan id 400 protocol 802.1q")
pe.run("ip link set dev vlan400 master vrf-purple")
pe.run("ip link set dev vlan400 up")
pe.run("bridge vlan add vid 400 dev bridge self")
pe.run("bridge vlan add dev vxlan0 vid 400")
pe.run("bridge vlan add dev vxlan0 vid 400 tunnel_info id 4000")
# add a vrf for testing DVNI # add a vrf for testing DVNI
if pe_name == "PE2": if pe_name == "PE2":
pe.run("ip link add vrf-blue type vrf table 2400")
pe.run("ip link add link bridge name vlan300 type vlan id 300 protocol 802.1q") pe.run("ip link add link bridge name vlan300 type vlan id 300 protocol 802.1q")
pe.run("ip link set dev vlan300 master vrf-blue") pe.run("ip link set dev vlan300 master vrf-blue")
pe.run("ip link set dev vlan300 up") pe.run("ip link set dev vlan300 up")
@ -199,6 +222,14 @@ def show_vni_json_elide_ifindex(pe, vni, expected):
return topotest.json_cmp(output_json, expected) return topotest.json_cmp(output_json, expected)
def show_bgp_l2vpn_evpn_route_type_prefix_json(pe, expected):
output_json = pe.vtysh_cmd(
"show bgp l2vpn evpn route type prefix json", isjson=True
)
return topotest.json_cmp(output_json, expected)
def check_vni_macs_present(tgen, router, vni, maclist): def check_vni_macs_present(tgen, router, vni, maclist):
result = router.vtysh_cmd("show evpn mac vni {} json".format(vni), isjson=True) result = router.vtysh_cmd("show evpn mac vni {} json".format(vni), isjson=True)
for rname, ifname in maclist: for rname, ifname in maclist:
@ -331,6 +362,7 @@ def mac_test_local_remote(local, remote):
remote_output_json = json.loads(remote_output) remote_output_json = json.loads(remote_output)
local_output_vni_json = json.loads(local_output_vni) local_output_vni_json = json.loads(local_output_vni)
# breakpoint()
for vni in local_output_json: for vni in local_output_json:
if vni not in remote_output_json: if vni not in remote_output_json:
continue continue
@ -542,6 +574,42 @@ def test_dvni():
# tgen.mininet_cli() # tgen.mininet_cli()
def test_pe_advertise_aggr_evpn_route():
"BGP advertise aggregated Type-5 prefix route"
tgen = get_topogen()
# Don't run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Checking BGP EVPN route contains non-aggregate prefixes")
pe1 = tgen.gears["PE1"]
json_file = "{}/{}/bgp.evpn.route.prefix.before.json".format(CWD, pe1.name)
expected = json.loads(open(json_file).read())
test_func = partial(show_bgp_l2vpn_evpn_route_type_prefix_json, pe1, expected)
_, result = topotest.run_and_expect(test_func, None, count=45, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(pe1.name)
assert result is None, assertmsg
logger.info("Configure BGP aggregate-address summary-only under ipv4-unicast")
pe1.cmd(
'vtysh -c "config t" -c "router bgp 65000 vrf vrf-purple" '
+ ' -c "address-family ipv4 unicast" '
+ ' -c "aggregate-address 10.27.0.0/16 summary-only" '
)
logger.info("Checking BGP EVPN route contains aggregated prefix")
pe1 = tgen.gears["PE1"]
json_file = "{}/{}/bgp.evpn.route.prefix.after.json".format(CWD, pe1.name)
expected = json.loads(open(json_file).read())
test_func = partial(show_bgp_l2vpn_evpn_route_type_prefix_json, pe1, expected)
_, result = topotest.run_and_expect(test_func, None, count=45, wait=1)
assertmsg = '"{}" JSON output mismatches'.format(pe1.name)
assert result is None, assertmsg
def test_memory_leak(): def test_memory_leak():
"Run the memory leak test and report results." "Run the memory leak test and report results."
tgen = get_topogen() tgen = get_topogen()