summaryrefslogtreecommitdiffstats
path: root/tests/topotests/bgp_link_bw_ip
diff options
context:
space:
mode:
Diffstat (limited to 'tests/topotests/bgp_link_bw_ip')
-rwxr-xr-xtests/topotests/bgp_link_bw_ip/__init__.py0
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/bgp-route-1.json19
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/bgp-route-2.json32
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/bgp-route-3.json32
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/bgp-route-4.json32
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/bgp-route-5.json29
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/bgpd.conf12
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-1.json20
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-2.json20
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-3.json20
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-4.json20
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-5.json20
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-6.json15
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-7.json15
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-8.json20
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/ip-route-9.json20
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/v4_route.json84
-rw-r--r--tests/topotests/bgp_link_bw_ip/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp_link_bw_ip/r10/bgpd.conf17
-rw-r--r--tests/topotests/bgp_link_bw_ip/r10/zebra.conf6
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/bgp-route-1.json19
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/bgp-route-2.json19
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json32
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/bgpd.conf13
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/ip-route-1.json19
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/ip-route-2.json20
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/ip-route-3.json15
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/zebra.conf10
-rw-r--r--tests/topotests/bgp_link_bw_ip/r3/bgp-route-1.json29
-rw-r--r--tests/topotests/bgp_link_bw_ip/r3/bgpd.conf12
-rw-r--r--tests/topotests/bgp_link_bw_ip/r3/zebra.conf7
-rw-r--r--tests/topotests/bgp_link_bw_ip/r4/bgp-route-1.json23
-rw-r--r--tests/topotests/bgp_link_bw_ip/r4/bgpd.conf32
-rw-r--r--tests/topotests/bgp_link_bw_ip/r4/ip-route-1.json21
-rw-r--r--tests/topotests/bgp_link_bw_ip/r4/zebra.conf10
-rw-r--r--tests/topotests/bgp_link_bw_ip/r5/bgpd.conf23
-rw-r--r--tests/topotests/bgp_link_bw_ip/r5/zebra.conf7
-rw-r--r--tests/topotests/bgp_link_bw_ip/r6/bgpd.conf24
-rw-r--r--tests/topotests/bgp_link_bw_ip/r6/zebra.conf7
-rw-r--r--tests/topotests/bgp_link_bw_ip/r7/bgpd.conf17
-rw-r--r--tests/topotests/bgp_link_bw_ip/r7/zebra.conf6
-rw-r--r--tests/topotests/bgp_link_bw_ip/r8/bgpd.conf17
-rw-r--r--tests/topotests/bgp_link_bw_ip/r8/zebra.conf6
-rw-r--r--tests/topotests/bgp_link_bw_ip/r9/bgpd.conf17
-rw-r--r--tests/topotests/bgp_link_bw_ip/r9/zebra.conf6
-rw-r--r--tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py588
46 files changed, 1439 insertions, 0 deletions
diff --git a/tests/topotests/bgp_link_bw_ip/__init__.py b/tests/topotests/bgp_link_bw_ip/__init__.py
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/__init__.py
diff --git a/tests/topotests/bgp_link_bw_ip/r1/bgp-route-1.json b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-1.json
new file mode 100644
index 0000000..3e3c35e
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-1.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/bgp-route-2.json b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-2.json
new file mode 100644
index 0000000..f07e89b
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-2.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/bgp-route-3.json b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-3.json
new file mode 100644
index 0000000..3501d12
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-3.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/bgp-route-4.json b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-4.json
new file mode 100644
index 0000000..b1ed004
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-4.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/bgp-route-5.json b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-5.json
new file mode 100644
index 0000000..89469b8
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/bgp-route-5.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r1/bgpd.conf
new file mode 100644
index 0000000..b1ec70d
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/bgpd.conf
@@ -0,0 +1,12 @@
+hostname r1
+!
+router bgp 65101
+ bgp router-id 11.1.1.1
+ no bgp ebgp-requires-policy
+ bgp bestpath as-path multipath-relax
+ neighbor 11.1.1.2 remote-as external
+ neighbor 11.1.1.2 timers 3 10
+ neighbor 11.1.1.6 remote-as external
+ neighbor 11.1.1.6 timers 3 10
+ neighbor 11.1.1.6 disable-link-bw-encoding-ieee
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-1.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-1.json
new file mode 100644
index 0000000..3c02e26
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-1.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-2.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-2.json
new file mode 100644
index 0000000..3c2d42c
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-2.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-3.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-3.json
new file mode 100644
index 0000000..3d80018
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-3.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-4.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-4.json
new file mode 100644
index 0000000..6b757ef
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-4.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-5.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-5.json
new file mode 100644
index 0000000..641ecab
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-5.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-6.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-6.json
new file mode 100644
index 0000000..6ed3f8e
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-6.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-7.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-7.json
new file mode 100644
index 0000000..95531d9
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-7.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-8.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-8.json
new file mode 100644
index 0000000..beac501
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-8.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/ip-route-9.json b/tests/topotests/bgp_link_bw_ip/r1/ip-route-9.json
new file mode 100644
index 0000000..eb27ce2
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/ip-route-9.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/v4_route.json b/tests/topotests/bgp_link_bw_ip/r1/v4_route.json
new file mode 100644
index 0000000..76c6396
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/v4_route.json
@@ -0,0 +1,84 @@
+{
+ "10.0.1.1\/32":[
+ {
+ "prefix":"10.0.1.1\/32",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "table":254,
+ "nexthops":[
+ {
+ "flags":9,
+ "ip":"0.0.0.0",
+ "afi":"ipv4",
+ "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,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "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,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "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,
+ "nexthops":[
+ {
+ "flags":11,
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true,
+ "onLink":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r1/zebra.conf b/tests/topotests/bgp_link_bw_ip/r1/zebra.conf
new file mode 100644
index 0000000..0fc81f9
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r1/zebra.conf
@@ -0,0 +1,7 @@
+!
+interface r1-eth0
+ ip address 11.1.1.1/30
+!
+interface r1-eth1
+ ip address 11.1.1.5/30
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r10/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r10/bgpd.conf
new file mode 100644
index 0000000..022270f
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r10/bgpd.conf
@@ -0,0 +1,17 @@
+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
+ no bgp ebgp-requires-policy
+ neighbor 11.1.6.1 remote-as external
+ neighbor 11.1.6.1 timers 3 10
+ !
+ address-family ipv4 unicast
+ redistribute connected route-map redist
+ !
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r10/zebra.conf b/tests/topotests/bgp_link_bw_ip/r10/zebra.conf
new file mode 100644
index 0000000..1a24fda
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r10/zebra.conf
@@ -0,0 +1,6 @@
+interface r10-eth0
+ ip address 11.1.6.2/30
+!
+interface r10-eth1
+ ip address 50.1.1.10/32
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-1.json b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-1.json
new file mode 100644
index 0000000..3c38689
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-1.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-2.json b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-2.json
new file mode 100644
index 0000000..1895cd8
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-2.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
new file mode 100644
index 0000000..dfc4171
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r2/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r2/bgpd.conf
new file mode 100644
index 0000000..0c0e859
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r2/bgpd.conf
@@ -0,0 +1,13 @@
+hostname r2
+!
+router bgp 65201
+ bgp router-id 11.1.2.1
+ bgp bestpath as-path multipath-relax
+ no bgp ebgp-requires-policy
+ neighbor 11.1.1.1 remote-as external
+ neighbor 11.1.1.1 timers 3 10
+ neighbor 11.1.2.2 remote-as external
+ neighbor 11.1.2.2 timers 3 10
+ neighbor 11.1.2.6 remote-as external
+ neighbor 11.1.2.6 timers 3 10
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r2/ip-route-1.json b/tests/topotests/bgp_link_bw_ip/r2/ip-route-1.json
new file mode 100644
index 0000000..131100a
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r2/ip-route-1.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r2/ip-route-2.json b/tests/topotests/bgp_link_bw_ip/r2/ip-route-2.json
new file mode 100644
index 0000000..7e2fa6b
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r2/ip-route-2.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r2/ip-route-3.json b/tests/topotests/bgp_link_bw_ip/r2/ip-route-3.json
new file mode 100644
index 0000000..d0509bb
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r2/ip-route-3.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r2/zebra.conf b/tests/topotests/bgp_link_bw_ip/r2/zebra.conf
new file mode 100644
index 0000000..23573a1
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r2/zebra.conf
@@ -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
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r3/bgp-route-1.json b/tests/topotests/bgp_link_bw_ip/r3/bgp-route-1.json
new file mode 100644
index 0000000..cddf127
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r3/bgp-route-1.json
@@ -0,0 +1,29 @@
+{
+ "prefix":"198.10.1.1/32",
+ "paths":[
+ {
+ "aspath":{
+ "string":"65303 65354",
+ "segments":[
+ {
+ "type":"as-sequence",
+ "list":[
+ 65303,
+ 65354
+ ]
+ }
+ ],
+ "length":2
+ },
+ "valid":true,
+ "extendedCommunity":{
+ "string":"LB:65303:125000 (1.000 Mbps)"
+ },
+ "nexthops":[
+ {
+ "ip":"11.1.3.2"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r3/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r3/bgpd.conf
new file mode 100644
index 0000000..cfd3949
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r3/bgpd.conf
@@ -0,0 +1,12 @@
+hostname r3
+!
+router bgp 65202
+ bgp router-id 11.1.3.1
+ bgp bestpath as-path multipath-relax
+ no bgp ebgp-requires-policy
+ neighbor 11.1.1.5 remote-as external
+ neighbor 11.1.1.5 timers 3 10
+ neighbor 11.1.3.2 remote-as external
+ neighbor 11.1.3.2 timers 3 10
+ neighbor 11.1.3.2 disable-link-bw-encoding-ieee
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r3/zebra.conf b/tests/topotests/bgp_link_bw_ip/r3/zebra.conf
new file mode 100644
index 0000000..d667669
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r3/zebra.conf
@@ -0,0 +1,7 @@
+!
+interface r3-eth0
+ ip address 11.1.1.6/30
+!
+interface r3-eth1
+ ip address 11.1.3.1/30
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r4/bgp-route-1.json b/tests/topotests/bgp_link_bw_ip/r4/bgp-route-1.json
new file mode 100644
index 0000000..87d1ae0
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r4/bgp-route-1.json
@@ -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"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r4/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r4/bgpd.conf
new file mode 100644
index 0000000..88b260f
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r4/bgpd.conf
@@ -0,0 +1,32 @@
+!
+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
+ no bgp ebgp-requires-policy
+ neighbor 11.1.2.1 remote-as external
+ neighbor 11.1.2.1 timers 3 10
+ neighbor 11.1.4.2 remote-as external
+ neighbor 11.1.4.2 timers 3 10
+ neighbor 11.1.4.6 remote-as external
+ neighbor 11.1.4.6 timers 3 10
+ !
+ address-family ipv4 unicast
+ neighbor 11.1.2.1 route-map anycast_ip out
+ !
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r4/ip-route-1.json b/tests/topotests/bgp_link_bw_ip/r4/ip-route-1.json
new file mode 100644
index 0000000..a9ccf07
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r4/ip-route-1.json
@@ -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
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_link_bw_ip/r4/zebra.conf b/tests/topotests/bgp_link_bw_ip/r4/zebra.conf
new file mode 100644
index 0000000..ef61f7e
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r4/zebra.conf
@@ -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
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
new file mode 100644
index 0000000..4014bfb
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
@@ -0,0 +1,23 @@
+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
+ no bgp ebgp-requires-policy
+ neighbor 11.1.2.5 remote-as external
+ neighbor 11.1.2.5 timers 3 10
+ neighbor 11.1.5.2 remote-as external
+ neighbor 11.1.5.2 timers 3 10
+ !
+ address-family ipv4 unicast
+ neighbor 11.1.2.5 route-map anycast_ip out
+ !
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r5/zebra.conf b/tests/topotests/bgp_link_bw_ip/r5/zebra.conf
new file mode 100644
index 0000000..66c6596
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r5/zebra.conf
@@ -0,0 +1,7 @@
+!
+interface r5-eth0
+ ip address 11.1.2.6/30
+!
+interface r5-eth1
+ ip address 11.1.5.1/30
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r6/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r6/bgpd.conf
new file mode 100644
index 0000000..89de8ee
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r6/bgpd.conf
@@ -0,0 +1,24 @@
+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
+ no bgp ebgp-requires-policy
+ neighbor 11.1.3.1 remote-as external
+ neighbor 11.1.3.1 timers 3 10
+ neighbor 11.1.3.1 disable-link-bw-encoding-ieee
+ neighbor 11.1.6.2 remote-as external
+ neighbor 11.1.6.2 timers 3 10
+ !
+ address-family ipv4 unicast
+ neighbor 11.1.3.1 route-map anycast_ip out
+ !
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r6/zebra.conf b/tests/topotests/bgp_link_bw_ip/r6/zebra.conf
new file mode 100644
index 0000000..66ff563
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r6/zebra.conf
@@ -0,0 +1,7 @@
+!
+interface r6-eth0
+ ip address 11.1.3.2/30
+!
+interface r6-eth1
+ ip address 11.1.6.1/30
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r7/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r7/bgpd.conf
new file mode 100644
index 0000000..39c0c81
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r7/bgpd.conf
@@ -0,0 +1,17 @@
+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
+ no bgp ebgp-requires-policy
+ neighbor 11.1.4.1 remote-as external
+ neighbor 11.1.4.1 timers 3 10
+ !
+ address-family ipv4 unicast
+ redistribute connected route-map redist
+ !
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r7/zebra.conf b/tests/topotests/bgp_link_bw_ip/r7/zebra.conf
new file mode 100644
index 0000000..38e36ca
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r7/zebra.conf
@@ -0,0 +1,6 @@
+interface r7-eth0
+ ip address 11.1.4.2/30
+!
+interface r7-eth1
+ ip address 50.1.1.7/32
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r8/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r8/bgpd.conf
new file mode 100644
index 0000000..ea1d546
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r8/bgpd.conf
@@ -0,0 +1,17 @@
+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
+ no bgp ebgp-requires-policy
+ neighbor 11.1.4.5 remote-as external
+ neighbor 11.1.4.5 timers 3 10
+ !
+ address-family ipv4 unicast
+ redistribute connected route-map redist
+ !
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r8/zebra.conf b/tests/topotests/bgp_link_bw_ip/r8/zebra.conf
new file mode 100644
index 0000000..1369e19
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r8/zebra.conf
@@ -0,0 +1,6 @@
+interface r8-eth0
+ ip address 11.1.4.6/30
+!
+interface r8-eth1
+ ip address 50.1.1.8/32
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r9/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r9/bgpd.conf
new file mode 100644
index 0000000..a6066ee
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r9/bgpd.conf
@@ -0,0 +1,17 @@
+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
+ no bgp ebgp-requires-policy
+ neighbor 11.1.5.1 remote-as external
+ neighbor 11.1.5.1 timers 3 10
+ !
+ address-family ipv4 unicast
+ redistribute connected route-map redist
+ !
+!
diff --git a/tests/topotests/bgp_link_bw_ip/r9/zebra.conf b/tests/topotests/bgp_link_bw_ip/r9/zebra.conf
new file mode 100644
index 0000000..c73caf3
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/r9/zebra.conf
@@ -0,0 +1,6 @@
+interface r9-eth0
+ ip address 11.1.5.2/30
+!
+interface r9-eth1
+ ip address 50.1.1.9/32
+!
diff --git a/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py b/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
new file mode 100644
index 0000000..4214f3a
--- /dev/null
+++ b/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
@@ -0,0 +1,588 @@
+#!/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 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.
+
+pytestmark = [pytest.mark.bgpd]
+
+
+"""
+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.
+"""
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # 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(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ 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"]
+ r3 = tgen.gears["r3"]
+
+ # 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 if bandwidth is properly encoded with non IEEE floatig-point (uint32) format on r3
+ logger.info(
+ "Check if bandwidth is properly encoded with non IEEE floatig-point (uint32) format on r3"
+ )
+ json_file = "{}/r3/bgp-route-1.json".format(CWD)
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, r3, "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 r3"
+ assert result is None, assertmsg
+
+ # 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))