summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/bgpd/test_bgp_table.c2
-rw-r--r--tests/bgpd/test_mpath.c7
-rw-r--r--tests/lib/cxxcompat.c113
-rw-r--r--tests/lib/test_privs.c2
-rw-r--r--tests/lib/test_srcdest_table.c10
-rw-r--r--tests/lib/test_table.c2
-rw-r--r--tests/subdir.am5
-rw-r--r--tests/topotests/all-protocol-startup/r1/ipv4_routes.ref12
-rw-r--r--tests/topotests/all-protocol-startup/r1/ipv6_routes.ref22
-rw-r--r--tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref2
-rwxr-xr-xtests/topotests/all-protocol-startup/test_all_protocol_startup.py43
-rw-r--r--tests/topotests/bfd-topo2/__init__.py0
-rw-r--r--tests/topotests/bfd-topo2/r1/bfdd.conf5
-rw-r--r--tests/topotests/bfd-topo2/r1/bgpd.conf13
-rw-r--r--tests/topotests/bfd-topo2/r1/ipv4_routes.json68
-rw-r--r--tests/topotests/bfd-topo2/r1/ipv6_routes.json63
-rw-r--r--tests/topotests/bfd-topo2/r1/peers.json29
-rw-r--r--tests/topotests/bfd-topo2/r1/zebra.conf6
-rw-r--r--tests/topotests/bfd-topo2/r2/bgpd.conf16
-rw-r--r--tests/topotests/bfd-topo2/r2/ipv4_routes.json108
-rw-r--r--tests/topotests/bfd-topo2/r2/ipv6_routes.json63
-rw-r--r--tests/topotests/bfd-topo2/r2/ospf6d.conf9
-rw-r--r--tests/topotests/bfd-topo2/r2/ospfd.conf9
-rw-r--r--tests/topotests/bfd-topo2/r2/peers.json42
-rw-r--r--tests/topotests/bfd-topo2/r2/zebra.conf15
-rw-r--r--tests/topotests/bfd-topo2/r3/ipv4_routes.json109
-rw-r--r--tests/topotests/bfd-topo2/r3/ipv6_routes.json2
-rw-r--r--tests/topotests/bfd-topo2/r3/ospfd.conf8
-rw-r--r--tests/topotests/bfd-topo2/r3/peers.json16
-rw-r--r--tests/topotests/bfd-topo2/r3/zebra.conf6
-rw-r--r--tests/topotests/bfd-topo2/r4/bfdd.conf5
-rw-r--r--tests/topotests/bfd-topo2/r4/ipv4_routes.json24
-rw-r--r--tests/topotests/bfd-topo2/r4/ipv6_routes.json63
-rw-r--r--tests/topotests/bfd-topo2/r4/ospf6d.conf8
-rw-r--r--tests/topotests/bfd-topo2/r4/peers.json29
-rw-r--r--tests/topotests/bfd-topo2/r4/zebra.conf6
-rw-r--r--tests/topotests/bfd-topo2/test_bfd_topo2.dot73
-rw-r--r--tests/topotests/bfd-topo2/test_bfd_topo2.jpgbin0 -> 24206 bytes
-rw-r--r--tests/topotests/bfd-topo2/test_bfd_topo2.py191
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py7
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py11
-rwxr-xr-xtests/topotests/docker/build.sh2
-rwxr-xr-xtests/topotests/docker/frr-topotests.sh4
-rw-r--r--tests/topotests/eigrp-topo1/r1/zebra.conf1
-rwxr-xr-xtests/topotests/eigrp-topo1/test_eigrp_topo1.py10
46 files changed, 1219 insertions, 23 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index 5453c0d80a..de648015f1 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -19,6 +19,7 @@
/lib/cli/test_commands
/lib/cli/test_commands_defun.c
/lib/northbound/test_oper_data
+/lib/cxxcompat
/lib/test_buffer
/lib/test_checksum
/lib/test_graph
diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c
index 73243dcacf..7b38df5f66 100644
--- a/tests/bgpd/test_bgp_table.c
+++ b/tests/bgpd/test_bgp_table.c
@@ -158,7 +158,7 @@ static void test_range_lookup(void)
"1.16.160.0/19", "1.16.32.0/20",
"1.16.32.0/21", "16.0.0.0/16"};
- int num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]);
+ int num_prefixes = array_size(prefixes);
for (int i = 0; i < num_prefixes; i++)
add_node(table, prefixes[i]);
diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c
index 04fbda42eb..0ecd0fdfec 100644
--- a/tests/bgpd/test_mpath.c
+++ b/tests/bgpd/test_mpath.c
@@ -205,7 +205,7 @@ struct peer test_mp_list_peer[] = {
{.local_as = 1, .as = 2}, {.local_as = 1, .as = 2},
{.local_as = 1, .as = 2},
};
-int test_mp_list_peer_count = sizeof(test_mp_list_peer) / sizeof(struct peer);
+int test_mp_list_peer_count = array_size(test_mp_list_peer);
struct attr test_mp_list_attr[4];
struct bgp_path_info test_mp_list_info[] = {
{.peer = &test_mp_list_peer[0], .attr = &test_mp_list_attr[0]},
@@ -214,8 +214,7 @@ struct bgp_path_info test_mp_list_info[] = {
{.peer = &test_mp_list_peer[3], .attr = &test_mp_list_attr[2]},
{.peer = &test_mp_list_peer[4], .attr = &test_mp_list_attr[3]},
};
-int test_mp_list_info_count =
- sizeof(test_mp_list_info) / sizeof(struct bgp_path_info);
+int test_mp_list_info_count = array_size(test_mp_list_info);
static int setup_bgp_mp_list(testcase_t *t)
{
@@ -370,7 +369,7 @@ testcase_t *all_tests[] = {
&test_bgp_path_info_mpath_update,
};
-int all_tests_count = (sizeof(all_tests) / sizeof(testcase_t *));
+int all_tests_count = array_size(all_tests);
/*=========================================================
* Test Driver Functions
diff --git a/tests/lib/cxxcompat.c b/tests/lib/cxxcompat.c
new file mode 100644
index 0000000000..530468642e
--- /dev/null
+++ b/tests/lib/cxxcompat.c
@@ -0,0 +1,113 @@
+/*
+ * C++ compatibility compile-time smoketest
+ * Copyright (C) 2019 David Lamparter for NetDEF, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "lib/zebra.h"
+
+#include "lib/agg_table.h"
+#include "lib/bfd.h"
+#include "lib/bitfield.h"
+#include "lib/buffer.h"
+#include "lib/checksum.h"
+#include "lib/command.h"
+#include "lib/command_graph.h"
+#include "lib/command_match.h"
+#include "lib/compiler.h"
+#include "lib/csv.h"
+#include "lib/debug.h"
+#include "lib/distribute.h"
+#include "lib/event_counter.h"
+#include "lib/ferr.h"
+#include "lib/fifo.h"
+#include "lib/filter.h"
+#include "lib/frr_pthread.h"
+#include "lib/frratomic.h"
+#include "lib/frrstr.h"
+#include "lib/getopt.h"
+#include "lib/graph.h"
+#include "lib/hash.h"
+#include "lib/hook.h"
+#include "lib/id_alloc.h"
+#include "lib/if.h"
+#include "lib/if_rmap.h"
+#include "lib/imsg.h"
+#include "lib/ipaddr.h"
+#include "lib/jhash.h"
+#include "lib/json.h"
+#include "lib/keychain.h"
+#include "lib/lib_errors.h"
+#include "lib/libfrr.h"
+#include "lib/libospf.h"
+#include "lib/linklist.h"
+#include "lib/log.h"
+#include "lib/logicalrouter.h"
+#include "lib/md5.h"
+#include "lib/memory.h"
+#include "lib/memory_vty.h"
+#include "lib/mlag.h"
+#include "lib/module.h"
+#include "lib/monotime.h"
+#include "lib/mpls.h"
+#include "lib/network.h"
+#include "lib/nexthop.h"
+#include "lib/nexthop_group.h"
+#include "lib/northbound.h"
+#include "lib/northbound_cli.h"
+#include "lib/northbound_db.h"
+#include "lib/ns.h"
+#include "lib/openbsd-tree.h"
+#include "lib/pbr.h"
+#include "lib/plist.h"
+#include "lib/pqueue.h"
+#include "lib/prefix.h"
+#include "lib/privs.h"
+#include "lib/ptm_lib.h"
+#include "lib/pw.h"
+#include "lib/qobj.h"
+#include "lib/queue.h"
+#include "lib/ringbuf.h"
+#include "lib/routemap.h"
+#include "lib/sbuf.h"
+#include "lib/sha256.h"
+#include "lib/sigevent.h"
+#include "lib/skiplist.h"
+#include "lib/sockopt.h"
+#include "lib/sockunion.h"
+#include "lib/spf_backoff.h"
+#include "lib/srcdest_table.h"
+#include "lib/stream.h"
+#include "lib/table.h"
+#include "lib/termtable.h"
+#include "lib/thread.h"
+#include "lib/vector.h"
+#include "lib/vlan.h"
+#include "lib/vrf.h"
+#include "lib/vty.h"
+#include "lib/vxlan.h"
+#include "lib/wheel.h"
+/* #include "lib/workqueue.h" -- macro problem with STAILQ_LAST */
+#include "lib/yang.h"
+#include "lib/yang_translator.h"
+#include "lib/yang_wrappers.h"
+#include "lib/zassert.h"
+#include "lib/zclient.h"
+
+int main(int argc, char **argv)
+{
+ return 0;
+}
diff --git a/tests/lib/test_privs.c b/tests/lib/test_privs.c
index e203da8f6e..fc3d908661 100644
--- a/tests/lib/test_privs.c
+++ b/tests/lib/test_privs.c
@@ -37,7 +37,7 @@ struct zebra_privs_t test_privs = {
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
- .cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]),
+ .cap_num_p = array_size(_caps_p),
.cap_num_i = 0};
struct option longopts[] = {{"help", no_argument, NULL, 'h'},
diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c
index 959358bbec..19a40b2184 100644
--- a/tests/lib/test_srcdest_table.c
+++ b/tests/lib/test_srcdest_table.c
@@ -105,7 +105,7 @@ static unsigned int log_key(void *data)
static bool log_cmp(const void *a, const void *b)
{
if (a == NULL || b == NULL)
- return 0;
+ return false;
return !memcmp(a, b, 2 * sizeof(struct prefix));
}
@@ -195,10 +195,10 @@ static void test_state_del_route(struct test_state *test,
XFREE(MTYPE_TMP, hash_entry_intern);
}
-static void verify_log(struct hash_backet *backet, void *arg)
+static void verify_log(struct hash_bucket *bucket, void *arg)
{
struct test_state *test = arg;
- struct prefix *hash_entry = backet->data;
+ struct prefix *hash_entry = bucket->data;
struct prefix *dst_p = &hash_entry[0];
struct prefix_ipv6 *src_p = (struct prefix_ipv6 *)&hash_entry[1];
struct route_node *rn = srcdest_rnode_lookup(test->table, dst_p, src_p);
@@ -209,9 +209,9 @@ static void verify_log(struct hash_backet *backet, void *arg)
route_unlock_node(rn);
}
-static void dump_log(struct hash_backet *backet, void *arg)
+static void dump_log(struct hash_bucket *bucket, void *arg)
{
- struct prefix *hash_entry = backet->data;
+ struct prefix *hash_entry = bucket->data;
struct prefix_ipv6 *dst_p = (struct prefix_ipv6 *)&hash_entry[0];
struct prefix_ipv6 *src_p = (struct prefix_ipv6 *)&hash_entry[1];
char *route_id = format_srcdest(dst_p, src_p);
diff --git a/tests/lib/test_table.c b/tests/lib/test_table.c
index 2b65040627..90d6c76bf1 100644
--- a/tests/lib/test_table.c
+++ b/tests/lib/test_table.c
@@ -478,7 +478,7 @@ static void test_iter_pause(void)
const char *prefixes[] = {"1.0.1.0/24", "1.0.1.0/25", "1.0.1.128/25",
"1.0.2.0/24", "2.0.0.0/8"};
- num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]);
+ num_prefixes = array_size(prefixes);
printf("\n\nTesting that route_table_iter_pause() works as expected\n");
table = route_table_init();
diff --git a/tests/subdir.am b/tests/subdir.am
index 42730cb83a..365fe00cc6 100644
--- a/tests/subdir.am
+++ b/tests/subdir.am
@@ -46,6 +46,7 @@ tests/ospf6d/tests_ospf6d_test_lsdb-test_lsdb.$(OBJEXT): tests/ospf6d/test_lsdb_
tests/ospf6d/test_lsdb-test_lsdb.$(OBJEXT): tests/ospf6d/test_lsdb_clippy.c
check_PROGRAMS = \
+ tests/lib/cxxcompat \
tests/lib/test_buffer \
tests/lib/test_checksum \
tests/lib/test_heavy_thread \
@@ -170,6 +171,10 @@ tests_isisd_test_isis_vertex_queue_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD)
tests_isisd_test_isis_vertex_queue_SOURCES = tests/isisd/test_isis_vertex_queue.c
+tests_lib_cxxcompat_CFLAGS = $(TESTS_CFLAGS) $(CXX_COMPAT_CFLAGS) $(WERROR)
+tests_lib_cxxcompat_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_cxxcompat_SOURCES = tests/lib/cxxcompat.c
+tests_lib_cxxcompat_LDADD = $(ALL_TESTS_LDADD)
tests_lib_cli_test_cli_CFLAGS = $(TESTS_CFLAGS)
tests_lib_cli_test_cli_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD)
diff --git a/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref b/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
new file mode 100644
index 0000000000..e75d896721
--- /dev/null
+++ b/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
@@ -0,0 +1,12 @@
+C>* 192.168.0.0/24 is directly connected, r1-eth0, XX:XX:XX
+C>* 192.168.1.0/26 is directly connected, r1-eth1, XX:XX:XX
+C>* 192.168.2.0/26 is directly connected, r1-eth2, XX:XX:XX
+C>* 192.168.3.0/26 is directly connected, r1-eth3, XX:XX:XX
+C>* 192.168.4.0/26 is directly connected, r1-eth4, XX:XX:XX
+C>* 192.168.5.0/26 is directly connected, r1-eth5, XX:XX:XX
+C>* 192.168.6.0/26 is directly connected, r1-eth6, XX:XX:XX
+C>* 192.168.7.0/26 is directly connected, r1-eth7, XX:XX:XX
+C>* 192.168.8.0/26 is directly connected, r1-eth8, XX:XX:XX
+C>* 192.168.9.0/26 is directly connected, r1-eth9, XX:XX:XX
+O 192.168.0.0/24 [110/10] is directly connected, r1-eth0, XX:XX:XX
+O 192.168.3.0/26 [110/10] is directly connected, r1-eth3, XX:XX:XX
diff --git a/tests/topotests/all-protocol-startup/r1/ipv6_routes.ref b/tests/topotests/all-protocol-startup/r1/ipv6_routes.ref
new file mode 100644
index 0000000000..88cee964d6
--- /dev/null
+++ b/tests/topotests/all-protocol-startup/r1/ipv6_routes.ref
@@ -0,0 +1,22 @@
+C>* fc00:0:0:1::/64 is directly connected, r1-eth1, XX:XX:XX
+C>* fc00:0:0:2::/64 is directly connected, r1-eth2, XX:XX:XX
+C>* fc00:0:0:3::/64 is directly connected, r1-eth3, XX:XX:XX
+C>* fc00:0:0:4::/64 is directly connected, r1-eth4, XX:XX:XX
+C>* fc00:0:0:5::/64 is directly connected, r1-eth5, XX:XX:XX
+C>* fc00:0:0:6::/64 is directly connected, r1-eth6, XX:XX:XX
+C>* fc00:0:0:7::/64 is directly connected, r1-eth7, XX:XX:XX
+C>* fc00:0:0:8::/64 is directly connected, r1-eth8, XX:XX:XX
+C>* fc00:0:0:9::/64 is directly connected, r1-eth9, XX:XX:XX
+C>* fc00::/64 is directly connected, r1-eth0, XX:XX:XX
+C>* fe80::/64 is directly connected, lo, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth0, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth1, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth2, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth3, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth4, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth5, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth6, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth7, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth8, XX:XX:XX
+C * fe80::/64 is directly connected, r1-eth9, XX:XX:XX
+O fc00:0:0:4::/64 [110/10] is directly connected, r1-eth4, XX:XX:XX
diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref
index 6777cd9fc3..85388c738d 100644
--- a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref
+++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref
@@ -1,7 +1,7 @@
BGP router identifier 192.168.0.1, local AS number 100 vrf-id 0
BGP table version 1
RIB entries 1, using XXXX bytes of memory
-Peers 4, using XXXX KiB of memory
+Peers 2, using XXXX KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
fc00:0:0:8::1000 4 100 0 0 0 0 0 never Active
diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
index fb2100e03d..239de55bd6 100755
--- a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
+++ b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
@@ -296,10 +296,53 @@ def test_converge_protocols():
sleep(60)
# Make sure that all daemons are running
+ failures = 0
for i in range(1, 2):
fatal_error = net['r%s' % i].checkRouterRunning()
assert fatal_error == "", fatal_error
+ print("Show that v4 routes are right\n");
+ v4_routesFile = '%s/r%s/ipv4_routes.ref' % (thisDir, i)
+ expected = open(v4_routesFile).read().rstrip()
+ expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
+
+ actual = net['r%s' %i].cmd('vtysh -c "show ip route" | /usr/bin/tail -n +7 | sort 2> /dev/null').rstrip()
+ # Drop time in last update
+ actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
+ actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
+ diff = topotest.get_textdiff(actual, expected,
+ title1="Actual IP Routing Table",
+ title2="Expected IP RoutingTable")
+ if diff:
+ sys.stderr.write('r%s failed IP Routing table check:\n%s\n' % (i, diff))
+ failures += 1
+ else:
+ print("r%s ok" %i)
+
+ assert failures == 0, "IP Routing table failed for r%s\n%s" % (i, diff)
+
+ failures = 0
+
+ print("Show that v6 routes are right\n")
+ v6_routesFile = '%s/r%s/ipv6_routes.ref' % (thisDir, i)
+ expected = open(v6_routesFile).read().rstrip()
+ expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1)
+
+ actual = net['r%s' %i].cmd('vtysh -c "show ipv6 route" | /usr/bin/tail -n +7 | sort 2> /dev/null').rstrip()
+ # Drop time in last update
+ actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
+ actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1)
+ diff = topotest.get_textdiff(actual, expected,
+ title1="Actual IPv6 Routing Table",
+ title2="Expected IPv6 RoutingTable")
+ if diff:
+ sys.stderr.write('r%s failed IPv6 Routing table check:\n%s\n' % (i, diff))
+ failures += 1
+ else:
+ print("r%s ok" %i)
+
+ assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff)
+
# For debugging after starting FRR/Quagga daemons, uncomment the next line
## CLI(net)
diff --git a/tests/topotests/bfd-topo2/__init__.py b/tests/topotests/bfd-topo2/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bfd-topo2/__init__.py
diff --git a/tests/topotests/bfd-topo2/r1/bfdd.conf b/tests/topotests/bfd-topo2/r1/bfdd.conf
new file mode 100644
index 0000000000..5c2571bdbd
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/bfdd.conf
@@ -0,0 +1,5 @@
+bfd
+ peer 2001:db8:4::1 multihop local-address 2001:db8:1::1
+ no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-topo2/r1/bgpd.conf b/tests/topotests/bfd-topo2/r1/bgpd.conf
new file mode 100644
index 0000000000..1623b4578b
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/bgpd.conf
@@ -0,0 +1,13 @@
+router bgp 101
+ bgp router-id 10.254.254.1
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r1-eth0 interface peer-group r2g
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ address-family ipv6 unicast
+ neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-topo2/r1/ipv4_routes.json b/tests/topotests/bfd-topo2/r1/ipv4_routes.json
new file mode 100644
index 0000000000..8a2ec25baa
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/ipv4_routes.json
@@ -0,0 +1,68 @@
+{
+ "10.0.3.0/24": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.0.3.0/24",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ],
+ "10.254.254.2/32": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.2/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.1/32",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r1/ipv6_routes.json b/tests/topotests/bfd-topo2/r1/ipv6_routes.json
new file mode 100644
index 0000000000..618853bd42
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/ipv6_routes.json
@@ -0,0 +1,63 @@
+{
+ "2001:db8:4::/64": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:4::/64",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ],
+ "2001:db8:1::/64": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 0,
+ "metric": 0,
+ "internalStatus": 2,
+ "prefix": "2001:db8:1::/64",
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "flags": 1,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:1::/64",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r1/peers.json b/tests/topotests/bfd-topo2/r1/peers.json
new file mode 100644
index 0000000000..b14351cd81
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/peers.json
@@ -0,0 +1,29 @@
+[
+ {
+ "multihop":true,
+ "peer":"2001:db8:4::1",
+ "local":"2001:db8:1::1",
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":300,
+ "transmit-interval":300,
+ "echo-interval":0,
+ "remote-receive-interval":300,
+ "remote-transmit-interval":300,
+ "remote-echo-interval":50
+ },
+ {
+ "multihop":false,
+ "interface":"r1-eth0",
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":300,
+ "transmit-interval":300,
+ "echo-interval":0,
+ "remote-receive-interval":300,
+ "remote-transmit-interval":300,
+ "remote-echo-interval":50
+ }
+]
diff --git a/tests/topotests/bfd-topo2/r1/zebra.conf b/tests/topotests/bfd-topo2/r1/zebra.conf
new file mode 100644
index 0000000000..7fe5eb218f
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/zebra.conf
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.1/32
+!
+interface r1-eth0
+ ipv6 address 2001:db8:1::1/64
+!
diff --git a/tests/topotests/bfd-topo2/r2/bgpd.conf b/tests/topotests/bfd-topo2/r2/bgpd.conf
new file mode 100644
index 0000000000..bf42d21812
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/bgpd.conf
@@ -0,0 +1,16 @@
+router bgp 102
+ bgp router-id 10.254.254.2
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r2-eth0 interface peer-group r2g
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ !
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-topo2/r2/ipv4_routes.json b/tests/topotests/bfd-topo2/r2/ipv4_routes.json
new file mode 100644
index 0000000000..b9d8afb430
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/ipv4_routes.json
@@ -0,0 +1,108 @@
+{
+ "10.0.3.0/24": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 0,
+ "metric": 10,
+ "internalStatus": 2,
+ "prefix": "10.0.3.0/24",
+ "nexthops": [
+ {
+ "active": true,
+ "directlyConnected": true,
+ "flags": 1,
+ "interfaceIndex": 3,
+ "interfaceName": "r2-eth1"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.0.3.0/24",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r2-eth1",
+ "interfaceIndex": 3,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.3/32": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 8,
+ "metric": 20,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.3/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r2-eth1",
+ "ip": "10.0.3.1",
+ "interfaceIndex": 3,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv4"
+ }
+ ]
+ }
+ ],
+ "10.254.254.2/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.2/32",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.1/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r2-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r2/ipv6_routes.json b/tests/topotests/bfd-topo2/r2/ipv6_routes.json
new file mode 100644
index 0000000000..004e7588aa
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/ipv6_routes.json
@@ -0,0 +1,63 @@
+{
+ "2001:db8:4::/64": [
+ {
+ "distance": 110,
+ "protocol": "ospf6",
+ "internalFlags": 0,
+ "metric": 10,
+ "internalStatus": 2,
+ "prefix": "2001:db8:4::/64",
+ "nexthops": [
+ {
+ "active": true,
+ "directlyConnected": true,
+ "flags": 1,
+ "interfaceIndex": 4,
+ "interfaceName": "r2-eth2"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:4::/64",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r2-eth2",
+ "interfaceIndex": 4,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1::/64": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:1::/64",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r2-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r2/ospf6d.conf b/tests/topotests/bfd-topo2/r2/ospf6d.conf
new file mode 100644
index 0000000000..f1cdb50285
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/ospf6d.conf
@@ -0,0 +1,9 @@
+interface r2-eth2
+ ipv6 ospf6 bfd
+!
+router ospf6
+ ospf6 router-id 10.254.254.2
+ redistribute connected
+ redistribute bgp
+ interface r2-eth2 area 0.0.0.1
+!
diff --git a/tests/topotests/bfd-topo2/r2/ospfd.conf b/tests/topotests/bfd-topo2/r2/ospfd.conf
new file mode 100644
index 0000000000..8e0c45980d
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/ospfd.conf
@@ -0,0 +1,9 @@
+interface r2-eth1
+ ip ospf area 0.0.0.1
+ ip ospf bfd
+!
+router ospf
+ ospf router-id 10.254.254.2
+ redistribute connected
+ redistribute bgp
+!
diff --git a/tests/topotests/bfd-topo2/r2/peers.json b/tests/topotests/bfd-topo2/r2/peers.json
new file mode 100644
index 0000000000..29075fcc80
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/peers.json
@@ -0,0 +1,42 @@
+[
+ {
+ "status": "up",
+ "transmit-interval": 300,
+ "remote-receive-interval": 300,
+ "echo-interval": 0,
+ "diagnostic": "ok",
+ "multihop": false,
+ "interface": "r2-eth0",
+ "remote-transmit-interval": 300,
+ "receive-interval": 300,
+ "remote-echo-interval": 50,
+ "remote-diagnostic": "ok"
+ },
+ {
+ "status": "up",
+ "transmit-interval": 300,
+ "remote-receive-interval": 300,
+ "echo-interval": 0,
+ "diagnostic": "ok",
+ "multihop": false,
+ "interface": "r2-eth2",
+ "remote-transmit-interval": 300,
+ "receive-interval": 300,
+ "remote-echo-interval": 50,
+ "remote-diagnostic": "ok"
+ },
+ {
+ "status": "up",
+ "transmit-interval": 300,
+ "remote-receive-interval": 300,
+ "echo-interval": 0,
+ "diagnostic": "ok",
+ "multihop": false,
+ "interface": "r2-eth1",
+ "remote-transmit-interval": 300,
+ "receive-interval": 300,
+ "remote-echo-interval": 50,
+ "remote-diagnostic": "ok",
+ "peer": "10.0.3.1"
+ }
+]
diff --git a/tests/topotests/bfd-topo2/r2/zebra.conf b/tests/topotests/bfd-topo2/r2/zebra.conf
new file mode 100644
index 0000000000..cccbf6574a
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/zebra.conf
@@ -0,0 +1,15 @@
+ip forwarding
+ipv6 forwarding
+!
+interface lo
+ ip address 10.254.254.2/32
+!
+interface r2-eth0
+ ipv6 address 2001:db8:1::2/64
+!
+interface r2-eth1
+ ip address 10.0.3.2/24
+!
+interface r2-eth2
+ ipv6 address 2001:db8:4::2/64
+!
diff --git a/tests/topotests/bfd-topo2/r3/ipv4_routes.json b/tests/topotests/bfd-topo2/r3/ipv4_routes.json
new file mode 100644
index 0000000000..14dfc692fe
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/ipv4_routes.json
@@ -0,0 +1,109 @@
+{
+ "10.0.3.0/24": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 0,
+ "metric": 10,
+ "internalStatus": 0,
+ "prefix": "10.0.3.0/24",
+ "nexthops": [
+ {
+ "active": true,
+ "directlyConnected": true,
+ "flags": 1,
+ "interfaceIndex": 2,
+ "interfaceName": "r3-eth0"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.0.3.0/24",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r3-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.3/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.3/32",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.2/32": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 8,
+ "metric": 20,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.2/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r3-eth0",
+ "ip": "10.0.3.2",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv4"
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 8,
+ "metric": 20,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.1/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r3-eth0",
+ "ip": "10.0.3.2",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv4"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r3/ipv6_routes.json b/tests/topotests/bfd-topo2/r3/ipv6_routes.json
new file mode 100644
index 0000000000..2c63c08510
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/ipv6_routes.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/bfd-topo2/r3/ospfd.conf b/tests/topotests/bfd-topo2/r3/ospfd.conf
new file mode 100644
index 0000000000..cf2a1bdf76
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/ospfd.conf
@@ -0,0 +1,8 @@
+interface r3-eth0
+ ip ospf area 0.0.0.1
+ ip ospf bfd
+!
+router ospf
+ ospf router-id 10.254.254.3
+ redistribute connected
+!
diff --git a/tests/topotests/bfd-topo2/r3/peers.json b/tests/topotests/bfd-topo2/r3/peers.json
new file mode 100644
index 0000000000..6698bff201
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/peers.json
@@ -0,0 +1,16 @@
+[
+ {
+ "status": "up",
+ "transmit-interval": 300,
+ "remote-receive-interval": 300,
+ "echo-interval": 0,
+ "diagnostic": "ok",
+ "multihop": false,
+ "interface": "r3-eth0",
+ "remote-transmit-interval": 300,
+ "receive-interval": 300,
+ "remote-echo-interval": 50,
+ "remote-diagnostic": "ok",
+ "peer": "10.0.3.2"
+ }
+]
diff --git a/tests/topotests/bfd-topo2/r3/zebra.conf b/tests/topotests/bfd-topo2/r3/zebra.conf
new file mode 100644
index 0000000000..96fd08c729
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/zebra.conf
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.3/32
+!
+interface r3-eth0
+ ip address 10.0.3.1/24
+!
diff --git a/tests/topotests/bfd-topo2/r4/bfdd.conf b/tests/topotests/bfd-topo2/r4/bfdd.conf
new file mode 100644
index 0000000000..fdb4412446
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/bfdd.conf
@@ -0,0 +1,5 @@
+bfd
+ peer 2001:db8:1::1 multihop local-address 2001:db8:4::1
+ no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-topo2/r4/ipv4_routes.json b/tests/topotests/bfd-topo2/r4/ipv4_routes.json
new file mode 100644
index 0000000000..ae1e97b017
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/ipv4_routes.json
@@ -0,0 +1,24 @@
+{
+ "10.254.254.4/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.4/32",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r4/ipv6_routes.json b/tests/topotests/bfd-topo2/r4/ipv6_routes.json
new file mode 100644
index 0000000000..33608b45aa
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/ipv6_routes.json
@@ -0,0 +1,63 @@
+{
+ "2001:db8:4::/64": [
+ {
+ "distance": 110,
+ "protocol": "ospf6",
+ "internalFlags": 0,
+ "metric": 10,
+ "internalStatus": 2,
+ "prefix": "2001:db8:4::/64",
+ "nexthops": [
+ {
+ "active": true,
+ "directlyConnected": true,
+ "flags": 1,
+ "interfaceIndex": 2,
+ "interfaceName": "r4-eth0"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:4::/64",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r4-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1::/64": [
+ {
+ "distance": 110,
+ "protocol": "ospf6",
+ "internalFlags": 8,
+ "metric": 10,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:1::/64",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r4-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r4/ospf6d.conf b/tests/topotests/bfd-topo2/r4/ospf6d.conf
new file mode 100644
index 0000000000..756597d6f8
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/ospf6d.conf
@@ -0,0 +1,8 @@
+interface r4-eth0
+ ipv6 ospf6 bfd
+!
+router ospf6
+ ospf6 router-id 10.254.254.4
+ redistribute connected
+ interface r4-eth0 area 0.0.0.1
+!
diff --git a/tests/topotests/bfd-topo2/r4/peers.json b/tests/topotests/bfd-topo2/r4/peers.json
new file mode 100644
index 0000000000..83101eb47f
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/peers.json
@@ -0,0 +1,29 @@
+[
+ {
+ "multihop":true,
+ "peer":"2001:db8:1::1",
+ "local":"2001:db8:4::1",
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":300,
+ "transmit-interval":300,
+ "echo-interval":0,
+ "remote-receive-interval":300,
+ "remote-transmit-interval":300,
+ "remote-echo-interval":50
+ },
+ {
+ "multihop":false,
+ "interface":"r4-eth0",
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":300,
+ "transmit-interval":300,
+ "echo-interval":0,
+ "remote-receive-interval":300,
+ "remote-transmit-interval":300,
+ "remote-echo-interval":50
+ }
+]
diff --git a/tests/topotests/bfd-topo2/r4/zebra.conf b/tests/topotests/bfd-topo2/r4/zebra.conf
new file mode 100644
index 0000000000..e4f8fd8514
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/zebra.conf
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.4/32
+!
+interface r4-eth0
+ ipv6 address 2001:db8:4::1/64
+!
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.dot b/tests/topotests/bfd-topo2/test_bfd_topo2.dot
new file mode 100644
index 0000000000..6b68fb398f
--- /dev/null
+++ b/tests/topotests/bfd-topo2/test_bfd_topo2.dot
@@ -0,0 +1,73 @@
+## 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 template {
+ label="bfd-topo2";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ shape=doubleoctagon
+ label="r3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r4 [
+ shape=doubleoctagon
+ label="r4",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ sw1 [
+ shape=oval,
+ label="sw1\n2001:db8:1::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw2 [
+ shape=oval,
+ label="sw2\n10.0.3.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw3 [
+ shape=oval,
+ label="sw3\n2001:db8:4::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ r1 -- sw1 [label="eth0"];
+ r2 -- sw1 [label="eth0"];
+
+ r2 -- sw2 [label="eth1"];
+ r3 -- sw2 [label="eth0"];
+
+ r2 -- sw3 [label="eth2"];
+ r4 -- sw3 [label="eth0"];
+}
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.jpg b/tests/topotests/bfd-topo2/test_bfd_topo2.jpg
new file mode 100644
index 0000000000..35fe562a80
--- /dev/null
+++ b/tests/topotests/bfd-topo2/test_bfd_topo2.jpg
Binary files differ
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.py b/tests/topotests/bfd-topo2/test_bfd_topo2.py
new file mode 100644
index 0000000000..773db129f0
--- /dev/null
+++ b/tests/topotests/bfd-topo2/test_bfd_topo2.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+
+#
+# test_bfd_topo2.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 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_bfd_topo2.py: Test the FRR/Quagga BFD daemon with multihop and BGP
+unnumbered.
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class BFDTopo(Topo):
+ "Test topology builder"
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ # Create 4 routers.
+ for routern in range(1, 5):
+ tgen.add_router('r{}'.format(routern))
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r2'])
+
+ switch = tgen.add_switch('s2')
+ switch.add_link(tgen.gears['r2'])
+ switch.add_link(tgen.gears['r3'])
+
+ switch = tgen.add_switch('s3')
+ switch.add_link(tgen.gears['r2'])
+ switch.add_link(tgen.gears['r4'])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(BFDTopo, mod.__name__)
+ tgen.start_topology()
+
+ 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_BFD,
+ os.path.join(CWD, '{}/bfdd.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP,
+ os.path.join(CWD, '{}/bgpd.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF,
+ os.path.join(CWD, '{}/ospfd.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF6,
+ os.path.join(CWD, '{}/ospf6d.conf'.format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+ # Verify that we are using the proper version and that the BFD
+ # daemon exists.
+ for router in router_list.values():
+ # Check for Version
+ if router.has_version('<', '5.1'):
+ tgen.set_error('Unsupported FRR version')
+ break
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_protocols_convergence():
+ """
+ Assert that all protocols have converged before checking for the BFD
+ statuses as they depend on it.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Check IPv4 routing tables.
+ logger.info("Checking IPv4 routes for convergence")
+ for router in tgen.routers().values():
+ json_file = '{}/{}/ipv4_routes.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ip route json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=160,
+ wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Check IPv6 routing tables.
+ logger.info("Checking IPv6 routes for convergence")
+ for router in tgen.routers().values():
+ json_file = '{}/{}/ipv6_routes.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ipv6 route json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=160,
+ wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+
+def test_bfd_connection():
+ "Assert that the BFD peers can find themselves."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info('waiting for bfd peers to go up')
+
+ for router in tgen.routers().values():
+ json_file = '{}/{}/peers.json'.format(CWD, router.name)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show bfd peers json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip('Memory leak test/report is disabled')
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
index 31e23faede..ce542413ba 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/customize.py
@@ -141,7 +141,10 @@ class ThisTestTopo(Topo):
switch[1].add_link(tgen.gears['r2'], nodeif='r2-eth2')
switch[1].add_link(tgen.gears['r3'], nodeif='r3-eth1')
+l3mdev_accept = 0
+
def ltemplatePreRouterStartHook():
+ global l3mdev_accept
cc = ltemplateRtrCmd()
krel = platform.release()
tgen = get_topogen()
@@ -172,7 +175,7 @@ def ltemplatePreRouterStartHook():
'ip ru add oif {0}-cust1 table 10',
'ip ru add iif {0}-cust1 table 10',
'ip link set dev {0}-cust1 up',
- 'sysctl -w net.ipv4.udp_l3mdev_accept={}'.format(l3mdev_accept)]
+ 'sysctl -w net.ipv4.tcp_l3mdev_accept={}'.format(l3mdev_accept)]
for rtr in rtrs:
router = tgen.gears[rtr]
for cmd in cmds:
@@ -202,7 +205,7 @@ def ltemplatePreRouterStartHook():
'ip ru add oif {0}-cust2 table 20',
'ip ru add iif {0}-cust2 table 20',
'ip link set dev {0}-cust2 up',
- 'sysctl -w net.ipv4.udp_l3mdev_accept={}'.format(l3mdev_accept)]
+ 'sysctl -w net.ipv4.tcp_l3mdev_accept={}'.format(l3mdev_accept)]
for rtr in rtrs:
for cmd in cmds:
cc.doCmd(tgen, rtr, cmd.format(rtr))
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
index 778d504040..f5d73a8c49 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
@@ -1,11 +1,12 @@
from lutil import luCommand
-
-rtrs = ['r1', 'r3', 'r4', 'ce1', 'ce2', 'ce3', 'ce4']
-for rtr in rtrs:
+from customize import l3mdev_accept
+l3mdev_rtrs = ['r1', 'r3', 'r4', 'ce4']
+for rtr in l3mdev_rtrs:
luCommand(rtr,'sysctl net.ipv4.tcp_l3mdev_accept',' = \d*','none','')
found = luLast()
- luCommand(rtr,'ss -aep',':bgp','pass','IPv4:bgp, l3mdev%s' % found.group(0))
- luCommand(rtr,'ss -aep',':.:bgp','pass','IPv6:bgp')
+ luCommand(rtr,'ss -naep',':179','pass','IPv4:bgp, l3mdev{}'.format(found.group(0)))
+ luCommand(rtr,'ss -naep',':.*:179','pass','IPv6:bgp')
+ luCommand(rtr,'sysctl net.ipv4.tcp_l3mdev_accept',' = {}'.format(l3mdev_accept),'pass','l3mdev matches expected (real/expected{}/{})'.format(found.group(0),l3mdev_accept))
rtrs = ['r1', 'r3', 'r4']
for rtr in rtrs:
diff --git a/tests/topotests/docker/build.sh b/tests/topotests/docker/build.sh
index 344fb2ffcb..70ce2efe85 100755
--- a/tests/topotests/docker/build.sh
+++ b/tests/topotests/docker/build.sh
@@ -26,5 +26,5 @@ cd "$(dirname "$0")"/..
exec docker build --pull \
--compress \
- -t frrouting/frr:topotests-latest \
+ -t frrouting/topotests:latest \
.
diff --git a/tests/topotests/docker/frr-topotests.sh b/tests/topotests/docker/frr-topotests.sh
index 6d8bea0002..ef916abcf3 100755
--- a/tests/topotests/docker/frr-topotests.sh
+++ b/tests/topotests/docker/frr-topotests.sh
@@ -136,7 +136,7 @@ if [ -z "$TOPOTEST_BUILDCACHE" ]; then
fi
if [ "${TOPOTEST_PULL:-1}" = "1" ]; then
- docker pull frrouting/frr:topotests-latest
+ docker pull frrouting/topotests:latest
fi
set -- --rm -i \
@@ -149,7 +149,7 @@ set -- --rm -i \
-e "TOPOTEST_SANITIZER=$TOPOTEST_SANITIZER" \
--privileged \
$TOPOTEST_OPTIONS \
- frrouting/frr:topotests-latest "$@"
+ frrouting/topotests:latest "$@"
if [ -t 0 ]; then
set -- -t "$@"
diff --git a/tests/topotests/eigrp-topo1/r1/zebra.conf b/tests/topotests/eigrp-topo1/r1/zebra.conf
index 8537f6dd80..56ae4a66f4 100644
--- a/tests/topotests/eigrp-topo1/r1/zebra.conf
+++ b/tests/topotests/eigrp-topo1/r1/zebra.conf
@@ -1,4 +1,5 @@
log file zebra.log
+debug zebra rib detail
!
hostname r1
!
diff --git a/tests/topotests/eigrp-topo1/test_eigrp_topo1.py b/tests/topotests/eigrp-topo1/test_eigrp_topo1.py
index 8ea2f0b506..1c00face43 100755
--- a/tests/topotests/eigrp-topo1/test_eigrp_topo1.py
+++ b/tests/topotests/eigrp-topo1/test_eigrp_topo1.py
@@ -171,6 +171,16 @@ def test_zebra_ipv4_routingTable():
assertmsg = 'Zebra IPv4 Routing Table verification failed for router {}'.format(router.name)
assert topotest.json_cmp(output, expected) is None, assertmsg
+def test_shut_interface_and_recover():
+ "Test shutdown of an interface and recovery of the interface"
+
+ tgen = get_topogen()
+ router = tgen.gears['r1']
+ router.run('ip link set r1-eth1 down')
+ topotest.sleep(5, 'Waiting for EIGRP convergence')
+ router.run('ip link set r1-eth1 up')
+
+
def test_shutdown_check_stderr():
if os.environ.get('TOPOTESTS_CHECK_STDERR') is None: