]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgp-ecmp-topo1: Add BGP Topology for rcmp testing
authorMartin Winter <mwinter@opensourcerouting.org>
Fri, 7 Jul 2017 09:49:55 +0000 (02:49 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 28 Nov 2018 01:22:12 +0000 (20:22 -0500)
Signed-off-by: Martin Winter <mwinter@opensourcerouting.org>
67 files changed:
tests/topotests/bgp-ecmp-topo1/__init__.py [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/bgp-ecmp-topo1.dot [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/bgp-ecmp-topo1.pdf [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/exabgp.env [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer1/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer1/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer1/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer10/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer10/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer10/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer11/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer11/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer11/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer12/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer12/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer12/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer13/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer13/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer13/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer14/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer14/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer14/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer15/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer15/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer15/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer16/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer16/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer16/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer17/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer17/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer17/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer18/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer18/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer18/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer19/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer19/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer19/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer2/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer2/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer2/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer20/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer20/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer20/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer3/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer3/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer3/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer4/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer4/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer4/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer5/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer5/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer5/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer6/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer6/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer6/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer7/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer7/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer7/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer8/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer8/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer8/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/peer9/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer9/exa-send.py [new file with mode: 0755]
tests/topotests/bgp-ecmp-topo1/peer9/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp-ecmp-topo1/test_bgp_ecmp_topo1.py [new file with mode: 0755]

diff --git a/tests/topotests/bgp-ecmp-topo1/__init__.py b/tests/topotests/bgp-ecmp-topo1/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
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 (file)
index 0000000..90295e1
--- /dev/null
@@ -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 (file)
index 0000000..b4d4f6a
Binary files /dev/null and b/tests/topotests/bgp-ecmp-topo1/bgp-ecmp-topo1.pdf differ
diff --git a/tests/topotests/bgp-ecmp-topo1/exabgp.env b/tests/topotests/bgp-ecmp-topo1/exabgp.env
new file mode 100644 (file)
index 0000000..a328e04
--- /dev/null
@@ -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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer1/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..85314a8
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 1 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer10/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..e052918
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 10 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer11/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..e4a14ea
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 11 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer12/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..2fbef70
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 12 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer13/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..0d6e746
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 13 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer14/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..5ad7740
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 14 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer15/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..fb7ecc4
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 15 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer16/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..ab8edbe
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 16 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer17/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..4955543
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 17 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer18/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..f44ff1b
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 18 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer19/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..16d2cfc
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 19 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer2/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..b9b5ee6
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 2 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer20/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..e8e49db
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 20 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer3/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..26f2589
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 3 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer4/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..b3aeb12
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 4 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer5/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..3de72cf
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 5 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer6/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..1b07fb7
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 6 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer7/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..6d0e82a
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 7 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer8/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..934e1c8
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 8 10";
+    }
+
+    process receive-routes {
+        run "./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-receive.py b/tests/topotests/bgp-ecmp-topo1/peer9/exa-receive.py
new file mode 100755 (executable)
index 0000000..5334ea5
--- /dev/null
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+"""
+exa-receive.py: Save received routes form ExaBGP into file
+"""
+
+from sys import stdin,argv
+from datetime import datetime
+
+# 1st arg is peer number
+peer = int(argv[1])
+
+# When the parent dies we are seeing continual newlines, so we only access so many before stopping
+counter = 0
+
+routesavefile = open('/tmp/peer%s-received.log' % peer, 'w')
+
+while True:
+    try:
+        line = stdin.readline()
+        timestamp = datetime.now().strftime('%Y%m%d_%H:%M:%S - ')
+        routesavefile.write(timestamp + line)
+        routesavefile.flush()
+
+        if line == "":
+            counter += 1
+            if counter > 100:
+                break
+            continue
+
+        counter = 0
+    except KeyboardInterrupt:
+        pass
+    except IOError:
+        # most likely a signal during readline
+        pass
+
+routesavefile.close()
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 (executable)
index 0000000..647c254
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+"""
+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 (file)
index 0000000..245bd29
--- /dev/null
@@ -0,0 +1,21 @@
+group controller {
+
+    process announce-routes {
+        run "./exa-send.py 9 10";
+    }
+
+    process receive-routes {
+        run "./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 (file)
index 0000000..1488fe9
--- /dev/null
@@ -0,0 +1,30 @@
+!
+hostname r1
+log file /tmp/r1-bgpd.log
+!
+router bgp 100
+ bgp router-id 10.0.255.1
+ bgp bestpath as-path multipath-relax
+ neighbor 10.0.1.101 remote-as 99
+ neighbor 10.0.1.102 remote-as 99
+ neighbor 10.0.1.103 remote-as 99
+ neighbor 10.0.1.104 remote-as 99
+ neighbor 10.0.1.105 remote-as 99
+ neighbor 10.0.2.106 remote-as 99
+ neighbor 10.0.2.107 remote-as 99
+ neighbor 10.0.2.108 remote-as 99
+ neighbor 10.0.2.109 remote-as 99
+ neighbor 10.0.2.110 remote-as 99
+ neighbor 10.0.3.111 remote-as 111
+ neighbor 10.0.3.112 remote-as 112
+ neighbor 10.0.3.113 remote-as 113
+ neighbor 10.0.3.114 remote-as 114
+ neighbor 10.0.3.115 remote-as 115
+ neighbor 10.0.4.116 remote-as 116
+ neighbor 10.0.4.117 remote-as 117
+ neighbor 10.0.4.118 remote-as 118
+ neighbor 10.0.4.119 remote-as 119
+ neighbor 10.0.4.120 remote-as 120
+ !
+!
+
diff --git a/tests/topotests/bgp-ecmp-topo1/r1/zebra.conf b/tests/topotests/bgp-ecmp-topo1/r1/zebra.conf
new file mode 100644 (file)
index 0000000..3022913
--- /dev/null
@@ -0,0 +1,16 @@
+!
+hostname r1
+log file /tmp/r1-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 100755 (executable)
index 0000000..cd64452
--- /dev/null
@@ -0,0 +1,175 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_ecmp_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2017 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# 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_ecmp_topo1.py: Test BGP topology with ECMP (Equal Cost MultiPath).
+"""
+
+import os
+import re
+import sys
+import pytest
+from time import sleep
+
+from mininet.topo import Topo
+from mininet.net import Mininet
+from mininet.node import Node, OVSSwitch, Host
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.link import Intf
+
+from functools import partial
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+from lib import topotest
+
+fatal_error = ""
+
+total_ebgp_peers = 20
+
+#####################################################
+##
+##   Network Topology Definition
+##
+#####################################################
+
+class NetworkTopo(Topo):
+    "BGP ECMP Topology 1"
+
+    def build(self, **_opts):
+
+        exabgpPrivateDirs = ['/etc/exabgp',
+                             '/var/run/exabgp',
+                             '/var/log']
+
+        # Setup Router
+        router = {}
+        router[1] = topotest.addRouter(self, 'r1')
+
+        # Setup Switches - 1 switch per 5 peering routers
+        switch = {}
+        for swNum in range(1, (total_ebgp_peers+4)/5 +1):
+            print("Create switch s%d", swNum)
+            switch[swNum] = self.addSwitch('s%d' % (swNum), cls=topotest.LegacySwitch)
+            self.addLink(switch[swNum], router[1], intfName2='r1-eth%d' % (swNum-1))
+
+        # Add 'total_ebgp_peers' number of eBGP ExaBGP neighbors
+        peer = {}
+        for peerNum in range(1, total_ebgp_peers+1):
+            swNum = ((peerNum -1) / 5 + 1)
+
+            peer[peerNum] = self.addHost('peer%s' % peerNum, ip='10.0.%s.%s/24' % (swNum, (peerNum+100)),
+                                    defaultRoute='via 10.0.%s.1' % swNum,
+                                    privateDirs=exabgpPrivateDirs)
+            self.addLink(switch[swNum], peer[peerNum], intfName2='peer%s-eth0' % peerNum)
+
+
+#####################################################
+##
+##   Tests starting
+##
+#####################################################
+
+def setup_module(module):
+    global topo, net
+
+    print("\n\n** %s: Setup Topology" % module.__name__)
+    print("******************************************\n")
+
+    print("Cleanup old Mininet runs")
+    os.system('sudo mn -c > /dev/null 2>&1')
+
+    thisDir = os.path.dirname(os.path.realpath(__file__))
+    topo = NetworkTopo()
+
+    net = Mininet(controller=None, topo=topo)
+    net.start()
+
+    # Starting Routers
+    for i in range(1, 2):
+        net['r%s' % i].loadConf('zebra', '%s/r%s/zebra.conf' % (thisDir, i))
+        net['r%s' % i].loadConf('bgpd', '%s/r%s/bgpd.conf' % (thisDir, i))
+        net['r%s' % i].startRouter()
+
+    # Starting Hosts and init ExaBGP on each of them
+    print('*** Starting BGP on all %d Peers in 10s' % total_ebgp_peers)
+    sleep(10)
+    for i in range(1, total_ebgp_peers+1):
+        net['peer%s' % i].cmd('cp %s/exabgp.env /etc/exabgp/exabgp.env' % thisDir)
+        net['peer%s' % i].cmd('cp %s/peer%s/* /etc/exabgp/' % (thisDir, i))
+        net['peer%s' % i].cmd('chmod 644 /etc/exabgp/*')
+        net['peer%s' % i].cmd('chmod 755 /etc/exabgp/*.py')
+        net['peer%s' % i].cmd('chown -R exabgp:exabgp /etc/exabgp')
+        net['peer%s' % i].cmd('exabgp -e /etc/exabgp/exabgp.env /etc/exabgp/exabgp.cfg')
+        print('peer%s' % i),
+    print('')
+
+    # For debugging after starting Quagga/FRR daemons, uncomment the next line
+    CLI(net)
+
+
+def teardown_module(module):
+    global net
+
+    print("\n\n** %s: Shutdown Topology" % module.__name__)
+    print("******************************************\n")
+
+    # Shutdown - clean up everything
+    print('*** Killing BGP on Peer routers')
+    # Killing ExaBGP
+    for i in range(1, total_ebgp_peers+1):
+        net['peer%s' % i].cmd('kill `cat /var/run/exabgp/exabgp.pid`')
+
+    # End - Shutdown network
+    net.stop()
+
+
+def test_router_running():
+    global fatal_error
+    global net
+
+    # Skip if previous fatal error condition is raised
+    if (fatal_error != ""):
+        pytest.skip(fatal_error)
+
+    print("\n\n** Check if FRR/Quagga is running on each Router node")
+    print("******************************************\n")
+    sleep(5)
+
+    # Starting Routers
+    for i in range(1, 2):
+        fatal_error = net['r%s' % i].checkRouterRunning()
+        assert fatal_error == "", fatal_error
+
+    # For debugging after starting FRR/Quagga daemons, uncomment the next line
+    # CLI(net)
+
+
+if __name__ == '__main__':
+
+    setLogLevel('info')
+    # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
+    # retval = pytest.main(["-s", "--tb=no"])
+    retval = pytest.main(["-s"])
+    sys.exit(retval)