]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgp_multiview_topo1: Add "bgp multiview" simple topology to test. Initial commit
authorMartin Winter <mwinter@netdef.org>
Thu, 24 Nov 2016 11:58:47 +0000 (03:58 -0800)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 28 Nov 2018 01:22:10 +0000 (20:22 -0500)
31 files changed:
tests/topotests/bgp_multiview_topo1/exabgp.env [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/peer1/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer1/exa-send.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer1/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/peer2/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer2/exa-send.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer2/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/peer3/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer3/exa-send.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer3/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/peer4/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer4/exa-send.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer4/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/peer5/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer5/exa-send.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer5/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/peer6/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer6/exa-send.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer6/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/peer7/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer7/exa-send.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer7/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/peer8/exa-receive.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer8/exa-send.py [new file with mode: 0755]
tests/topotests/bgp_multiview_topo1/peer8/exabgp.cfg [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1.ref [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2.ref [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3.ref [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py [new file with mode: 0755]

diff --git a/tests/topotests/bgp_multiview_topo1/exabgp.env b/tests/topotests/bgp_multiview_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_multiview_topo1/peer1/exa-receive.py b/tests/topotests/bgp_multiview_topo1/peer1/exa-receive.py
new file mode 100755 (executable)
index 0000000..8e65f1a
--- /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' % 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_multiview_topo1/peer1/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer1/exa-send.py
new file mode 100755 (executable)
index 0000000..2de2bce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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])
+
+# Announce numRoutes different routes per PE
+for i in range(0, numRoutes):
+    stdout.write('announce route 10.%s.%s.0/24 med 100 community %i:1 next-hop 172.16.1.%i\n' % ((peer+100), i, peer, peer))
+    stdout.flush()
+
+# Announce 1 overlapping route per peer
+stdout.write('announce route 10.0.1.0/24 next-hop 172.16.1.%i\n' % peer)
+stdout.flush()
+
+#Loop endlessly to allow ExaBGP to continue running
+while True:
+    sleep(1)
diff --git a/tests/topotests/bgp_multiview_topo1/peer1/exabgp.cfg b/tests/topotests/bgp_multiview_topo1/peer1/exabgp.cfg
new file mode 100644 (file)
index 0000000..8991610
--- /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 172.16.1.254 {
+        router-id 172.16.1.1;
+        local-address 172.16.1.1;
+        local-as 65001;
+        peer-as 100;
+        graceful-restart;
+    }
+
+}
diff --git a/tests/topotests/bgp_multiview_topo1/peer2/exa-receive.py b/tests/topotests/bgp_multiview_topo1/peer2/exa-receive.py
new file mode 100755 (executable)
index 0000000..8e65f1a
--- /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' % 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_multiview_topo1/peer2/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer2/exa-send.py
new file mode 100755 (executable)
index 0000000..2de2bce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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])
+
+# Announce numRoutes different routes per PE
+for i in range(0, numRoutes):
+    stdout.write('announce route 10.%s.%s.0/24 med 100 community %i:1 next-hop 172.16.1.%i\n' % ((peer+100), i, peer, peer))
+    stdout.flush()
+
+# Announce 1 overlapping route per peer
+stdout.write('announce route 10.0.1.0/24 next-hop 172.16.1.%i\n' % peer)
+stdout.flush()
+
+#Loop endlessly to allow ExaBGP to continue running
+while True:
+    sleep(1)
diff --git a/tests/topotests/bgp_multiview_topo1/peer2/exabgp.cfg b/tests/topotests/bgp_multiview_topo1/peer2/exabgp.cfg
new file mode 100644 (file)
index 0000000..efddec5
--- /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 172.16.1.254 {
+        router-id 172.16.1.2;
+        local-address 172.16.1.2;
+        local-as 65002;
+        peer-as 100;
+        graceful-restart;
+    }
+
+}
diff --git a/tests/topotests/bgp_multiview_topo1/peer3/exa-receive.py b/tests/topotests/bgp_multiview_topo1/peer3/exa-receive.py
new file mode 100755 (executable)
index 0000000..8e65f1a
--- /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' % 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_multiview_topo1/peer3/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer3/exa-send.py
new file mode 100755 (executable)
index 0000000..2de2bce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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])
+
+# Announce numRoutes different routes per PE
+for i in range(0, numRoutes):
+    stdout.write('announce route 10.%s.%s.0/24 med 100 community %i:1 next-hop 172.16.1.%i\n' % ((peer+100), i, peer, peer))
+    stdout.flush()
+
+# Announce 1 overlapping route per peer
+stdout.write('announce route 10.0.1.0/24 next-hop 172.16.1.%i\n' % peer)
+stdout.flush()
+
+#Loop endlessly to allow ExaBGP to continue running
+while True:
+    sleep(1)
diff --git a/tests/topotests/bgp_multiview_topo1/peer3/exabgp.cfg b/tests/topotests/bgp_multiview_topo1/peer3/exabgp.cfg
new file mode 100644 (file)
index 0000000..abffe32
--- /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 172.16.1.254 {
+        router-id 172.16.1.3;
+        local-address 172.16.1.3;
+        local-as 65003;
+        peer-as 100;
+        graceful-restart;
+    }
+
+}
diff --git a/tests/topotests/bgp_multiview_topo1/peer4/exa-receive.py b/tests/topotests/bgp_multiview_topo1/peer4/exa-receive.py
new file mode 100755 (executable)
index 0000000..8e65f1a
--- /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' % 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_multiview_topo1/peer4/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer4/exa-send.py
new file mode 100755 (executable)
index 0000000..2de2bce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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])
+
+# Announce numRoutes different routes per PE
+for i in range(0, numRoutes):
+    stdout.write('announce route 10.%s.%s.0/24 med 100 community %i:1 next-hop 172.16.1.%i\n' % ((peer+100), i, peer, peer))
+    stdout.flush()
+
+# Announce 1 overlapping route per peer
+stdout.write('announce route 10.0.1.0/24 next-hop 172.16.1.%i\n' % peer)
+stdout.flush()
+
+#Loop endlessly to allow ExaBGP to continue running
+while True:
+    sleep(1)
diff --git a/tests/topotests/bgp_multiview_topo1/peer4/exabgp.cfg b/tests/topotests/bgp_multiview_topo1/peer4/exabgp.cfg
new file mode 100644 (file)
index 0000000..27dfef9
--- /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 172.16.1.254 {
+        router-id 172.16.1.4;
+        local-address 172.16.1.4;
+        local-as 65004;
+        peer-as 100;
+        graceful-restart;
+    }
+
+}
diff --git a/tests/topotests/bgp_multiview_topo1/peer5/exa-receive.py b/tests/topotests/bgp_multiview_topo1/peer5/exa-receive.py
new file mode 100755 (executable)
index 0000000..8e65f1a
--- /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' % 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_multiview_topo1/peer5/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer5/exa-send.py
new file mode 100755 (executable)
index 0000000..2de2bce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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])
+
+# Announce numRoutes different routes per PE
+for i in range(0, numRoutes):
+    stdout.write('announce route 10.%s.%s.0/24 med 100 community %i:1 next-hop 172.16.1.%i\n' % ((peer+100), i, peer, peer))
+    stdout.flush()
+
+# Announce 1 overlapping route per peer
+stdout.write('announce route 10.0.1.0/24 next-hop 172.16.1.%i\n' % peer)
+stdout.flush()
+
+#Loop endlessly to allow ExaBGP to continue running
+while True:
+    sleep(1)
diff --git a/tests/topotests/bgp_multiview_topo1/peer5/exabgp.cfg b/tests/topotests/bgp_multiview_topo1/peer5/exabgp.cfg
new file mode 100644 (file)
index 0000000..9326aed
--- /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 172.16.1.254 {
+        router-id 172.16.1.5;
+        local-address 172.16.1.5;
+        local-as 65005;
+        peer-as 100;
+        graceful-restart;
+    }
+
+}
diff --git a/tests/topotests/bgp_multiview_topo1/peer6/exa-receive.py b/tests/topotests/bgp_multiview_topo1/peer6/exa-receive.py
new file mode 100755 (executable)
index 0000000..8e65f1a
--- /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' % 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_multiview_topo1/peer6/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer6/exa-send.py
new file mode 100755 (executable)
index 0000000..2de2bce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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])
+
+# Announce numRoutes different routes per PE
+for i in range(0, numRoutes):
+    stdout.write('announce route 10.%s.%s.0/24 med 100 community %i:1 next-hop 172.16.1.%i\n' % ((peer+100), i, peer, peer))
+    stdout.flush()
+
+# Announce 1 overlapping route per peer
+stdout.write('announce route 10.0.1.0/24 next-hop 172.16.1.%i\n' % peer)
+stdout.flush()
+
+#Loop endlessly to allow ExaBGP to continue running
+while True:
+    sleep(1)
diff --git a/tests/topotests/bgp_multiview_topo1/peer6/exabgp.cfg b/tests/topotests/bgp_multiview_topo1/peer6/exabgp.cfg
new file mode 100644 (file)
index 0000000..f99976b
--- /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 172.16.1.254 {
+        router-id 172.16.1.6;
+        local-address 172.16.1.6;
+        local-as 65006;
+        peer-as 100;
+        graceful-restart;
+    }
+
+}
diff --git a/tests/topotests/bgp_multiview_topo1/peer7/exa-receive.py b/tests/topotests/bgp_multiview_topo1/peer7/exa-receive.py
new file mode 100755 (executable)
index 0000000..8e65f1a
--- /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' % 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_multiview_topo1/peer7/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer7/exa-send.py
new file mode 100755 (executable)
index 0000000..2de2bce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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])
+
+# Announce numRoutes different routes per PE
+for i in range(0, numRoutes):
+    stdout.write('announce route 10.%s.%s.0/24 med 100 community %i:1 next-hop 172.16.1.%i\n' % ((peer+100), i, peer, peer))
+    stdout.flush()
+
+# Announce 1 overlapping route per peer
+stdout.write('announce route 10.0.1.0/24 next-hop 172.16.1.%i\n' % peer)
+stdout.flush()
+
+#Loop endlessly to allow ExaBGP to continue running
+while True:
+    sleep(1)
diff --git a/tests/topotests/bgp_multiview_topo1/peer7/exabgp.cfg b/tests/topotests/bgp_multiview_topo1/peer7/exabgp.cfg
new file mode 100644 (file)
index 0000000..2dea4c9
--- /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 172.16.1.254 {
+        router-id 172.16.1.7;
+        local-address 172.16.1.7;
+        local-as 65007;
+        peer-as 100;
+        graceful-restart;
+    }
+
+}
diff --git a/tests/topotests/bgp_multiview_topo1/peer8/exa-receive.py b/tests/topotests/bgp_multiview_topo1/peer8/exa-receive.py
new file mode 100755 (executable)
index 0000000..8e65f1a
--- /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' % 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_multiview_topo1/peer8/exa-send.py b/tests/topotests/bgp_multiview_topo1/peer8/exa-send.py
new file mode 100755 (executable)
index 0000000..2de2bce
--- /dev/null
@@ -0,0 +1,28 @@
+#!/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])
+
+# Announce numRoutes different routes per PE
+for i in range(0, numRoutes):
+    stdout.write('announce route 10.%s.%s.0/24 med 100 community %i:1 next-hop 172.16.1.%i\n' % ((peer+100), i, peer, peer))
+    stdout.flush()
+
+# Announce 1 overlapping route per peer
+stdout.write('announce route 10.0.1.0/24 next-hop 172.16.1.%i\n' % peer)
+stdout.flush()
+
+#Loop endlessly to allow ExaBGP to continue running
+while True:
+    sleep(1)
diff --git a/tests/topotests/bgp_multiview_topo1/peer8/exabgp.cfg b/tests/topotests/bgp_multiview_topo1/peer8/exabgp.cfg
new file mode 100644 (file)
index 0000000..ae3c5eb
--- /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 172.16.1.254 {
+        router-id 172.16.1.8;
+        local-address 172.16.1.8;
+        local-as 65008;
+        peer-as 100;
+        graceful-restart;
+    }
+
+}
diff --git a/tests/topotests/bgp_multiview_topo1/r1/bgpd.conf b/tests/topotests/bgp_multiview_topo1/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..7cfcb6c
--- /dev/null
@@ -0,0 +1,49 @@
+!
+! Zebra configuration saved from vty
+!   2015/12/24 21:46:33
+!
+log file /tmp/r1-bgpd.log
+!
+!debug bgp events
+!debug bgp keepalives
+!debug bgp updates
+!debug bgp fsm
+!debug bgp filters
+!debug bgp zebra
+!
+bgp multiple-instance
+!
+router bgp 100 view 1
+ bgp router-id 172.30.1.1
+ network 172.20.0.0/28 route-map local1
+ timers bgp 60 180
+ neighbor 172.16.1.1 remote-as 65001
+ neighbor 172.16.1.2 remote-as 65002
+ neighbor 172.16.1.5 remote-as 65005
+!
+router bgp 100 view 2
+ bgp router-id 172.30.1.1
+ network 172.20.0.0/28 route-map local2
+ timers bgp 60 180
+ neighbor 172.16.1.3 remote-as 65003
+ neighbor 172.16.1.4 remote-as 65004
+!
+router bgp 100 view 3
+ bgp router-id 172.30.1.1
+ network 172.20.0.0/28
+ timers bgp 60 180
+ neighbor 172.16.1.6 remote-as 65006
+ neighbor 172.16.1.7 remote-as 65007
+ neighbor 172.16.1.8 remote-as 65008
+!
+route-map local1 permit 10
+ set community 100:9999 additive
+ set metric 0
+!
+route-map local2 permit 10
+ set as-path prepend 100 100 100 100 100
+ set community 100:1 additive
+ set metric 9999
+!
+line vty
+!
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1.ref
new file mode 100644 (file)
index 0000000..0e8bf84
--- /dev/null
@@ -0,0 +1,40 @@
+BGP table version is 0, local router ID is 172.30.1.1
+Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+              i internal, r RIB-failure, S Stale, R Removed
+Origin codes: i - IGP, e - EGP, ? - incomplete
+
+   Network          Next Hop            Metric LocPrf Weight Path
+*  10.0.1.0/24      172.16.1.5                             0 65005 i
+*                   172.16.1.2                             0 65002 i
+*>                  172.16.1.1                             0 65001 i
+*> 10.101.0.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.1.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.2.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.3.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.4.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.5.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.6.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.7.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.8.0/24    172.16.1.1             100              0 65001 i
+*> 10.101.9.0/24    172.16.1.1             100              0 65001 i
+*> 10.102.0.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.1.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.2.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.3.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.4.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.5.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.6.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.7.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.8.0/24    172.16.1.2             100              0 65002 i
+*> 10.102.9.0/24    172.16.1.2             100              0 65002 i
+*> 10.105.0.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.1.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.2.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.3.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.4.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.5.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.6.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.7.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.8.0/24    172.16.1.5             100              0 65005 i
+*> 10.105.9.0/24    172.16.1.5             100              0 65005 i
+*> 172.20.0.0/28    0.0.0.0                  0          32768 i
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2.ref
new file mode 100644 (file)
index 0000000..cfdbaeb
--- /dev/null
@@ -0,0 +1,29 @@
+BGP table version is 0, local router ID is 172.30.1.1
+Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+              i internal, r RIB-failure, S Stale, R Removed
+Origin codes: i - IGP, e - EGP, ? - incomplete
+
+   Network          Next Hop            Metric LocPrf Weight Path
+*  10.0.1.0/24      172.16.1.4                             0 65004 i
+*>                  172.16.1.3                             0 65003 i
+*> 10.103.0.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.1.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.2.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.3.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.4.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.5.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.6.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.7.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.8.0/24    172.16.1.3             100              0 65003 i
+*> 10.103.9.0/24    172.16.1.3             100              0 65003 i
+*> 10.104.0.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.1.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.2.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.3.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.4.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.5.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.6.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.7.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.8.0/24    172.16.1.4             100              0 65004 i
+*> 10.104.9.0/24    172.16.1.4             100              0 65004 i
+*> 172.20.0.0/28    0.0.0.0               9999          32768 100 100 100 100 100 i
diff --git a/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3.ref b/tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3.ref
new file mode 100644 (file)
index 0000000..f0f471d
--- /dev/null
@@ -0,0 +1,40 @@
+BGP table version is 0, local router ID is 172.30.1.1
+Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+              i internal, r RIB-failure, S Stale, R Removed
+Origin codes: i - IGP, e - EGP, ? - incomplete
+
+   Network          Next Hop            Metric LocPrf Weight Path
+*  10.0.1.0/24      172.16.1.8                             0 65008 i
+*                   172.16.1.7                             0 65007 i
+*>                  172.16.1.6                             0 65006 i
+*> 10.106.0.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.1.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.2.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.3.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.4.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.5.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.6.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.7.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.8.0/24    172.16.1.6             100              0 65006 i
+*> 10.106.9.0/24    172.16.1.6             100              0 65006 i
+*> 10.107.0.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.1.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.2.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.3.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.4.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.5.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.6.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.7.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.8.0/24    172.16.1.7             100              0 65007 i
+*> 10.107.9.0/24    172.16.1.7             100              0 65007 i
+*> 10.108.0.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.1.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.2.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.3.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.4.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.5.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.6.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.7.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.8.0/24    172.16.1.8             100              0 65008 i
+*> 10.108.9.0/24    172.16.1.8             100              0 65008 i
+*> 172.20.0.0/28    0.0.0.0                  0          32768 i
diff --git a/tests/topotests/bgp_multiview_topo1/r1/zebra.conf b/tests/topotests/bgp_multiview_topo1/r1/zebra.conf
new file mode 100644 (file)
index 0000000..6aebf56
--- /dev/null
@@ -0,0 +1,23 @@
+!
+! Zebra configuration saved from vty
+!   2015/12/24 16:48:27
+!
+log file /tmp/r1-zebra.log
+!
+hostname r1
+!
+interface r1-stub
+ description Stub Network
+ ip address 172.20.0.1/28
+ no link-detect
+!
+interface r1-eth0
+ description to PE router - vlan1
+ ip address 172.16.1.254/24
+ no link-detect
+!
+ip forwarding
+!
+!
+line vty
+!
diff --git a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py
new file mode 100755 (executable)
index 0000000..3af993d
--- /dev/null
@@ -0,0 +1,366 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_multiview_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2016 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_multiview_topo1.py: Simple Quagga Route-Server Test
+
+See Topology Diagram bgp-routeserver-1.pdf
+"""
+
+import os
+import re
+import sys
+import difflib
+import StringIO
+
+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
+from time import sleep
+
+import pytest
+
+def int2dpid(dpid):
+    "Converting Integer to DPID"
+
+    try:
+        dpid = hex(dpid)[2:]
+        dpid = '0'*(16-len(dpid))+dpid
+        return dpid
+    except IndexError:
+        raise Exception('Unable to derive default datapath ID - '
+                        'please either specify a dpid or use a '
+                        'canonical switch name such as s23.')
+
+class LinuxRouter(Node):
+    "A Node with IPv4/IPv6 forwarding enabled."
+
+    def config(self, **params):
+        super(LinuxRouter, self).config(**params)
+        # Enable forwarding on the router
+        self.cmd('sysctl net.ipv4.ip_forward=1')
+        self.cmd('sysctl net.ipv6.conf.all.forwarding=1')
+    def terminate(self):
+        """
+        Terminate generic LinuxRouter Mininet instance
+        """
+        self.cmd('sysctl net.ipv4.ip_forward=0')
+        self.cmd('sysctl net.ipv6.conf.all.forwarding=0')
+        super(LinuxRouter, self).terminate()
+
+class QuaggaRouter(Node):
+    "A Node with IPv4/IPv6 forwarding enabled and Quagga as Routing Engine"
+
+    def config(self, **params):
+        super(QuaggaRouter, self).config(**params)
+        # Enable forwarding on the router
+        self.cmd('sysctl net.ipv4.ip_forward=1')
+        self.cmd('sysctl net.ipv6.conf.all.forwarding=1')
+        self.cmd('chown quagga:quaggavty /etc/quagga')
+        self.daemons = {'zebra': 0, 'ripd': 0, 'ripngd': 0, 'ospfd': 0,
+                        'ospf6d': 0, 'isisd': 0, 'bgpd': 0, 'pimd': 0}
+    def terminate(self):
+        # Delete Running Quagga Daemons
+        rundaemons = self.cmd('ls -1 /var/run/quagga/*.pid')
+        for d in StringIO.StringIO(rundaemons):
+            self.cmd('kill -7 `cat %s`' % d.rstrip())
+            self.waitOutput()
+        # Disable forwarding
+        self.cmd('sysctl net.ipv4.ip_forward=0')
+        self.cmd('sysctl net.ipv6.conf.all.forwarding=0')
+        super(QuaggaRouter, self).terminate()
+    def removeIPs(self):
+        for interface in self.intfNames():
+            self.cmd('ip address flush', interface)
+    def loadConf(self, daemon, source=None):
+        # print "Daemons before:", self.daemons
+        if daemon in self.daemons.keys():
+            self.daemons[daemon] = 1
+            if source is None:
+                self.cmd('touch /etc/quagga/%s.conf' % daemon)
+                self.waitOutput()
+            else:
+                self.cmd('cp %s /etc/quagga/%s.conf' % (source, daemon))
+                self.waitOutput()
+            self.cmd('chmod 640 /etc/quagga/%s.conf' % daemon)
+            self.waitOutput()
+            self.cmd('chown quagga:quagga /etc/quagga/%s.conf' % daemon)
+            self.waitOutput()
+        else:
+            print("No daemon %s known" % daemon)
+        # print "Daemons after:", self.daemons
+    def startQuagga(self):
+        # Disable integrated-vtysh-config
+        self.cmd('echo "no service integrated-vtysh-config" > /etc/quagga/vtysh.conf')
+        with open("/etc/quagga/vtysh.conf", "w") as vtyshfile:
+            vtyshfile.write('no service integrated-vtysh-config')
+        self.cmd('chown quagga:quaggavty /etc/quagga/vtysh.conf')
+        # Remove IP addresses from OS first - we have them in zebra.conf
+        self.removeIPs()
+        # Start Zebra first
+        if self.daemons['zebra'] == 1:
+            self.cmd('/usr/lib/quagga/zebra -d')
+            self.waitOutput()
+            print('%s: zebra started' % self)
+            sleep(1)
+        # Fix Link-Local Addresses
+        # Somehow (on Mininet only), Zebra removes the IPv6 Link-Local addresses on start. Fix this
+        self.cmd('for i in `ls /sys/class/net/` ; do mac=`cat /sys/class/net/$i/address`; IFS=\':\'; set $mac; unset IFS; ip address add dev $i scope link fe80::$(printf %02x $((0x$1 ^ 2)))$2:${3}ff:fe$4:$5$6/64; done')
+        # Now start all the other daemons
+        for daemon in self.daemons:
+            if (self.daemons[daemon] == 1) and (daemon != 'zebra'):
+                self.cmd('/usr/lib/quagga/%s -d' % daemon)
+                self.waitOutput()
+                print('%s: %s started' % (self, daemon))
+    def checkQuaggaRunning(self):
+        daemonsRunning = self.cmd('vtysh -c "show log" | grep "Logging configuration for"')
+        for daemon in self.daemons:
+            if (self.daemons[daemon] == 1):
+                assert daemon in daemonsRunning, "Daemon %s not running" % daemon
+
+
+class LegacySwitch(OVSSwitch):
+    "A Legacy Switch without OpenFlow"
+
+    def __init__(self, name, **params):
+        OVSSwitch.__init__(self, name, failMode='standalone', **params)
+        self.switchIP = None
+
+
+#####################################################
+##
+##   Network Topology Definition
+##
+#####################################################
+
+class NetworkTopo(Topo):
+    "A LinuxRouter connecting three IP subnets"
+
+    def build(self, **_opts):
+
+        quaggaPrivateDirs = ['/etc/quagga',
+                             '/var/run/quagga',
+                             '/var/log',
+                             '/var/run/ssh']
+        exabgpPrivateDirs = ['/etc/exabgp',
+                             '/var/run/exabgp',
+                             '/var/log']
+        
+        # Setup Routers
+        quagga = {}
+        for i in range(1, 2):
+            quagga[i] = self.addNode('r%s' % i, cls=QuaggaRouter,
+                                     privateDirs=quaggaPrivateDirs)
+
+        # Setup Provider BGP peers
+        peer = {}
+        for i in range(1, 9):
+            peer[i] = self.addHost('peer%s' % i, ip='172.16.1.%s/24' % i,
+                                    defaultRoute='via 172.16.1.254',
+                                    privateDirs=exabgpPrivateDirs)
+
+        # Setup Switches
+        switch = {}
+        # First switch is for a dummy interface (for local network)
+        switch[0] = self.addSwitch('sw0', cls=LegacySwitch)
+        self.addLink(switch[0], quagga[1], intfName2='r1-stub')
+        # Second switch is for connection to all peering routers
+        switch[1] = self.addSwitch('sw1', cls=LegacySwitch)
+        self.addLink(switch[1], quagga[1], intfName2='r1-eth0')
+        for j in range(1, 9):
+            self.addLink(switch[1], peer[j], intfName2='peer%s-eth0' % j)
+
+
+#####################################################
+##
+##   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].startQuagga()
+
+    # Starting PE Hosts and init ExaBGP on each of them
+    print('*** Starting BGP on all 8 Peers in 10s')
+    sleep(10)
+    for i in range(1, 9):
+        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 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, 9):
+        net['peer%s' % i].cmd('kill `cat /var/run/exabgp/exabgp.pid`')
+
+    # End - Shutdown network
+    net.stop()
+
+def test_quagga_running():
+    global net
+
+    print("\n\n** Check if Quagga is running on each Router node")
+    print("******************************************\n")
+    sleep(5)
+
+    # Starting Routers
+    for i in range(1, 2):
+        net['r%s' % i].checkQuaggaRunning()
+
+def test_bgp_converge():
+    "Check for BGP converged on all peers and BGP views"
+
+    global net
+
+    # Wait for BGP to converge  (All Neighbors in either Full or TwoWay State)
+    print("\n\n** Verify for BGP to converge")
+    print("******************************************\n")
+    timeout = 60
+    while timeout > 0:
+        print("Timeout in %s: " % timeout),
+        sys.stdout.flush()
+        # Look for any node not yet converged
+        for i in range(1, 2):
+            for view in range(1, 4):
+                notConverged = net['r%s' % i].cmd('vtysh -c "show ip bgp view %s summary" 2> /dev/null | grep ^[0-9] | grep -v " 11$"' % view)
+                if notConverged:
+                    print('Waiting for r%s, view %s' % (i, view))
+                    sys.stdout.flush()
+                    break
+            if notConverged:
+                break
+        if notConverged:
+            sleep(5)
+            timeout -= 5
+        else:
+            print('Done')
+            break
+    else:
+        # Bail out with error if a router fails to converge
+        bgpStatus = net['r%s' % i].cmd('show ip bgp view %s summary"')
+
+        assert False, "BGP did not converge:\n%s" % bgpStatus
+
+    print("BGP converged.")
+
+    # if timeout < 60:
+    #     # Only wait if we actually went through a convergence
+    #     print("\nwaiting 15s for routes to populate")
+    #     sleep(15)
+
+    # For debugging after starting Quagga daemons, uncomment the next line
+    # CLI(net)
+
+def test_bgp_routingTable():
+    global net
+
+    thisDir = os.path.dirname(os.path.realpath(__file__))
+
+    # Verify OSPFv3 Routing Table
+    print("\n\n** Verifing BGP Routing Tables")
+    print("******************************************\n")
+    failures = 0
+    for i in range(1, 2):
+        for view in range(1, 4):
+            refTableFile = '%s/r%s/show_ip_bgp_view_%s.ref' % (thisDir, i, view)
+            if os.path.isfile(refTableFile):
+                # Read expected result from file
+                expected = open(refTableFile).read().rstrip()
+                # Fix newlines (make them all the same)
+                expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
+
+                # Actual output from router
+                actual = net['r%s' % i].cmd('vtysh -c "show ip bgp view %s" 2> /dev/null' % view).rstrip()
+    
+                # Fix inconsitent spaces between 0.99.24 and newer versions of Quagga...
+                actual = re.sub('0             0', '0              0', actual)
+                actual = re.sub(r'([0-9])         32768', r'\1          32768', actual)
+                # Remove summary line (changed recently)
+                actual = re.sub(r'Total number.*', '', actual)
+                actual = re.sub(r'Displayed.*', '', actual)
+                actual = actual.rstrip()
+
+                # Fix newlines (make them all the same)
+                actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
+
+            # Generate Diff
+            diff = ''.join(difflib.unified_diff(actual, expected))
+            # Empty string if it matches, otherwise diff contains unified diff
+
+            if diff:
+                sys.stderr.write('r%s failed Routing Table Check for view %s:\n%s\n' 
+                                 % (i, view, diff))
+                failures += 1
+            else:
+                print("r%s ok" % i)
+
+            assert failures == 0, "Routing Table verification failed for router r%s, view %s:\n%s" % (i, view, diff)
+
+    # For debugging after starting Quagga daemons, uncomment the next line
+    # CLI(net)
+
+
+if __name__ == '__main__':
+
+    setLogLevel('info')
+    retval = pytest.main(["-s"])
+    sys.exit(retval)