]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bfd-bgp-cbit-topo3: add bfd bgp cbit topotest test
authorPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 16 Apr 2019 10:16:17 +0000 (12:16 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Tue, 14 May 2019 14:49:49 +0000 (16:49 +0200)
this test simulates the case where r1 keeps staled entries of r2,
because r2 is a 'non stop forwarding' device. For instance, r2 restarts
to be upgraded, then r1 keeps the entries, thus avoiding to flush
entries in the dataplane. Here, BFD is used, and the bgp
check-control-plane-failure command is used to inform BGP that if BFD
goes down, this may be because remote peer is restarting, and this may
be necessary to keep the entries of remote.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
16 files changed:
tests/topotests/bfd-bgp-cbit-topo3/__init__.py [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r1/bgp_ipv6_routes_down.json [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r1/ipv6_routes.json [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r1/peers.json [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r3/bgp_ipv6_routes_down.json [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r3/bgpd.conf [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r3/ipv6_routes.json [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r3/peers.json [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r3/peers_down.json [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/r3/zebra.conf [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.dot [new file with mode: 0644]
tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py [new file with mode: 0755]

diff --git a/tests/topotests/bfd-bgp-cbit-topo3/__init__.py b/tests/topotests/bfd-bgp-cbit-topo3/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/bgp_ipv6_routes_down.json b/tests/topotests/bfd-bgp-cbit-topo3/r1/bgp_ipv6_routes_down.json
new file mode 100644 (file)
index 0000000..54ae57f
--- /dev/null
@@ -0,0 +1,103 @@
+{
+    "vrfId": 0,
+    "vrfName": "default",
+    "routerId": "10.254.254.1",
+    "localAS": 101,
+    "routes":
+    {
+        "2001:db8:6::/64": [
+            {
+                "stale": true,
+                "valid": true,
+                "bestpath": true,
+                "pathFrom": "external",
+                "prefix": "2001:db8:6::",
+                "prefixLen": 64,
+                "network": "2001:db8:6::\/64",
+                "med": 0,
+                "metric": 0,
+                "weight": 0,
+                "peerId": "2001:db8:4::1",
+                "origin": "IGP",
+                "nexthops": [
+                    { "ip": "2001:db8:4::1",
+                      "afi": "ipv6",
+                      "scope": "global",
+                      "used": true
+                    }
+                ]
+            }
+        ],
+        "2001:db8:7::/64": [
+            {
+                "stale": true,
+                "valid": true,
+                "bestpath": true,
+                "pathFrom": "external",
+                "prefix": "2001:db8:7::",
+                "prefixLen": 64, "network":
+                "2001:db8:7::\/64",
+                "med": 0,
+                "metric": 0,
+                "weight": 0,
+                "peerId": "2001:db8:4::1",
+                "origin": "IGP",
+                "nexthops": [
+                    {
+                        "ip": "2001:db8:4::1",
+                        "afi": "ipv6",
+                        "scope": "global",
+                        "used": true
+                    }
+                ]
+            }
+        ],
+        "2001:db8:8::/64": [
+            {
+                "valid": true,
+                "bestpath": true,
+                "pathFrom": "external",
+                "prefix": "2001:db8:8::",
+                "prefixLen": 64,
+                "network": "2001:db8:8::\/64",
+                "med": 0,
+                "metric": 0,
+              "weight": 32768,
+                "peerId": "(unspec)",
+                "origin": "IGP",
+                "nexthops": [
+                    {
+                        "ip": "::",
+                        "afi": "ipv6",
+                        "scope": "global",
+                        "used": true
+                    }
+                ]
+            }
+        ],
+        "2001:db8:9::/64": [
+            {
+                "valid": true,
+                "bestpath": true,
+                "pathFrom": "external",
+                "prefix": "2001:db8:9::",
+                "prefixLen": 64,
+                "network": "2001:db8:9::\/64",
+                "med": 0,
+                "metric": 0,
+                "weight": 32768,
+                "peerId": "(unspec)",
+                "origin": "IGP",
+                "nexthops": [
+                    {
+                        "ip": "::",
+                        "afi": "ipv6",
+                        "scope": "global",
+                        "used": true
+                    }
+                ]
+            }
+        ]
+    }
+}
+
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/bgpd.conf b/tests/topotests/bfd-bgp-cbit-topo3/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..fa6d60a
--- /dev/null
@@ -0,0 +1,20 @@
+debug bgp neighbor-events
+router bgp 101
+ bgp router-id 10.254.254.1
+ timers bgp 8 24
+ bgp graceful-restart
+ neighbor 2001:db8:4::1 remote-as 102
+ neighbor 2001:db8:4::1 remote-as external
+ neighbor 2001:db8:4::1 bfd
+ neighbor 2001:db8:4::1 bfd check-control-plane-failure
+ neighbor 2001:db8:4::1 update-source 2001:db8:1::1
+ neighbor 2001:db8:4::1 ebgp-multihop 5
+ address-family ipv4 unicast
+  no neighbor 2001:db8:4::1 activate
+ exit-address-family
+ address-family ipv6 unicast
+  network 2001:db8:8::/64
+  network 2001:db8:9::/64 
+  neighbor 2001:db8:4::1 activate
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/ipv6_routes.json b/tests/topotests/bfd-bgp-cbit-topo3/r1/ipv6_routes.json
new file mode 100644 (file)
index 0000000..8eea183
--- /dev/null
@@ -0,0 +1,80 @@
+{
+  "2001:db8:1::/64": [{
+        "distance": 0,
+        "protocol": "connected",
+        "metric": 0,
+        "selected": true,
+        "destSelected": true,
+        "prefix": "2001:db8:1::/64",
+        "nexthops": [{
+                "directlyConnected": true,
+                "interfaceName": "r1-eth0",
+                "fib": true,
+                "flags": 3,
+                "active": true
+            }
+        ]
+    }
+  ],
+  "2001:db8:4::/64": [{
+        "distance": 1,
+        "protocol": "static",
+        "metric": 0,
+        "selected": true,
+        "destSelected": true,
+        "prefix": "2001:db8:4::/64",
+        "nexthops": [{
+                "interfaceName": "r1-eth0",
+                "fib": true,
+                "flags": 3,
+                "active": true,
+                "afi": "ipv6"
+            }
+        ]
+    }
+  ],
+  "2001:db8:6::/64": [{
+        "distance": 20,
+        "protocol": "bgp",
+        "metric": 0,
+        "selected": true,
+        "destSelected": true,
+        "prefix": "2001:db8:6::/64",
+        "nexthops": [{
+                "ip":"2001:db8:4::1",
+                "active": true,
+                "afi": "ipv6",
+                "recursive":true
+            },
+            {
+                "fib":true,
+                "ip":"2001:db8:1::2",
+                "afi": "ipv6",
+                "interfaceName": "r1-eth0"
+            }
+        ]
+    }
+  ],
+  "2001:db8:7::/64": [{
+        "distance": 20,
+        "protocol": "bgp",
+        "metric": 0,
+        "selected": true,
+        "destSelected": true,
+        "prefix": "2001:db8:7::/64",
+        "nexthops": [{
+                "ip":"2001:db8:4::1",
+                "active": true,
+                "afi": "ipv6",
+                "recursive": true
+            },
+            {
+                "fib":true,
+                "ip":"2001:db8:1::2",
+                "afi": "ipv6",
+                "interfaceName":"r1-eth0"
+            }
+        ]
+    }
+  ]
+}
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/peers.json b/tests/topotests/bfd-bgp-cbit-topo3/r1/peers.json
new file mode 100644 (file)
index 0000000..d1927ae
--- /dev/null
@@ -0,0 +1,16 @@
+[
+    {
+        "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
+    }
+]
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json b/tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json
new file mode 100644 (file)
index 0000000..25b47f1
--- /dev/null
@@ -0,0 +1,14 @@
+[
+    {
+        "multihop":true,
+        "peer":"2001:db8:4::1",
+        "local":"2001:db8:1::1",
+        "status":"up",
+        "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-bgp-cbit-topo3/r1/zebra.conf b/tests/topotests/bfd-bgp-cbit-topo3/r1/zebra.conf
new file mode 100644 (file)
index 0000000..3a30cd4
--- /dev/null
@@ -0,0 +1,8 @@
+interface lo
+ ip address 10.254.254.1/32
+!
+interface r1-eth0
+ ipv6 address 2001:db8:1::1/64
+!
+ipv6 route 2001:db8:4::/64 2001:db8:1::2
+
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r2/zebra.conf b/tests/topotests/bfd-bgp-cbit-topo3/r2/zebra.conf
new file mode 100644 (file)
index 0000000..0f70be1
--- /dev/null
@@ -0,0 +1,9 @@
+ip forwarding
+ipv6 forwarding
+!
+interface r2-eth0
+ ipv6 address 2001:db8:1::2/64
+!
+interface r2-eth1
+ ipv6 address 2001:db8:4::2/64
+!
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/bgp_ipv6_routes_down.json b/tests/topotests/bfd-bgp-cbit-topo3/r3/bgp_ipv6_routes_down.json
new file mode 100644 (file)
index 0000000..a3bb222
--- /dev/null
@@ -0,0 +1,55 @@
+{
+    "vrfId": 0,
+    "vrfName": "default",
+    "routerId": "10.254.254.3",
+    "localAS": 102,
+    "routes":
+    {
+        "2001:db8:6::/64": [
+            {
+                "valid": true,
+                "bestpath": true,
+                "pathFrom": "external",
+                "prefix": "2001:db8:6::",
+                "prefixLen": 64,
+                "network": "2001:db8:6::\/64",
+                "med": 0,
+                "metric": 0,
+                "weight": 32768,
+                "peerId": "(unspec)",
+                "origin": "IGP",
+                "nexthops": [
+                    {
+                        "ip": "::",
+                        "afi": "ipv6",
+                        "scope": "global",
+                        "used": true
+                    }
+                ]
+            }
+        ],
+        "2001:db8:7::/64": [
+            {
+                "valid": true,
+                "bestpath": true,
+                "pathFrom": "external",
+                "prefix": "2001:db8:7::",
+                "prefixLen": 64,
+                "network": "2001:db8:7::\/64",
+                "med": 0,
+                "metric": 0,
+                "weight": 32768,
+                "peerId": "(unspec)",
+                "origin": "IGP",
+                "nexthops": [
+                    {
+                        "ip": "::",
+                        "afi": "ipv6",
+                        "scope": "global",
+                        "used": true
+                    }
+                ]
+            }
+        ]
+    }
+}
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/bgpd.conf b/tests/topotests/bfd-bgp-cbit-topo3/r3/bgpd.conf
new file mode 100644 (file)
index 0000000..ea53340
--- /dev/null
@@ -0,0 +1,25 @@
+debug bgp neighbor-events
+router bgp 102
+ bgp router-id 10.254.254.3
+ timers bgp 20 60
+ bgp graceful-restart
+ ! simulate NSF machine
+ bgp graceful-restart preserve-fw-state
+ bgp graceful-restart stalepath-time 900
+ bgp graceful-restart restart-time 900
+ neighbor 2001:db8:1::1 remote-as 101
+ neighbor 2001:db8:1::1 remote-as external
+ neighbor 2001:db8:1::1 update-source 2001:db8:4::1
+ neighbor 2001:db8:1::1 bfd
+ neighbor 2001:db8:1::1 ebgp-multihop 5
+ !
+ address-family ipv4 unicast
+  no neighbor 2001:db8:1::1 activate
+ exit-address-family
+ !
+ address-family ipv6 unicast
+  neighbor 2001:db8:1::1 activate
+  network 2001:db8:6::/64
+  network 2001:db8:7::/64
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/ipv6_routes.json b/tests/topotests/bfd-bgp-cbit-topo3/r3/ipv6_routes.json
new file mode 100644 (file)
index 0000000..09808cc
--- /dev/null
@@ -0,0 +1,80 @@
+{
+  "2001:db8:1::/64": [{
+      "distance": 1,
+      "protocol": "static",
+      "metric": 0,
+      "selected": true,
+      "destSelected": true,
+      "prefix": "2001:db8:1::/64",
+      "nexthops": [{
+          "interfaceName": "r3-eth0",
+          "fib": true,
+          "flags": 3,
+          "active": true,
+          "afi": "ipv6"
+        }
+      ]
+    }
+  ],
+  "2001:db8:4::/64": [{
+      "distance": 0,
+      "protocol": "connected",
+      "metric": 0,
+      "selected": true,
+      "destSelected": true,
+      "prefix": "2001:db8:4::/64",
+      "nexthops": [{
+          "directlyConnected": true,
+          "interfaceName": "r3-eth0",
+          "fib": true,
+          "flags": 3,
+          "active": true
+        }
+      ]
+    }
+  ],
+  "2001:db8:8::/64": [{
+      "distance": 20,
+      "protocol": "bgp",
+      "metric": 0,
+      "selected": true,
+      "destSelected": true,
+      "prefix": "2001:db8:8::/64",
+      "nexthops": [{
+          "ip":"2001:db8:1::1",
+          "active": true,
+          "afi": "ipv6",
+          "recursive":true
+        },
+        {
+          "fib":true,
+          "ip":"2001:db8:4::2",
+          "afi": "ipv6",
+          "interfaceName":"r3-eth0"
+        }
+      ]
+    }
+  ],
+  "2001:db8:9::/64": [{
+      "distance": 20,
+      "protocol": "bgp",
+      "metric": 0,
+      "selected": true,
+      "destSelected": true,
+      "prefix": "2001:db8:9::/64",
+      "nexthops": [{
+          "ip":"2001:db8:1::1",
+          "active": true,
+          "afi": "ipv6",
+          "recursive":true
+        },
+        {
+          "fib":true,
+          "ip":"2001:db8:4::2",
+          "afi": "ipv6",
+          "interfaceName":"r3-eth0"
+        }
+      ]
+    }
+  ]
+}
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/peers.json b/tests/topotests/bfd-bgp-cbit-topo3/r3/peers.json
new file mode 100644 (file)
index 0000000..5193f2a
--- /dev/null
@@ -0,0 +1,16 @@
+[
+    {
+        "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
+    }
+]
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/peers_down.json b/tests/topotests/bfd-bgp-cbit-topo3/r3/peers_down.json
new file mode 100644 (file)
index 0000000..9e4bd26
--- /dev/null
@@ -0,0 +1,14 @@
+[
+    {
+        "multihop":true,
+        "peer":"2001:db8:1::1",
+        "local":"2001:db8:4::1",
+        "status":"down",
+        "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-bgp-cbit-topo3/r3/zebra.conf b/tests/topotests/bfd-bgp-cbit-topo3/r3/zebra.conf
new file mode 100644 (file)
index 0000000..7759251
--- /dev/null
@@ -0,0 +1,7 @@
+interface lo
+ ip address 10.254.254.3/32
+!
+interface r3-eth0
+ ipv6 address 2001:db8:4::1/64
+!
+ipv6 route 2001:db8:1::/64 2001:db8:4::2
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.dot b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.dot
new file mode 100644 (file)
index 0000000..270de82
--- /dev/null
@@ -0,0 +1,58 @@
+## 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="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,
+  ];
+
+  # Connections
+  r1 -- sw1 [label="eth0"];
+  r2 -- sw1 [label="eth0"];
+
+  r2 -- sw2 [label="eth1"];
+  r3 -- sw2 [label="eth0"];
+}
diff --git a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py
new file mode 100755 (executable)
index 0000000..59858d6
--- /dev/null
@@ -0,0 +1,248 @@
+#!/usr/bin/env python
+
+#
+# test_bfd_bgp_cbit_topo3.py
+#
+# Copyright (c) 2019 6WIND
+#
+# 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_bgp_cbit_topo3.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, 4):
+            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'])
+
+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))
+        )
+
+    # 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 IPv6 routing tables.
+    logger.info("Checking IPv6 routes for convergence")
+    for router in tgen.routers().values():
+        if router.name == 'r2':
+            continue
+        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=40,
+                                            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():
+        if router.name == 'r2':
+            continue
+        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_bfd_loss_intermediate():
+    """
+    Assert that BFD notices the bfd link down failure.
+    but BGP entries should still be present
+    """
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info('removing IPv6 address from r2 to simulate loss of connectivity')
+    # Disable r2-eth0 ipv6 address
+    cmd = 'vtysh -c \"configure terminal\" -c \"interface r2-eth1\" -c "no ipv6 address 2001:db8:4::2/64\"'
+    tgen.net['r2'].cmd(cmd)
+    # Wait the minimum time we can before checking that BGP/BFD
+    # converged.
+    logger.info('waiting for BFD converge down')
+
+    # Check that BGP converged quickly.
+    for router in tgen.routers().values():
+        if router.name == 'r2':
+            continue
+        json_file = '{}/{}/peers_down.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
+
+    logger.info('waiting for BGP entries to become stale')
+    for router in tgen.routers().values():
+        if router.name == 'r2':
+            continue
+        json_file = '{}/{}/bgp_ipv6_routes_down.json'.format(CWD, router.name)
+        expected = json.loads(open(json_file).read())
+
+        test_func = partial(topotest.router_json_cmp,
+                            router, 'show bgp ipv6 json', expected)
+        _, result = topotest.run_and_expect(test_func, None, count=50, wait=1)
+        assertmsg = '"{}" JSON output mismatches'.format(router.name)
+        assert result is None, assertmsg
+
+    logger.info("Checking IPv6 routes on r1 should still be present")
+    for router in tgen.routers().values():
+        if router.name == 'r2':
+            continue
+        if router.name == 'r3':
+            continue
+        json_file = '{}/r1/ipv6_routes.json'.format(CWD)
+        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=30,
+                                            wait=0.5)
+        assertmsg = '"{}" JSON output mismatches'.format(router.name)
+        assert result is None, assertmsg
+
+def test_bfd_comes_back_again():
+    """
+    Assert that BFD notices the bfd link up
+    and that ipv6 entries appear back
+    """
+    tgen = get_topogen()
+    logger.info('re-adding IPv6 address from r2 to simulate connectivity is back')
+    # adds back r2-eth0 ipv6 address
+    cmd = 'vtysh -c \"configure terminal\" -c \"interface r2-eth1\" -c "ipv6 address 2001:db8:4::2/64\"'
+    tgen.net['r2'].cmd(cmd)
+
+    # Wait the minimum time we can before checking that BGP/BFD
+    # converged.
+    logger.info('waiting for BFD to converge up')
+
+    # Check that BGP converged quickly.
+    for router in tgen.routers().values():
+        if router.name == 'r2':
+            continue
+        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))