summaryrefslogtreecommitdiffstats
path: root/tests/topotests/bgp_ecmp_topo1
diff options
context:
space:
mode:
Diffstat (limited to 'tests/topotests/bgp_ecmp_topo1')
-rw-r--r--tests/topotests/bgp_ecmp_topo1/__init__.py0
-rw-r--r--tests/topotests/bgp_ecmp_topo1/bgp-ecmp-topo1.dot206
-rw-r--r--tests/topotests/bgp_ecmp_topo1/bgp-ecmp-topo1.pdfbin0 -> 21367 bytes
-rw-r--r--tests/topotests/bgp_ecmp_topo1/exabgp.env54
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer1/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer1/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer10/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer10/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer11/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer11/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer12/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer12/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer13/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer13/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer14/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer14/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer15/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer15/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer16/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer16/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer17/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer17/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer18/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer18/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer19/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer19/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer2/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer2/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer20/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer20/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer3/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer3/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer4/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer4/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer5/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer5/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer6/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer6/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer7/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer7/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer8/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer8/exabgp.cfg21
-rwxr-xr-xtests/topotests/bgp_ecmp_topo1/peer9/exa-send.py66
-rw-r--r--tests/topotests/bgp_ecmp_topo1/peer9/exabgp.cfg21
-rw-r--r--tests/topotests/bgp_ecmp_topo1/r1/bgpd.conf51
-rw-r--r--tests/topotests/bgp_ecmp_topo1/r1/summary.txt131
-rw-r--r--tests/topotests/bgp_ecmp_topo1/r1/summary20.txt129
-rw-r--r--tests/topotests/bgp_ecmp_topo1/r1/zebra.conf16
-rw-r--r--tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py170
49 files changed, 2497 insertions, 0 deletions
diff --git a/tests/topotests/bgp_ecmp_topo1/__init__.py b/tests/topotests/bgp_ecmp_topo1/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/__init__.py
diff --git a/tests/topotests/bgp_ecmp_topo1/bgp-ecmp-topo1.dot b/tests/topotests/bgp_ecmp_topo1/bgp-ecmp-topo1.dot
new file mode 100644
index 0000000..90295e1
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/bgp-ecmp-topo1.dot
@@ -0,0 +1,206 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph ospf_ecmp_iBGP_topo1 {
+ label="bgp ecmp topo1 - eBGP with different AS numbers";
+ labelloc="t";
+
+ # Routers
+ r1 [
+ label="r1\nrtr-id 10.0.255.1/32",
+ shape=doubleoctagon,
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # 4 Switches for eBGP Peers
+ s1 [
+ label="s1\n10.0.1.0/24",
+ shape=oval,
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s2 [
+ label="s2\n10.0.2.0/24",
+ shape=oval,
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s3 [
+ label="s3\n10.0.3.0/24",
+ shape=oval,
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s4 [
+ label="s4\n10.0.4.0/24",
+ shape=oval,
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # 20 ExaBGP Peers AS 101...120
+ peer1 [
+ label="eBGP peer1\nAS99\nrtr-id 10.0.1.101/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer2 [
+ label="eBGP peer2\nAS99\nrtr-id 10.0.1.102/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer3 [
+ label="eBGP peer3\nAS99\nrtr-id 10.0.1.103/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer4 [
+ label="eBGP peer4\nAS99\nrtr-id 10.0.1.104/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer5 [
+ label="eBGP peer5\nAS99\nrtr-id 10.0.1.105/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer6 [
+ label="eBGP peer6\nAS99\nrtr-id 10.0.2.106/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer7 [
+ label="eBGP peer7\nAS99\nrtr-id 10.0.2.107/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer8 [
+ label="eBGP peer8\nAS99\nrtr-id 10.0.2.108/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer9 [
+ label="eBGP peer9\nAS99\nrtr-id 10.0.2.109/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer10 [
+ label="eBGP peer10\nAS99\nrtr-id 10.0.2.110/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer11 [
+ label="eBGP peer11\nAS111\nrtr-id 10.0.3.111/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer12 [
+ label="eBGP peer12\nAS112\nrtr-id 10.0.3.112/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer13 [
+ label="eBGP peer13\nAS113\nrtr-id 10.0.3.113/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer14 [
+ label="eBGP peer14\nAS114\nrtr-id 10.0.3.114/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer15 [
+ label="eBGP peer15\nAS115\nrtr-id 10.0.3.115/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer16 [
+ label="eBGP peer16\nAS116\nrtr-id 10.0.4.116/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer17 [
+ label="eBGP peer17\nAS117\nrtr-id 10.0.4.117/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer18 [
+ label="eBGP peer18\nAS118\nrtr-id 10.0.4.118/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer19 [
+ label="eBGP peer19\nAS119\nrtr-id 10.0.4.119/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+ peer20 [
+ label="eBGP peer20\nAS120\nrtr-id 10.0.4.120/32",
+ shape=rectangle,
+ fillcolor="#eee3d3",
+ style=filled,
+ ];
+
+ # Connections
+ r1 -- s1 [label="eth0\n.1"];
+ r1 -- s2 [label="eth1\n.1"];
+ r1 -- s3 [label="eth2\n.1"];
+ r1 -- s4 [label="eth3\n.1"];
+
+ peer1 -- s1 [label="eth0\n.101"];
+ peer2 -- s1 [label="eth0\n.102"];
+ peer3 -- s1 [label="eth0\n.103"];
+ peer4 -- s1 [label="eth0\n.104"];
+ peer5 -- s1 [label="eth0\n.105"];
+ peer6 -- s2 [label="eth0\n.106"];
+ peer7 -- s2 [label="eth0\n.107"];
+ peer8 -- s2 [label="eth0\n.108"];
+ peer9 -- s2 [label="eth0\n.109"];
+ peer10 -- s2 [label="eth0\n.110"];
+ peer11 -- s3 [label="eth0\n.111"];
+ peer12 -- s3 [label="eth0\n.112"];
+ peer13 -- s3 [label="eth0\n.113"];
+ peer14 -- s3 [label="eth0\n.114"];
+ peer15 -- s3 [label="eth0\n.115"];
+ peer16 -- s4 [label="eth0\n.116"];
+ peer17 -- s4 [label="eth0\n.117"];
+ peer18 -- s4 [label="eth0\n.118"];
+ peer19 -- s4 [label="eth0\n.119"];
+ peer20 -- s4 [label="eth0\n.120"];
+
+ # Arrange network to make cleaner diagram
+ { rank=same peer1 peer2 peer3 peer4 peer5 } -- s1 -- { rank=same peer6 peer7 peer8 peer9 peer10 } -- s2
+ -- { rank=same peer11 peer12 peer13 peer14 peer15 } -- s3 -- { rank=same peer16 peer17 peer18 peer19 peer20 } -- s4
+ -- { rank=same r1 } [style=invis]
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/bgp-ecmp-topo1.pdf b/tests/topotests/bgp_ecmp_topo1/bgp-ecmp-topo1.pdf
new file mode 100644
index 0000000..b4d4f6a
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/bgp-ecmp-topo1.pdf
Binary files differ
diff --git a/tests/topotests/bgp_ecmp_topo1/exabgp.env b/tests/topotests/bgp_ecmp_topo1/exabgp.env
new file mode 100644
index 0000000..a328e04
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/exabgp.env
@@ -0,0 +1,54 @@
+
+[exabgp.api]
+encoder = text
+highres = false
+respawn = false
+socket = ''
+
+[exabgp.bgp]
+openwait = 60
+
+[exabgp.cache]
+attributes = true
+nexthops = true
+
+[exabgp.daemon]
+daemonize = true
+pid = '/var/run/exabgp/exabgp.pid'
+user = 'exabgp'
+##daemonize = false
+
+[exabgp.log]
+all = false
+configuration = true
+daemon = true
+destination = '/var/log/exabgp.log'
+enable = true
+level = INFO
+message = false
+network = true
+packets = false
+parser = false
+processes = true
+reactor = true
+rib = false
+routes = false
+short = false
+timers = false
+
+[exabgp.pdb]
+enable = false
+
+[exabgp.profile]
+enable = false
+file = ''
+
+[exabgp.reactor]
+speed = 1.0
+
+[exabgp.tcp]
+acl = false
+bind = ''
+delay = 0
+once = false
+port = 179
diff --git a/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer1/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer1/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer1/exabgp.cfg
new file mode 100644
index 0000000..2d0ca89
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer1/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 1 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 1";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.1.1 {
+ router-id 10.0.1.101;
+ local-address 10.0.1.101;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer10/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer10/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer10/exabgp.cfg
new file mode 100644
index 0000000..0c842a0
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer10/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 10 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 10";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.2.1 {
+ router-id 10.0.2.110;
+ local-address 10.0.2.110;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer11/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer11/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer11/exabgp.cfg
new file mode 100644
index 0000000..936dc57
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer11/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 11 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 11";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.3.1 {
+ router-id 10.0.3.111;
+ local-address 10.0.3.111;
+ local-as 111;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer12/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer12/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer12/exabgp.cfg
new file mode 100644
index 0000000..56b33ea
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer12/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 12 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 12";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.3.1 {
+ router-id 10.0.3.112;
+ local-address 10.0.3.112;
+ local-as 112;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer13/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer13/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer13/exabgp.cfg
new file mode 100644
index 0000000..b933ffb
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer13/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 13 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 13";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.3.1 {
+ router-id 10.0.3.113;
+ local-address 10.0.3.113;
+ local-as 113;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer14/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer14/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer14/exabgp.cfg
new file mode 100644
index 0000000..bcfa41e
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer14/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 14 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 14";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.3.1 {
+ router-id 10.0.3.114;
+ local-address 10.0.3.114;
+ local-as 114;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer15/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer15/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer15/exabgp.cfg
new file mode 100644
index 0000000..022e835
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer15/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 15 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 15";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.3.1 {
+ router-id 10.0.3.115;
+ local-address 10.0.3.115;
+ local-as 115;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer16/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer16/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer16/exabgp.cfg
new file mode 100644
index 0000000..0649202
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer16/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 16 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 16";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.4.1 {
+ router-id 10.0.4.116;
+ local-address 10.0.4.116;
+ local-as 116;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer17/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer17/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer17/exabgp.cfg
new file mode 100644
index 0000000..0aeeed9
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer17/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 17 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 17";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.4.1 {
+ router-id 10.0.4.117;
+ local-address 10.0.4.117;
+ local-as 117;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer18/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer18/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer18/exabgp.cfg
new file mode 100644
index 0000000..352c030
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer18/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 18 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 18";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.4.1 {
+ router-id 10.0.4.118;
+ local-address 10.0.4.118;
+ local-as 118;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer19/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer19/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer19/exabgp.cfg
new file mode 100644
index 0000000..9913c22
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer19/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 19 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 19";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.4.1 {
+ router-id 10.0.4.119;
+ local-address 10.0.4.119;
+ local-as 119;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer2/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer2/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer2/exabgp.cfg
new file mode 100644
index 0000000..46b436d
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer2/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 2 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 2";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.1.1 {
+ router-id 10.0.1.102;
+ local-address 10.0.1.102;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer20/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer20/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer20/exabgp.cfg
new file mode 100644
index 0000000..17fb816
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer20/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 20 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 20";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.4.1 {
+ router-id 10.0.4.120;
+ local-address 10.0.4.120;
+ local-as 120;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer3/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer3/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer3/exabgp.cfg
new file mode 100644
index 0000000..acd5775
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer3/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 3 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 3";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.1.1 {
+ router-id 10.0.1.103;
+ local-address 10.0.1.103;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer4/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer4/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer4/exabgp.cfg
new file mode 100644
index 0000000..4c9a989
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer4/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 4 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 4";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.1.1 {
+ router-id 10.0.1.104;
+ local-address 10.0.1.104;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer5/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer5/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer5/exabgp.cfg
new file mode 100644
index 0000000..eba2aae
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer5/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 5 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 5";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.1.1 {
+ router-id 10.0.1.105;
+ local-address 10.0.1.105;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer6/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer6/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer6/exabgp.cfg
new file mode 100644
index 0000000..38b6af0
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer6/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 6 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 6";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.2.1 {
+ router-id 10.0.2.106;
+ local-address 10.0.2.106;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer7/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer7/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer7/exabgp.cfg
new file mode 100644
index 0000000..7631e43
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer7/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 7 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 7";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.2.1 {
+ router-id 10.0.2.107;
+ local-address 10.0.2.107;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer8/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer8/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer8/exabgp.cfg
new file mode 100644
index 0000000..1cd1cd9
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer8/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 8 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 8";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.2.1 {
+ router-id 10.0.2.108;
+ local-address 10.0.2.108;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py b/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py
new file mode 100755
index 0000000..6bef355
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer9/exa-send.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python2
+
+"""
+exa-send.py: Send a few testroutes with ExaBGP
+"""
+
+from sys import stdout, argv
+from time import sleep
+
+sleep(5)
+
+# 1st arg is peer number
+# 2nd arg is number of routes to send
+peer = int(argv[1])
+numRoutes = int(argv[2])
+if peer <= 10:
+ asnum = 99
+else:
+ asnum = peer + 100
+
+# Announce numRoutes equal routes per PE - different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.201.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes per PE - different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.202.%s.0/24 med 100 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.203.%s.0/24 med %i next-hop 10.0.%i.%i origin igp\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100)
+ )
+ stdout.flush()
+
+# Announce numRoutes equal routes with different med per PE and different neighbor AS, but same source AS
+for i in range(0, numRoutes):
+ stdout.write(
+ "announce route 10.204.%s.0/24 med %i next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (i, peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+ )
+ stdout.flush()
+
+# Announce 2 different route per peer
+stdout.write(
+ "announce route 10.205.%i.0/24 next-hop 10.0.%i.%i origin igp\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100)
+)
+stdout.write(
+ "announce route 10.206.%i.0/24 next-hop 10.0.%i.%i origin igp as-path [ %i 200 ]\n"
+ % (peer, (((peer - 1) / 5) + 1), peer + 100, asnum)
+)
+stdout.flush()
+
+# Loop endlessly to allow ExaBGP to continue running
+while True:
+ sleep(1)
diff --git a/tests/topotests/bgp_ecmp_topo1/peer9/exabgp.cfg b/tests/topotests/bgp_ecmp_topo1/peer9/exabgp.cfg
new file mode 100644
index 0000000..5771553
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/peer9/exabgp.cfg
@@ -0,0 +1,21 @@
+group controller {
+
+ process announce-routes {
+ run "/etc/exabgp/exa-send.py 9 10";
+ }
+
+ process receive-routes {
+ run "/etc/exabgp/exa-receive.py 9";
+ receive-routes;
+ encoder text;
+ }
+
+ neighbor 10.0.2.1 {
+ router-id 10.0.2.109;
+ local-address 10.0.2.109;
+ local-as 99;
+ peer-as 100;
+ graceful-restart;
+ }
+
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/r1/bgpd.conf b/tests/topotests/bgp_ecmp_topo1/r1/bgpd.conf
new file mode 100644
index 0000000..49981ac
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/r1/bgpd.conf
@@ -0,0 +1,51 @@
+!
+hostname r1
+log file bgpd.log
+!
+router bgp 100
+ bgp router-id 10.0.255.1
+ bgp bestpath as-path multipath-relax
+ no bgp ebgp-requires-policy
+ neighbor 10.0.1.101 remote-as 99
+ neighbor 10.0.1.101 timers 3 10
+ neighbor 10.0.1.102 remote-as 99
+ neighbor 10.0.1.102 timers 3 10
+ neighbor 10.0.1.103 remote-as 99
+ neighbor 10.0.1.103 timers 3 10
+ neighbor 10.0.1.104 remote-as 99
+ neighbor 10.0.1.104 timers 3 10
+ neighbor 10.0.1.105 remote-as 99
+ neighbor 10.0.1.105 timers 3 10
+ neighbor 10.0.2.106 remote-as 99
+ neighbor 10.0.2.106 timers 3 10
+ neighbor 10.0.2.107 remote-as 99
+ neighbor 10.0.2.107 timers 3 10
+ neighbor 10.0.2.108 remote-as 99
+ neighbor 10.0.2.108 timers 3 10
+ neighbor 10.0.2.109 remote-as 99
+ neighbor 10.0.2.109 timers 3 10
+ neighbor 10.0.2.110 remote-as 99
+ neighbor 10.0.2.110 timers 3 10
+ neighbor 10.0.3.111 remote-as 111
+ neighbor 10.0.3.111 timers 3 10
+ neighbor 10.0.3.112 remote-as 112
+ neighbor 10.0.3.112 timers 3 10
+ neighbor 10.0.3.113 remote-as 113
+ neighbor 10.0.3.113 timers 3 10
+ neighbor 10.0.3.114 remote-as 114
+ neighbor 10.0.3.114 timers 3 10
+ neighbor 10.0.3.115 remote-as 115
+ neighbor 10.0.3.115 timers 3 10
+ neighbor 10.0.4.116 remote-as 116
+ neighbor 10.0.4.116 timers 3 10
+ neighbor 10.0.4.117 remote-as 117
+ neighbor 10.0.4.117 timers 3 10
+ neighbor 10.0.4.118 remote-as 118
+ neighbor 10.0.4.118 timers 3 10
+ neighbor 10.0.4.119 remote-as 119
+ neighbor 10.0.4.119 timers 3 10
+ neighbor 10.0.4.120 remote-as 120
+ neighbor 10.0.4.120 timers 3 10
+ !
+!
+
diff --git a/tests/topotests/bgp_ecmp_topo1/r1/summary.txt b/tests/topotests/bgp_ecmp_topo1/r1/summary.txt
new file mode 100644
index 0000000..68de28a
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/r1/summary.txt
@@ -0,0 +1,131 @@
+{
+"ipv4Unicast":{
+ "routerId":"10.0.255.1",
+ "as":100,
+ "vrfName":"default",
+ "peerCount":20,
+ "peers":{
+ "10.0.1.101":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.1.102":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.1.103":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.1.104":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.1.105":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.106":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.107":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.108":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.109":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.110":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.111":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.112":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.113":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.114":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.115":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.116":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.117":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.118":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.119":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.120":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ }
+ },
+ "totalPeers":20
+}
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt b/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt
new file mode 100644
index 0000000..4895cdb
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/r1/summary20.txt
@@ -0,0 +1,129 @@
+{
+ "routerId":"10.0.255.1",
+ "as":100,
+ "vrfName":"default",
+ "peerCount":20,
+ "peers":{
+ "10.0.1.101":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.1.102":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.1.103":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.1.104":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.1.105":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.106":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.107":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.108":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.109":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.2.110":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.111":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.112":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.113":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.114":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.3.115":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.116":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.117":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.118":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.119":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ },
+ "10.0.4.120":{
+ "outq":0,
+ "inq":0,
+ "pfxRcd":42,
+ "state":"Established"
+ }
+ },
+ "totalPeers":20
+}
diff --git a/tests/topotests/bgp_ecmp_topo1/r1/zebra.conf b/tests/topotests/bgp_ecmp_topo1/r1/zebra.conf
new file mode 100644
index 0000000..77c76cd
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/r1/zebra.conf
@@ -0,0 +1,16 @@
+!
+hostname r1
+log file zebra.log
+!
+interface r1-eth0
+ ip address 10.0.1.1/24
+!
+interface r1-eth1
+ ip address 10.0.2.1/24
+!
+interface r1-eth2
+ ip address 10.0.3.1/24
+!
+interface r1-eth3
+ ip address 10.0.4.1/24
+!
diff --git a/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py b/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py
new file mode 100644
index 0000000..97751ec
--- /dev/null
+++ b/tests/topotests/bgp_ecmp_topo1/test_bgp_ecmp_topo1.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python2
+# SPDX-License-Identifier: ISC
+
+#
+# test_bgp_ecmp_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2017 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+
+"""
+test_bgp_ecmp_topo1.py: Test BGP topology with ECMP (Equal Cost MultiPath).
+"""
+
+import json
+import functools
+import os
+import sys
+import pytest
+
+# 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]
+
+
+total_ebgp_peers = 20
+
+#####################################################
+#
+# Network Topology Definition
+#
+#####################################################
+
+
+def build_topo(tgen):
+ router = tgen.add_router("r1")
+
+ # Setup Switches - 1 switch per 5 peering routers
+ for swNum in range(1, (total_ebgp_peers + 4) // 5 + 1):
+ switch = tgen.add_switch("s{}".format(swNum))
+ switch.add_link(router)
+
+ # Add 'total_ebgp_peers' number of eBGP ExaBGP neighbors
+ for peerNum in range(1, total_ebgp_peers + 1):
+ swNum = (peerNum - 1) // 5 + 1
+
+ peer_ip = "10.0.{}.{}".format(swNum, peerNum + 100)
+ peer_route = "via 10.0.{}.1".format(swNum)
+ peer = tgen.add_exabgp_peer(
+ "peer{}".format(peerNum), ip=peer_ip, defaultRoute=peer_route
+ )
+
+ switch = tgen.gears["s{}".format(swNum)]
+ switch.add_link(peer)
+
+
+#####################################################
+#
+# Tests starting
+#
+#####################################################
+
+
+def setup_module(module):
+ tgen = Topogen(build_topo, module.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ 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))
+ )
+ router.start()
+
+ # Starting Hosts and init ExaBGP on each of them
+ topotest.sleep(10, "starting BGP on all {} peers".format(total_ebgp_peers))
+ peer_list = tgen.exabgp_peers()
+ for pname, peer in peer_list.items():
+ peer_dir = os.path.join(CWD, pname)
+ env_file = os.path.join(CWD, "exabgp.env")
+ peer.start(peer_dir, env_file)
+ logger.info(pname)
+
+
+def teardown_module(module):
+ del module
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_convergence():
+ "Test for BGP topology convergence"
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Expected result
+ router = tgen.gears["r1"]
+ if router.has_version("<", "3.0"):
+ reffile = os.path.join(CWD, "r1/summary20.txt")
+ else:
+ reffile = os.path.join(CWD, "r1/summary.txt")
+
+ expected = json.loads(open(reffile).read())
+
+ def _output_summary_cmp(router, cmd, data):
+ """
+ Runs `cmd` that returns JSON data (normally the command ends
+ with 'json') and compare with `data` contents.
+ """
+ output = router.vtysh_cmd(cmd, isjson=True)
+ return topotest.json_cmp(output, data)
+
+ test_func = functools.partial(
+ _output_summary_cmp, router, "show ip bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assertmsg = "BGP router network did not converge"
+ assert res is None, assertmsg
+
+
+def test_bgp_ecmp():
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ expect = {
+ "routerId": "10.0.255.1",
+ "routes": {},
+ }
+
+ for net in range(1, 5):
+ for subnet in range(0, 10):
+ netkey = "10.20{}.{}.0/24".format(net, subnet)
+ expect["routes"][netkey] = []
+ for _ in range(0, 10):
+ peer = {"multipath": True, "valid": True}
+ expect["routes"][netkey].append(peer)
+
+ test_func = functools.partial(
+ topotest.router_json_cmp, tgen.gears["r1"], "show ip bgp json", expect
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assertmsg = 'expected multipath routes in "show ip bgp" output'
+ assert res is None, assertmsg
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))