summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2019-09-30 14:49:40 +0200
committerDonald Sharp <sharpd@cumulusnetworks.com>2019-10-01 13:45:38 +0200
commitaa2a0498f348a0c5d19f6138ee91dd0bac295bc9 (patch)
treecdb9c64a99241cd0f3754e5f2424031caff95650 /tests
parentMerge pull request #5085 from qlyoung/strip-trailing-whitespace-2019 (diff)
downloadfrr-aa2a0498f348a0c5d19f6138ee91dd0bac295bc9.tar.xz
frr-aa2a0498f348a0c5d19f6138ee91dd0bac295bc9.zip
tests: Add a topology that shows broken ibgp behavior
In a leaf/spine topology with only IBGP connections, where the same network is being redistributed at multiple points in the network ( say a redistribute connected at both leaf and spines ) we end up in a state where zebra gets very confused. eva# show ip route Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP, F - PBR, f - OpenFabric, > - selected route, * - FIB route, q - queued route, r - rejected route C>* 192.168.1.0/24 is directly connected, tor1-eth0, 00:00:30 C>* 192.168.2.0/24 is directly connected, tor1-eth1, 00:00:30 B 192.168.3.0/24 [200/0] via 192.168.4.2 inactive, 00:00:25 via 192.168.6.2 inactive, 00:00:25 B>* 192.168.4.0/24 [200/0] via 192.168.2.3, tor1-eth1, 00:00:25 * via 192.168.6.2 inactive, 00:00:25 C>* 192.168.5.0/24 is directly connected, tor1-eth2, 00:00:30 B>* 192.168.6.0/24 [200/0] via 192.168.4.2 inactive, 00:00:25 * via 192.168.5.4, tor1-eth2, 00:00:25 Effectively we have ibgp routes recursing through ibgp routes and there is no metric to discern whom to listen to. This draft: https://tools.ietf.org/html/draft-ietf-idr-bgp-optimal-route-reflection-19 appears to address this issue. From looking at both cisco and arista deployments they are handling this issue by having the route reflector prefer the localy learned routes over from their clients. Add this topology, in a broken state, so that when we do fix this issue it is a simple matter of touching this topology up and re-adding it to the normal daily builds. I also wanted to add this topology since it is in a state of `doneness` and I wanted to move onto my normal day job without having to remember about this test. This topology is not configured to be run as part of the normal topotests. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine1/bgpd.conf8
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine1/show_ip_route.json_ref162
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine1/staticd.conf1
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine1/zebra.conf9
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine2/show_ip_route.json_ref162
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine2/staticd.conf1
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine2/zebra.conf9
-rwxr-xr-xtests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py245
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor1/bgpd.conf5
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor1/show_ip_route.json_ref169
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor1/staticd.conf1
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor1/zebra.conf12
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor2/bgpd.conf5
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor2/show_ip_route.json_ref169
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor2/staticd.conf1
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor2/zebra.conf13
-rw-r--r--tests/topotests/pytest.ini2
18 files changed, 981 insertions, 1 deletions
diff --git a/tests/topotests/bgp_rr_ibgp/spine1/bgpd.conf b/tests/topotests/bgp_rr_ibgp/spine1/bgpd.conf
new file mode 100644
index 000000000..29a119c29
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/spine1/bgpd.conf
@@ -0,0 +1,8 @@
+hostname spine1
+router bgp 99
+ neighbor 192.168.2.1 remote-as internal
+ neighbor 192.168.4.2 remote-as internal
+ address-family ipv4 uni
+ redistribute connected
+ neighbor 192.168.2.1 route-reflector-client
+ neighbor 192.168.4.2 route-reflector-client
diff --git a/tests/topotests/bgp_rr_ibgp/spine1/show_ip_route.json_ref b/tests/topotests/bgp_rr_ibgp/spine1/show_ip_route.json_ref
new file mode 100644
index 000000000..552e96ddb
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/spine1/show_ip_route.json_ref
@@ -0,0 +1,162 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"spine1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"spine1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.3.0\/24":[
+ {
+ "prefix":"192.168.3.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.4.2",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"spine1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.4.0\/24":[
+ {
+ "prefix":"192.168.4.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"spine1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.5.0\/24":[
+ {
+ "prefix":"192.168.5.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"spine1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.6.0\/24":[
+ {
+ "prefix":"192.168.6.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.4.2",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"spine1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_rr_ibgp/spine1/staticd.conf b/tests/topotests/bgp_rr_ibgp/spine1/staticd.conf
new file mode 100644
index 000000000..6d8f0952d
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/spine1/staticd.conf
@@ -0,0 +1 @@
+hostname spine1
diff --git a/tests/topotests/bgp_rr_ibgp/spine1/zebra.conf b/tests/topotests/bgp_rr_ibgp/spine1/zebra.conf
new file mode 100644
index 000000000..ea25462d5
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/spine1/zebra.conf
@@ -0,0 +1,9 @@
+hostname spine1
+ip forwarding
+ipv6 forwarding
+
+int spine1-eth0
+ ip addr 192.168.2.3/24
+
+int spine1-eth1
+ ip addr 192.168.4.3/24
diff --git a/tests/topotests/bgp_rr_ibgp/spine2/bgpd.conf b/tests/topotests/bgp_rr_ibgp/spine2/bgpd.conf
new file mode 100644
index 000000000..a865b388a
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/spine2/bgpd.conf
@@ -0,0 +1,8 @@
+hostname spine2
+router bgp 99
+ neighbor 192.168.5.1 remote-as internal
+ neighbor 192.168.6.2 remote-as internal
+ address-family ipv4 uni
+ redistribute connected
+ neighbor 192.168.5.1 route-reflector-client
+ neighbor 192.168.6.2 route-reflector-client
diff --git a/tests/topotests/bgp_rr_ibgp/spine2/show_ip_route.json_ref b/tests/topotests/bgp_rr_ibgp/spine2/show_ip_route.json_ref
new file mode 100644
index 000000000..c428a8832
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/spine2/show_ip_route.json_ref
@@ -0,0 +1,162 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.5.1",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"spine2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.5.1",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"spine2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.3.0\/24":[
+ {
+ "prefix":"192.168.3.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.6.2",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"spine2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.4.0\/24":[
+ {
+ "prefix":"192.168.4.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.6.2",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"spine2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.5.0\/24":[
+ {
+ "prefix":"192.168.5.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"spine2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.6.0\/24":[
+ {
+ "prefix":"192.168.6.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"spine2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_rr_ibgp/spine2/staticd.conf b/tests/topotests/bgp_rr_ibgp/spine2/staticd.conf
new file mode 100644
index 000000000..3ee14d262
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/spine2/staticd.conf
@@ -0,0 +1 @@
+hostname spine2
diff --git a/tests/topotests/bgp_rr_ibgp/spine2/zebra.conf b/tests/topotests/bgp_rr_ibgp/spine2/zebra.conf
new file mode 100644
index 000000000..a06681fbc
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/spine2/zebra.conf
@@ -0,0 +1,9 @@
+hostname spine2
+ip forwarding
+ipv6 forwarding
+
+int spine2-eth0
+ ip addr 192.168.5.4/24
+
+int spine2-eth1
+ ip addr 192.168.6.4/24
diff --git a/tests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py b/tests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py
new file mode 100755
index 000000000..c28394a7a
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/test_bgp_rr_ibgp_topo1.py
@@ -0,0 +1,245 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_rr_ibgp_topo1.py
+#
+# Copyright (c) 2019 by
+# Cumulus Networks, Inc.
+# Donald Sharp
+#
+# 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_rr_ibgp_topo1.py: Testing IBGP with RR and no IGP
+
+
+ In a leaf/spine topology with only IBGP connections, where
+ the same network is being redistributed at multiple points
+ in the network ( say a redistribute connected at both leaf and spines )
+ we end up in a state where zebra gets very confused.
+
+ eva# show ip route
+ Codes: K - kernel route, C - connected, S - static, R - RIP,
+ O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
+ T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
+ F - PBR, f - OpenFabric,
+ > - selected route, * - FIB route, q - queued route, r - rejected route
+
+ C>* 192.168.1.0/24 is directly connected, tor1-eth0, 00:00:30
+ C>* 192.168.2.0/24 is directly connected, tor1-eth1, 00:00:30
+ B 192.168.3.0/24 [200/0] via 192.168.4.2 inactive, 00:00:25
+ via 192.168.6.2 inactive, 00:00:25
+ B>* 192.168.4.0/24 [200/0] via 192.168.2.3, tor1-eth1, 00:00:25
+ * via 192.168.6.2 inactive, 00:00:25
+ C>* 192.168.5.0/24 is directly connected, tor1-eth2, 00:00:30
+ B>* 192.168.6.0/24 [200/0] via 192.168.4.2 inactive, 00:00:25
+ * via 192.168.5.4, tor1-eth2, 00:00:25
+
+ Effectively we have ibgp routes recursing through ibgp routes
+ and there is no metric to discern whom to listen to.
+
+ This draft:
+ https://tools.ietf.org/html/draft-ietf-idr-bgp-optimal-route-reflection-19
+
+ appears to address this issue. From looking at both cisco and arista
+ deployments they are handling this issue by having the route reflector
+ prefer the localy learned routes over from their clients.
+
+ Add this topology, in a broken state, so that when we do fix this issue
+ it is a simple matter of touching this topology up and re-adding it
+ to the normal daily builds. I also wanted to add this topology
+ since it is in a state of `doneness` and I wanted to move onto
+ my normal day job without having to remember about this test.
+
+ This topology is not configured to be run as part of the normal
+ topotests.
+
+"""
+
+import os
+import re
+import sys
+import pytest
+import json
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+#####################################################
+##
+## Network Topology Definition
+##
+#####################################################
+
+class NetworkTopo(Topo):
+ "BGP_RR_IBGP Topology 1"
+
+ def build(self, **_opts):
+ "Build function"
+
+ tgen = get_topogen(self)
+
+ tgen.add_router('tor1')
+ tgen.add_router('tor2')
+ tgen.add_router('spine1')
+ tgen.add_router('spine2')
+
+ # First switch is for a dummy interface (for local network)
+ # on tor1
+ # 192.168.1.0/24
+ switch = tgen.add_switch('sw1')
+ switch.add_link(tgen.gears['tor1'])
+
+ # 192.168.2.0/24 - tor1 <-> spine1 connection
+ switch = tgen.add_switch('sw2')
+ switch.add_link(tgen.gears['tor1'])
+ switch.add_link(tgen.gears['spine1'])
+
+ # 3rd switch is for a dummy interface (for local netwokr)
+ # 192.168.3.0/24 - tor2
+ switch = tgen.add_switch('sw3')
+ switch.add_link(tgen.gears['tor2'])
+
+ # 192.168.4.0/24 - tor2 <-> spine1 connection
+ switch = tgen.add_switch('sw4')
+ switch.add_link(tgen.gears['tor2'])
+ switch.add_link(tgen.gears['spine1'])
+
+ # 192.168.5.0/24 - tor1 <-> spine2 connection
+ switch = tgen.add_switch('sw5')
+ switch.add_link(tgen.gears['tor1'])
+ switch.add_link(tgen.gears['spine2'])
+
+ # 192.168.6.0/24 - tor2 <-> spine2 connection
+ switch = tgen.add_switch('sw6')
+ switch.add_link(tgen.gears['tor2'])
+ switch.add_link(tgen.gears['spine2'])
+
+#####################################################
+##
+## Tests starting
+##
+#####################################################
+
+def setup_module(module):
+ "Setup topology"
+ tgen = Topogen(NetworkTopo, module.__name__)
+ tgen.start_topology()
+
+ # This is a sample of configuration loading.
+ router_list = tgen.routers()
+ for rname, router in router_list.iteritems():
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, '{}/zebra.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP,
+ os.path.join(CWD, '{}/bgpd.conf'.format(rname))
+ )
+
+ tgen.start_router()
+ # tgen.mininet_cli()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def test_converge_protocols():
+ "Wait for protocol convergence"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ topotest.sleep(5, 'Waiting for BGP_RR_IBGP convergence')
+
+
+def test_bgp_rr_ibgp_routes():
+ "Test Route Reflection"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Verify BGP_RR_IBGP Status
+ logger.info("Verifying BGP_RR_IBGP routes")
+
+def test_zebra_ipv4_routingTable():
+ "Test 'show ip route'"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ failures = 0
+ router_list = tgen.routers().values()
+ for router in router_list:
+ output = router.vtysh_cmd('show ip route json', isjson=True)
+ refTableFile = '{}/{}/show_ip_route.json_ref'.format(CWD, router.name)
+ expected = json.loads(open(refTableFile).read())
+
+ assertmsg = 'Zebra IPv4 Routing Table verification failed for router {}'.format(router.name)
+ assert topotest.json_cmp(output, expected) is None, assertmsg
+
+def test_shutdown_check_stderr():
+ if os.environ.get('TOPOTESTS_CHECK_STDERR') is None:
+ pytest.skip('Skipping test for Stderr output and memory leaks')
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Verifying unexpected STDERR output from daemons")
+
+ router_list = tgen.routers().values()
+ for router in router_list:
+ router.stop()
+
+ log = tgen.net[router.name].getStdErr('bgpd')
+ if log:
+ logger.error('BGPd StdErr Log:' + log)
+ log = tgen.net[router.name].getStdErr('zebra')
+ if log:
+ logger.error('Zebra StdErr Log:' + log)
+
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
+
+#
+# Auxiliary Functions
+#
diff --git a/tests/topotests/bgp_rr_ibgp/tor1/bgpd.conf b/tests/topotests/bgp_rr_ibgp/tor1/bgpd.conf
new file mode 100644
index 000000000..44a78dffd
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/tor1/bgpd.conf
@@ -0,0 +1,5 @@
+hostname tor1
+router bgp 99
+ neighbor 192.168.2.3 remote-as internal
+ neighbor 192.168.5.4 remote-as internal
+ redistribute connected
diff --git a/tests/topotests/bgp_rr_ibgp/tor1/show_ip_route.json_ref b/tests/topotests/bgp_rr_ibgp/tor1/show_ip_route.json_ref
new file mode 100644
index 000000000..223dcebbc
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/tor1/show_ip_route.json_ref
@@ -0,0 +1,169 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"tor1-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"tor1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.3.0\/24":[
+ {
+ "prefix":"192.168.3.0\/24",
+ "protocol":"bgp",
+ "distance":200,
+ "metric":0,
+ "table":254,
+ "internalStatus":0,
+ "internalFlags":5,
+ "internalNextHopNum":2,
+ "internalNextHopActiveNum":0,
+ "nexthops":[
+ {
+ "flags":0,
+ "ip":"192.168.4.2",
+ "afi":"ipv4"
+ },
+ {
+ "flags":0,
+ "ip":"192.168.6.2",
+ "afi":"ipv4"
+ }
+ ]
+ }
+ ],
+ "192.168.4.0\/24":[
+ {
+ "prefix":"192.168.4.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":2,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"tor1-eth1",
+ "active":true
+ },
+ {
+ "flags":0,
+ "ip":"192.168.6.2",
+ "afi":"ipv4"
+ }
+ ]
+ }
+ ],
+ "192.168.5.0\/24":[
+ {
+ "prefix":"192.168.5.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":4,
+ "interfaceName":"tor1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.6.0\/24":[
+ {
+ "prefix":"192.168.6.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":2,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":0,
+ "ip":"192.168.4.2",
+ "afi":"ipv4"
+ },
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.5.4",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"tor1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_rr_ibgp/tor1/staticd.conf b/tests/topotests/bgp_rr_ibgp/tor1/staticd.conf
new file mode 100644
index 000000000..bb8d510b0
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/tor1/staticd.conf
@@ -0,0 +1 @@
+hostname tor1
diff --git a/tests/topotests/bgp_rr_ibgp/tor1/zebra.conf b/tests/topotests/bgp_rr_ibgp/tor1/zebra.conf
new file mode 100644
index 000000000..f2fa71350
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/tor1/zebra.conf
@@ -0,0 +1,12 @@
+hostname tor1
+ip forwarding
+ipv6 forwarding
+
+int tor1-eth0
+ ip addr 192.168.1.1/24
+
+int tor1-eth1
+ ip addr 192.168.2.1/24
+
+int tor1-eth2
+ ip addr 192.168.5.1/24
diff --git a/tests/topotests/bgp_rr_ibgp/tor2/bgpd.conf b/tests/topotests/bgp_rr_ibgp/tor2/bgpd.conf
new file mode 100644
index 000000000..5ef1de260
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/tor2/bgpd.conf
@@ -0,0 +1,5 @@
+hostname tor2
+router bgp 99
+ neighbor 192.168.4.3 remote-as internal
+ neighbor 192.168.6.4 remote-as internal
+ redistribute connected
diff --git a/tests/topotests/bgp_rr_ibgp/tor2/show_ip_route.json_ref b/tests/topotests/bgp_rr_ibgp/tor2/show_ip_route.json_ref
new file mode 100644
index 000000000..5f041b8c6
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/tor2/show_ip_route.json_ref
@@ -0,0 +1,169 @@
+{
+ "192.168.1.0\/24":[
+ {
+ "prefix":"192.168.1.0\/24",
+ "protocol":"bgp",
+ "distance":200,
+ "metric":0,
+ "table":254,
+ "internalStatus":0,
+ "internalFlags":5,
+ "internalNextHopNum":2,
+ "internalNextHopActiveNum":0,
+ "nexthops":[
+ {
+ "flags":0,
+ "ip":"192.168.2.1",
+ "afi":"ipv4"
+ },
+ {
+ "flags":0,
+ "ip":"192.168.5.1",
+ "afi":"ipv4"
+ }
+ ]
+ }
+ ],
+ "192.168.2.0\/24":[
+ {
+ "prefix":"192.168.2.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":2,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.4.3",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"tor2-eth1",
+ "active":true
+ },
+ {
+ "flags":0,
+ "ip":"192.168.5.1",
+ "afi":"ipv4"
+ }
+ ]
+ }
+ ],
+ "192.168.3.0\/24":[
+ {
+ "prefix":"192.168.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":2,
+ "interfaceName":"tor2-eth0",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.4.0\/24":[
+ {
+ "prefix":"192.168.4.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"tor2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.5.0\/24":[
+ {
+ "prefix":"192.168.5.0\/24",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":200,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":13,
+ "internalNextHopNum":2,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":0,
+ "ip":"192.168.2.1",
+ "afi":"ipv4"
+ },
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"192.168.6.4",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"tor2-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "192.168.6.0\/24":[
+ {
+ "prefix":"192.168.6.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":4,
+ "interfaceName":"tor2-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_rr_ibgp/tor2/staticd.conf b/tests/topotests/bgp_rr_ibgp/tor2/staticd.conf
new file mode 100644
index 000000000..03098e75d
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/tor2/staticd.conf
@@ -0,0 +1 @@
+hostname tor2
diff --git a/tests/topotests/bgp_rr_ibgp/tor2/zebra.conf b/tests/topotests/bgp_rr_ibgp/tor2/zebra.conf
new file mode 100644
index 000000000..3318cbb19
--- /dev/null
+++ b/tests/topotests/bgp_rr_ibgp/tor2/zebra.conf
@@ -0,0 +1,13 @@
+hostname tor2
+ip forwarding
+ipv6 forwarding
+
+int tor2-eth0
+ ip addr 192.168.3.2/24
+
+int tor2-eth1
+ ip addr 192.168.4.2/24
+
+
+int tor2-eth2
+ ip addr 192.168.6.2/24
diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini
index b65f93856..b052bb7c8 100644
--- a/tests/topotests/pytest.ini
+++ b/tests/topotests/pytest.ini
@@ -1,6 +1,6 @@
# Skip pytests example directory
[pytest]
-norecursedirs = .git example-test example-topojson-test lib docker bgp-ecmp-topo2
+norecursedirs = .git example-test example-topojson-test lib docker bgp-ecmp-topo2 bgp_rr_ibgp
[topogen]
# Default configuration values