mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 05:18:47 +00:00
tests: Add tests for BGP link-bandwidth and weighted ECMP
Implement tests to verify BGP link-bandwidth and weighted ECMP functionality. These tests validate one of the primary use cases for weighted ECMP (a.k.a. Unequal cost multipath) using BGP link-bandwidth: https://tools.ietf.org/html/draft-mohanty-bess-ebgp-dmz The included tests are: Test #1: Test BGP link-bandwidth advertisement based on number of multipaths Test #2: Test cumulative link-bandwidth propagation Test #3: Test weighted ECMP - multipath with next hop weights Test #4: Test weighted ECMP rebalancing upon change (link flap) Test #5: Test weighted ECMP for a second anycast IP Test #6: Test paths with and without link-bandwidth - receiver should resort to regular ECMP Test #7: Test different options for processing link-bandwidth on the receiver Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
This commit is contained in:
parent
feca4f1e67
commit
000022d205
0
tests/topotests/bgp_link_bw_ip/__init__.py
Executable file
0
tests/topotests/bgp_link_bw_ip/__init__.py
Executable file
19
tests/topotests/bgp_link_bw_ip/r1/bgp-route-1.json
Normal file
19
tests/topotests/bgp_link_bw_ip/r1/bgp-route-1.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"bestpath":{
|
||||
"overall":true
|
||||
},
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65301:125000 (1.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
32
tests/topotests/bgp_link_bw_ip/r1/bgp-route-2.json
Normal file
32
tests/topotests/bgp_link_bw_ip/r1/bgp-route-2.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65303:125000 (1.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"bestpath":{
|
||||
"overall":true
|
||||
},
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65201:375000 (3.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
32
tests/topotests/bgp_link_bw_ip/r1/bgp-route-3.json
Normal file
32
tests/topotests/bgp_link_bw_ip/r1/bgp-route-3.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65303:125000 (1.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"bestpath":{
|
||||
"overall":true
|
||||
},
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65301:250000 (2.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
32
tests/topotests/bgp_link_bw_ip/r1/bgp-route-4.json
Normal file
32
tests/topotests/bgp_link_bw_ip/r1/bgp-route-4.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"prefix":"198.10.1.11\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65303:125000 (1.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"bestpath":{
|
||||
"overall":true
|
||||
},
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65201:250000 (2.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
29
tests/topotests/bgp_link_bw_ip/r1/bgp-route-5.json
Normal file
29
tests/topotests/bgp_link_bw_ip/r1/bgp-route-5.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"bestpath":{
|
||||
"overall":true
|
||||
},
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65201:375000 (3.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.1.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
8
tests/topotests/bgp_link_bw_ip/r1/bgpd.conf
Normal file
8
tests/topotests/bgp_link_bw_ip/r1/bgpd.conf
Normal file
@ -0,0 +1,8 @@
|
||||
hostname r1
|
||||
!
|
||||
router bgp 65101
|
||||
bgp router-id 11.1.1.1
|
||||
bgp bestpath as-path multipath-relax
|
||||
neighbor 11.1.1.2 remote-as external
|
||||
neighbor 11.1.1.6 remote-as external
|
||||
!
|
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-1.json
Normal file
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-1.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.6",
|
||||
"weight":25
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":75
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-2.json
Normal file
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-2.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.6",
|
||||
"weight":33
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":66
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-3.json
Normal file
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-3.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"198.10.1.11\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.11\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.6",
|
||||
"weight":33
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":66
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-4.json
Normal file
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-4.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":1
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.6",
|
||||
"weight":1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-5.json
Normal file
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-5.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"198.10.1.11\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.11\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":1
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.6",
|
||||
"weight":1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
15
tests/topotests/bgp_link_bw_ip/r1/ip-route-6.json
Normal file
15
tests/topotests/bgp_link_bw_ip/r1/ip-route-6.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":100
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
15
tests/topotests/bgp_link_bw_ip/r1/ip-route-7.json
Normal file
15
tests/topotests/bgp_link_bw_ip/r1/ip-route-7.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"198.10.1.11\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.11\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":100
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-8.json
Normal file
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-8.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.6",
|
||||
"weight":1
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":100
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-9.json
Normal file
20
tests/topotests/bgp_link_bw_ip/r1/ip-route-9.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"198.10.1.11\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.11\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.6",
|
||||
"weight":1
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.1.2",
|
||||
"weight":100
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
104
tests/topotests/bgp_link_bw_ip/r1/v4_route.json
Normal file
104
tests/topotests/bgp_link_bw_ip/r1/v4_route.json
Normal file
@ -0,0 +1,104 @@
|
||||
{
|
||||
"10.0.1.1\/32":[
|
||||
{
|
||||
"prefix":"10.0.1.1\/32",
|
||||
"protocol":"ospf",
|
||||
"distance":110,
|
||||
"metric":10,
|
||||
"table":254,
|
||||
"internalStatus":0,
|
||||
"internalFlags":0,
|
||||
"internalNextHopNum":1,
|
||||
"internalNextHopActiveNum":1,
|
||||
"nexthops":[
|
||||
{
|
||||
"flags":9,
|
||||
"ip":"0.0.0.0",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":2,
|
||||
"interfaceName":"r1-eth0",
|
||||
"active":true,
|
||||
"onLink":true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"prefix":"10.0.1.1\/32",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"destSelected":true,
|
||||
"distance":0,
|
||||
"metric":0,
|
||||
"installed":true,
|
||||
"table":254,
|
||||
"internalStatus":16,
|
||||
"internalFlags":8,
|
||||
"internalNextHopNum":1,
|
||||
"internalNextHopActiveNum":1,
|
||||
"nexthops":[
|
||||
{
|
||||
"flags":3,
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":2,
|
||||
"interfaceName":"r1-eth0",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.3.4\/32":[
|
||||
{
|
||||
"prefix":"10.0.3.4\/32",
|
||||
"protocol":"connected",
|
||||
"selected":true,
|
||||
"destSelected":true,
|
||||
"distance":0,
|
||||
"metric":0,
|
||||
"installed":true,
|
||||
"table":254,
|
||||
"internalStatus":16,
|
||||
"internalFlags":8,
|
||||
"internalNextHopNum":1,
|
||||
"internalNextHopActiveNum":1,
|
||||
"nexthops":[
|
||||
{
|
||||
"flags":3,
|
||||
"fib":true,
|
||||
"directlyConnected":true,
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r1-eth1",
|
||||
"active":true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"10.0.20.1\/32":[
|
||||
{
|
||||
"prefix":"10.0.20.1\/32",
|
||||
"protocol":"ospf",
|
||||
"selected":true,
|
||||
"destSelected":true,
|
||||
"distance":110,
|
||||
"metric":20,
|
||||
"installed":true,
|
||||
"table":254,
|
||||
"internalStatus":16,
|
||||
"internalFlags":8,
|
||||
"internalNextHopNum":1,
|
||||
"internalNextHopActiveNum":1,
|
||||
"nexthops":[
|
||||
{
|
||||
"flags":11,
|
||||
"fib":true,
|
||||
"ip":"10.0.3.2",
|
||||
"afi":"ipv4",
|
||||
"interfaceIndex":3,
|
||||
"interfaceName":"r1-eth1",
|
||||
"active":true,
|
||||
"onLink":true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
7
tests/topotests/bgp_link_bw_ip/r1/zebra.conf
Normal file
7
tests/topotests/bgp_link_bw_ip/r1/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
||||
!
|
||||
interface r1-eth0
|
||||
ip address 11.1.1.1/30
|
||||
!
|
||||
interface r1-eth1
|
||||
ip address 11.1.1.5/30
|
||||
!
|
15
tests/topotests/bgp_link_bw_ip/r10/bgpd.conf
Normal file
15
tests/topotests/bgp_link_bw_ip/r10/bgpd.conf
Normal file
@ -0,0 +1,15 @@
|
||||
hostname r10
|
||||
!
|
||||
ip prefix-list redist seq 10 permit 0.0.0.0/0 ge 32
|
||||
!
|
||||
route-map redist permit 10
|
||||
match ip address prefix-list redist
|
||||
!
|
||||
router bgp 65354
|
||||
bgp router-id 11.1.6.2
|
||||
neighbor 11.1.6.1 remote-as external
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
redistribute connected route-map redist
|
||||
!
|
||||
!
|
6
tests/topotests/bgp_link_bw_ip/r10/zebra.conf
Normal file
6
tests/topotests/bgp_link_bw_ip/r10/zebra.conf
Normal file
@ -0,0 +1,6 @@
|
||||
interface r10-eth0
|
||||
ip address 11.1.6.2/30
|
||||
!
|
||||
interface r10-eth1
|
||||
ip address 50.1.1.10/32
|
||||
!
|
19
tests/topotests/bgp_link_bw_ip/r2/bgp-route-1.json
Normal file
19
tests/topotests/bgp_link_bw_ip/r2/bgp-route-1.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"bestpath":{
|
||||
"overall":true
|
||||
},
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65301:125000 (1.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.2.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
19
tests/topotests/bgp_link_bw_ip/r2/bgp-route-2.json
Normal file
19
tests/topotests/bgp_link_bw_ip/r2/bgp-route-2.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"bestpath":{
|
||||
"overall":true
|
||||
},
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65301:250000 (2.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.2.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
32
tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
Normal file
32
tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65302:125000 (1.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.2.6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"bestpath":{
|
||||
"overall":true
|
||||
},
|
||||
"extendedCommunity":{
|
||||
"string":"LB:65301:250000 (2.000 Mbps)"
|
||||
},
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.2.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
9
tests/topotests/bgp_link_bw_ip/r2/bgpd.conf
Normal file
9
tests/topotests/bgp_link_bw_ip/r2/bgpd.conf
Normal file
@ -0,0 +1,9 @@
|
||||
hostname r2
|
||||
!
|
||||
router bgp 65201
|
||||
bgp router-id 11.1.2.1
|
||||
bgp bestpath as-path multipath-relax
|
||||
neighbor 11.1.1.1 remote-as external
|
||||
neighbor 11.1.2.2 remote-as external
|
||||
neighbor 11.1.2.6 remote-as external
|
||||
!
|
19
tests/topotests/bgp_link_bw_ip/r2/ip-route-1.json
Normal file
19
tests/topotests/bgp_link_bw_ip/r2/ip-route-1.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"protocol":"bgp",
|
||||
"selected":true,
|
||||
"installed":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.2.2",
|
||||
"interfaceName":"r2-eth1",
|
||||
"active":true,
|
||||
"weight":1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
20
tests/topotests/bgp_link_bw_ip/r2/ip-route-2.json
Normal file
20
tests/topotests/bgp_link_bw_ip/r2/ip-route-2.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.2.6",
|
||||
"weight":33
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.2.2",
|
||||
"weight":66
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
15
tests/topotests/bgp_link_bw_ip/r2/ip-route-3.json
Normal file
15
tests/topotests/bgp_link_bw_ip/r2/ip-route-3.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.2.2",
|
||||
"weight":1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
10
tests/topotests/bgp_link_bw_ip/r2/zebra.conf
Normal file
10
tests/topotests/bgp_link_bw_ip/r2/zebra.conf
Normal file
@ -0,0 +1,10 @@
|
||||
!
|
||||
interface r2-eth0
|
||||
ip address 11.1.1.2/30
|
||||
!
|
||||
interface r2-eth1
|
||||
ip address 11.1.2.1/30
|
||||
!
|
||||
interface r2-eth2
|
||||
ip address 11.1.2.5/30
|
||||
!
|
8
tests/topotests/bgp_link_bw_ip/r3/bgpd.conf
Normal file
8
tests/topotests/bgp_link_bw_ip/r3/bgpd.conf
Normal file
@ -0,0 +1,8 @@
|
||||
hostname r3
|
||||
!
|
||||
router bgp 65202
|
||||
bgp router-id 11.1.3.1
|
||||
bgp bestpath as-path multipath-relax
|
||||
neighbor 11.1.1.5 remote-as external
|
||||
neighbor 11.1.3.2 remote-as external
|
||||
!
|
7
tests/topotests/bgp_link_bw_ip/r3/zebra.conf
Normal file
7
tests/topotests/bgp_link_bw_ip/r3/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
||||
!
|
||||
interface r3-eth0
|
||||
ip address 11.1.1.6/30
|
||||
!
|
||||
interface r3-eth1
|
||||
ip address 11.1.3.1/30
|
||||
!
|
23
tests/topotests/bgp_link_bw_ip/r4/bgp-route-1.json
Normal file
23
tests/topotests/bgp_link_bw_ip/r4/bgp-route-1.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"paths":[
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.4.6"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valid":true,
|
||||
"multipath":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"ip":"11.1.4.2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
28
tests/topotests/bgp_link_bw_ip/r4/bgpd.conf
Normal file
28
tests/topotests/bgp_link_bw_ip/r4/bgpd.conf
Normal file
@ -0,0 +1,28 @@
|
||||
!
|
||||
log file bgpd.log
|
||||
!
|
||||
debug bgp updates
|
||||
debug bgp zebra
|
||||
debug bgp bestpath 198.10.1.1/32
|
||||
!
|
||||
hostname r4
|
||||
!
|
||||
ip prefix-list anycast_ip seq 10 permit 198.10.1.0/24 le 32
|
||||
!
|
||||
route-map anycast_ip permit 10
|
||||
match ip address prefix-list anycast_ip
|
||||
set extcommunity bandwidth num-multipaths
|
||||
!
|
||||
route-map anycast_ip permit 20
|
||||
!
|
||||
router bgp 65301
|
||||
bgp router-id 11.1.4.1
|
||||
bgp bestpath as-path multipath-relax
|
||||
neighbor 11.1.2.1 remote-as external
|
||||
neighbor 11.1.4.2 remote-as external
|
||||
neighbor 11.1.4.6 remote-as external
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor 11.1.2.1 route-map anycast_ip out
|
||||
!
|
||||
!
|
21
tests/topotests/bgp_link_bw_ip/r4/ip-route-1.json
Normal file
21
tests/topotests/bgp_link_bw_ip/r4/ip-route-1.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"198.10.1.1\/32":[
|
||||
{
|
||||
"prefix":"198.10.1.1\/32",
|
||||
"protocol":"bgp",
|
||||
"selected":true,
|
||||
"nexthops":[
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.4.2",
|
||||
"weight":1
|
||||
},
|
||||
{
|
||||
"fib":true,
|
||||
"ip":"11.1.4.6",
|
||||
"weight":1
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
10
tests/topotests/bgp_link_bw_ip/r4/zebra.conf
Normal file
10
tests/topotests/bgp_link_bw_ip/r4/zebra.conf
Normal file
@ -0,0 +1,10 @@
|
||||
!
|
||||
interface r4-eth0
|
||||
ip address 11.1.2.2/30
|
||||
!
|
||||
interface r4-eth1
|
||||
ip address 11.1.4.1/30
|
||||
!
|
||||
interface r4-eth2
|
||||
ip address 11.1.4.5/30
|
||||
!
|
20
tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
Normal file
20
tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
Normal file
@ -0,0 +1,20 @@
|
||||
hostname r5
|
||||
!
|
||||
ip prefix-list anycast_ip seq 10 permit 198.10.1.0/24 le 32
|
||||
!
|
||||
route-map anycast_ip permit 10
|
||||
match ip address prefix-list anycast_ip
|
||||
set extcommunity bandwidth num-multipaths
|
||||
!
|
||||
route-map anycast_ip permit 20
|
||||
!
|
||||
router bgp 65302
|
||||
bgp router-id 11.1.5.1
|
||||
bgp bestpath as-path multipath-relax
|
||||
neighbor 11.1.2.5 remote-as external
|
||||
neighbor 11.1.5.2 remote-as external
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor 11.1.2.5 route-map anycast_ip out
|
||||
!
|
||||
!
|
7
tests/topotests/bgp_link_bw_ip/r5/zebra.conf
Normal file
7
tests/topotests/bgp_link_bw_ip/r5/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
||||
!
|
||||
interface r5-eth0
|
||||
ip address 11.1.2.6/30
|
||||
!
|
||||
interface r5-eth1
|
||||
ip address 11.1.5.1/30
|
||||
!
|
20
tests/topotests/bgp_link_bw_ip/r6/bgpd.conf
Normal file
20
tests/topotests/bgp_link_bw_ip/r6/bgpd.conf
Normal file
@ -0,0 +1,20 @@
|
||||
hostname r6
|
||||
!
|
||||
ip prefix-list anycast_ip seq 10 permit 198.10.1.0/24 le 32
|
||||
!
|
||||
route-map anycast_ip permit 10
|
||||
match ip address prefix-list anycast_ip
|
||||
set extcommunity bandwidth num-multipaths
|
||||
!
|
||||
route-map anycast_ip permit 20
|
||||
!
|
||||
router bgp 65303
|
||||
bgp router-id 11.1.6.1
|
||||
bgp bestpath as-path multipath-relax
|
||||
neighbor 11.1.3.1 remote-as external
|
||||
neighbor 11.1.6.2 remote-as external
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
neighbor 11.1.3.1 route-map anycast_ip out
|
||||
!
|
||||
!
|
7
tests/topotests/bgp_link_bw_ip/r6/zebra.conf
Normal file
7
tests/topotests/bgp_link_bw_ip/r6/zebra.conf
Normal file
@ -0,0 +1,7 @@
|
||||
!
|
||||
interface r6-eth0
|
||||
ip address 11.1.3.2/30
|
||||
!
|
||||
interface r6-eth1
|
||||
ip address 11.1.6.1/30
|
||||
!
|
15
tests/topotests/bgp_link_bw_ip/r7/bgpd.conf
Normal file
15
tests/topotests/bgp_link_bw_ip/r7/bgpd.conf
Normal file
@ -0,0 +1,15 @@
|
||||
hostname r7
|
||||
!
|
||||
ip prefix-list redist seq 10 permit 0.0.0.0/0 ge 32
|
||||
!
|
||||
route-map redist permit 10
|
||||
match ip address prefix-list redist
|
||||
!
|
||||
router bgp 65351
|
||||
bgp router-id 11.1.4.2
|
||||
neighbor 11.1.4.1 remote-as external
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
redistribute connected route-map redist
|
||||
!
|
||||
!
|
6
tests/topotests/bgp_link_bw_ip/r7/zebra.conf
Normal file
6
tests/topotests/bgp_link_bw_ip/r7/zebra.conf
Normal file
@ -0,0 +1,6 @@
|
||||
interface r7-eth0
|
||||
ip address 11.1.4.2/30
|
||||
!
|
||||
interface r7-eth1
|
||||
ip address 50.1.1.7/32
|
||||
!
|
15
tests/topotests/bgp_link_bw_ip/r8/bgpd.conf
Normal file
15
tests/topotests/bgp_link_bw_ip/r8/bgpd.conf
Normal file
@ -0,0 +1,15 @@
|
||||
hostname r8
|
||||
!
|
||||
ip prefix-list redist seq 10 permit 0.0.0.0/0 ge 32
|
||||
!
|
||||
route-map redist permit 10
|
||||
match ip address prefix-list redist
|
||||
!
|
||||
router bgp 65352
|
||||
bgp router-id 11.1.4.6
|
||||
neighbor 11.1.4.5 remote-as external
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
redistribute connected route-map redist
|
||||
!
|
||||
!
|
6
tests/topotests/bgp_link_bw_ip/r8/zebra.conf
Normal file
6
tests/topotests/bgp_link_bw_ip/r8/zebra.conf
Normal file
@ -0,0 +1,6 @@
|
||||
interface r8-eth0
|
||||
ip address 11.1.4.6/30
|
||||
!
|
||||
interface r8-eth1
|
||||
ip address 50.1.1.8/32
|
||||
!
|
15
tests/topotests/bgp_link_bw_ip/r9/bgpd.conf
Normal file
15
tests/topotests/bgp_link_bw_ip/r9/bgpd.conf
Normal file
@ -0,0 +1,15 @@
|
||||
hostname r9
|
||||
!
|
||||
ip prefix-list redist seq 10 permit 0.0.0.0/0 ge 32
|
||||
!
|
||||
route-map redist permit 10
|
||||
match ip address prefix-list redist
|
||||
!
|
||||
router bgp 65353
|
||||
bgp router-id 11.1.5.2
|
||||
neighbor 11.1.5.1 remote-as external
|
||||
!
|
||||
address-family ipv4 unicast
|
||||
redistribute connected route-map redist
|
||||
!
|
||||
!
|
6
tests/topotests/bgp_link_bw_ip/r9/zebra.conf
Normal file
6
tests/topotests/bgp_link_bw_ip/r9/zebra.conf
Normal file
@ -0,0 +1,6 @@
|
||||
interface r9-eth0
|
||||
ip address 11.1.5.2/30
|
||||
!
|
||||
interface r9-eth1
|
||||
ip address 50.1.1.9/32
|
||||
!
|
515
tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
Executable file
515
tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
Executable file
@ -0,0 +1,515 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
#
|
||||
# test_bgp_linkbw_ip.py
|
||||
#
|
||||
# Copyright (c) 2020 by
|
||||
# Cumulus Networks, Inc
|
||||
# Vivek Venkatraman
|
||||
#
|
||||
# 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_bgp_linkbw_ip.py: Test weighted ECMP using BGP link-bandwidth
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from functools import partial
|
||||
import pytest
|
||||
import json
|
||||
|
||||
# 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
|
||||
|
||||
"""
|
||||
This topology is for validating one of the primary use cases for
|
||||
weighted ECMP (a.k.a. Unequal cost multipath) using BGP link-bandwidth:
|
||||
https://tools.ietf.org/html/draft-mohanty-bess-ebgp-dmz
|
||||
|
||||
The topology consists of two PODs. Pod-1 consists of a spine switch
|
||||
and two leaf switches, with two servers attached to the first leaf and
|
||||
one to the second leaf. Pod-2 consists of one spine and one leaf, with
|
||||
one server connected to the leaf. The PODs are connected by a super-spine
|
||||
switch.
|
||||
|
||||
Note that the use of the term "switch" above is in keeping with common
|
||||
data-center terminology. These devices are all regular routers; for
|
||||
this scenario, the servers are also routers as they have to announce
|
||||
anycast IP (VIP) addresses via BGP.
|
||||
"""
|
||||
|
||||
class BgpLinkBwTopo(Topo):
|
||||
"Test topology builder"
|
||||
def build(self, *_args, **_opts):
|
||||
"Build function"
|
||||
tgen = get_topogen(self)
|
||||
|
||||
# Create 10 routers - 1 super-spine, 2 spines, 3 leafs
|
||||
# and 4 servers
|
||||
routers = {}
|
||||
for i in range(1, 11):
|
||||
routers[i] = tgen.add_router('r{}'.format(i))
|
||||
|
||||
# Create 13 "switches" - to interconnect the above routers
|
||||
switches = {}
|
||||
for i in range(1, 14):
|
||||
switches[i] = tgen.add_switch('s{}'.format(i))
|
||||
|
||||
# Interconnect R1 (super-spine) to R2 and R3 (the two spines)
|
||||
switches[1].add_link(tgen.gears['r1'])
|
||||
switches[1].add_link(tgen.gears['r2'])
|
||||
switches[2].add_link(tgen.gears['r1'])
|
||||
switches[2].add_link(tgen.gears['r3'])
|
||||
|
||||
# Interconnect R2 (spine in pod-1) to R4 and R5 (the associated
|
||||
# leaf switches)
|
||||
switches[3].add_link(tgen.gears['r2'])
|
||||
switches[3].add_link(tgen.gears['r4'])
|
||||
switches[4].add_link(tgen.gears['r2'])
|
||||
switches[4].add_link(tgen.gears['r5'])
|
||||
|
||||
# Interconnect R3 (spine in pod-2) to R6 (associated leaf)
|
||||
switches[5].add_link(tgen.gears['r3'])
|
||||
switches[5].add_link(tgen.gears['r6'])
|
||||
|
||||
# Interconnect leaf switches to servers
|
||||
switches[6].add_link(tgen.gears['r4'])
|
||||
switches[6].add_link(tgen.gears['r7'])
|
||||
switches[7].add_link(tgen.gears['r4'])
|
||||
switches[7].add_link(tgen.gears['r8'])
|
||||
switches[8].add_link(tgen.gears['r5'])
|
||||
switches[8].add_link(tgen.gears['r9'])
|
||||
switches[9].add_link(tgen.gears['r6'])
|
||||
switches[9].add_link(tgen.gears['r10'])
|
||||
|
||||
# Create empty networks for the servers
|
||||
switches[10].add_link(tgen.gears['r7'])
|
||||
switches[11].add_link(tgen.gears['r8'])
|
||||
switches[12].add_link(tgen.gears['r9'])
|
||||
switches[13].add_link(tgen.gears['r10'])
|
||||
|
||||
def setup_module(mod):
|
||||
"Sets up the pytest environment"
|
||||
tgen = Topogen(BgpLinkBwTopo, mod.__name__)
|
||||
tgen.start_topology()
|
||||
|
||||
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_BGP,
|
||||
os.path.join(CWD, '{}/bgpd.conf'.format(rname))
|
||||
)
|
||||
|
||||
# Initialize all routers.
|
||||
tgen.start_router()
|
||||
|
||||
#tgen.mininet_cli()
|
||||
|
||||
def teardown_module(mod):
|
||||
"Teardown the pytest environment"
|
||||
tgen = get_topogen()
|
||||
tgen.stop_topology()
|
||||
|
||||
def test_bgp_linkbw_adv():
|
||||
"Test #1: Test BGP link-bandwidth advertisement based on number of multipaths"
|
||||
logger.info('\nTest #1: Test BGP link-bandwidth advertisement based on number of multipaths')
|
||||
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip('skipped because of router(s) failure')
|
||||
|
||||
r1 = tgen.gears['r1']
|
||||
r2 = tgen.gears['r2']
|
||||
|
||||
# Configure anycast IP on server r7
|
||||
logger.info('Configure anycast IP on server r7')
|
||||
|
||||
tgen.net['r7'].cmd('ip addr add 198.10.1.1/32 dev r7-eth1')
|
||||
|
||||
# Check on spine router r2 for link-bw advertisement by leaf router r4
|
||||
logger.info('Check on spine router r2 for link-bw advertisement by leaf router r4')
|
||||
|
||||
json_file = '{}/r2/bgp-route-1.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r2, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on spine router r2'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Check on spine router r2 that default weight is used as there is no multipath
|
||||
logger.info('Check on spine router r2 that default weight is used as there is no multipath')
|
||||
|
||||
json_file = '{}/r2/ip-route-1.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r2, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on spine router r2'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Check on super-spine router r1 that link-bw has been propagated by spine router r2
|
||||
logger.info('Check on super-spine router r1 that link-bw has been propagated by spine router r2')
|
||||
|
||||
json_file = '{}/r1/bgp-route-1.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
def test_bgp_cumul_linkbw():
|
||||
"Test #2: Test cumulative link-bandwidth propagation"
|
||||
logger.info('\nTest #2: Test cumulative link-bandwidth propagation')
|
||||
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip('skipped because of router(s) failure')
|
||||
|
||||
r1 = tgen.gears['r1']
|
||||
r2 = tgen.gears['r2']
|
||||
r4 = tgen.gears['r4']
|
||||
|
||||
# Configure anycast IP on additional server r8
|
||||
logger.info('Configure anycast IP on server r8')
|
||||
|
||||
tgen.net['r8'].cmd('ip addr add 198.10.1.1/32 dev r8-eth1')
|
||||
|
||||
# Check multipath on leaf router r4
|
||||
logger.info('Check multipath on leaf router r4')
|
||||
|
||||
json_file = '{}/r4/bgp-route-1.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r4, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on leaf router r4'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Check regular ECMP is in effect on leaf router r4
|
||||
logger.info('Check regular ECMP is in effect on leaf router r4')
|
||||
|
||||
json_file = '{}/r4/ip-route-1.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r4, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on leaf router r4'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Check on spine router r2 that leaf has propagated the cumulative link-bw based on num-multipaths
|
||||
logger.info('Check on spine router r2 that leaf has propagated the cumulative link-bw based on num-multipaths')
|
||||
|
||||
json_file = '{}/r2/bgp-route-2.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r2, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on spine router r2'
|
||||
assert result is None, assertmsg
|
||||
|
||||
def test_weighted_ecmp():
|
||||
"Test #3: Test weighted ECMP - multipath with next hop weights"
|
||||
logger.info('\nTest #3: Test weighted ECMP - multipath with next hop weights')
|
||||
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip('skipped because of router(s) failure')
|
||||
|
||||
r1 = tgen.gears['r1']
|
||||
r2 = tgen.gears['r2']
|
||||
|
||||
# Configure anycast IP on additional server r9
|
||||
logger.info('Configure anycast IP on server r9')
|
||||
|
||||
tgen.net['r9'].cmd('ip addr add 198.10.1.1/32 dev r9-eth1')
|
||||
|
||||
# Check multipath on spine router r2
|
||||
logger.info('Check multipath on spine router r2')
|
||||
json_file = '{}/r2/bgp-route-3.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r2, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on spine router r2'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Check weighted ECMP is in effect on the spine router r2
|
||||
logger.info('Check weighted ECMP is in effect on the spine router r2')
|
||||
|
||||
json_file = '{}/r2/ip-route-2.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r2, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on spine router r2'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Configure anycast IP on additional server r10
|
||||
logger.info('Configure anycast IP on server r10')
|
||||
|
||||
tgen.net['r10'].cmd('ip addr add 198.10.1.1/32 dev r10-eth1')
|
||||
|
||||
# Check multipath on super-spine router r1
|
||||
logger.info('Check multipath on super-spine router r1')
|
||||
json_file = '{}/r1/bgp-route-2.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Check weighted ECMP is in effect on the super-spine router r1
|
||||
logger.info('Check weighted ECMP is in effect on the super-spine router r1')
|
||||
json_file = '{}/r1/ip-route-1.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
def test_weighted_ecmp_link_flap():
|
||||
"Test #4: Test weighted ECMP rebalancing upon change (link flap)"
|
||||
logger.info('\nTest #4: Test weighted ECMP rebalancing upon change (link flap)')
|
||||
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip('skipped because of router(s) failure')
|
||||
|
||||
r1 = tgen.gears['r1']
|
||||
r2 = tgen.gears['r2']
|
||||
|
||||
# Bring down link on server r9
|
||||
logger.info('Bring down link on server r9')
|
||||
|
||||
tgen.net['r9'].cmd('ip link set dev r9-eth1 down')
|
||||
|
||||
# Check spine router r2 has only one path
|
||||
logger.info('Check spine router r2 has only one path')
|
||||
|
||||
json_file = '{}/r2/ip-route-3.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r2, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on spine router r2'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Check link-bandwidth change and weighted ECMP rebalance on super-spine router r1
|
||||
logger.info('Check link-bandwidth change and weighted ECMP rebalance on super-spine router r1')
|
||||
|
||||
json_file = '{}/r1/bgp-route-3.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
json_file = '{}/r1/ip-route-2.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Bring up link on server r9
|
||||
logger.info('Bring up link on server r9')
|
||||
|
||||
tgen.net['r9'].cmd('ip link set dev r9-eth1 up')
|
||||
|
||||
# Check link-bandwidth change and weighted ECMP rebalance on super-spine router r1
|
||||
logger.info('Check link-bandwidth change and weighted ECMP rebalance on super-spine router r1')
|
||||
|
||||
json_file = '{}/r1/bgp-route-2.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
json_file = '{}/r1/ip-route-1.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
def test_weighted_ecmp_second_anycast_ip():
|
||||
"Test #5: Test weighted ECMP for a second anycast IP"
|
||||
logger.info('\nTest #5: Test weighted ECMP for a second anycast IP')
|
||||
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip('skipped because of router(s) failure')
|
||||
|
||||
r1 = tgen.gears['r1']
|
||||
r2 = tgen.gears['r2']
|
||||
|
||||
# Configure anycast IP on additional server r7, r9 and r10
|
||||
logger.info('Configure anycast IP on server r7, r9 and r10')
|
||||
|
||||
tgen.net['r7'].cmd('ip addr add 198.10.1.11/32 dev r7-eth1')
|
||||
tgen.net['r9'].cmd('ip addr add 198.10.1.11/32 dev r9-eth1')
|
||||
tgen.net['r10'].cmd('ip addr add 198.10.1.11/32 dev r10-eth1')
|
||||
|
||||
# Check link-bandwidth and weighted ECMP on super-spine router r1
|
||||
logger.info('Check link-bandwidth and weighted ECMP on super-spine router r1')
|
||||
|
||||
json_file = '{}/r1/bgp-route-4.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show bgp ipv4 uni 198.10.1.11/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
json_file = '{}/r1/ip-route-3.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.11/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
def test_paths_with_and_without_linkbw():
|
||||
"Test #6: Test paths with and without link-bandwidth - receiver should resort to regular ECMP"
|
||||
logger.info('\nTest #6: Test paths with and without link-bandwidth - receiver should resort to regular ECMP')
|
||||
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip('skipped because of router(s) failure')
|
||||
|
||||
r1 = tgen.gears['r1']
|
||||
|
||||
# Configure leaf router r6 to not advertise any link-bandwidth
|
||||
logger.info('Configure leaf router r6 to not advertise any link-bandwidth')
|
||||
|
||||
tgen.net['r6'].cmd('vtysh -c \"conf t\" -c \"router bgp 65303\" -c \"address-family ipv4 unicast\" -c \"no neighbor 11.1.3.1 route-map anycast_ip out\"')
|
||||
|
||||
# Check link-bandwidth change on super-spine router r1
|
||||
logger.info('Check link-bandwidth change on super-spine router r1')
|
||||
|
||||
json_file = '{}/r1/bgp-route-5.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show bgp ipv4 uni 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Check super-spine router r1 resorts to regular ECMP
|
||||
logger.info('Check super-spine router r1 resorts to regular ECMP')
|
||||
|
||||
json_file = '{}/r1/ip-route-4.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
json_file = '{}/r1/ip-route-5.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.11/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=50, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
def test_linkbw_handling_options():
|
||||
"Test #7: Test different options for processing link-bandwidth on the receiver"
|
||||
logger.info('\nTest #7: Test different options for processing link-bandwidth on the receiver')
|
||||
|
||||
tgen = get_topogen()
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip('skipped because of router(s) failure')
|
||||
|
||||
r1 = tgen.gears['r1']
|
||||
|
||||
# Configure super-spine r1 to skip multipaths without link-bandwidth
|
||||
logger.info('Configure super-spine r1 to skip multipaths without link-bandwidth')
|
||||
|
||||
tgen.net['r1'].cmd('vtysh -c \"conf t\" -c \"router bgp 65101\" -c \"bgp bestpath bandwidth skip-missing\"')
|
||||
|
||||
# Check super-spine router r1 resorts to only one path as other path is skipped
|
||||
logger.info('Check super-spine router r1 resorts to only one path as other path is skipped')
|
||||
|
||||
json_file = '{}/r1/ip-route-6.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
json_file = '{}/r1/ip-route-7.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.11/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
# Configure super-spine r1 to use default-weight for multipaths without link-bandwidth
|
||||
logger.info('Configure super-spine r1 to use default-weight for multipaths without link-bandwidth')
|
||||
|
||||
tgen.net['r1'].cmd('vtysh -c \"conf t\" -c \"router bgp 65101\" -c \"bgp bestpath bandwidth default-weight-for-missing\"')
|
||||
|
||||
# Check super-spine router r1 uses ECMP with weight 1 for path without link-bandwidth
|
||||
logger.info('Check super-spine router r1 uses ECMP with weight 1 for path without link-bandwidth')
|
||||
|
||||
json_file = '{}/r1/ip-route-8.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.1/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
json_file = '{}/r1/ip-route-9.json'.format(CWD)
|
||||
expected = json.loads(open(json_file).read())
|
||||
test_func = partial(topotest.router_json_cmp,
|
||||
r1, 'show ip route 198.10.1.11/32 json', expected)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=200, wait=0.5)
|
||||
assertmsg = 'JSON output mismatch on super-spine router r1'
|
||||
assert result is None, assertmsg
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
Loading…
Reference in New Issue
Block a user